Compare commits

...

60 Commits

Author SHA1 Message Date
Simon Rozman
4ef335b6aa Version set to 2.0-alpha6 2016-04-29 13:09:19 +02:00
Simon Rozman
15365aff46 Input language detection added
(closes #2)
2016-04-29 12:54:39 +02:00
Simon Rozman
4a27d62b4e ZRCola::LangConvert() function added 2016-04-29 12:35:59 +02:00
Simon Rozman
38bf070a4a Auto-start on logon feature added
(closes #8)
2016-04-29 09:51:40 +02:00
Simon Rozman
c7df06ba1e Fixed order in SQL queries for consistent ZRCola.zrcdb generation 2016-04-26 15:43:33 +02:00
Simon Rozman
b9d636fb30 CharDescGenerate job added to generate character descriptions 2016-04-26 15:26:11 +02:00
Simon Rozman
ac005c0b77 Merge branch 'master' of https://github.com/Amebis/ZRCola 2016-04-23 22:23:00 +02:00
Simon Rozman
58f354f028 GUI edit boxes labeled now 2016-04-23 22:22:46 +02:00
Simon Rozman
a1a1852552 GUI edit boxes labeled now 2016-04-23 22:16:03 +02:00
Simon Rozman
7807e8a918 ZRCola.fbp added to project 2016-04-23 22:14:49 +02:00
Simon Rozman
3daaff4260 Script to import UnicodeData.txt to ZRCola.mdb added 2016-04-23 14:02:50 +02:00
Simon Rozman
840c8240b7 Composer panel settings moved for simpler configuration organization 2016-04-23 06:38:48 +02:00
Simon Rozman
21114d818c On-screen Unicode dump added
(closes #14)
2016-04-22 16:12:59 +02:00
Simon Rozman
7a424da3fc Code to Save & Restore text moved to wxZRColaComposerPanel to avoid confusion with GUI persistence 2016-04-22 14:24:17 +02:00
Simon Rozman
82d2fc42bd Minor updates of auto-saving feature 2016-04-22 13:39:34 +02:00
Simon Rozman
5f755aa3d9 Auto-Save & Restore of text added
(closes #16)
2016-04-22 13:29:30 +02:00
Simon Rozman
8c51f9c2a6 Ambiguous decomposition sequences now decompose to first ranked decomposition
(resolves #18)
2016-04-22 11:30:42 +02:00
Simon Rozman
5df7ca886b Decomposition before composition added
(resolves #17)
2016-04-22 11:00:11 +02:00
Simon Rozman
2e89edb62c Source and destination index mapping on the left side of the first transformation issue fixed 2016-04-22 10:59:29 +02:00
Simon Rozman
a021dd31f7 ZRCola::mapping is generic now 2016-04-20 12:24:23 +02:00
Simon Rozman
5e4331903b Language names are displayed with the localized full name now
(closes #15)
2016-04-13 20:39:14 +02:00
Simon Rozman
55c76265df Redundant check removed 2016-04-13 12:41:41 +02:00
Simon Rozman
5a2fcf7cb2 Version set to 2.0-alpha5. 2016-04-13 11:05:09 +02:00
Simon Rozman
4fba54bdb2 Text language for decomposition GUI support added
(closes #1)
2016-04-13 11:03:38 +02:00
Simon Rozman
ab3ef08a5f Translation database moved to ZRColaApp 2016-04-12 14:47:14 +02:00
Simon Rozman
c21e1b8198 Sub-module update 2016-04-11 13:53:08 +02:00
Simon Rozman
7e6eaefd42 Doxygen annotation update 2016-04-11 13:52:57 +02:00
Simon Rozman
f735bd5bee Decomposition can omit language specific characters now 2016-04-11 13:28:19 +02:00
Simon Rozman
b7f3305019 ZRCola::langid_t moved to common.h 2016-04-11 12:51:49 +02:00
Simon Rozman
b194662c03 Typo in documentation fixed 2016-04-11 12:41:40 +02:00
Simon Rozman
177edd19e8 Languages and language-specific characters added to the database 2016-04-11 12:41:22 +02:00
Simon Rozman
fc93474b9a Characters with decompositions starting with # do not decompose any more. 2016-04-11 10:21:11 +02:00
Simon Rozman
02f164cee6 Version set to 2.0-alpha4 2016-04-08 14:54:18 +02:00
Simon Rozman
a35c0d83ca Merge branch 'master' of https://github.com/Amebis/ZRCola 2016-04-08 14:49:47 +02:00
Simon Rozman
6b4ed23801 ZRCola database updated
(resolves #7)
2016-04-08 14:49:27 +02:00
Simon Rozman
2c602ad659 ZRCola database updated 2016-04-08 14:48:23 +02:00
Simon Rozman
279537b1f3 Combinations with partial longer match not composed issue resolved
(resolves #6)
2016-04-08 14:45:28 +02:00
Simon Rozman
f918c49bfd Accessing an element of table before determining size issue resolved 2016-04-08 13:48:33 +02:00
Simon Rozman
72c29a692e GUI aligned with stock text 2016-04-08 13:22:23 +02:00
Simon Rozman
fc78a650a2 Select All (text) feature added 2016-04-08 13:01:09 +02:00
Simon Rozman
acec7098e5 Minor GUI improvements 2016-04-08 12:44:35 +02:00
Simon Rozman
98eff47054 Clipboard events are forwarded to focused control now
(resolves #12)
2016-04-08 12:35:38 +02:00
Simon Rozman
cd2c20fc06 Version set to 2.0-alpha3. 2016-04-08 09:22:10 +02:00
Simon Rozman
ac772671cc Publish target split into PublishPre and Publish 2016-04-08 09:21:53 +02:00
Simon Rozman
acfe980705 Non-working OEM key sequences issue fixed
resolves #5
2016-04-07 14:52:45 +02:00
Simon Rozman
426b7a6227 Keyboard sequence monitoring upgraded not to react on modifier keys, canceling multi-key sequences when non-first key modifier pressed 2016-04-07 14:49:28 +02:00
Simon Rozman
834743c7dd Cleanup 2016-04-07 13:10:54 +02:00
Simon Rozman
c8628ef4eb Key sequence import fixed (resolves #7) 2016-04-07 12:53:19 +02:00
Simon Rozman
4f52304fe9 Advertised shortcuts disabled (closes #4) 2016-04-07 10:50:31 +02:00
Simon Rozman
eef80067bb Language setting moved from HKCU (per-user) to HKLM (global) 2016-04-07 09:41:29 +02:00
Simon Rozman
9240288245 Generic module names replaced 2016-04-06 14:14:35 +02:00
Simon Rozman
1b41ff7aab Version set to 2.0-alpha2 2016-04-06 13:21:24 +02:00
Simon Rozman
61af77e7b6 Main window size and position is remembered now 2016-04-06 13:15:03 +02:00
Simon Rozman
ee7f94d776 Old configuration delete added 2016-04-06 13:12:44 +02:00
Simon Rozman
1cb4f470c6 Application's config is global now 2016-04-06 13:09:33 +02:00
Simon Rozman
8fd0437502 GUI upgrade: Edit menu added, tool bar added, status bar added 2016-04-06 12:33:38 +02:00
Simon Rozman
93361f0edb Partial key sequence match no longer propagates the event 2016-04-06 12:29:07 +02:00
Simon Rozman
2007d04812 Non-Slovenian setup no longer include Slovenian localization 2016-04-05 14:54:54 +02:00
Simon Rozman
a4aff5151e Merged consecutive characters issue fixed 2016-04-05 14:38:59 +02:00
Simon Rozman
ce43a99b30 Sub-module update 2016-04-04 15:36:28 +02:00
72 changed files with 15013 additions and 423 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -53,7 +53,9 @@ All :: "$(LANG).$(PLAT).$(CFG).Component-1.idt"
Component ComponentId Directory_ Attributes Condition KeyPath
s$(MSIBUILD_LENGTH_ID) S38 s$(MSIBUILD_LENGTH_ID) i2 S255 S$(MSIBUILD_LENGTH_ID)
Component Component
!IF "$(LANG)" == "Sl"
compwxstd.mo.sl_SI {A5FEEA94-08CA-4E12-993F-A115601EF258} ZRCOLALOCSLSIDIR $(MSIBUILD_COMPONENT_ATTRIB_FILE) filewxstd.mo.sl_SI
!ENDIF
compLocalizationRepositoryPath {0E96110A-C38D-4600-9AE2-B8B59AF53A00} ZRCOLALOCDIR $(MSIBUILD_COMPONENT_ATTRIB_REGISTRY) regLocalizationRepositoryPath
compLanguage {B78359AC-9484-402C-8384-3A4595B39389} ZRCOLALOCDIR $(MSIBUILD_COMPONENT_ATTRIB_REGISTRY) regLanguage
compDatabasePath {DF3C720D-50BB-4377-9EE0-9AC21C02B9DD} ZRCOLADATADIR $(MSIBUILD_COMPONENT_ATTRIB_REGISTRY) regDatabasePath
@@ -62,6 +64,9 @@ comp00_ZRCola_Re.ttf {B6CE8B39-11DC-4B59-B10C-3F0FFE8F81AF} FontsFolder 0 file0
comp00_ZRCola_It.ttf {10613965-2874-470D-9D5A-B7D535AA3317} FontsFolder 0 file00_ZRCola_It.ttf
comp00_ZRCola_Bd.ttf {C036BE8D-6D2F-4DBF-99D6-F53702EAEBB6} FontsFolder 0 file00_ZRCola_Bd.ttf
comp00_ZRCola_BI.ttf {883DDA9A-DA85-4FC4-95B7-EF0E08766DEF} FontsFolder 0 file00_ZRCola_BI.ttf
!IF "$(LANG)" == "Sl"
compZRCola.zrcdb.mo.sl_SI {6572EAD1-EE48-46A1-A28E-77985B667F67} ZRCOLALOCSLSIDIR $(MSIBUILD_COMPONENT_ATTRIB_FILE) fileZRCola.zrcdb.mo.sl_SI
!ENDIF
<<NOKEEP
@@ -226,12 +231,17 @@ All :: "$(LANG).$(PLAT).$(CFG).File-1.idt"
File Component_ FileName FileSize Version Language Attributes Sequence
s$(MSIBUILD_LENGTH_ID) s$(MSIBUILD_LENGTH_ID) l255 i4 S$(MSIBUILD_LENGTH_ID) S20 I2 i2
File File
!IF "$(LANG)" == "Sl"
filewxstd.mo.sl_SI compwxstd.mo.sl_SI wxstd.mo 0 1060 0 1
!ENDIF
fileZRCola.zrcdb compZRCola.zrcdb ZRCOLA~1.ZRC|ZRCola.zrcdb 0 0 1
file00_ZRCola_Re.ttf comp00_ZRCola_Re.ttf 00_ZRC~1.TTF|00_ZRCola_Re.ttf 0 0 1
file00_ZRCola_It.ttf comp00_ZRCola_It.ttf 00_ZRC~2.TTF|00_ZRCola_It.ttf 0 0 1
file00_ZRCola_Bd.ttf comp00_ZRCola_Bd.ttf 00_ZRC~3.TTF|00_ZRCola_Bd.ttf 0 0 1
file00_ZRCola_BI.ttf comp00_ZRCola_BI.ttf 00_ZRC~4.TTF|00_ZRCola_BI.ttf 0 0 1
!IF "$(LANG)" == "Sl"
fileZRCola.zrcdb.mo.sl_SI compZRCola.zrcdb.mo.sl_SI ZRCOLA~1.MO|ZRCola-zrcdb.mo 0 1060 0 1
!ENDIF
<<NOKEEP
@@ -313,6 +323,7 @@ s$(MSIBUILD_LENGTH_ID) l0
Property Property
ARPPRODUCTICON iconZRCola.ico
ALLUSERS 1
DISABLEADVTSHORTCUTS 1
INSTALLLEVEL 3
InstallMode Typical
SecureCustomProperties OLDPRODUCTFOUND;NEWPRODUCTFOUND
@@ -342,7 +353,7 @@ regDatabasePath 2 SOFTWARE\Amebis\ZRCola DatabasePath [ZRCOLADATADIR] compDataba
Registry Root Key Name Value Component_
s$(MSIBUILD_LENGTH_ID) i2 l255 L255 L0 s$(MSIBUILD_LENGTH_ID)
1252 Registry Registry
regLanguage 1 SOFTWARE\Amebis\ZRCola Language #60 compLanguage
regLanguage 2 SOFTWARE\Amebis\ZRCola Language #60 compLanguage
<<NOKEEP
"De.$(PLAT).$(CFG).Registry-2.idt" : "En.$(PLAT).$(CFG).Registry-2.idtx" "..\locale\de_DE.po"

View File

@@ -82,6 +82,7 @@ Setup \
SetupDebug \
Register \
Unregister \
PublishPre \
Publish :: "MSI\MSIBuild\Version\Version.mak"
$(MAKE) /f "Makefile" /$(MAKEFLAGS) HAS_VERSION=1 $@
@@ -183,12 +184,15 @@ RegisterShortcuts :: \
UnregisterShortcuts ::
-if exist "$(PROGRAMDATA)\Microsoft\Windows\Start Menu\Programs\ZRCola" rd /s /q "$(PROGRAMDATA)\Microsoft\Windows\Start Menu\Programs\ZRCola"
Publish :: \
PublishPre :: \
"$(PUBLISH_PACKAGE_DIR)" \
$(REDIST_EN_WIN32) \
$(REDIST_EN_X64) \
$(REDIST_SL_WIN32) \
$(REDIST_SL_X64) \
$(REDIST_SL_X64)
Publish :: \
PublishPre \
"$(PUBLISH_DIR)\catalog-0000.xml"

Submodule Updater updated: e88f1b429f...f1a3ae730a

View File

@@ -74,7 +74,9 @@ compZRCola.exe.Win32 {F30B6545-6203-4B7D-8575-85245A0F90E5} ZRCOLABINDIR 0 file
!IF "$(PLAT)" == "x64"
compZRCola.exe.x64 {D45B105D-2303-459A-AF4B-52AC3AAD5510} ZRCOLABINDIR 256 fileZRCola.exe.x64
!ENDIF
!IF "$(LANG)" == "Sl"
compZRCola.mo.sl_SI {7FF95C71-D8DE-4D2B-A26D-FEB5A1F54D63} ZRCOLALOCSLSIDIR $(MSIBUILD_COMPONENT_ATTRIB_FILE) fileZRCola.mo.sl_SI
!ENDIF
<<NOKEEP
@@ -117,17 +119,20 @@ Feature_ Component_
s$(MSIBUILD_LENGTH_ID) s$(MSIBUILD_LENGTH_ID)
FeatureComponents Feature_ Component_
featZRCola compZRCola.exe.$(PLAT)
featZRCola compZRCola.mo.sl_SI
featZRCola complibZRCola.dll.$(PLAT)
featZRCola complibZRColaUI.dll.$(PLAT)
featZRCola compwxExtend.dll.$(PLAT)
featZRCola compwxExtend.mo.sl_SI
featZRCola compwxstd.mo.sl_SI
featZRCola compLocalizationRepositoryPath
featZRCola compLanguage
featZRCola compDatabasePath
featZRCola compZRCola.zrcdb
featZRCola comp00_ZRCola_Re.ttf
!IF "$(LANG)" == "Sl"
featZRCola compZRCola.mo.sl_SI
featZRCola compZRCola.zrcdb.mo.sl_SI
featZRCola compwxExtend.mo.sl_SI
featZRCola compwxstd.mo.sl_SI
!ENDIF
<<NOKEEP
@@ -143,7 +148,9 @@ File Component_ FileName FileSize Version Language Attributes Sequence
s$(MSIBUILD_LENGTH_ID) s$(MSIBUILD_LENGTH_ID) l255 i4 S$(MSIBUILD_LENGTH_ID) S20 I2 i2
File File
fileZRCola.exe.$(PLAT) compZRCola.exe.$(PLAT) ZRCola.exe 0 0 1536 1
!IF "$(LANG)" == "Sl"
fileZRCola.mo.sl_SI compZRCola.mo.sl_SI ZRCola.mo 0 1060 0 1
!ENDIF
<<NOKEEP

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -106,7 +106,14 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="res\edit_copy.ico" />
<None Include="res\edit_cut.ico" />
<None Include="res\edit_paste.ico" />
<None Include="res\send_abort.ico" />
<None Include="res\send_composed.ico" />
<None Include="res\send_decomposed.ico" />
<None Include="res\zrcola.ico" />
<None Include="ZRCola.fbp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ZRCola.rc" />

View File

@@ -62,6 +62,27 @@
<None Include="res\zrcola.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="res\send_abort.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="res\send_composed.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="res\send_decomposed.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="res\edit_copy.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="res\edit_cut.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="res\edit_paste.ico">
<Filter>Resource Files</Filter>
</None>
<None Include="ZRCola.fbp">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="ZRCola.rc">

View File

@@ -1,8 +1,8 @@
msgid ""
msgstr ""
"Project-Id-Version: ZRCola\n"
"POT-Creation-Date: 2016-03-14 17:18+0100\n"
"PO-Revision-Date: 2016-03-14 17:18+0100\n"
"POT-Creation-Date: 2016-04-29 12:50+0200\n"
"PO-Revision-Date: 2016-04-29 12:50+0200\n"
"Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n"
"Language-Team: Amebis, d. o. o., Kamnik <info@amebis.si>\n"
"Language: sl_SI\n"
@@ -17,27 +17,36 @@ msgstr ""
"X-Poedit-KeywordsList: _\n"
"X-Poedit-SearchPath-0: .\n"
#: zrcolafrm.cpp:58
#: zrcolafrm.cpp:76
#, c-format
msgid "Select %s language for decomposition"
msgstr "Izberi jezik %s za razstavljanje"
#: zrcolafrm.cpp:87
msgid ""
"ZRCola keyboard shortcut Win+Z could not be registered. Some functionality "
"ZRCola keyboard shortcut Win+F5 could not be registered. Some functionality "
"will not be available."
msgstr ""
"ZRColine bližnjice na tipkovnici Win+Z ni mogoče registrirati. Nekaj "
"ZRColine bližnjice na tipkovnici Win+F5 ni mogoče registrirati. Nekaj "
"funkcionalnosti ne bo na voljo."
#: zrcolafrm.cpp:58 zrcolafrm.cpp:60
#: zrcolafrm.cpp:87 zrcolafrm.cpp:89
msgid "Warning"
msgstr "Opozorilo"
#: zrcolafrm.cpp:60
#: zrcolafrm.cpp:89
msgid ""
"ZRCola keyboard shortcut Win+Shift+Z could not be registered. Some "
"functionality will not be available."
"ZRCola keyboard shortcut Win+F6 could not be registered. Some functionality "
"will not be available."
msgstr ""
"ZRColine bližnjice na tipkovnici Win+Shift+Z ni mogoče registrirati. Nekaj "
"ZRColine bližnjice na tipkovnici Win+F6 ni mogoče registrirati. Nekaj "
"funkcionalnosti ne bo na voljo."
#: zrcolafrm.cpp:140
#: zrcolafrm.cpp:151
msgid "Start ZRCola automatically on logon"
msgstr "Samodejno zaženi ZRColo ob prijavi"
#: zrcolafrm.cpp:309
#, c-format
msgid ""
"ZRCola v%s\n"
@@ -46,60 +55,190 @@ msgstr ""
"ZRCola v%s\n"
"Vse pravice pridržane 2015-%s Amebis"
#: zrcolafrm.cpp:140
#: zrcolafrm.cpp:309
msgid "About ZRCola"
msgstr "O ZRColi"
#: zrcolagui.cpp:32
msgid "&Start on Logon"
msgstr "Z&aženi ob prijavi"
#: zrcolagui.cpp:32
msgid "Start this program automatically on logon"
msgstr "Samodejno zaženi ta program ob prijavi"
#: zrcolagui.cpp:38
msgid "E&xit"
msgstr "I&zhod"
#: zrcolagui.cpp:35
msgid "&File"
msgstr "&Datoteka"
#: zrcolagui.cpp:38
msgid "Quit this program"
msgstr "Zapri ta program"
#: zrcolagui.cpp:39
msgid "&About"
msgstr "O progr&amu"
#: zrcolagui.cpp:41
msgid "&Program"
msgstr "&Program"
#: zrcolagui.cpp:42
#: zrcolagui.cpp:74
msgid "Select &All"
msgstr "Izberi &vse"
#: zrcolagui.cpp:74
msgid "Select all text"
msgstr "Izberi celotno besedilo"
#: zrcolagui.cpp:80
msgid "&Send Composed"
msgstr "Pošlji &sestavljeno"
#: zrcolagui.cpp:80 zrcolagui.cpp:137
msgid "Send composed text to source window"
msgstr "Pošlji sestavljeno besedilo izvornemu oknu"
#: zrcolagui.cpp:89
msgid "Send &Decomposed"
msgstr "Pošlji &razstavljeno"
#: zrcolagui.cpp:89 zrcolagui.cpp:139
msgid "Send decomposed text to source window"
msgstr "Pošlji razstavljeno besedilo izvornemu oknu"
#: zrcolagui.cpp:98
msgid "Abort (De)composition"
msgstr "Prekini raz/sestavljanje"
#: zrcolagui.cpp:98
msgid "Abort composition and return focus to source window"
msgstr "Prekini sestavljanje in vrni fokus nazaj izvornemu oknu"
#: zrcolagui.cpp:107
msgid "&Language"
msgstr "&Jezik"
#: zrcolagui.cpp:109
msgid "&Automatic"
msgstr "S&amodejno"
#: zrcolagui.cpp:109
msgid "Set language according to keyboard layout automatically"
msgstr "Samodejno nastavi jezik glede na izbrano tipkovnico"
#: zrcolagui.cpp:116
msgid "&Edit"
msgstr "Ur&edi"
#: zrcolagui.cpp:123
msgid "&Help"
msgstr "&Pomoč"
#: zrcolagui.h:47 MSIBuild/En.Win32.Debug.Feature-2.idtx:4
#: MSIBuild/En.Win32.Debug.Shortcut-2.idtx:4
#: MSIBuild/En.Win32.Release.Feature-2.idtx:4
#: zrcolagui.cpp:129
msgid "Cut"
msgstr "Izreži"
#: zrcolagui.cpp:129
msgid "Cut selection"
msgstr "Izreži izbor"
#: zrcolagui.cpp:131
msgid "Copy"
msgstr "Kopiraj"
#: zrcolagui.cpp:131
msgid "Copy selection"
msgstr "Kopiraj izbor"
#: zrcolagui.cpp:133
msgid "Paste"
msgstr "Prilepi"
#: zrcolagui.cpp:133
msgid "Paste selection"
msgstr "Prilepi izbor"
#: zrcolagui.cpp:137
msgid "Send Composed"
msgstr "Pošlji sestavljeno"
#: zrcolagui.cpp:139
msgid "Send Decomposed"
msgstr "Pošlji razstavljeno"
#: zrcolagui.cpp:141
msgid "Language:"
msgstr "Jezik:"
#: zrcolagui.cpp:190
msgid "Decomposed Text"
msgstr "Razstavljeno besedilo"
#: zrcolagui.cpp:210
msgid "Decomposed Unicode Dump"
msgstr "Unicode razstavljenega"
#: zrcolagui.cpp:237
msgid "Composed Text"
msgstr "Sestavljeno besedilo"
#: zrcolagui.cpp:257
msgid "Composed Unicode Dump"
msgstr "Unicode sestavljenega"
#: zrcolagui.h:77 MSIBuild/En.Win32.Release.Feature-2.idtx:4
#: MSIBuild/En.Win32.Release.Shortcut-2.idtx:4
#: MSIBuild/En.x64.Debug.Feature-2.idtx:4
#: MSIBuild/En.x64.Debug.Shortcut-2.idtx:4
#: MSIBuild/En.x64.Release.Feature-2.idtx:4
#: MSIBuild/En.x64.Release.Shortcut-2.idtx:4
msgid "ZRCola"
msgstr "ZRCola"
# Windows charset for this language (decimal)
#: MSIBuild/En.Win32.Debug.Feature-2.idtx:3
#: MSIBuild/En.Win32.Debug.Shortcut-2.idtx:3
#: MSIBuild/En.Win32.Release.Feature-2.idtx:3
#: MSIBuild/En.Win32.Release.Shortcut-2.idtx:3
#: MSIBuild/En.x64.Debug.Feature-2.idtx:3
#: MSIBuild/En.x64.Debug.Shortcut-2.idtx:3
#: MSIBuild/En.x64.Release.Feature-2.idtx:3
#: MSIBuild/En.x64.Release.Shortcut-2.idtx:3
msgid "1252"
msgstr "1250"
#: MSIBuild/En.Win32.Debug.Feature-2.idtx:4
#: MSIBuild/En.Win32.Debug.Shortcut-2.idtx:4
#: MSIBuild/En.Win32.Release.Feature-2.idtx:4
#: MSIBuild/En.Win32.Release.Shortcut-2.idtx:4
#: MSIBuild/En.x64.Debug.Feature-2.idtx:4
#: MSIBuild/En.x64.Debug.Shortcut-2.idtx:4
#: MSIBuild/En.x64.Release.Feature-2.idtx:4
#: MSIBuild/En.x64.Release.Shortcut-2.idtx:4
msgid "Input system for linguistic use"
msgstr "Vnašalni sistem za jezikoslovno rabo"
#~ msgid "&About"
#~ msgstr "O progr&amu"
#~ msgid "Cuts selected text and puts it on the clipboard"
#~ msgstr "Izreže izbrano besedilo in ga shrani na odložišče"
#~ msgid "Copies selected text to the clipboard"
#~ msgstr "Kopira izbrano besedilo na odložišče"
#~ msgid "Inserts text from the clipboard"
#~ msgstr "Vstavi besedilo z odložišča"
#~ msgid "&Copy"
#~ msgstr "&Kopiraj"
#~ msgid "&Paste"
#~ msgstr "&Prilepi"
#~ msgid "&File"
#~ msgstr "&Datoteka"
#~ msgid "Send Decomposed (F6)"
#~ msgstr "Pošlji razstavljeno (F6)"
#~ msgid "Send Composed (F5)"
#~ msgstr "Pošlji sestavljeno (F5)"
#~ msgid ""
#~ "ZRCola keyboard shortcut Win+Shift+Z could not be registered. Some "
#~ "functionality will not be available."
#~ msgstr ""
#~ "ZRColine bližnjice na tipkovnici Win+Shift+Z ni mogoče registrirati. "
#~ "Nekaj funkcionalnosti ne bo na voljo."
#, fuzzy
#~ msgid "Authentication progress real time monitor"
#~ msgstr "Nadzira postopek overovljanja v realnem času"

BIN
ZRCola/res/edit_copy.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

1593
ZRCola/res/edit_copy.pdf Normal file

File diff suppressed because one or more lines are too long

BIN
ZRCola/res/edit_cut.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

1707
ZRCola/res/edit_cut.pdf Normal file

File diff suppressed because one or more lines are too long

BIN
ZRCola/res/edit_paste.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

1727
ZRCola/res/edit_paste.pdf Normal file

File diff suppressed because one or more lines are too long

BIN
ZRCola/res/send_abort.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

1603
ZRCola/res/send_abort.pdf Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

1688
ZRCola/res/send_composed.pdf Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

File diff suppressed because one or more lines are too long

View File

@@ -25,7 +25,10 @@
#include "zrcolafrm.h"
#include "zrcolakeyhndlr.h"
#include <wx/ffile.h>
#include <wx/msgdlg.h>
#include <wx/persist.h>
#include <wx/persist/toplevel.h>
#include <wxex/common.h>
#include <fstream>
@@ -33,3 +36,9 @@
#include <vector>
#include <stdex/idrec.h>
#if defined(__WXMSW__)
#include <Msi.h>
#include <ShObjIdl.h>
#include <ShlGuid.h>
#endif

View File

@@ -18,6 +18,9 @@
*/
#include "stdafx.h"
#if defined(__WXMSW__)
#pragma comment(lib, "msi.lib")
#endif
//////////////////////////////////////////////////////////////////////////
@@ -27,31 +30,90 @@
wxIMPLEMENT_APP(ZRColaApp);
ZRColaApp::ZRColaApp() :
m_config(wxT(ZRCOLA_CFG_APPLICATION), wxT(ZRCOLA_CFG_VENDOR)),
wxApp()
ZRColaApp::ZRColaApp() : wxApp()
{
}
bool ZRColaApp::OnInit()
{
#if defined(__WXMSW__)
// To compensate migration to non-advertised shortcut, do the Microsoft Installer's feature completeness check manually.
// If execution got this far in the first place (EXE and dependent DLLs are present and loadable).
// Furthermore, this increments program usage counter.
if (::MsiQueryFeatureState(_T(ZRCOLA_VERSION_GUID), _T("featZRCola")) != INSTALLSTATE_UNKNOWN)
::MsiUseFeature(_T(ZRCOLA_VERSION_GUID), _T("featZRCola"));
#endif
wxConfigBase *cfgPrev = wxConfigBase::Set(new wxConfig(wxT(ZRCOLA_CFG_APPLICATION), wxT(ZRCOLA_CFG_VENDOR)));
if (cfgPrev) wxDELETE(cfgPrev);
if (!wxApp::OnInit())
return false;
// Set desired locale.
wxLanguage language = (wxLanguage)m_config.Read(wxT("Language"), wxLANGUAGE_DEFAULT);
wxLanguage language = (wxLanguage)wxConfigBase::Get()->Read(wxT("Language"), wxLANGUAGE_DEFAULT);
if (wxLocale::IsAvailable(language)) {
wxString sPath;
if (m_config.Read(wxT("LocalizationRepositoryPath"), &sPath))
if (wxConfigBase::Get()->Read(wxT("LocalizationRepositoryPath"), &sPath))
m_locale.AddCatalogLookupPathPrefix(sPath);
wxVERIFY(m_locale.Init(language));
wxVERIFY(m_locale.AddCatalog(wxT("wxExtend")));
wxVERIFY(m_locale.AddCatalog(wxT("ZRCola")));
wxVERIFY(m_locale.AddCatalog(wxT("ZRCola-zrcdb")));
}
std::fstream dat((LPCTSTR)GetDatabasePath(), std::ios_base::in | std::ios_base::binary);
if (dat.good()) {
if (stdex::idrec::find<ZRCola::recordid_t, ZRCola::recordsize_t, ZRCOLA_RECORD_ALIGN>(dat, ZRCOLA_DB_ID, sizeof(ZRCola::recordid_t))) {
ZRCola::recordsize_t size;
dat.read((char*)&size, sizeof(ZRCola::recordsize_t));
if (dat.good()) {
bool has_translation_data = false;
for (;;) {
ZRCola::recordid_t id;
if (!stdex::idrec::read_id(dat, id, size)) break;
if (id == ZRCola::translation_rec::id) {
dat >> ZRCola::translation_rec(m_t_db);
if (dat.good()) {
has_translation_data = true;
} else {
wxFAIL_MSG(wxT("Error reading translation data from ZRCola.zrcdb."));
m_t_db.idxComp .clear();
m_t_db.idxDecomp.clear();
m_t_db.data .clear();
}
} else if (id == ZRCola::langchar_rec::id) {
dat >> ZRCola::langchar_rec(m_lc_db);
if (!dat.good()) {
wxFAIL_MSG(wxT("Error reading language character data from ZRCola.zrcdb."));
m_lc_db.idxChr.clear();
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
m_lc_db.idxLng.clear();
#endif
m_lc_db.data .clear();
}
} else if (id == ZRCola::language_rec::id) {
dat >> ZRCola::language_rec(m_lang_db);
if (!dat.good()) {
wxFAIL_MSG(wxT("Error reading language character data from ZRCola.zrcdb."));
m_lang_db.idxLng.clear();
m_lang_db.data .clear();
}
}
}
if (!has_translation_data)
wxFAIL_MSG(wxT("ZRCola.zrcdb has no translation data."));
}
} else
wxFAIL_MSG(wxT("ZRCola.zrcdb is not a valid ZRCola database."));
}
wxZRColaFrame* mainFrame = new wxZRColaFrame();
wxPersistentRegisterAndRestore<wxZRColaFrame>(mainFrame);
mainFrame->Show();
return true;

View File

@@ -28,6 +28,8 @@ class ZRColaApp;
#include <wx/app.h>
#include <wx/config.h>
#include <wx/intl.h>
#include <zrcola/language.h>
#include <zrcola/translate.h>
///
@@ -42,8 +44,8 @@ public:
/// Called when application initializes.
///
/// \returns
/// - true if initialization succeeded
/// - false otherwise
/// - \c true if initialization succeeded
/// - \c false otherwise
///
virtual bool OnInit();
@@ -54,8 +56,12 @@ public:
inline wxString GetDatabasePath() const;
public:
ZRCola::translation_db m_t_db; ///< Translation database
ZRCola::langchar_db m_lc_db; ///< Language character database
ZRCola::language_db m_lang_db; ///< Language database
protected:
wxConfig m_config; ///< Application configuration
wxLocale m_locale; ///< Current locale
};
@@ -66,7 +72,7 @@ wxDECLARE_APP(ZRColaApp);
inline wxString ZRColaApp::GetDatabasePath() const
{
wxString sPath;
if (m_config.Read(wxT("DatabasePath"), &sPath)) {
if (wxConfigBase::Get()->Read(wxT("DatabasePath"), &sPath)) {
if (!wxEndsWithPathSeparator(sPath))
sPath << wxFILE_SEP_PATH;
} else {

View File

@@ -24,41 +24,65 @@
// wxZRColaComposerPanel
//////////////////////////////////////////////////////////////////////////
BEGIN_EVENT_TABLE(wxZRColaComposerPanel, wxZRColaComposerPanelBase)
EVT_TIMER(wxZRColaComposerPanel::wxID_TIMER, wxZRColaComposerPanel::OnTimerTimeout)
END_EVENT_TABLE()
wxZRColaComposerPanel::wxZRColaComposerPanel(wxWindow* parent) :
m_progress(false),
m_selDecomposed(0, 0),
m_selComposed(0, 0),
wxZRColaComposerPanelBase(parent)
{
std::fstream dat((LPCTSTR)((ZRColaApp*)wxTheApp)->GetDatabasePath(), std::ios_base::in | std::ios_base::binary);
if (dat.good()) {
if (stdex::idrec::find<ZRCola::recordid_t, ZRCola::recordsize_t, ZRCOLA_RECORD_ALIGN>(dat, ZRCOLA_DB_ID, sizeof(ZRCola::recordid_t))) {
ZRCola::recordsize_t size;
dat.read((char*)&size, sizeof(ZRCola::recordsize_t));
if (dat.good()) {
ZRCola::translation_rec rec(m_t_db);
if (rec.find(dat, size)) {
dat >> rec;
if (!dat.good()) {
wxFAIL_MSG(wxT("Error reading translation data from ZRCola.zrcdb."));
m_t_db.idxComp .clear();
m_t_db.idxDecomp.clear();
m_t_db.data .clear();
}
} else
wxFAIL_MSG(wxT("ZRCola.zrcdb has no translation data."));
}
} else
wxFAIL_MSG(wxT("ZRCola.zrcdb is not a valid ZRCola database."));
}
m_decomposed->PushEventHandler(&m_keyhandler);
// Create timer for saving the state.
m_timer = new wxTimer(this, wxID_TIMER);
// Restore the previously saved state (if exists).
wxString fileName(GetStateFileName());
if (wxFileExists(fileName)) {
wxFFile file(fileName, wxT("rb"));
if (file.IsOpened()) {
// Load decomposed text.
unsigned __int64 n;
file.Read(&n, sizeof(n));
if (!file.Error()) {
wxString decomposed;
file.Read(wxStringBuffer(decomposed, n), sizeof(wchar_t)*n);
if (!file.Error()) {
// Load composed text.
file.Read(&n, sizeof(n));
if (!file.Error()) {
wxString composed;
file.Read(wxStringBuffer(composed, n), sizeof(wchar_t)*n);
if (!file.Error()) {
// Restore state.
m_progress = true;
m_decomposed->SetValue(decomposed);
m_composed->SetValue(composed);
m_progress = false;
}
}
}
}
}
}
}
wxZRColaComposerPanel::~wxZRColaComposerPanel()
{
if (m_timer)
delete m_timer;
m_decomposed->PopEventHandler();
// This is a controlled exit. Purge saved state.
wxString fileName(GetStateFileName());
if (wxFileExists(fileName))
wxRemoveFile(fileName);
}
@@ -73,7 +97,27 @@ void wxZRColaComposerPanel::OnDecomposedPaint(wxPaintEvent& event)
// Save new selection first, to avoid loop.
m_selDecomposed.first = from;
m_selDecomposed.second = to;
m_composed->SetSelection(m_mapping.to_composed(from), m_mapping.to_composed(to));
m_decomposedHex->SetSelection(m_mappingDecomposedHex.to_dst(from), m_mappingDecomposedHex.to_dst(to));
m_composed->SetSelection(from = m_mapping2.to_dst(m_mapping1.to_dst(from)), to = m_mapping2.to_dst(m_mapping1.to_dst(to)));
m_composedHex->SetSelection(m_mappingComposedHex.to_dst(from), m_mappingComposedHex.to_dst(to));
}
}
void wxZRColaComposerPanel::OnDecomposedHexPaint(wxPaintEvent& event)
{
event.Skip();
long from, to;
m_decomposedHex->GetSelection(&from, &to);
if (m_selDecomposedHex.first != from || m_selDecomposedHex.second != to) {
// Save new selection first, to avoid loop.
m_selDecomposedHex.first = from;
m_selDecomposedHex.second = to;
m_decomposed->SetSelection(from = m_mappingDecomposedHex.to_src(from), to = m_mappingDecomposedHex.to_src(to));
m_composed->SetSelection(from = m_mapping2.to_dst(m_mapping1.to_dst(from)), to = m_mapping2.to_dst(m_mapping1.to_dst(to)));
m_composedHex->SetSelection(m_mappingComposedHex.to_dst(from), m_mappingComposedHex.to_dst(to));
}
}
@@ -84,27 +128,49 @@ void wxZRColaComposerPanel::OnDecomposedText(wxCommandEvent& event)
// We are being updated by wxZRColaComposerPanel::OnComposedText()
event.Skip();
} else {
m_timer->Stop();
#ifdef __WINDOWS__
// Use Windows GetWindowText() function to avoid line ending conversion incompletely imposed by wxWidgets.
WXHWND hWnd = m_decomposed->GetHWND();
std::vector<wchar_t> src((std::vector<wchar_t>::size_type)::GetWindowTextLengthW(hWnd) + 1);
size_t len = ::GetWindowTextLengthW(hWnd);
std::vector<wchar_t> src(len + 1);
::GetWindowTextW(hWnd, src.data(), src.size());
#else
wxString src(m_decomposed->GetValue());
size_t len = src.Length();
#endif
std::wstring norm;
((ZRColaApp*)wxTheApp)->m_t_db.Decompose(src.data(), len, norm, &m_mapping1);
std::wstring dst;
m_t_db.Compose(src.data(), src.size(), dst, &m_mapping);
((ZRColaApp*)wxTheApp)->m_t_db.Compose(norm.data(), norm.size(), dst, &m_mapping2);
long from, to;
m_decomposed->GetSelection(&from, &to);
// Update decomposed HEX dump.
wxString hex;
GetHex(hex, m_mappingDecomposedHex, src.data(), len);
m_decomposedHex->SetValue(hex);
m_decomposedHex->SetSelection(m_mappingDecomposedHex.to_dst(from), m_mappingDecomposedHex.to_dst(to));
// Update composed text.
m_progress = true;
m_composed->SetValue(dst);
m_composed->SetSelection(m_mapping.to_composed(from), m_mapping.to_composed(to));
m_composed->SetSelection(from = m_mapping2.to_dst(m_mapping1.to_dst(from)), to = m_mapping2.to_dst(m_mapping1.to_dst(to)));
// Update composed HEX dump.
GetHex(hex, m_mappingComposedHex, dst.data(), dst.length());
m_composedHex->SetValue(hex);
m_composedHex->SetSelection(m_mappingComposedHex.to_dst(from), m_mappingComposedHex.to_dst(to));
event.Skip();
m_progress = false;
// Schedule state save after 3s.
m_timer->Start(3000, true);
}
}
@@ -120,7 +186,27 @@ void wxZRColaComposerPanel::OnComposedPaint(wxPaintEvent& event)
// Save new selection first, to avoid loop.
m_selComposed.first = from;
m_selComposed.second = to;
m_decomposed->SetSelection(m_mapping.to_decomposed(from), m_mapping.to_decomposed(to));
m_composedHex->SetSelection(m_mappingComposedHex.to_dst(from), m_mappingComposedHex.to_dst(to));
m_decomposed->SetSelection(from = m_mapping1.to_src(m_mapping2.to_src(from)), to = m_mapping1.to_src(m_mapping2.to_src(to)));
m_decomposedHex->SetSelection(m_mappingDecomposedHex.to_dst(from), m_mappingDecomposedHex.to_dst(to));
}
}
void wxZRColaComposerPanel::OnComposedHexPaint(wxPaintEvent& event)
{
event.Skip();
long from, to;
m_composedHex->GetSelection(&from, &to);
if (m_selComposedHex.first != from || m_selComposedHex.second != to) {
// Save new selection first, to avoid loop.
m_selComposedHex.first = from;
m_selComposedHex.second = to;
m_composed->SetSelection(from = m_mappingComposedHex.to_src(from), to = m_mappingComposedHex.to_src(to));
m_decomposed->SetSelection(from = m_mapping1.to_src(m_mapping2.to_src(from)), to = m_mapping1.to_src(m_mapping2.to_src(to)));
m_decomposedHex->SetSelection(m_mappingDecomposedHex.to_dst(from), m_mappingDecomposedHex.to_dst(to));
}
}
@@ -131,26 +217,178 @@ void wxZRColaComposerPanel::OnComposedText(wxCommandEvent& event)
// We are being updated by wxZRColaComposerPanel::OnDecomposedText()
event.Skip();
} else {
m_timer->Stop();
#ifdef __WINDOWS__
// Use Windows GetWindowTextLength() function to avoid line ending conversion incompletely imposed by wxWidgets.
WXHWND hWnd = m_composed->GetHWND();
std::vector<wchar_t> src((std::vector<wchar_t>::size_type)::GetWindowTextLengthW(hWnd) + 1);
size_t len = ::GetWindowTextLengthW(hWnd);
std::vector<wchar_t> src(len + 1);
::GetWindowTextW(hWnd, src.data(), src.size());
#else
wxString src(m_composed->GetValue());
size_t len = src.Length();
#endif
ZRColaApp *app = (ZRColaApp*)wxTheApp;
std::wstring dst;
m_t_db.Decompose(src.data(), src.size(), dst, &m_mapping);
wxZRColaFrame *mainWnd = dynamic_cast<wxZRColaFrame*>(wxGetActiveWindow());
if (mainWnd)
app->m_t_db.Decompose(src.data(), len, &app->m_lc_db, mainWnd->m_lang, dst, &m_mapping2);
else
app->m_t_db.Decompose(src.data(), len, dst, &m_mapping2);
m_mapping1.clear();
m_mapping2.invert();
long from, to;
m_composed->GetSelection(&from, &to);
// Update composed HEX dump.
wxString hex;
GetHex(hex, m_mappingComposedHex, src.data(), len);
m_composedHex->SetValue(hex);
m_composedHex->SetSelection(m_mappingComposedHex.to_dst(from), m_mappingComposedHex.to_dst(to));
// Update decomposed text.
m_progress = true;
m_decomposed->SetValue(dst);
m_decomposed->SetSelection(m_mapping.to_decomposed(from), m_mapping.to_decomposed(to));
m_decomposed->SetSelection(from = m_mapping1.to_src(m_mapping2.to_src(from)), to = m_mapping1.to_src(m_mapping2.to_src(to)));
// Update decomposed HEX dump.
GetHex(hex, m_mappingDecomposedHex, dst.data(), dst.length());
m_decomposedHex->SetValue(hex);
m_decomposedHex->SetSelection(m_mappingDecomposedHex.to_dst(from), m_mappingDecomposedHex.to_dst(to));
event.Skip();
m_progress = false;
// Schedule state save after 3s.
m_timer->Start(3000, true);
}
}
void wxZRColaComposerPanel::OnTimerTimeout(wxTimerEvent& event)
{
wxString fileName(GetStateFileName());
wxFFile file(fileName, wxT("wb"));
if (file.IsOpened()) {
// Save decomposed text.
{
#ifdef __WINDOWS__
// Use Windows GetWindowText() function to avoid line ending conversion incompletely imposed by wxWidgets.
WXHWND hWnd = m_decomposed->GetHWND();
unsigned __int64 len = ::GetWindowTextLengthW(hWnd);
std::vector<wchar_t> text(len + 1);
::GetWindowTextW(hWnd, text.data(), text.size());
#else
wxString text(m_decomposed->GetValue());
unsigned __int64 len = text.Length();
#endif
file.Write(&len, sizeof(len));
file.Write(text.data(), sizeof(wchar_t)*len);
}
// Save composed text.
{
#ifdef __WINDOWS__
// Use Windows GetWindowText() function to avoid line ending conversion incompletely imposed by wxWidgets.
WXHWND hWnd = m_composed->GetHWND();
unsigned __int64 len = ::GetWindowTextLengthW(hWnd);
std::vector<wchar_t> text(len + 1);
::GetWindowTextW(hWnd, text.data(), text.size());
#else
wxString text(m_composed->GetValue());
unsigned __int64 len = text.Length();
#endif
file.Write(&len, sizeof(len));
file.Write(text.data(), sizeof(wchar_t)*len);
}
}
event.Skip();
}
wxString wxZRColaComposerPanel::GetStateFileName()
{
wxString path;
path = wxFileName::GetTempDir();
if (!wxEndsWithPathSeparator(path))
path += wxFILE_SEP_PATH;
if (!wxDirExists(path))
wxMkdir(path);
wxString fileName(path);
fileName += wxT("ZRColaComposerPanel-state.tmp");
return fileName;
}
void wxZRColaComposerPanel::GetHex(wxString &hex, ZRCola::mapping_vector &mapping, const wchar_t *src, size_t len)
{
bool first = true;
hex.clear();
mapping.clear();
for (size_t i = 0; i < len && src[i]; i++) {
wchar_t c = src[i];
if (c == L'\n' || c == '\r') {
hex += c;
first = true;
} else {
hex += wxString::Format(first ? wxT("%04X") : wxT(" %04X"), src[i]);
mapping.push_back(ZRCola::mapping(i + 1, hex.Length()));
first = false;
}
}
}
//////////////////////////////////////////////////////////////////////////
// wxPersistentZRColaComposerPanel
//////////////////////////////////////////////////////////////////////////
wxPersistentZRColaComposerPanel::wxPersistentZRColaComposerPanel(wxZRColaComposerPanel *wnd) : wxPersistentWindow<wxZRColaComposerPanel>(wnd)
{
}
wxString wxPersistentZRColaComposerPanel::GetKind() const
{
return wxT(wxPERSIST_TLW_KIND);
}
void wxPersistentZRColaComposerPanel::Save() const
{
const wxZRColaComposerPanel * const wnd = static_cast<const wxZRColaComposerPanel*>(GetWindow());
SaveValue(wxT("splitDecomposed"), wnd->m_splitterDecomposed->GetSashPosition());
SaveValue(wxT("splitComposed" ), wnd->m_splitterComposed ->GetSashPosition());
}
bool wxPersistentZRColaComposerPanel::Restore()
{
wxZRColaComposerPanel * const wnd = static_cast<wxZRColaComposerPanel*>(GetWindow());
int sashVal;
if (RestoreValue(wxT("splitDecomposed"), &sashVal)) {
// wxFormBuilder sets initial splitter stash in idle event handler after GUI settles. Overriding our loaded value. Disconnect it's idle event handler.
wnd->m_splitterDecomposed->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaComposerPanelBase::m_splitterDecomposedOnIdle ), NULL, wnd );
wnd->m_splitterDecomposed->SetSashPosition(sashVal);
}
if (RestoreValue(wxT("splitComposed"), &sashVal)) {
// wxFormBuilder sets initial splitter stash in idle event handler after GUI settles. Overriding our loaded value. Disconnect it's idle event handler.
wnd->m_splitterComposed->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaComposerPanelBase::m_splitterComposedOnIdle ), NULL, wnd );
wnd->m_splitterComposed->SetSashPosition(sashVal);
}
return true;
}

View File

@@ -27,7 +27,8 @@ class wxZRColaComposerPanel;
#include "zrcolagui.h"
#include "zrcolakeyhndlr.h"
#include <zrcola/translate.h>
#include <wx/persist/window.h>
#include <wx/timer.h>
#include <utility>
@@ -37,23 +38,61 @@ class wxZRColaComposerPanel;
class wxZRColaComposerPanel : public wxZRColaComposerPanelBase
{
public:
enum
{
wxID_TIMER = 1,
};
wxZRColaComposerPanel(wxWindow* parent);
virtual ~wxZRColaComposerPanel();
friend class wxZRColaFrame; // Allow main frame direct access to our members.
friend class wxZRColaFrame; // Allow main frame direct access to our members.
friend class wxPersistentZRColaComposerPanel; // Allow saving/restoring window state.
protected:
virtual void OnDecomposedPaint(wxPaintEvent& event);
virtual void OnDecomposedHexPaint(wxPaintEvent& event);
virtual void OnDecomposedText(wxCommandEvent& event);
virtual void OnComposedPaint(wxPaintEvent& event);
virtual void OnComposedHexPaint(wxPaintEvent& event);
virtual void OnComposedText(wxCommandEvent& event);
virtual void OnTimerTimeout(wxTimerEvent& event);
DECLARE_EVENT_TABLE()
static wxString GetStateFileName();
static void GetHex(wxString &hex, ZRCola::mapping_vector &mapping, const wchar_t *src, size_t len);
protected:
ZRCola::translation_db m_t_db; ///< Translation database
bool m_progress; ///< Boolean flag to avoid recursive updates of composed and decomposed text controls
ZRCola::mapping_vector m_mapping; ///< Character index mapping vector between composed and decomposed text
bool m_progress; ///< Boolean flag to avoid recursive updates of composed and decomposed text controls
ZRCola::mapping_vector m_mapping1; ///< Character index mapping vector between decomposed and normalized text
ZRCola::mapping_vector m_mapping2; ///< Character index mapping vector between normalized and composed text
std::pair<long, long>
m_selDecomposed, ///< Character index of selected text in decomposed text control
m_selComposed; ///< Character index of selected text in composed text control
wxZRColaKeyHandler m_keyhandler; ///< Key handler for decomposed window
m_selDecomposed, ///< Character index of selected text in decomposed text control
m_selDecomposedHex, ///< Character index of selected text in decomposed HEX dump text control
m_selComposed, ///< Character index of selected text in composed text control
m_selComposedHex; ///< Character index of selected text in composed HEX dump text control
wxZRColaKeyHandler m_keyhandler; ///< Key handler for decomposed window
wxTimer *m_timer; ///< Timer to trigger the state save
ZRCola::mapping_vector m_mappingDecomposedHex; ///< Character index mapping vector between decomposed text and its HEX dump
ZRCola::mapping_vector m_mappingComposedHex; ///< Character index mapping vector between composed text and its HEX dump
};
///
/// Supports saving/restoring wxZRColaComposerPanel state
///
class wxPersistentZRColaComposerPanel : public wxPersistentWindow<wxZRColaComposerPanel>
{
public:
wxPersistentZRColaComposerPanel(wxZRColaComposerPanel *wnd);
virtual wxString GetKind() const;
virtual void Save() const;
virtual bool Restore();
};
inline wxPersistentObject *wxCreatePersistentObject(wxZRColaComposerPanel *wnd)
{
return new wxPersistentZRColaComposerPanel(wnd);
}

View File

@@ -25,17 +25,31 @@
//////////////////////////////////////////////////////////////////////////
wxBEGIN_EVENT_TABLE(wxZRColaFrame, wxZRColaFrameBase)
EVT_UPDATE_UI_RANGE(wxZRColaFrame::wxID_SEND_COMPOSED, wxZRColaFrame::wxID_SEND_DECOMPOSED, wxZRColaFrame::OnSendUpdate)
EVT_UPDATE_UI (wxID_AUTOSTART , wxZRColaFrame::OnAutostartUpdate )
EVT_MENU (wxID_AUTOSTART , wxZRColaFrame::OnAutostart )
EVT_MENU (wxID_EXIT , wxZRColaFrame::OnExit )
EVT_MENU(wxZRColaFrame::wxID_SEND_COMPOSED , wxZRColaFrame::OnSendComposed )
EVT_MENU(wxZRColaFrame::wxID_SEND_DECOMPOSED , wxZRColaFrame::OnSendDecomposed )
EVT_MENU(wxZRColaFrame::wxID_SEND_ABORT , wxZRColaFrame::OnSendAbort )
EVT_MENU( wxID_EXIT , wxZRColaFrame::OnExit )
EVT_MENU( wxID_ABOUT , wxZRColaFrame::OnAbout )
EVT_UPDATE_UI_RANGE(wxID_CUT, wxID_CLEAR , wxZRColaFrame::OnForwardEventUpdate )
EVT_MENU_RANGE (wxID_CUT, wxID_CLEAR , wxZRColaFrame::OnForwardEvent )
EVT_UPDATE_UI (wxID_SELECTALL , wxZRColaFrame::OnForwardEventUpdate )
EVT_MENU (wxID_SELECTALL , wxZRColaFrame::OnForwardEvent )
EVT_UPDATE_UI_RANGE(wxID_SEND_COMPOSED, wxID_SEND_ABORT , wxZRColaFrame::OnSendUpdate )
EVT_MENU (wxID_SEND_COMPOSED , wxZRColaFrame::OnSendComposed )
EVT_MENU (wxID_SEND_DECOMPOSED , wxZRColaFrame::OnSendDecomposed )
EVT_MENU (wxID_SEND_ABORT , wxZRColaFrame::OnSendAbort )
EVT_UPDATE_UI (wxID_DECOMP_LANG_AUTO , wxZRColaFrame::OnDecomposedLanguageAutoUpdate)
EVT_MENU (wxID_DECOMP_LANG_AUTO , wxZRColaFrame::OnDecomposedLanguageAuto )
EVT_UPDATE_UI_RANGE(wxID_DECOMP_LANGUAGE_START, wxID_DECOMP_LANGUAGE_END, wxZRColaFrame::OnDecomposedLanguageUpdate )
EVT_MENU_RANGE (wxID_DECOMP_LANGUAGE_START, wxID_DECOMP_LANGUAGE_END, wxZRColaFrame::OnDecomposedLanguage )
EVT_MENU (wxID_ABOUT , wxZRColaFrame::OnAbout )
wxEND_EVENT_TABLE()
wxZRColaFrame::wxZRColaFrame() :
m_lang_auto(true),
m_hWndSource(NULL),
wxZRColaFrameBase(NULL)
{
@@ -49,6 +63,23 @@ wxZRColaFrame::wxZRColaFrame() :
SetIcon(wxICON(00_zrcola.ico));
#endif
// Populate language lists.
memcpy(m_lang, ZRCOLA_LANG_VOID, sizeof(m_lang));
ZRColaApp *app = ((ZRColaApp*)wxTheApp);
m_toolDecompLanguage->Clear();
for (size_t i = 0, n = app->m_lang_db.idxLng.size(); i < n; i++) {
const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[i];
wxString
label(lang.name, lang.name_len),
label_tran(wxGetTranslation(label));
if (i < wxID_DECOMP_LANGUAGE_END - wxID_DECOMP_LANGUAGE_START + 1)
m_menuDecompLanguage->AppendRadioItem(wxID_DECOMP_LANGUAGE_START + i, label_tran, wxString::Format(_("Select %s language for decomposition"), (const wxStringCharType*)label_tran));
m_toolDecompLanguage->Insert(label_tran, i);
if (memcmp(m_lang, lang.id, sizeof(m_lang)) == 0)
m_toolDecompLanguage->Select(i);
}
// Set focus.
m_panel->m_decomposed->SetFocus();
// Register global hotkey(s).
@@ -57,25 +88,114 @@ wxZRColaFrame::wxZRColaFrame() :
if (!RegisterHotKey(wxZRColaHKID_INVOKE_DECOMPOSE, wxMOD_WIN, VK_F6))
wxMessageBox(_("ZRCola keyboard shortcut Win+F6 could not be registered. Some functionality will not be available."), _("Warning"), wxOK | wxICON_WARNING);
// Register frame specific hotkey(s).
{
wxAcceleratorEntry entries[3];
entries[0].Set(wxACCEL_NORMAL, WXK_F5 , wxID_SEND_COMPOSED);
entries[1].Set(wxACCEL_NORMAL, WXK_F6 , wxID_SEND_DECOMPOSED);
entries[2].Set(wxACCEL_NORMAL, WXK_ESCAPE, wxID_SEND_ABORT);
SetAcceleratorTable(wxAcceleratorTable(_countof(entries), entries));
#if defined(__WXMSW__)
// Register notification sink for language detection.
m_ulRefCount = 1;
m_tfSource = NULL;
ITfInputProcessorProfiles *pProfiles;
HRESULT hr = CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_INPROC_SERVER, IID_ITfInputProcessorProfiles, (LPVOID*)&pProfiles);
if(SUCCEEDED(hr)) {
hr = pProfiles->QueryInterface(IID_ITfSource, (LPVOID*)&m_tfSource);
if(SUCCEEDED(hr)) {
hr = m_tfSource->AdviseSink(IID_ITfLanguageProfileNotifySink, (ITfLanguageProfileNotifySink*)this, &m_dwCookie);
if (FAILED(hr) || m_dwCookie == -1) {
m_tfSource->Release();
m_tfSource = NULL;
}
}
pProfiles->Release();
}
#endif
}
wxZRColaFrame::~wxZRColaFrame()
{
#if defined(__WXMSW__)
if (m_tfSource) {
m_tfSource->UnadviseSink(m_dwCookie);
m_tfSource->Release();
}
#endif
// Unregister global hotkey(s).
UnregisterHotKey(wxZRColaHKID_INVOKE_DECOMPOSE);
UnregisterHotKey(wxZRColaHKID_INVOKE_COMPOSE);
}
void wxZRColaFrame::OnAutostartUpdate(wxUpdateUIEvent& event)
{
#if defined(__WXMSW__)
wxString linkName(wxExpandEnvVars("%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\ZRCola.lnk"));
event.Check(wxFileExists(linkName));
#else
event.Enable(false);
#endif
}
void wxZRColaFrame::OnAutostart(wxCommandEvent& event)
{
#if defined(__WXMSW__)
wxString linkName(wxExpandEnvVars("%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\ZRCola.lnk"));
if (wxFileExists(linkName)) {
// The shortcut already exists. Remove it.
wxRemoveFile(linkName);
} else {
// Create the shortcut.
IShellLink *sl;
HRESULT hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&sl);
if (SUCCEEDED(hr)) {
// Setup ZRCola shortcut.
sl->SetPath(wxTheApp->argv[0]);
sl->SetDescription(_("Start ZRCola automatically on logon"));
sl->SetShowCmd(SW_SHOWMINNOACTIVE);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
IPersistFile *pf;
hr = sl->QueryInterface(IID_IPersistFile, (LPVOID*)&pf);
if (SUCCEEDED(hr)) {
// Save the link by calling IPersistFile::Save.
hr = pf->Save(linkName, TRUE);
pf->Release();
}
sl->Release();
}
}
#endif
}
void wxZRColaFrame::OnExit(wxCommandEvent& event)
{
Close();
}
void wxZRColaFrame::OnForwardEventUpdate(wxUpdateUIEvent& event)
{
wxControl *focusWnd = wxDynamicCast(FindFocus(), wxControl);
if (focusWnd && !m_toolbar->IsDescendant(focusWnd))
focusWnd->GetEventHandler()->ProcessEvent(event);
else
event.Enable(false);
}
void wxZRColaFrame::OnForwardEvent(wxCommandEvent& event)
{
wxControl *focusWnd = wxDynamicCast(FindFocus(), wxControl);
if (focusWnd)
focusWnd->GetEventHandler()->ProcessEvent(event);
else
event.Skip();
}
void wxZRColaFrame::OnSendUpdate(wxUpdateUIEvent& event)
{
event.Enable(m_hWndSource ? true : false);
@@ -107,19 +227,82 @@ void wxZRColaFrame::OnSendAbort(wxCommandEvent& event)
::SetActiveWindow(m_hWndSource);
::SetForegroundWindow(m_hWndSource);
m_hWndSource = NULL;
// Select all input in composer to prepare for the overwrite next time.
m_panel->m_decomposed->SelectAll();
m_panel->m_composed->SelectAll();
}
// Select all input in composer to prepare for the overwrite next time.
m_panel->m_decomposed->SelectAll();
m_panel->m_composed->SelectAll();
event.Skip();
}
void wxZRColaFrame::OnExit(wxCommandEvent& event)
void wxZRColaFrame::OnDecomposedLanguageAutoUpdate(wxUpdateUIEvent& event)
{
Close();
#if defined(__WXMSW__)
event.Check(m_lang_auto);
#else
event.Enable(false);
#endif
}
void wxZRColaFrame::OnDecomposedLanguageAuto(wxCommandEvent& event)
{
// Toggle auto language flag.
m_lang_auto = !m_lang_auto;
if (m_lang_auto) {
#if defined(__WXMSW__)
// Set keyboard language.
HKL hkl = ::GetKeyboardLayout(0);
ZRCola::LangConvert(LOWORD(hkl), m_lang);
UpdateDecomposedLanguage();
#endif
}
}
void wxZRColaFrame::OnDecomposedLanguageUpdate(wxUpdateUIEvent& event)
{
ZRColaApp *app = ((ZRColaApp*)wxTheApp);
const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[event.GetId() - wxID_DECOMP_LANGUAGE_START];
event.Check(memcmp(m_lang, lang.id, sizeof(m_lang)) == 0);
}
void wxZRColaFrame::OnDecomposedLanguage(wxCommandEvent& event)
{
ZRColaApp *app = ((ZRColaApp*)wxTheApp);
size_t i = event.GetId() - wxID_DECOMP_LANGUAGE_START;
const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[i];
if (memcmp(m_lang, lang.id, sizeof(m_lang)) != 0) {
memcpy(m_lang, lang.id, sizeof(m_lang));
m_toolDecompLanguage->Select(i);
// Notify composed text something changed and should re-decompose.
wxCommandEvent event2(wxEVT_COMMAND_TEXT_UPDATED);
m_panel->m_composed->ProcessWindowEvent(event2);
m_lang_auto = false;
}
}
void wxZRColaFrame::OnDecompLanguageChoice(wxCommandEvent& event)
{
ZRColaApp *app = ((ZRColaApp*)wxTheApp);
size_t i = event.GetSelection();
const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[i];
if (memcmp(m_lang, lang.id, sizeof(m_lang)) != 0) {
memcpy(m_lang, lang.id, sizeof(m_lang));
// Notify composed text something changed and should re-decompose.
wxCommandEvent event2(wxEVT_COMMAND_TEXT_UPDATED);
m_panel->m_composed->ProcessWindowEvent(event2);
m_lang_auto = false;
}
}
@@ -129,27 +312,85 @@ void wxZRColaFrame::OnAbout(wxCommandEvent& event)
}
#if defined(__WXMSW__)
HRESULT STDMETHODCALLTYPE wxZRColaFrame::OnLanguageChange(LANGID langid, __RPC__out BOOL *pfAccept)
{
if (pfAccept) *pfAccept = TRUE;
return S_OK;
}
HRESULT STDMETHODCALLTYPE wxZRColaFrame::OnLanguageChanged()
{
if (m_lang_auto) {
// Set keyboard language.
HKL hkl = ::GetKeyboardLayout(0);
ZRCola::LangConvert(LOWORD(hkl), m_lang);
UpdateDecomposedLanguage();
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE wxZRColaFrame::QueryInterface(REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject)
{
if (!ppvObject)
return E_INVALIDARG;
if (riid == IID_IUnknown)
*ppvObject = static_cast<IUnknown*>(this);
else if (riid == IID_ITfLanguageProfileNotifySink)
*ppvObject = static_cast<ITfLanguageProfileNotifySink*>(this);
else {
*ppvObject = NULL;
return E_NOINTERFACE;
}
AddRef();
return NOERROR;
}
ULONG STDMETHODCALLTYPE wxZRColaFrame::AddRef()
{
InterlockedIncrement(&m_ulRefCount);
return m_ulRefCount;
}
ULONG STDMETHODCALLTYPE wxZRColaFrame::Release()
{
// Decrement the object's internal counter.
ULONG ulRefCount = InterlockedDecrement(&m_ulRefCount);
if (m_ulRefCount == 0)
delete this;
return ulRefCount;
}
#endif
void wxZRColaFrame::DoSend(const wxString& str)
{
// Prepare the INPUT table.
wxString::size_type n = str.length();
wxString::const_iterator i_str = str.begin();
std::vector<INPUT> input(n);
std::vector<INPUT> input;
input.reserve(n*2);
for (std::vector<INPUT>::size_type i = 0; i < n; i++, i_str++) {
wxString::char_type c = *i_str;
INPUT &inp = input[i];
inp.type = INPUT_KEYBOARD;
inp.ki.dwFlags = KEYEVENTF_UNICODE;
inp.ki.time = 0;
inp.ki.dwExtraInfo = 0;
if (c == L'\n') {
// Enter (Return) key is sent as CR virtual key code.
inp.ki.wVk = VK_RETURN;
inp.ki.wScan = L'\r';
} else {
inp.ki.wVk = 0;
inp.ki.wScan = c;
}
// Add key down event.
INPUT inp = { INPUT_KEYBOARD };
inp.ki.dwFlags = KEYEVENTF_UNICODE;
inp.ki.wScan = c != L'\n' ? c : L'\r'; // Enter (Return) key is sent as CR.
input.push_back(inp);
// Add key up event.
inp.ki.dwFlags |= KEYEVENTF_KEYUP;
input.push_back(inp);
}
// Return focus to the source window and send the input.
@@ -165,6 +406,22 @@ void wxZRColaFrame::DoSend(const wxString& str)
}
void wxZRColaFrame::UpdateDecomposedLanguage()
{
ZRColaApp *app = ((ZRColaApp*)wxTheApp);
// Find language on the language list.
ZRCola::language_db::language *l = new ZRCola::language_db::language;
memcpy(l->id, m_lang, sizeof(l->id));
l->name_len = 0;
ZRCola::language_db::indexLang::size_type start, end;
m_toolDecompLanguage->SetSelection(app->m_lang_db.idxLng.find(*l, start, end) ? start : -1);
delete l;
}
#ifdef __WXMSW__
WXLRESULT wxZRColaFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
{
if (message == WM_HOTKEY) {
@@ -210,3 +467,58 @@ WXLRESULT wxZRColaFrame::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM
} else
return wxZRColaFrameBase::MSWWindowProc(message, wParam, lParam);
}
#endif
//////////////////////////////////////////////////////////////////////////
// wxPersistentZRColaFrame
//////////////////////////////////////////////////////////////////////////
wxPersistentZRColaFrame::wxPersistentZRColaFrame(wxZRColaFrame *wnd) : wxPersistentTLW(wnd)
{
}
void wxPersistentZRColaFrame::Save() const
{
const wxZRColaFrame * const wnd = static_cast<const wxZRColaFrame*>(GetWindow());
wxPersistentZRColaComposerPanel(wnd->m_panel).Save();
SaveValue(wxT("langAuto"), wnd->m_lang_auto);
SaveValue(wxT("lang" ), wxString::FromAscii(wnd->m_lang, sizeof(wnd->m_lang)));
wxPersistentTLW::Save();
}
bool wxPersistentZRColaFrame::Restore()
{
const bool r = wxPersistentTLW::Restore();
wxZRColaFrame * const wnd = static_cast<wxZRColaFrame*>(GetWindow());
ZRColaApp *app = ((ZRColaApp*)wxTheApp);
wxString lang;
// Restore automatic language detection setting first.
RestoreValue(wxT("langAuto"), &(wnd->m_lang_auto));
if (wnd->m_lang_auto) {
#if defined(__WXMSW__)
// Set keyboard language.
HKL hkl = ::GetKeyboardLayout(0);
ZRCola::LangConvert(LOWORD(hkl), wnd->m_lang);
#endif
} else if (RestoreValue(wxT("lang"), &lang) && lang.Length() == 3) {
// The language was read from configuration.
memcpy(wnd->m_lang, (const char*)lang.c_str(), sizeof(wnd->m_lang));
} else if (!app->m_lang_db.idxLng.empty()) {
const ZRCola::language_db::language &lang = app->m_lang_db.idxLng[0];
memcpy(wnd->m_lang, lang.id, sizeof(wnd->m_lang));
} else
memcpy(wnd->m_lang, ZRCOLA_LANG_VOID, sizeof(wnd->m_lang));
wnd->UpdateDecomposedLanguage();
wxPersistentZRColaComposerPanel(wnd->m_panel).Restore();
return r;
}

View File

@@ -27,6 +27,11 @@ class wxZRColaFrame;
#pragma once
#include "zrcolagui.h"
#include <zrcola/language.h>
#include <wx/persist/toplevel.h>
#if defined(__WXMSW__)
#include <msctf.h>
#endif
///
@@ -39,34 +44,89 @@ class wxZRColaFrame;
///
/// ZRCola main frame
///
class wxZRColaFrame : public wxZRColaFrameBase
class wxZRColaFrame :
public wxZRColaFrameBase
#if defined(__WXMSW__)
, protected ITfLanguageProfileNotifySink
#endif
{
protected:
enum {
wxID_SEND_COMPOSED = wxID_HIGHEST,
wxID_SEND_DECOMPOSED,
wxID_SEND_ABORT,
public:
enum
{
wxID_DECOMP_LANGUAGE_START = 6000,
wxID_DECOMP_LANGUAGE_END = 6099,
};
public:
wxZRColaFrame();
virtual ~wxZRColaFrame();
friend class wxPersistentZRColaFrame;
friend class wxZRColaComposerPanel;
protected:
void OnAutostartUpdate(wxUpdateUIEvent& event);
void OnAutostart(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnForwardEventUpdate(wxUpdateUIEvent& event);
void OnForwardEvent(wxCommandEvent& event);
void OnSendUpdate(wxUpdateUIEvent& event);
void OnSendComposed(wxCommandEvent& event);
void OnSendDecomposed(wxCommandEvent& event);
void OnSendAbort(wxCommandEvent& event);
void OnExit(wxCommandEvent& event);
void OnDecomposedLanguageAutoUpdate(wxUpdateUIEvent& event);
void OnDecomposedLanguageAuto(wxCommandEvent& event);
void OnDecomposedLanguageUpdate(wxUpdateUIEvent& event);
void OnDecomposedLanguage(wxCommandEvent& event);
virtual void OnDecompLanguageChoice(wxCommandEvent& event);
void OnAbout(wxCommandEvent& event);
wxDECLARE_EVENT_TABLE();
protected:
#if defined(__WXMSW__)
ITfSource *m_tfSource; ///< Text Services install sink helper
DWORD m_dwCookie; ///< Text Services installed sink cookie
// ITfLanguageProfileNotifySink implementation
virtual HRESULT STDMETHODCALLTYPE OnLanguageChange(LANGID langid, __RPC__out BOOL *pfAccept);
virtual HRESULT STDMETHODCALLTYPE OnLanguageChanged();
// IUnknown implementation
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
ULONG m_ulRefCount; ///< COM object reference count
#endif
private:
void DoSend(const wxString& str);
void UpdateDecomposedLanguage();
protected:
#ifdef __WXMSW__
virtual WXLRESULT MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam);
#endif
protected:
bool m_lang_auto; ///< Automatic language selection according to keyboard layout
ZRCola::langid_t m_lang; ///< Language for decomposing
WXHWND m_hWndSource; ///< handle of the active window, when the ZRCola hotkey was pressed
};
///
/// Supports saving/restoring wxZRColaFrame GUI state
///
class wxPersistentZRColaFrame : public wxPersistentTLW
{
public:
wxPersistentZRColaFrame(wxZRColaFrame *wnd);
virtual void Save() const;
virtual bool Restore();
};
inline wxPersistentObject *wxCreatePersistentObject(wxZRColaFrame *wnd)
{
return new wxPersistentZRColaFrame(wnd);
}

View File

@@ -22,27 +22,131 @@ wxHelpProvider::Set( new wxHelpControllerHelpProvider );
static wxFBContextSensitiveHelpSetter s_wxFBSetTheHelpProvider;
///////////////////////////////////////////////////////////////////////////
wxZRColaFrameBase::wxZRColaFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style )
wxZRColaFrameBase::wxZRColaFrameBase( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxFrame( parent, id, title, pos, size, style, name )
{
this->SetSizeHints( wxSize( 150,150 ), wxDefaultSize );
m_menubar = new wxMenuBar( 0 );
m_menuFile = new wxMenu();
wxMenuItem* m_menuItemExit;
m_menuItemExit = new wxMenuItem( m_menuFile, wxID_EXIT, wxString( _("E&xit") ) + wxT('\t') + wxT("Alt+F4"), wxEmptyString, wxITEM_NORMAL );
m_menuFile->Append( m_menuItemExit );
m_menuProgram = new wxMenu();
wxMenuItem* m_menuItemAutoStart;
m_menuItemAutoStart = new wxMenuItem( m_menuProgram, wxID_AUTOSTART, wxString( _("&Start on Logon") ) , _("Start this program automatically on logon"), wxITEM_CHECK );
m_menuProgram->Append( m_menuItemAutoStart );
m_menubar->Append( m_menuFile, _("&File") );
m_menuProgram->AppendSeparator();
wxMenuItem* m_menuItemExit;
m_menuItemExit = new wxMenuItem( m_menuProgram, wxID_EXIT, wxString( _("E&xit") ) + wxT('\t') + wxT("Alt+F4"), _("Quit this program"), wxITEM_NORMAL );
m_menuProgram->Append( m_menuItemExit );
m_menubar->Append( m_menuProgram, _("&Program") );
m_menuEdit = new wxMenu();
wxMenuItem* m_menuItemEditCut;
m_menuItemEditCut = new wxMenuItem( m_menuEdit, wxID_CUT, wxString( wxEmptyString ) , wxEmptyString, wxITEM_NORMAL );
#ifdef __WXMSW__
m_menuItemEditCut->SetBitmaps( wxIcon( wxT("edit_cut.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#elif (defined( __WXGTK__ ) || defined( __WXOSX__ ))
m_menuItemEditCut->SetBitmap( wxIcon( wxT("edit_cut.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#endif
m_menuEdit->Append( m_menuItemEditCut );
wxMenuItem* m_menuItemEditCopy;
m_menuItemEditCopy = new wxMenuItem( m_menuEdit, wxID_COPY, wxString( wxEmptyString ) , wxEmptyString, wxITEM_NORMAL );
#ifdef __WXMSW__
m_menuItemEditCopy->SetBitmaps( wxIcon( wxT("edit_copy.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#elif (defined( __WXGTK__ ) || defined( __WXOSX__ ))
m_menuItemEditCopy->SetBitmap( wxIcon( wxT("edit_copy.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#endif
m_menuEdit->Append( m_menuItemEditCopy );
wxMenuItem* m_menuItemEditPaste;
m_menuItemEditPaste = new wxMenuItem( m_menuEdit, wxID_PASTE, wxString( wxEmptyString ) , wxEmptyString, wxITEM_NORMAL );
#ifdef __WXMSW__
m_menuItemEditPaste->SetBitmaps( wxIcon( wxT("edit_paste.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#elif (defined( __WXGTK__ ) || defined( __WXOSX__ ))
m_menuItemEditPaste->SetBitmap( wxIcon( wxT("edit_paste.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#endif
m_menuEdit->Append( m_menuItemEditPaste );
m_menuEdit->AppendSeparator();
wxMenuItem* m_menuSelectAll;
m_menuSelectAll = new wxMenuItem( m_menuEdit, wxID_SELECTALL, wxString( _("Select &All") ) + wxT('\t') + wxT("Ctrl+A"), _("Select all text"), wxITEM_NORMAL );
m_menuEdit->Append( m_menuSelectAll );
m_menuEdit->AppendSeparator();
wxMenuItem* m_menuItemSendComposed;
m_menuItemSendComposed = new wxMenuItem( m_menuEdit, wxID_SEND_COMPOSED, wxString( _("&Send Composed") ) + wxT('\t') + wxT("F5"), _("Send composed text to source window"), wxITEM_NORMAL );
#ifdef __WXMSW__
m_menuItemSendComposed->SetBitmaps( wxIcon( wxT("send_composed.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#elif (defined( __WXGTK__ ) || defined( __WXOSX__ ))
m_menuItemSendComposed->SetBitmap( wxIcon( wxT("send_composed.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#endif
m_menuEdit->Append( m_menuItemSendComposed );
wxMenuItem* m_menuItemSendDecomposed;
m_menuItemSendDecomposed = new wxMenuItem( m_menuEdit, wxID_SEND_DECOMPOSED, wxString( _("Send &Decomposed") ) + wxT('\t') + wxT("F6"), _("Send decomposed text to source window"), wxITEM_NORMAL );
#ifdef __WXMSW__
m_menuItemSendDecomposed->SetBitmaps( wxIcon( wxT("send_decomposed.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#elif (defined( __WXGTK__ ) || defined( __WXOSX__ ))
m_menuItemSendDecomposed->SetBitmap( wxIcon( wxT("send_decomposed.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#endif
m_menuEdit->Append( m_menuItemSendDecomposed );
wxMenuItem* m_menuItemSendAbort;
m_menuItemSendAbort = new wxMenuItem( m_menuEdit, wxID_SEND_ABORT, wxString( _("Abort (De)composition") ) + wxT('\t') + wxT("Esc"), _("Abort composition and return focus to source window"), wxITEM_NORMAL );
#ifdef __WXMSW__
m_menuItemSendAbort->SetBitmaps( wxIcon( wxT("send_abort.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#elif (defined( __WXGTK__ ) || defined( __WXOSX__ ))
m_menuItemSendAbort->SetBitmap( wxIcon( wxT("send_abort.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 16, 16 ) );
#endif
m_menuEdit->Append( m_menuItemSendAbort );
m_menuDecompLanguage = new wxMenu();
wxMenuItem* m_menuDecompLanguageItem = new wxMenuItem( m_menuEdit, wxID_ANY, _("&Language"), wxEmptyString, wxITEM_NORMAL, m_menuDecompLanguage );
wxMenuItem* m_menuDecompLanguageAuto;
m_menuDecompLanguageAuto = new wxMenuItem( m_menuDecompLanguage, wxID_DECOMP_LANG_AUTO, wxString( _("&Automatic") ) , _("Set language according to keyboard layout automatically"), wxITEM_CHECK );
m_menuDecompLanguage->Append( m_menuDecompLanguageAuto );
m_menuDecompLanguage->AppendSeparator();
m_menuEdit->Append( m_menuDecompLanguageItem );
m_menubar->Append( m_menuEdit, _("&Edit") );
m_menuHelp = new wxMenu();
wxMenuItem* m_menuItemAbout;
m_menuItemAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( _("&About") ) , wxEmptyString, wxITEM_NORMAL );
m_menuItemAbout = new wxMenuItem( m_menuHelp, wxID_ABOUT, wxString( wxEmptyString ) , wxEmptyString, wxITEM_NORMAL );
m_menuHelp->Append( m_menuItemAbout );
m_menubar->Append( m_menuHelp, _("&Help") );
this->SetMenuBar( m_menubar );
m_toolbar = this->CreateToolBar( wxTB_HORIZONTAL, wxID_ANY );
m_toolbar->SetToolBitmapSize( wxSize( 16,16 ) );
m_toolEditCut = m_toolbar->AddTool( wxID_CUT, _("Cut"), wxIcon( wxT("edit_cut.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 24, 24 ), wxNullBitmap, wxITEM_NORMAL, _("Cut"), _("Cut selection"), NULL );
m_toolEditCopy = m_toolbar->AddTool( wxID_COPY, _("Copy"), wxIcon( wxT("edit_copy.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 24, 24 ), wxNullBitmap, wxITEM_NORMAL, _("Copy"), _("Copy selection"), NULL );
m_toolEditPaste = m_toolbar->AddTool( wxID_PASTE, _("Paste"), wxIcon( wxT("edit_paste.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 24, 24 ), wxNullBitmap, wxITEM_NORMAL, _("Paste"), _("Paste selection"), NULL );
m_toolbar->AddSeparator();
m_toolSendComposed = m_toolbar->AddTool( wxID_SEND_COMPOSED, _("Send Composed"), wxIcon( wxT("send_composed.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 24, 24 ), wxNullBitmap, wxITEM_NORMAL, _("Send Composed"), _("Send composed text to source window"), NULL );
m_toolSendDecomposed = m_toolbar->AddTool( wxID_SEND_DECOMPOSED, _("Send Decomposed"), wxIcon( wxT("send_decomposed.ico"), wxBITMAP_TYPE_ICO_RESOURCE, 24, 24 ), wxNullBitmap, wxITEM_NORMAL, _("Send Decomposed"), _("Send decomposed text to source window"), NULL );
m_toolDecompLanguageLbl = new wxStaticText( m_toolbar, wxID_ANY, _("Language:"), wxDefaultPosition, wxDefaultSize, wxALIGN_RIGHT );
m_toolDecompLanguageLbl->Wrap( -1 );
m_toolbar->AddControl( m_toolDecompLanguageLbl );
wxArrayString m_toolDecompLanguageChoices;
m_toolDecompLanguage = new wxChoice( m_toolbar, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_toolDecompLanguageChoices, 0 );
m_toolDecompLanguage->SetSelection( 0 );
m_toolbar->AddControl( m_toolDecompLanguage );
m_toolbar->Realize();
wxBoxSizer* bSizerMain;
bSizerMain = new wxBoxSizer( wxVERTICAL );
@@ -53,41 +157,132 @@ wxZRColaFrameBase::wxZRColaFrameBase( wxWindow* parent, wxWindowID id, const wxS
this->SetSizer( bSizerMain );
this->Layout();
m_statusBar = this->CreateStatusBar( 1, wxST_SIZEGRIP, wxID_ANY );
this->Centre( wxBOTH );
// Connect Events
m_toolDecompLanguage->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( wxZRColaFrameBase::OnDecompLanguageChoice ), NULL, this );
}
wxZRColaFrameBase::~wxZRColaFrameBase()
{
// Disconnect Events
m_toolDecompLanguage->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( wxZRColaFrameBase::OnDecompLanguageChoice ), NULL, this );
}
wxZRColaComposerPanelBase::wxZRColaComposerPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style ) : wxPanel( parent, id, pos, size, style )
wxZRColaComposerPanelBase::wxZRColaComposerPanelBase( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxPanel( parent, id, pos, size, style, name )
{
wxBoxSizer* bSizerEditor;
bSizerEditor = new wxBoxSizer( wxVERTICAL );
wxBoxSizer* bSizerMain;
bSizerMain = new wxBoxSizer( wxVERTICAL );
m_decomposed = new wxTextCtrl( this, wxID_DECOMPOSED, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_CENTRE|wxTE_MULTILINE );
m_splitterDecomposed = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3D|wxSP_LIVE_UPDATE );
m_splitterDecomposed->SetSashGravity( 1 );
m_splitterDecomposed->Connect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaComposerPanelBase::m_splitterDecomposedOnIdle ), NULL, this );
m_splitterDecomposed->SetMinimumPaneSize( 5 );
m_panelDecomposedEdit = new wxPanel( m_splitterDecomposed, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerDecomposedEdit;
bSizerDecomposedEdit = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* bSizerDecomposedEdit2;
bSizerDecomposedEdit2 = new wxStaticBoxSizer( new wxStaticBox( m_panelDecomposedEdit, wxID_ANY, _("Decomposed Text") ), wxVERTICAL );
m_decomposed = new wxTextCtrl( bSizerDecomposedEdit2->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
m_decomposed->SetFont( wxFont( 20, 70, 90, 90, false, wxT("00 ZRCola") ) );
m_decomposed->SetMinSize( wxSize( 100,25 ) );
bSizerEditor->Add( m_decomposed, 50, wxALL|wxEXPAND, 5 );
bSizerDecomposedEdit2->Add( m_decomposed, 1, wxEXPAND, 5 );
m_composed = new wxTextCtrl( this, wxID_COMPOSED, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_CENTRE|wxTE_MULTILINE );
bSizerDecomposedEdit->Add( bSizerDecomposedEdit2, 1, wxEXPAND, 5 );
m_panelDecomposedEdit->SetSizer( bSizerDecomposedEdit );
m_panelDecomposedEdit->Layout();
bSizerDecomposedEdit->Fit( m_panelDecomposedEdit );
m_panelDecomposedHex = new wxPanel( m_splitterDecomposed, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerDecomposedHex;
bSizerDecomposedHex = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* bSizerDecomposedHex2;
bSizerDecomposedHex2 = new wxStaticBoxSizer( new wxStaticBox( m_panelDecomposedHex, wxID_ANY, _("Decomposed Unicode Dump") ), wxVERTICAL );
m_decomposedHex = new wxTextCtrl( bSizerDecomposedHex2->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
m_decomposedHex->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 76, 90, 90, false, wxEmptyString ) );
bSizerDecomposedHex2->Add( m_decomposedHex, 1, wxEXPAND, 5 );
bSizerDecomposedHex->Add( bSizerDecomposedHex2, 1, wxEXPAND, 5 );
m_panelDecomposedHex->SetSizer( bSizerDecomposedHex );
m_panelDecomposedHex->Layout();
bSizerDecomposedHex->Fit( m_panelDecomposedHex );
m_splitterDecomposed->SplitVertically( m_panelDecomposedEdit, m_panelDecomposedHex, -5 );
bSizerMain->Add( m_splitterDecomposed, 50, wxALL|wxEXPAND, 5 );
m_splitterComposed = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSP_3D|wxSP_LIVE_UPDATE );
m_splitterComposed->SetSashGravity( 1 );
m_splitterComposed->Connect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaComposerPanelBase::m_splitterComposedOnIdle ), NULL, this );
m_splitterComposed->SetMinimumPaneSize( 5 );
m_panelComposedEdit = new wxPanel( m_splitterComposed, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerComposedEdit;
bSizerComposedEdit = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* bSizerComposedEdit2;
bSizerComposedEdit2 = new wxStaticBoxSizer( new wxStaticBox( m_panelComposedEdit, wxID_ANY, _("Composed Text") ), wxVERTICAL );
m_composed = new wxTextCtrl( bSizerComposedEdit2->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE );
m_composed->SetFont( wxFont( 20, 70, 90, 90, false, wxT("00 ZRCola") ) );
m_composed->SetMinSize( wxSize( 100,25 ) );
bSizerEditor->Add( m_composed, 50, wxALL|wxEXPAND, 5 );
bSizerComposedEdit2->Add( m_composed, 1, wxEXPAND, 5 );
this->SetSizer( bSizerEditor );
bSizerComposedEdit->Add( bSizerComposedEdit2, 1, wxEXPAND, 5 );
m_panelComposedEdit->SetSizer( bSizerComposedEdit );
m_panelComposedEdit->Layout();
bSizerComposedEdit->Fit( m_panelComposedEdit );
m_panelComposedHex = new wxPanel( m_splitterComposed, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizerComposedHex;
bSizerComposedHex = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* bSizerComposedHex2;
bSizerComposedHex2 = new wxStaticBoxSizer( new wxStaticBox( m_panelComposedHex, wxID_ANY, _("Composed Unicode Dump") ), wxVERTICAL );
m_composedHex = new wxTextCtrl( bSizerComposedHex2->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
m_composedHex->SetFont( wxFont( wxNORMAL_FONT->GetPointSize(), 76, 90, 90, false, wxEmptyString ) );
bSizerComposedHex2->Add( m_composedHex, 1, wxEXPAND, 5 );
bSizerComposedHex->Add( bSizerComposedHex2, 1, wxEXPAND, 5 );
m_panelComposedHex->SetSizer( bSizerComposedHex );
m_panelComposedHex->Layout();
bSizerComposedHex->Fit( m_panelComposedHex );
m_splitterComposed->SplitVertically( m_panelComposedEdit, m_panelComposedHex, -5 );
bSizerMain->Add( m_splitterComposed, 50, wxALL|wxEXPAND, 5 );
this->SetSizer( bSizerMain );
this->Layout();
bSizerEditor->Fit( this );
bSizerMain->Fit( this );
// Connect Events
m_decomposed->Connect( wxEVT_PAINT, wxPaintEventHandler( wxZRColaComposerPanelBase::OnDecomposedPaint ), NULL, this );
m_decomposed->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaComposerPanelBase::OnDecomposedText ), NULL, this );
m_decomposedHex->Connect( wxEVT_PAINT, wxPaintEventHandler( wxZRColaComposerPanelBase::OnDecomposedHexPaint ), NULL, this );
m_composed->Connect( wxEVT_PAINT, wxPaintEventHandler( wxZRColaComposerPanelBase::OnComposedPaint ), NULL, this );
m_composed->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaComposerPanelBase::OnComposedText ), NULL, this );
m_composedHex->Connect( wxEVT_PAINT, wxPaintEventHandler( wxZRColaComposerPanelBase::OnComposedHexPaint ), NULL, this );
}
wxZRColaComposerPanelBase::~wxZRColaComposerPanelBase()
@@ -95,7 +290,9 @@ wxZRColaComposerPanelBase::~wxZRColaComposerPanelBase()
// Disconnect Events
m_decomposed->Disconnect( wxEVT_PAINT, wxPaintEventHandler( wxZRColaComposerPanelBase::OnDecomposedPaint ), NULL, this );
m_decomposed->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaComposerPanelBase::OnDecomposedText ), NULL, this );
m_decomposedHex->Disconnect( wxEVT_PAINT, wxPaintEventHandler( wxZRColaComposerPanelBase::OnDecomposedHexPaint ), NULL, this );
m_composed->Disconnect( wxEVT_PAINT, wxPaintEventHandler( wxZRColaComposerPanelBase::OnComposedPaint ), NULL, this );
m_composed->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaComposerPanelBase::OnComposedText ), NULL, this );
m_composedHex->Disconnect( wxEVT_PAINT, wxPaintEventHandler( wxZRColaComposerPanelBase::OnComposedHexPaint ), NULL, this );
}

View File

@@ -21,11 +21,17 @@
#include <wx/font.h>
#include <wx/colour.h>
#include <wx/settings.h>
#include <wx/stattext.h>
#include <wx/choice.h>
#include <wx/toolbar.h>
#include "zrcolacomppnl.h"
#include <wx/sizer.h>
#include <wx/statusbr.h>
#include <wx/frame.h>
#include <wx/textctrl.h>
#include <wx/statbox.h>
#include <wx/panel.h>
#include <wx/splitter.h>
///////////////////////////////////////////////////////////////////////////
@@ -37,14 +43,38 @@ class wxZRColaFrameBase : public wxFrame
private:
protected:
enum
{
wxID_AUTOSTART = 1000,
wxID_SEND_COMPOSED,
wxID_SEND_DECOMPOSED,
wxID_SEND_ABORT,
wxID_DECOMP_LANG_AUTO
};
wxMenuBar* m_menubar;
wxMenu* m_menuFile;
wxMenu* m_menuProgram;
wxMenu* m_menuEdit;
wxMenu* m_menuDecompLanguage;
wxMenu* m_menuHelp;
wxToolBar* m_toolbar;
wxToolBarToolBase* m_toolEditCut;
wxToolBarToolBase* m_toolEditCopy;
wxToolBarToolBase* m_toolEditPaste;
wxToolBarToolBase* m_toolSendComposed;
wxToolBarToolBase* m_toolSendDecomposed;
wxStaticText* m_toolDecompLanguageLbl;
wxChoice* m_toolDecompLanguage;
wxZRColaComposerPanel* m_panel;
wxStatusBar* m_statusBar;
// Virtual event handlers, overide them in your derived class
virtual void OnDecompLanguageChoice( wxCommandEvent& event ) { event.Skip(); }
public:
wxZRColaFrameBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("ZRCola"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 600,400 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL );
wxZRColaFrameBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("ZRCola"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 600,400 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL, const wxString& name = wxT("ZRCola") );
~wxZRColaFrameBase();
@@ -58,26 +88,42 @@ class wxZRColaComposerPanelBase : public wxPanel
private:
protected:
enum
{
wxID_DECOMPOSED = 1000,
wxID_COMPOSED
};
wxSplitterWindow* m_splitterDecomposed;
wxPanel* m_panelDecomposedEdit;
wxTextCtrl* m_decomposed;
wxPanel* m_panelDecomposedHex;
wxTextCtrl* m_decomposedHex;
wxSplitterWindow* m_splitterComposed;
wxPanel* m_panelComposedEdit;
wxTextCtrl* m_composed;
wxPanel* m_panelComposedHex;
wxTextCtrl* m_composedHex;
// Virtual event handlers, overide them in your derived class
virtual void OnDecomposedPaint( wxPaintEvent& event ) { event.Skip(); }
virtual void OnDecomposedText( wxCommandEvent& event ) { event.Skip(); }
virtual void OnDecomposedHexPaint( wxPaintEvent& event ) { event.Skip(); }
virtual void OnComposedPaint( wxPaintEvent& event ) { event.Skip(); }
virtual void OnComposedText( wxCommandEvent& event ) { event.Skip(); }
virtual void OnComposedHexPaint( wxPaintEvent& event ) { event.Skip(); }
public:
wxZRColaComposerPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL );
wxZRColaComposerPanelBase( wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxTAB_TRAVERSAL, const wxString& name = wxT("ZRColaComposerPanel") );
~wxZRColaComposerPanelBase();
void m_splitterDecomposedOnIdle( wxIdleEvent& )
{
m_splitterDecomposed->SetSashPosition( -5 );
m_splitterDecomposed->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaComposerPanelBase::m_splitterDecomposedOnIdle ), NULL, this );
}
void m_splitterComposedOnIdle( wxIdleEvent& )
{
m_splitterComposed->SetSashPosition( -5 );
m_splitterComposed->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaComposerPanelBase::m_splitterComposedOnIdle ), NULL, this );
}
};

View File

@@ -54,52 +54,64 @@ bool wxZRColaKeyHandler::ProcessEvent(wxEvent& event)
{
if (event.GetEventType() == wxEVT_KEY_DOWN) {
// The character event occured.
ZRCola::keyseq_db::indexKey::size_type start, end;
bool found;
wxKeyEvent &e = (wxKeyEvent&)event;
if (e.GetUnicodeKey() || !e.HasAnyModifiers()) {
ZRCola::keyseq_db::indexKey::size_type start, end;
bool found;
wxFrame *pFrame = wxDynamicCast(wxTheApp->GetTopWindow(), wxFrame);
{
// Parse key event and save it at the end of the key sequence.
wxKeyEvent &e = (wxKeyEvent&)event;
ZRCola::keyseq_db::keyseq::key_t key;
key.key = e.GetKeyCode(); //wxToupper(e.m_uniChar);
key.modifiers =
(e.ShiftDown() ? ZRCola::keyseq_db::keyseq::SHIFT : 0) |
(e.ControlDown() ? ZRCola::keyseq_db::keyseq::CTRL : 0) |
(e.AltDown() ? ZRCola::keyseq_db::keyseq::ALT : 0);
m_seq.push_back(key);
{
// Parse key event and save it at the end of the key sequence.
ZRCola::keyseq_db::keyseq::key_t key;
key.key = e.GetRawKeyCode();
key.modifiers =
(e.ShiftDown() ? ZRCola::keyseq_db::keyseq::SHIFT : 0) |
(e.ControlDown() ? ZRCola::keyseq_db::keyseq::CTRL : 0) |
(e.AltDown() ? ZRCola::keyseq_db::keyseq::ALT : 0);
m_seq.push_back(key);
std::vector<ZRCola::keyseq_db::keyseq::key_t>::size_type n = m_seq.size();
ZRCola::keyseq_db::keyseq *ks = (ZRCola::keyseq_db::keyseq*)new char[sizeof(ZRCola::keyseq_db::keyseq) + sizeof(ZRCola::keyseq_db::keyseq::key_t)*n];
ks->chr = 0;
ks->seq_len = n;
memcpy(ks->seq, m_seq.data(), sizeof(ZRCola::keyseq_db::keyseq::key_t)*n);
found = m_ks_db.idxKey.find(*ks, start, end);
delete ks;
}
std::vector<ZRCola::keyseq_db::keyseq::key_t>::size_type n = m_seq.size();
ZRCola::keyseq_db::keyseq *ks = (ZRCola::keyseq_db::keyseq*)new char[sizeof(ZRCola::keyseq_db::keyseq) + sizeof(ZRCola::keyseq_db::keyseq::key_t)*n];
ks->chr = 0;
ks->seq_len = n;
memcpy(ks->seq, m_seq.data(), sizeof(ZRCola::keyseq_db::keyseq::key_t)*n);
found = m_ks_db.idxKey.find(*ks, start, end);
delete ks;
}
if (found) {
// The exact key sequence found.
const ZRCola::keyseq_db::keyseq &ks = m_ks_db.idxKey[start];
m_seq.clear();
if (found) {
// The exact key sequence found.
const ZRCola::keyseq_db::keyseq &ks = m_ks_db.idxKey[start];
m_seq.clear();
wxObject *obj = event.GetEventObject();
if (obj && obj->IsKindOf(wxCLASSINFO(wxTextCtrl))) {
// Push text to source control.
((wxTextCtrl*)obj)->WriteText(ks.chr);
if (pFrame && pFrame->GetStatusBar())
pFrame->SetStatusText(wxEmptyString);
wxObject *obj = event.GetEventObject();
if (obj && obj->IsKindOf(wxCLASSINFO(wxTextCtrl))) {
// Push text to source control.
((wxTextCtrl*)obj)->WriteText(ks.chr);
// Event is fully processed now.
event.StopPropagation();
return true;
}
} else if (start < m_ks_db.idxKey.size() &&
ZRCola::keyseq_db::keyseq::CompareSequence(m_seq.data(), m_seq.size(), m_ks_db.idxKey[start].seq, std::min<unsigned __int16>(m_ks_db.idxKey[start].seq_len, m_seq.size())) == 0)
{
// The sequence is a partial match. Continue watching.
if (pFrame && pFrame->GetStatusBar())
pFrame->SetStatusText(ZRCola::keyseq_db::GetSequenceAsText(m_seq.data(), m_seq.size()));
// Event is fully processed now.
event.StopPropagation();
return true;
} else {
// The key sequence has no future chance to match. Start all over again.
m_seq.clear();
if (pFrame && pFrame->GetStatusBar())
pFrame->SetStatusText(wxEmptyString);
}
} else if (start < m_ks_db.idxKey.size() &&
ZRCola::keyseq_db::keyseq::CompareSequence(m_seq.data(), m_seq.size(), m_ks_db.idxKey[start].seq, std::min<unsigned __int16>(m_ks_db.idxKey[start].seq_len, m_seq.size())) == 0)
{
// The sequence is a partial match. Continue watching.
//event.StopPropagation();
//return true;
} else {
// The key sequence has no future chance to match. Start all over again.
m_seq.clear();
}
}

View File

@@ -99,15 +99,58 @@ void ZRCola::DBSource::LogErrors() const
}
bool ZRCola::DBSource::GetValue(const ATL::CComPtr<ADOField>& f, bool& val) const
{
wxASSERT_MSG(f, wxT("field is empty"));
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_BOOL)), false);
val = V_BOOL(&v) ? true : false;
return true;
}
bool ZRCola::DBSource::GetValue(const ATL::CComPtr<ADOField>& f, int& val) const
{
wxASSERT_MSG(f, wxT("field is empty"));
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_I4)), false);
val = V_I4(&v);
return true;
}
bool ZRCola::DBSource::GetValue(const ATL::CComPtr<ADOField>& f, std::wstring& val) const
{
wxASSERT_MSG(f, wxT("field is empty"));
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_BSTR)), false);
val.reserve(::SysStringLen(V_BSTR(&v)));
val = V_BSTR(&v);
return true;
}
bool ZRCola::DBSource::GetUnicodeCharacter(const ATL::CComPtr<ADOField>& f, wchar_t& chr) const
{
wxASSERT_MSG(f, wxT("field is empty"));
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_BSTR)), false);
// Parse the field. Must be exactly one Unicode code.
wxVERIFY(SUCCEEDED(v.ChangeType(VT_BSTR)));
UINT i = 0, n = ::SysStringLen(V_BSTR(&v));
chr = 0;
for (; i < n && V_BSTR(&v)[i]; i++) {
@@ -136,9 +179,9 @@ bool ZRCola::DBSource::GetUnicodeString(const ATL::CComPtr<ADOField>& f, std::ws
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_BSTR)), false);
// Parse the field. Must be "xxxx+xxxx+xxxx..." sequence.
wxVERIFY(SUCCEEDED(v.ChangeType(VT_BSTR)));
str.clear();
for (UINT i = 0, n = ::SysStringLen(V_BSTR(&v)); i < n && V_BSTR(&v)[i];) {
// Parse Unicode code.
@@ -165,64 +208,93 @@ bool ZRCola::DBSource::GetUnicodeString(const ATL::CComPtr<ADOField>& f, std::ws
}
bool ZRCola::DBSource::GetKeySequence(const ATL::CComPtr<ADOField>& f, std::vector<keyseq::keycode>& seq) const
bool ZRCola::DBSource::GetKeyCode(const ATL::CComPtr<ADOField>& f, ZRCola::DBSource::keyseq::keycode& kc) const
{
wxASSERT_MSG(f, wxT("field is empty"));
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxVERIFY(SUCCEEDED(v.ChangeType(VT_BSTR)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_BSTR)), false);
// Convert to uppercase.
_wcsupr_l(V_BSTR(&v), m_locale);
// Parse the field. Must be comma delimited sequence of key codes.
seq.clear();
// Parse the field.
memset(&kc, 0, sizeof(kc));
for (UINT i = 0, n = ::SysStringLen(V_BSTR(&v)); i < n && V_BSTR(&v)[i];) {
keyseq::keycode kc = {};
while (i < n && V_BSTR(&v)[i]) {
// Parse key code.
static const wchar_t str_shift[] = L"SHIFT+", str_ctrl[] = L"CTRL+", str_alt[] = L"ALT+";
if (i + _countof(str_shift) <= n && wmemcmp(V_BSTR(&v) + i, str_shift, _countof(str_shift) - 1) == 0) {
kc.shift = true;
i += _countof(str_shift) - 1;
} else if (i + _countof(str_ctrl) <= n && wmemcmp(V_BSTR(&v) + i, str_ctrl, _countof(str_ctrl) - 1) == 0) {
kc.ctrl = true;
i += _countof(str_ctrl) - 1;
} else if (i + _countof(str_alt) <= n && wmemcmp(V_BSTR(&v) + i, str_alt, _countof(str_alt) - 1) == 0) {
kc.alt = true;
i += _countof(str_alt) - 1;
} else {
kc.key = V_BSTR(&v)[i];
i++;
break;
// Parse key code.
if (i) {
// Check for "+" separator.
if (V_BSTR(&v)[i] != L'+') {
ATL::CComBSTR fieldname; wxVERIFY(SUCCEEDED(f->get_Name(&fieldname)));
_ftprintf(stderr, wxT("%s: error ZCC0070: Syntax error in \"%.*ls\" field (\"%.*ls\"). Key codes must be \"Ctrl+Alt+<key>\" formatted.\n"), m_filename.c_str(), fieldname.Length(), (BSTR)fieldname, n, V_BSTR(&v));
}
i++;
if (i >= n || !V_BSTR(&v)[i]) {
ATL::CComBSTR fieldname; wxVERIFY(SUCCEEDED(f->get_Name(&fieldname)));
_ftprintf(stderr, wxT("%s: error ZCC0071: Syntax error in \"%.*ls\" field (\"%.*ls\"). Trailing separator \"+\" found.\n"), m_filename.c_str(), fieldname.Length(), (BSTR)fieldname, n, V_BSTR(&v));
}
}
if (i < n && V_BSTR(&v)[i] && V_BSTR(&v)[i] != L',' && !_iswspace_l(V_BSTR(&v)[i], m_locale)) {
ATL::CComBSTR fieldname; wxVERIFY(SUCCEEDED(f->get_Name(&fieldname)));
_ftprintf(stderr, wxT("%s: error ZCC0060: Syntax error in \"%.*ls\" field (\"%.*ls\"). Key sequences must be \"Ctrl+Alt+<key>\" formatted, delimited by commas and/or space.\n"), m_filename.c_str(), fieldname.Length(), (BSTR)fieldname, n, V_BSTR(&v));
return false;
}
if (seq.size() > 0xffff) {
_ftprintf(stderr, wxT("%s: warning ZCC0061: Key sequence \"%.*ls...\" too long. Ignored.\n"), (LPCTSTR)m_filename.c_str(), std::min<UINT>(n, 20), V_BSTR(&v));
return false;
}
seq.push_back(kc);
// Skip delimiter(s) and whitespace.
for (; i < n && V_BSTR(&v)[i] && (V_BSTR(&v)[i] == L',' || _iswspace_l(V_BSTR(&v)[i], m_locale)); i++);
}
if (seq.empty()) {
_ftprintf(stderr, wxT("%s: warning ZCC0062: Empty key sequence. Ignored.\n"), (LPCTSTR)m_filename.c_str());
return false;
static const wchar_t str_shift[] = L"SHIFT", str_ctrl[] = L"CTRL", str_alt[] = L"ALT";
if (i + _countof(str_shift) - 1 <= n && wmemcmp(V_BSTR(&v) + i, str_shift, _countof(str_shift) - 1) == 0) {
kc.shift = true;
i += _countof(str_shift) - 1;
} else if (i + _countof(str_ctrl) - 1 <= n && wmemcmp(V_BSTR(&v) + i, str_ctrl, _countof(str_ctrl) - 1) == 0) {
kc.ctrl = true;
i += _countof(str_ctrl) - 1;
} else if (i + _countof(str_alt) - 1 <= n && wmemcmp(V_BSTR(&v) + i, str_alt, _countof(str_alt) - 1) == 0) {
kc.alt = true;
i += _countof(str_alt) - 1;
} else {
kc.key = V_BSTR(&v)[i];
i++;
}
}
return true;
}
bool ZRCola::DBSource::GetLanguage(const ATL::CComPtr<ADOField>& f, ZRCola::langid_t& lang) const
{
wxASSERT_MSG(f, wxT("field is empty"));
ATL::CComVariant v;
wxVERIFY(SUCCEEDED(f->get_Value(&v)));
wxCHECK(SUCCEEDED(v.ChangeType(VT_BSTR)), false);
// Convert to lowercase.
_wcslwr_l(V_BSTR(&v), m_locale);
// Parse the field.
size_t n = wcsnlen(V_BSTR(&v), ::SysStringLen(V_BSTR(&v)));
if (n != 3) {
ATL::CComBSTR fieldname; wxVERIFY(SUCCEEDED(f->get_Name(&fieldname)));
_ftprintf(stderr, wxT("%s: error ZCC0080: Syntax error in \"%.*ls\" field (\"%.*ls\"). Language ID must be exactly three (3) characters long.\n"), m_filename.c_str(), fieldname.Length(), (BSTR)fieldname, n, V_BSTR(&v));
return false;
}
for (size_t i = 0;; i++) {
if (i < sizeof(lang)) {
if (i < n) {
wchar_t c = V_BSTR(&v)[i];
if ((unsigned short)c > 0x7f) {
ATL::CComBSTR fieldname; wxVERIFY(SUCCEEDED(f->get_Name(&fieldname)));
_ftprintf(stderr, wxT("%s: error ZCC0081: Syntax error in \"%.*ls\" field (\"%.*ls\"). Language ID must contain ASCII characters only.\n"), m_filename.c_str(), fieldname.Length(), (BSTR)fieldname, n, V_BSTR(&v));
return false;
}
lang[i] = (char)c;
} else
lang[i] = 0;
} else
break;
}
return true;
}
bool ZRCola::DBSource::SelectTranslations(ATL::CComPtr<ADORecordset> &rs) const
{
// Create a new recordset.
@@ -230,7 +302,12 @@ bool ZRCola::DBSource::SelectTranslations(ATL::CComPtr<ADORecordset> &rs) const
wxCHECK(SUCCEEDED(::CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_ALL, IID_IADORecordset, (LPVOID*)&rs)), false);
// Open it.
if (FAILED(rs->Open(ATL::CComVariant(L"SELECT [komb], [znak] FROM [VRS_ReplChar] WHERE [rang_komb]=1"), ATL::CComVariant(m_db), adOpenStatic, adLockReadOnly, adCmdText))) {
if (FAILED(rs->Open(ATL::CComVariant(
L"SELECT [komb], [znak], [rang_znak] "
L"FROM [VRS_ReplChar] "
L"WHERE [rang_komb]=1 "
L"ORDER BY [znak], [rang_znak], [komb]"), ATL::CComVariant(m_db), adOpenStatic, adLockReadOnly, adCmdText)))
{
_ftprintf(stderr, wxT("%s: error ZCC0040: Error loading compositions from database. Please make sure the file is ZRCola.zrc compatible.\n"), m_filename.c_str());
LogErrors();
return false;
@@ -259,6 +336,12 @@ bool ZRCola::DBSource::GetTranslation(const ATL::CComPtr<ADORecordset>& rs, ZRCo
wxCHECK(GetUnicodeCharacter(f, t.chr), false);
}
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"rang_znak"), &f)));
wxCHECK(GetValue(f, t.rank), false);
}
return true;
}
@@ -270,7 +353,11 @@ bool ZRCola::DBSource::SelectKeySequences(ATL::CComPtr<ADORecordset> &rs) const
wxCHECK(SUCCEEDED(::CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_ALL, IID_IADORecordset, (LPVOID*)&rs)), false);
// Open it.
if (FAILED(rs->Open(ATL::CComVariant(L"SELECT DISTINCT [Znak], [tipka] FROM [wrd_KeyCodes]"), ATL::CComVariant(m_db), adOpenStatic, adLockReadOnly, adCmdText))) {
if (FAILED(rs->Open(ATL::CComVariant(
L"SELECT DISTINCT [VRS_KeyCodes].[Znak], [VRS_CharGroup].[Name] AS [CharGroup], [VRS_KeyCodes].[KeyCode], [VRS_KeyCodes].[Shift] "
L"FROM [VRS_KeyCodes] LEFT JOIN [VRS_CharGroup] ON [VRS_CharGroup].[CharGroup]=[VRS_KeyCodes].[CharGroup] "
L"ORDER BY [VRS_CharGroup].[Name], [VRS_KeyCodes].[KeyCode], [VRS_KeyCodes].[Shift], [VRS_KeyCodes].[Znak]"), ATL::CComVariant(m_db), adOpenStatic, adLockReadOnly, adCmdText)))
{
_ftprintf(stderr, wxT("%s: error ZCC0050: Error loading key sequences from database. Please make sure the file is ZRCola.zrc compatible.\n"), m_filename.c_str());
LogErrors();
return false;
@@ -293,10 +380,126 @@ bool ZRCola::DBSource::GetKeySequence(const ATL::CComPtr<ADORecordset>& rs, ZRCo
wxCHECK(GetUnicodeCharacter(f, ks.chr), false);
}
keyseq::keycode kc1;
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"tipka"), &f)));
wxCHECK(GetKeySequence(f, ks.seq), false);
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"CharGroup"), &f)));
wxCHECK(GetKeyCode(f, kc1), false);
}
int keycode;
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"KeyCode"), &f)));
wxCHECK(GetValue(f, keycode), false);
}
bool shift;
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"Shift"), &f)));
wxCHECK(GetValue(f, shift), false);
}
ks.seq.clear();
if (kc1.key) {
// First key in the sequence is complete.
ks.seq.push_back(kc1);
keyseq::keycode kc2 = { keycode, shift };
ks.seq.push_back(kc2);
} else {
// First key in the sequence is only modifier(s).
kc1.key = keycode;
if (shift) kc1.shift = true;
ks.seq.push_back(kc1);
}
return true;
}
bool ZRCola::DBSource::SelectLanguages(ATL::CComPtr<ADORecordset> &rs) const
{
// Create a new recordset.
if (rs) rs.Release();
wxCHECK(SUCCEEDED(::CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_ALL, IID_IADORecordset, (LPVOID*)&rs)), false);
// Open it.
if (FAILED(rs->Open(ATL::CComVariant(
L"SELECT DISTINCT [entCode], [Jezik_En] "
L"FROM [VRS_Jezik] "
L"ORDER BY [entCode], [Jezik_En]"), ATL::CComVariant(m_db), adOpenStatic, adLockReadOnly, adCmdText)))
{
_ftprintf(stderr, wxT("%s: error ZCC0060: Error loading languages from database. Please make sure the file is ZRCola.zrc compatible.\n"), m_filename.c_str());
LogErrors();
return false;
}
return true;
}
bool ZRCola::DBSource::GetLanguage(const ATL::CComPtr<ADORecordset>& rs, ZRCola::DBSource::language& lang) const
{
wxASSERT_MSG(rs, wxT("recordset is empty"));
ATL::CComPtr<ADOFields> flds;
wxVERIFY(SUCCEEDED(rs->get_Fields(&flds)));
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"entCode"), &f)));
wxCHECK(GetLanguage(f, lang.id), false);
}
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"Jezik_En"), &f)));
wxCHECK(GetValue(f, lang.name), false);
}
return true;
}
bool ZRCola::DBSource::SelectLanguageCharacters(ATL::CComPtr<ADORecordset> &rs) const
{
// Create a new recordset.
if (rs) rs.Release();
wxCHECK(SUCCEEDED(::CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_ALL, IID_IADORecordset, (LPVOID*)&rs)), false);
// Open it.
if (FAILED(rs->Open(ATL::CComVariant(
L"SELECT DISTINCT [znak], [lang] "
L"FROM [VRS_CharLocal] "
L"ORDER BY [znak], [lang]"), ATL::CComVariant(m_db), adOpenStatic, adLockReadOnly, adCmdText)))
{
_ftprintf(stderr, wxT("%s: error ZCC0090: Error loading language characters from database. Please make sure the file is ZRCola.zrc compatible.\n"), m_filename.c_str());
LogErrors();
return false;
}
return true;
}
bool ZRCola::DBSource::GetLanguageCharacter(const ATL::CComPtr<ADORecordset>& rs, ZRCola::DBSource::langchar& lc) const
{
wxASSERT_MSG(rs, wxT("recordset is empty"));
ATL::CComPtr<ADOFields> flds;
wxVERIFY(SUCCEEDED(rs->get_Fields(&flds)));
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"znak"), &f)));
wxCHECK(GetUnicodeCharacter(f, lc.chr), false);
}
{
ATL::CComPtr<ADOField> f;
wxVERIFY(SUCCEEDED(flds->get_Item(ATL::CComVariant(L"lang"), &f)));
wxCHECK(GetLanguage(f, lc.lang), false);
}
return true;

View File

@@ -19,6 +19,8 @@
#pragma once
#include <zrcola/common.h>
#include <atlbase.h>
#include <adoint.h>
#include <string>
@@ -39,6 +41,7 @@ namespace ZRCola {
public:
wchar_t chr; ///< Composed character
std::wstring str; ///< Decomposed string
int rank; ///< Decomposition rank
};
@@ -62,6 +65,26 @@ namespace ZRCola {
std::vector<keycode> seq; ///< Key sequence
};
///
/// Language
///
class language {
public:
ZRCola::langid_t id; ///< Language ID
std::wstring name; ///< Language name
};
///
/// Language Character
///
class langchar {
public:
wchar_t chr; ///> Character
ZRCola::langid_t lang; ///< Language ID
};
public:
DBSource();
virtual ~DBSource();
@@ -115,6 +138,45 @@ namespace ZRCola {
}
///
/// Gets boolean from ZRCola.zrc database
///
/// \param[in] f Data field
/// \param[out] val Output boolean value
///
/// \returns
/// - true when successful
/// - false otherwise
///
bool GetValue(const ATL::CComPtr<ADOField>& f, bool& val) const;
///
/// Gets integer from ZRCola.zrc database
///
/// \param[in] f Data field
/// \param[out] val Output integer value
///
/// \returns
/// - true when successful
/// - false otherwise
///
bool GetValue(const ATL::CComPtr<ADOField>& f, int& val) const;
///
/// Gets string from ZRCola.zrc database
///
/// \param[in] f Data field
/// \param[out] val Output string value
///
/// \returns
/// - true when successful
/// - false otherwise
///
bool GetValue(const ATL::CComPtr<ADOField>& f, std::wstring& val) const;
///
/// Gets encoded Unicode character from ZRCola.zrc database
///
@@ -142,16 +204,29 @@ namespace ZRCola {
///
/// Gets encoded key sequence from ZRCola.zrc database
/// Gets encoded key from ZRCola.zrc database
///
/// \param[in] f Data field
/// \param[out] seq Output sequence
/// \param[in] f Data field
/// \param[out] kc Output key code
///
/// \returns
/// - true when successful
/// - false otherwise
///
bool GetKeySequence(const ATL::CComPtr<ADOField>& f, std::vector<keyseq::keycode>& seq) const;
bool GetKeyCode(const ATL::CComPtr<ADOField>& f, keyseq::keycode& kc) const;
///
/// Gets language ID from ZRCola.zrc database
///
/// \param[in] f Data field
/// \param[out] lang Language
///
/// \returns
/// - true when successful
/// - false otherwise
///
bool GetLanguage(const ATL::CComPtr<ADOField>& f, langid_t& lang) const;
///
@@ -203,6 +278,56 @@ namespace ZRCola {
///
bool GetKeySequence(const ATL::CComPtr<ADORecordset>& rs, keyseq& ks) const;
///
/// Returns languages
///
/// \param[out] rs Recordset with results
///
/// \returns
/// - true when query succeeds
/// - false otherwise
///
bool SelectLanguages(ATL::CComPtr<ADORecordset>& rs) const;
///
/// Returns language data
///
/// \param[in] rs Recordset with results
/// \param[out] lang Language
///
/// \returns
/// - true when succeeded
/// - false otherwise
///
bool GetLanguage(const ATL::CComPtr<ADORecordset>& rs, language& lang) const;
///
/// Returns language character
///
/// \param[out] rs Recordset with results
///
/// \returns
/// - true when query succeeds
/// - false otherwise
///
bool SelectLanguageCharacters(ATL::CComPtr<ADORecordset>& rs) const;
///
/// Returns language character data
///
/// \param[in] rs Recordset with results
/// \param[out] lang Language character data
///
/// \returns
/// - true when succeeded
/// - false otherwise
///
bool GetLanguageCharacter(const ATL::CComPtr<ADORecordset>& rs, langchar& lc) const;
protected:
std::basic_string<TCHAR> m_filename; ///< Database filename
ATL::CComPtr<ADOConnection> m_db; ///< Database

View File

@@ -1,8 +1,8 @@
msgid ""
msgstr ""
"Project-Id-Version: ZRColaCompile\n"
"POT-Creation-Date: 2016-03-14 17:18+0100\n"
"PO-Revision-Date: 2016-03-14 17:18+0100\n"
"POT-Creation-Date: 2016-04-13 18:11+0200\n"
"PO-Revision-Date: 2016-04-13 18:11+0200\n"
"Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n"
"Language-Team: Amebis, d. o. o., Kamnik <info@amebis.si>\n"
"Language: sl_SI\n"
@@ -17,14 +17,18 @@ msgstr ""
"X-Poedit-KeywordsList: _\n"
"X-Poedit-SearchPath-0: .\n"
#: main.cpp:165
#: main.cpp:276
msgid "Show this help message"
msgstr "Pokaži to sporočilo pomoči"
#: main.cpp:166
msgid "input file"
msgstr "vhodna datoteka"
#: main.cpp:277
msgid "<input file>"
msgstr "<vhodna datoteka>"
#: main.cpp:167
msgid "output file"
msgstr "izhodna datoteka"
#: main.cpp:278
msgid "<output file>"
msgstr "<izhodna datoteka>"
#: main.cpp:279
msgid "<output POT catalog>"
msgstr "<izhodni katalog POT>"

View File

@@ -132,6 +132,117 @@ inline std::ostream& operator <<(std::ostream& stream, const ZRCola::keyseq_db &
}
///
/// Writes language database to a stream
///
/// \param[in] stream Output stream
/// \param[in] db Language database
///
/// \returns The stream \p stream
///
inline std::ostream& operator <<(std::ostream& stream, const ZRCola::language_db &db)
{
unsigned __int32 count;
// Write index count.
ZRCola::language_db::indexLang::size_type lang_count = db.idxLng.size();
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
// 4G check
if (lang_count > 0xffffffff) {
stream.setstate(std::ios_base::failbit);
return stream;
}
#endif
if (stream.fail()) return stream;
count = (unsigned __int32)lang_count;
stream.write((const char*)&count, sizeof(count));
// Write language index.
if (stream.fail()) return stream;
stream.write((const char*)db.idxLng.data(), sizeof(unsigned __int32)*count);
// Write data count.
std::vector<unsigned __int16>::size_type data_count = db.data.size();
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
// 4G check
if (data_count > 0xffffffff) {
stream.setstate(std::ios_base::failbit);
return stream;
}
#endif
if (stream.fail()) return stream;
count = (unsigned __int32)data_count;
stream.write((const char*)&count, sizeof(count));
// Write data.
if (stream.fail()) return stream;
stream.write((const char*)db.data.data(), sizeof(unsigned __int16)*count);
return stream;
}
///
/// Writes language character database to a stream
///
/// \param[in] stream Output stream
/// \param[in] db Language character database
///
/// \returns The stream \p stream
///
inline std::ostream& operator <<(std::ostream& stream, const ZRCola::langchar_db &db)
{
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
assert(db.idxChr.size() == db.idxLng.size());
#endif
unsigned __int32 count;
// Write index count.
ZRCola::langchar_db::indexChar::size_type lc_count = db.idxChr.size();
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
// 4G check
if (lc_count > 0xffffffff) {
stream.setstate(std::ios_base::failbit);
return stream;
}
#endif
if (stream.fail()) return stream;
count = (unsigned __int32)lc_count;
stream.write((const char*)&count, sizeof(count));
// Write character index.
if (stream.fail()) return stream;
stream.write((const char*)db.idxChr.data(), sizeof(unsigned __int32)*count);
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
// Write language index.
if (stream.fail()) return stream;
stream.write((const char*)db.idxLng.data(), sizeof(unsigned __int32)*count);
#endif
// Write data count.
std::vector<unsigned __int16>::size_type data_count = db.data.size();
#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)
// 4G check
if (data_count > 0xffffffff) {
stream.setstate(std::ios_base::failbit);
return stream;
}
#endif
if (stream.fail()) return stream;
count = (unsigned __int32)data_count;
stream.write((const char*)&count, sizeof(count));
// Write data.
if (stream.fail()) return stream;
stream.write((const char*)db.data.data(), sizeof(unsigned __int16)*count);
return stream;
}
///
/// Main function
///
@@ -163,8 +274,9 @@ int _tmain(int argc, _TCHAR *argv[])
static const wxCmdLineEntryDesc cmdLineDesc[] =
{
{ wxCMD_LINE_SWITCH, "h" , "help", _("Show this help message"), wxCMD_LINE_VAL_NONE , wxCMD_LINE_OPTION_HELP },
{ wxCMD_LINE_PARAM , NULL, NULL , _("input file") , wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
{ wxCMD_LINE_PARAM , NULL, NULL , _("output file") , wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
{ wxCMD_LINE_PARAM , NULL, NULL , _("<input file>" ), wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
{ wxCMD_LINE_PARAM , NULL, NULL , _("<output file>" ), wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION_MANDATORY },
{ wxCMD_LINE_PARAM , NULL, NULL , _("<output POT catalog>" ), wxCMD_LINE_VAL_STRING, wxCMD_LINE_OPTION },
{ wxCMD_LINE_NONE }
};
@@ -206,6 +318,10 @@ int _tmain(int argc, _TCHAR *argv[])
bool has_errors = false;
// Set of strings to translate.
bool build_pot = parser.GetParamCount() > 2;
std::set<std::wstring> pot;
// Open file ID.
std::streamoff dst_start = stdex::idrec::open<ZRCola::recordid_t, ZRCola::recordsize_t>(dst, ZRCOLA_DB_ID);
@@ -230,6 +346,8 @@ int _tmain(int argc, _TCHAR *argv[])
// Add translation to index and data.
unsigned __int32 idx = db.data.size();
db.data.push_back(trans.chr);
wxASSERT_MSG((int)0xffff8000 <= trans.rank && trans.rank <= (int)0x00007fff, wxT("transformation rank out of bounds"));
db.data.push_back((unsigned __int16)trans.rank);
std::wstring::size_type n = trans.str.length();
wxASSERT_MSG(n <= 0xffff, wxT("transformation string too long"));
db.data.push_back((unsigned __int16)n);
@@ -259,7 +377,6 @@ int _tmain(int argc, _TCHAR *argv[])
}
}
{
// Get key sequences.
ATL::CComPtr<ADORecordset> rs;
@@ -329,6 +446,109 @@ int _tmain(int argc, _TCHAR *argv[])
}
}
{
// Get languages.
ATL::CComPtr<ADORecordset> rs;
if (src.SelectLanguages(rs)) {
size_t count = src.GetRecordsetCount(rs);
if (count < 0xffffffff) { // 4G check (-1 is reserved for error condition)
ZRCola::DBSource::language lang;
ZRCola::language_db db;
// Preallocate memory.
db.idxLng.reserve(count);
db.data .reserve(count*4);
// Parse languages and build index and data.
while (!ZRCola::DBSource::IsEOF(rs)) {
// Read language from the database.
if (src.GetLanguage(rs, lang)) {
// Add language to index and data.
unsigned __int32 idx = db.data.size();
for (std::wstring::size_type i = 0; i < sizeof(ZRCola::langid_t)/sizeof(unsigned __int16); i++)
db.data.push_back(((const unsigned __int16*)lang.id)[i]);
std::wstring::size_type n = lang.name.length();
wxASSERT_MSG(n <= 0xffff, wxT("language name too long"));
db.data.push_back((unsigned __int16)n);
for (std::wstring::size_type i = 0; i < n; i++)
db.data.push_back(lang.name[i]);
db.idxLng.push_back(idx);
if (build_pot)
pot.insert(lang.name);
} else
has_errors = true;
wxVERIFY(SUCCEEDED(rs->MoveNext()));
}
// Sort indices.
db.idxLng.sort();
// Write languages to file.
dst << ZRCola::language_rec(db);
} else {
_ftprintf(stderr, wxT("%s: error ZCC0009: Error getting language count from database or too many languages.\n"), (LPCTSTR)filenameIn.c_str());
has_errors = true;
}
} else {
_ftprintf(stderr, wxT("%s: error ZCC0008: Error getting languages from database. Please make sure the file is ZRCola.zrc compatible.\n"), (LPCTSTR)filenameIn.c_str());
has_errors = true;
}
}
{
// Get language characters.
ATL::CComPtr<ADORecordset> rs;
if (src.SelectLanguageCharacters(rs)) {
size_t count = src.GetRecordsetCount(rs);
if (count < 0xffffffff) { // 4G check (-1 is reserved for error condition)
ZRCola::DBSource::langchar lc;
ZRCola::langchar_db db;
// Preallocate memory.
db.idxChr.reserve(count);
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
db.idxLng.reserve(count);
#endif
db.data .reserve(count*4);
// Parse language characters and build index and data.
while (!ZRCola::DBSource::IsEOF(rs)) {
// Read language characters from the database.
if (src.GetLanguageCharacter(rs, lc)) {
// Add language characters to index and data.
unsigned __int32 idx = db.data.size();
db.data.push_back(lc.chr);
for (std::wstring::size_type i = 0; i < sizeof(ZRCola::langid_t)/sizeof(unsigned __int16); i++)
db.data.push_back(((const unsigned __int16*)lc.lang)[i]);
db.idxChr.push_back(idx);
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
db.idxLng.push_back(idx);
#endif
} else
has_errors = true;
wxVERIFY(SUCCEEDED(rs->MoveNext()));
}
// Sort indices.
db.idxChr .sort();
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
db.idxLng.sort();
#endif
// Write language characters to file.
dst << ZRCola::langchar_rec(db);
} else {
_ftprintf(stderr, wxT("%s: error ZCC0011: Error getting language characters count from database or too many langchars.\n"), (LPCTSTR)filenameIn.c_str());
has_errors = true;
}
} else {
_ftprintf(stderr, wxT("%s: error ZCC0010: Error getting language characters from database. Please make sure the file is ZRCola.zrc compatible.\n"), (LPCTSTR)filenameIn.c_str());
has_errors = true;
}
}
stdex::idrec::close<ZRCola::recordid_t, ZRCola::recordsize_t, ZRCOLA_RECORD_ALIGN>(dst, dst_start);
if (dst.fail()) {
@@ -336,6 +556,50 @@ int _tmain(int argc, _TCHAR *argv[])
has_errors = true;
}
if (!has_errors && build_pot) {
const wxString& filenamePot = parser.GetParam(2);
std::fstream dst((LPCTSTR)filenamePot, std::ios_base::out | std::ios_base::trunc);
if (dst.good()) {
dst << "msgid \"\"" << std::endl
<< "msgstr \"\"" << std::endl
<< "\"Project-Id-Version: ZRCola.zrcdb\\n\"" << std::endl
<< "\"Language: en\\n\"" << std::endl
<< "\"MIME-Version: 1.0\\n\"" << std::endl
<< "\"Content-Type: text/plain; charset=UTF-8\\n\"" << std::endl
<< "\"Content-Transfer-Encoding: 8bit\\n\"" << std::endl
<< "\"X-Generator: ZRColaCompile " << ZRCOLA_VERSION_STR << "\\n\"" << std::endl;
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
for (std::set<std::wstring>::const_iterator i = pot.cbegin(); i != pot.cend(); ++i) {
// Convert UTF-16 to UTF-8 and escape.
std::string t(conv.to_bytes(*i)), u;
for (size_t i = 0, n = t.size(); i < n; i++) {
char c = t[i];
switch (c) {
case '\'': u += "\\\'"; break;
case '\"': u += "\\\""; break;
case '\n': u += "\\\n"; break;
case '\t': u += "\\\t"; break;
default : u += c;
}
}
dst << std::endl
<< "msgid \"" << u << "\"" << std::endl
<< "msgstr \"\"" << std::endl;
}
if (dst.fail()) {
_ftprintf(stderr, wxT("%s: error ZCC0013: Writing to POT catalog failed.\n"), (LPCTSTR)filenameOut.c_str());
has_errors = true;
}
dst.close();
} else {
_ftprintf(stderr, wxT("%s: error ZCC0012: Error opening POT catalog.\n"), filenameOut.fn_str());
has_errors = true;
}
}
if (has_errors) {
dst.close();
wxRemoveFile(filenameOut);

View File

@@ -24,6 +24,7 @@
#include "../include/zrcola.h"
#include "dbsource.h"
#include <zrcola/language.h>
#include <zrcola/translate.h>
#include <zrcolaui/keyboard.h>
@@ -45,4 +46,6 @@
#include <stdlib.h>
#include <codecvt>
#include <fstream>
#include <set>

655
bin/ZRCUpdate.wsf Normal file
View File

@@ -0,0 +1,655 @@
<?xml version="1.0"?>
<!--
Copyright 2016 Amebis
This file is part of ZRCola.
ZRCola is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ZRCola is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ZRCola. If not, see <http://www.gnu.org/licenses/>.
-->
<package>
<job id="CharImport">
<runtime>
<description>Unicode Character Description Update - Amebis, Copyright © 2016</description>
<unnamed name="&lt;ZRCola.mdb&gt;" required="true" helpstring="ZRCola database"/>
<unnamed name="&lt;UnicodeData.txt&gt;" required="true" helpstring="Unicode character database (from http://www.unicode.org/Public/UNIDATA/UnicodeData.txt)"/>
<named name="F" type="simple" required="false" helpstring="Force overwrite of existing data"/>
</runtime>
<reference object="ADODB.Connection"/>
<reference object="ADODB.Command"/>
<reference object="ADODB.Recordset"/>
<reference object="Scripting.FileSystemObject"/>
<script language="JScript"><![CDATA[
if (WScript.Arguments.Unnamed.Length < 2) {
WScript.Arguments.ShowUsage();
WScript.Quit(1);
}
var force = WScript.Arguments.Named.Exists("F") ? true : false;
// Open ZRCola database.
var db = WScript.CreateObject("ADODB.Connection");
db.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq=" + WScript.Arguments.Unnamed(0) + ";Uid=;Pwd=;");
try {
// Open Unicode Data file.
var
fso = WScript.CreateObject("Scripting.FileSystemObject"),
f = fso.OpenTextFile(WScript.Arguments.Unnamed(1), ForReading);
try {
var
now = new Date(),
com = WScript.CreateObject("ADODB.Command"), param_znak,
rs = WScript.CreateObject("ADODB.Recordset");
com.Prepared = true;
com.ActiveConnection = db;
com.CommandType = adCmdText;
com.CommandText = "SELECT TOP 1 * FROM [VRS_CharList] WHERE [znak]=?";
com.Parameters.Append(param_znak = com.CreateParameter("znak", adChar, adParamInput, 4));
rs.CursorLocation = adUseClient;
rs.CursorType = adOpenDynamic;
rs.LockType = adLockOptimistic;
db.BeginTrans();
try {
// Parse Unicode Data file.
while (!f.AtEndOfStream) {
var
line = f.ReadLine(),
fields = line.split(";"),
unicode = parseInt(fields[0], 16),
v;
if (unicode < 0x0020 || 0xffff < unicode) {
// Skip characters outside of 0020-FFFF range.
continue;
}
// Convert Unicode HEX code to uppercase for consistent database experience.
fields[ 0] = fields[ 0].toUpperCase();
fields[12] = fields[12] != "" ? fields[12].toUpperCase() : fields[ 0];
fields[13] = fields[13] != "" ? fields[13].toUpperCase() : fields[ 0];
fields[14] = fields[14] != "" ? fields[14].toUpperCase() : fields[12];
var
desc_en = fields[1] != "<control>" ? fields[1] : fields[10],
dig_dec = fields[6] != "" ? parseInt(fields[6], 10) : null,
digit = fields[7] != "" ? parseInt(fields[7], 10) : null,
mirror = fields[9] == "Y" || fields[9] == "y";
if (fields[1].charAt(0) == "<") {
// Skip range start and stop descriptors.
continue;
}
// Search the character.
param_znak.Value = fields[0];
rs.Open(com);
try {
if (rs.EOF) {
// If a character does not exist yet, create it.
rs.AddNew();
rs("znak" ).Value = fields[0];
rs("znakZRCOLA" ).Value = String.fromCharCode(unicode);
rs("opis_en" ).Value = desc_en;
rs("kat" ).Value = fields[2];
rs("komb" ).Value = parseInt(fields[3], 10);
rs("stevka10" ).Value = dig_dec;
rs("stevka" ).Value = digit;
rs("stevilo" ).Value = fields[8];
rs("zrcali" ).Value = mirror ? 1 : 0;
rs("znak_v" ).Value = fields[12];
rs("znakZRCOLA_v" ).Value = String.fromCharCode(parseInt(fields[12], 16));
rs("znak_m" ).Value = fields[13];
rs("znakZRCOLA_m" ).Value = String.fromCharCode(parseInt(fields[13], 16));
rs("znak_tc" ).Value = fields[14];
rs("znakZRCOLA_tc").Value = String.fromCharCode(parseInt(fields[14], 16));
rs.Update();
} else {
var updated = false;
if (force || (v = rs("opis_en").Value) == null || v == "") { rs("opis_en" ).Value = desc_en; updated = true; }
if (force || (v = rs("kat" ).Value) == null || v == "") { rs("kat" ).Value = fields[2]; updated = true; }
if (force || (v = rs("komb" ).Value) == null ) { rs("komb" ).Value = parseInt(fields[3], 10); updated = true; }
if (force ) { rs("stevka10").Value = dig_dec; updated = true; }
if (force ) { rs("stevka" ).Value = digit; updated = true; }
if (force ) { rs("stevilo" ).Value = fields[8]; updated = true; }
if (force ) { rs("zrcali" ).Value = mirror ? 1 : 0; updated = true; }
if (force ) { rs("znak_v" ).Value = fields[12]; rs("znakZRCOLA_v" ).Value = String.fromCharCode(parseInt(fields[12], 16)); updated = true; }
if (force ) { rs("znak_m" ).Value = fields[13]; rs("znakZRCOLA_m" ).Value = String.fromCharCode(parseInt(fields[13], 16)); updated = true; }
if (force ) { rs("znak_tc" ).Value = fields[14]; rs("znakZRCOLA_tc").Value = String.fromCharCode(parseInt(fields[14], 16)); updated = true; }
if (updated) {
// Changing [updat] field causes Microsoft Cursor Engine: Row cannot be located for updating. Some values may have been changed since it was last read.
//rs("updat").Value = (new Date(now.getTime() + now.getTimezoneOffset()*60*1000)).getVarDate();
rs.Update();
}
}
} finally {
rs.Close();
}
}
db.CommitTrans();
} catch (err) {
db.RollbackTrans();
throw err;
}
} finally {
f.Close();
}
} finally {
db.Close();
}
WScript.Quit(0);
]]></script>
</job>
<job id="CharDescGenerate">
<runtime>
<description>Dynamic Character Description Generator - Amebis, Copyright © 2016</description>
<unnamed name="&lt;ZRCola.mdb&gt;" required="true" helpstring="ZRCola database"/>
<named name="F" type="simple" required="false" helpstring="Force overwrite of existing data"/>
</runtime>
<reference object="ADODB.Connection"/>
<reference object="ADODB.Command"/>
<reference object="ADODB.Recordset"/>
<script language="JScript"><![CDATA[
if (WScript.Arguments.Unnamed.Length < 1) {
WScript.Arguments.ShowUsage();
WScript.Quit(1);
}
function ZRColaDecompositionParser(db)
{
// Prepare query for existing character description search.
this.com_desc = WScript.CreateObject("ADODB.Command");
this.com_desc.Prepared = true;
this.com_desc.ActiveConnection = db;
this.com_desc.CommandType = adCmdText;
this.com_desc.CommandText = "SELECT TOP 1 [opis_en] FROM [VRS_CharList] WHERE [znak]=?";
this.com_desc.Parameters.Append(this.param_desc_znak = this.com_desc.CreateParameter("znak", adChar, adParamInput, 4));
this.rs_desc = WScript.CreateObject("ADODB.Recordset");
this.rs_desc.CursorLocation = adUseClient;
this.rs_desc.CursorType = adOpenStatic;
this.rs_desc.LockType = adLockReadOnly;
}
ZRColaDecompositionParser.prototype.nextChar = function()
{
if (!this.decomposed.length) {
this.sym = null;
this.desc = null;
return;
}
// Get next character.
this.sym = this.decomposed.shift();
// Get character's description.
this.param_desc_znak.Value = this.sym;
this.rs_desc.Open(this.com_desc);
try {
if (!this.rs_desc.EOF) {
var v;
if ((v = this.rs_desc("opis_en").Value) != null && v != "")
this.desc = v;
else
throw new Error(this.sym + " character has no description.");
} else
throw new Error(this.sym + " character not found.");
} finally {
this.rs_desc.Close();
}
}
ZRColaDecompositionParser.prototype.modifiers = function()
{
var desc = "";
for (;;) {
if (
this.sym >= "E000" && this.sym <= "E05B" || // 1st Set of Modifiers
this.sym >= "E063" && this.sym <= "E0BB" || // 2nd Set of Modifiers
this.sym == "003A" || // Colon
this.sym == "2019") // Right Single Quotation Mark
{
desc += (desc.length ? " AND " : "") + this.desc;
this.nextChar();
} else if (this.sym >= "02B0" && this.sym <= "02FF") {
// Standard Unicode Modifiers
if (this.desc.indexOf("MODIFIER LETTER ") == 0)
this.desc = this.desc.substring(16);
desc += (desc.length ? " AND " : "") + this.desc;
this.nextChar();
} else
break;
}
return desc.length ? desc : null;
}
ZRColaDecompositionParser.prototype.envelopes = function()
{
var desc = "";
for (;;) {
if (
this.sym == "E0C0" || // Circle
this.sym == "E0C2" || // Square
this.sym == "E0CA") // Diamond
{
desc += (desc.length ? " AND " : "") + this.desc;
this.nextChar();
} else
break;
}
return desc.length ? desc : null;
}
ZRColaDecompositionParser.prototype.parentheses = function(open, close, desc)
{
if (this.sym == open) {
// Parenthesis Start
this.nextChar();
var desc_p = desc + " " + this.expression();
if (this.sym == close) {
// Parenthesis End
this.nextChar();
} else
throw new Error(this.sym + " is unexpected. Should end with " + close + ".");
return desc_p;
} else
return null;
}
ZRColaDecompositionParser.prototype.character = function()
{
var desc;
if (desc = this.parentheses("E0C5", "E0C6", "SUPERSCRIPTED")) {
// Superscript
return desc;
} else if (desc = this.parentheses("E2E0", "E2E1", "EVA DOUBLED")) {
// EVA Double
return desc;
} else if (desc = this.parentheses("E2E2", "E2E3", "EVA CONDENSED")) {
// EVA Condensed
return desc;
} else if (desc = this.parentheses("E2E4", "E2E5", "EVA EMPHASIZED")) {
// EVA Emphasis
return desc;
} else if (desc = this.parentheses("E2E6", "E2E7", "EVA STRIKED")) {
// EVA Strike
return desc;
} else if (desc = this.parentheses("E2E8", "E2E9", "EVA UNDEALED")) {
// EVA Undeal
return desc;
} else if (desc = this.parentheses("E2EA", "E2EB", "EVA ITALIC")) {
// EVA Italic
return desc;
} else if (desc = this.parentheses("E2EC", "E2ED", "EVA SUPERSCRIPTED")) {
// EVA Superscript
return desc;
} else if (desc = this.parentheses("E2EE", "E2EF", "EVA SUBSCRIPTED")) {
// EVA Subscript
return desc;
} else if (this.sym < "E000" || this.sym > "E0FC") {
// Base Character
desc = this.desc;
this.nextChar();
var has_with = desc.indexOf(" WITH ") >= 0;
for (;;) {
var desc2;
if (desc2 = this.modifiers()) {
desc += (has_with ? " AND " : " WITH ") + desc2;
has_with = true;
} else if (desc2 = this.envelopes()) {
desc += " IN " + desc2;
has_with = false;
} else
break;
}
return desc;
} else
throw new Error("Syntax error");
}
ZRColaDecompositionParser.prototype.term = function()
{
var desc = new Array(this.character());
while (this.sym == "E0C4") {
// Ligature
this.nextChar();
desc.push(this.character());
}
if (desc.length == 1) {
return desc[0];
} else if (desc.length == 2) {
if (desc[0] == desc[1])
return "DOUBLE " + desc[0];
} else if (desc.length == 3) {
if (desc[0] == desc[1] && desc[0] == desc[2])
return "TRIPLE " + desc[0];
}
return desc.join(" AND ") + " LIGATURE";
}
ZRColaDecompositionParser.prototype.expression = function()
{
var desc = "";
if (this.sym >= "E0F0" && this.sym <= "E0FC") {
// Prefix modifier
desc += this.desc + " ";
this.nextChar();
}
desc += this.term();
while (
this.sym >= "E05C" && this.sym <= "E062" ||
this.sym == "E0C1" || this.sym == "E0C3" || this.sym == "E0C7" || this.sym == "E0CB" || this.sym == "E0D0" || this.sym == "E0D1")
{
// Joiner
desc += " " + this.desc + " WITH ";
this.nextChar();
var desc2 = "";
for (;;) {
var desc3;
if (desc3 = this.modifiers())
desc2 += (desc2.length ? " AND " : " WITH ") + desc3;
else if (desc3 = this.envelopes())
desc2 += " IN " + desc3;
else
break;
}
desc += this.term();
desc += desc2;
}
return desc;
}
ZRColaDecompositionParser.prototype.parse = function(decomposed)
{
this.decomposed = decomposed.slice(0); // Duplicate array.
this.nextChar();
var desc = this.expression();
if (this.sym != null)
throw new Error("Unexpected trailing characters.");
return desc;
}
var force = WScript.Arguments.Named.Exists("F") ? true : false;
// Open ZRCola database.
var db = WScript.CreateObject("ADODB.Connection");
db.Open("Driver={Microsoft Access Driver (*.mdb)};Dbq=" + WScript.Arguments.Unnamed(0) + ";Uid=;Pwd=;");
try {
// Prepare query for character decomposition.
var com_comp = WScript.CreateObject("ADODB.Command"), param_comp_znak;
com_comp.Prepared = true;
com_comp.ActiveConnection = db;
com_comp.CommandType = adCmdText;
com_comp.CommandText = "SELECT UCase([komb]) AS [kombUC] FROM [VRS_ReplChar] WHERE [znak]=? ORDER BY [rang_znak] ASC";
com_comp.Parameters.Append(param_comp_znak = com_comp.CreateParameter("znak", adChar, adParamInput, 4));
db.BeginTrans();
try {
// Query all private-use characters.
var rs = WScript.CreateObject("ADODB.Recordset");
rs.CursorLocation = adUseClient;
rs.Open("SELECT * FROM [VRS_CharList] WHERE 'E000'<=[znak] AND [znak]<='F8FF' AND [kat] IS NULL", db, adOpenDynamic, adLockOptimistic, adCmdText);
try {
var rs_comp = WScript.CreateObject("ADODB.Recordset");
rs_comp.CursorLocation = adUseClient;
rs_comp.CursorType = adOpenStatic;
rs_comp.LockType = adLockReadOnly;
var parser = new ZRColaDecompositionParser(db);
for (; !rs.EOF; rs.MoveNext()) {
var v;
if (!force && (v = rs("opis_en").Value) != null && v != "") {
// This character already has the description.
continue;
}
// Decompose character.
var chr = rs("znak").Value;
param_comp_znak.Value = chr;
rs_comp.Open(com_comp);
try {
for (; !rs_comp.EOF; rs_comp.MoveNext()) {
var
decomposed = (v = rs_comp("kombUC").Value) != null ? (new String(v)).split("+") : new Array(),
n = decomposed.length;
if (n > 0) {
try {
var desc = parser.parse(decomposed);
rs("opis_en").value = desc;
rs.update();
break;
} catch (err) {
// We couldn't generate character description according to decomposition.
WScript.Echo(chr + " >> " + decomposed.join("+") + ": " + err.message);
}
};
}
} finally {
rs_comp.Close();
}
}
} finally {
rs.Close();
}
db.CommitTrans();
} catch (err) {
db.RollbackTrans();
throw err;
}
} finally {
db.Close();
}
WScript.Quit(0);
]]></script>
</job>
<signature>
** SIG ** MIIXmAYJKoZIhvcNAQcCoIIXiTCCF4UCAQExCzAJBgUr
** SIG ** DgMCGgUAMGcGCisGAQQBgjcCAQSgWTBXMDIGCisGAQQB
** SIG ** gjcCAR4wJAIBAQQQcAVhGs441BGiowAQS9NQkAIBAAIB
** SIG ** AAIBAAIBAAIBADAhMAkGBSsOAwIaBQAEFPhq7XksMSKn
** SIG ** 4Rdbedv+eKDdjJ50oIISyDCCA+4wggNXoAMCAQICEH6T
** SIG ** 6/t8xk5Z6kuad9QG/DswDQYJKoZIhvcNAQEFBQAwgYsx
** SIG ** CzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENh
** SIG ** cGUxFDASBgNVBAcTC0R1cmJhbnZpbGxlMQ8wDQYDVQQK
** SIG ** EwZUaGF3dGUxHTAbBgNVBAsTFFRoYXd0ZSBDZXJ0aWZp
** SIG ** Y2F0aW9uMR8wHQYDVQQDExZUaGF3dGUgVGltZXN0YW1w
** SIG ** aW5nIENBMB4XDTEyMTIyMTAwMDAwMFoXDTIwMTIzMDIz
** SIG ** NTk1OVowXjELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5
** SIG ** bWFudGVjIENvcnBvcmF0aW9uMTAwLgYDVQQDEydTeW1h
** SIG ** bnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIENBIC0g
** SIG ** RzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
** SIG ** AQCxrLNJVEuXHBIK2CV5kSJXKm/cuCbEQ3Nrwr8uUFr7
** SIG ** FMJ2jkMBJUO0oeJF9Oi3e8N0zCLXtJQAAvdN7b+0t0Qk
** SIG ** a81fRTvRRM5DEnMXgotptCvLmR6schsmTXEfsTHd+1Fh
** SIG ** AlOmqvVJLAV4RaUvic7nmef+jOJXPz3GktxK+Hsz5HkK
** SIG ** +/B1iEGc/8UDUZmq12yfk2mHZSmDhcJgFMTIyTsU2sCB
** SIG ** 8B8NdN6SIqvK9/t0fCfm90obf6fDni2uiuqm5qonFn1h
** SIG ** 95hxEbziUKFL5V365Q6nLJ+qZSDT2JboyHylTkhE/xni
** SIG ** RAeSC9dohIBdanhkRc1gRn5UwRN8xXnxycFxAgMBAAGj
** SIG ** gfowgfcwHQYDVR0OBBYEFF+a9W5czMx0mtTdfe8/2+xM
** SIG ** gC7dMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcwAYYW
** SIG ** aHR0cDovL29jc3AudGhhd3RlLmNvbTASBgNVHRMBAf8E
** SIG ** CDAGAQH/AgEAMD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6
** SIG ** Ly9jcmwudGhhd3RlLmNvbS9UaGF3dGVUaW1lc3RhbXBp
** SIG ** bmdDQS5jcmwwEwYDVR0lBAwwCgYIKwYBBQUHAwgwDgYD
** SIG ** VR0PAQH/BAQDAgEGMCgGA1UdEQQhMB+kHTAbMRkwFwYD
** SIG ** VQQDExBUaW1lU3RhbXAtMjA0OC0xMA0GCSqGSIb3DQEB
** SIG ** BQUAA4GBAAMJm495739ZMKrvaLX64wkdu0+CBl03X6ZS
** SIG ** nxaN6hySCURu9W3rWHww6PlpjSNzCxJvR6muORH4KrGb
** SIG ** sBrDjutZlgCtzgxNstAxpghcKnr84nodV0yoZRjpeUBi
** SIG ** JZZux8c3aoMhCI5B6t3ZVz8dd0mHKhYGXqY4aiISo1EZ
** SIG ** g362MIIEozCCA4ugAwIBAgIQDs/0OMj+vzVuBNhqmBsa
** SIG ** UDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEd
** SIG ** MBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAu
** SIG ** BgNVBAMTJ1N5bWFudGVjIFRpbWUgU3RhbXBpbmcgU2Vy
** SIG ** dmljZXMgQ0EgLSBHMjAeFw0xMjEwMTgwMDAwMDBaFw0y
** SIG ** MDEyMjkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMR0wGwYD
** SIG ** VQQKExRTeW1hbnRlYyBDb3Jwb3JhdGlvbjE0MDIGA1UE
** SIG ** AxMrU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNl
** SIG ** cyBTaWduZXIgLSBHNDCCASIwDQYJKoZIhvcNAQEBBQAD
** SIG ** ggEPADCCAQoCggEBAKJjCzlEuLsjp0RJuw7/ofBhClOT
** SIG ** sJjbrSwPSsVu/4Y8U1UPFc4EPyv9qZaW2b5heQtbyUyG
** SIG ** duXgQ0sile7CK0PBn9hotI5AT+6FOLkRxSPyZFjwFTJv
** SIG ** TlehroikAtcqHs1L4d1j1ReJMluwXplaqJ0oUA4X7pbb
** SIG ** YTtFUR3PElYLkkf8q672Zj1HrHBy55LnX80QucSDZJQZ
** SIG ** vSWA4ejSIqXQugJ6oXeTW2XD7hd0vEGGKtwITIySjJEt
** SIG ** nndEH2jWqHR32w5bMotWizO92WPISZ06xcXqMwvS8aMb
** SIG ** 9Iu+2bNXizveBKd6IrIkri7HcMW+ToMmCPsLvalPmQjh
** SIG ** EChyqs0CAwEAAaOCAVcwggFTMAwGA1UdEwEB/wQCMAAw
** SIG ** FgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/
** SIG ** BAQDAgeAMHMGCCsGAQUFBwEBBGcwZTAqBggrBgEFBQcw
** SIG ** AYYeaHR0cDovL3RzLW9jc3Aud3Muc3ltYW50ZWMuY29t
** SIG ** MDcGCCsGAQUFBzAChitodHRwOi8vdHMtYWlhLndzLnN5
** SIG ** bWFudGVjLmNvbS90c3MtY2EtZzIuY2VyMDwGA1UdHwQ1
** SIG ** MDMwMaAvoC2GK2h0dHA6Ly90cy1jcmwud3Muc3ltYW50
** SIG ** ZWMuY29tL3Rzcy1jYS1nMi5jcmwwKAYDVR0RBCEwH6Qd
** SIG ** MBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0yMDQ4LTIwHQYD
** SIG ** VR0OBBYEFEbGaaMOShQe1UzaUmMXP142vA3mMB8GA1Ud
** SIG ** IwQYMBaAFF+a9W5czMx0mtTdfe8/2+xMgC7dMA0GCSqG
** SIG ** SIb3DQEBBQUAA4IBAQB4O7SRKgBM8I9iMDd4o4QnB28Y
** SIG ** st4l3KDUlAOqhk4ln5pAAxzdzuN5yyFoBtq2MrRtv/Qs
** SIG ** JmMz5ElkbQ3mw2cO9wWkNWx8iRbG6bLfsundIMZxD82V
** SIG ** dNy2XN69Nx9DeOZ4tc0oBCCjqvFLxIgpkQ6A0RH83Vx2
** SIG ** bk9eDkVGQW4NsOo4mrE62glxEPwcebSAe6xp9P2ctgwW
** SIG ** K/F/Wwk9m1viFsoTgW0ALjgNqCmPLOGy9FqpAa8VnCwv
** SIG ** SRvbIrvD/niUUcOGsYKIXfA9tFGheTMrLnu53CAJE3Hr
** SIG ** ahlbz+ilMFcsiUk/uc9/yb8+ImhjU5q9aXSsxR08f5Lg
** SIG ** w7wc2AR1MIIEzjCCA7agAwIBAgIQMHo2eqo+aIGm+U8I
** SIG ** yzs5ZDANBgkqhkiG9w0BAQsFADB/MQswCQYDVQQGEwJV
** SIG ** UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24x
** SIG ** HzAdBgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsx
** SIG ** MDAuBgNVBAMTJ1N5bWFudGVjIENsYXNzIDMgU0hBMjU2
** SIG ** IENvZGUgU2lnbmluZyBDQTAeFw0xNTEwMDkwMDAwMDBa
** SIG ** Fw0xODExMDcyMzU5NTlaMGExCzAJBgNVBAYTAlNJMREw
** SIG ** DwYDVQQIEwhTbG92ZW5pYTEPMA0GA1UEBxMGS2Ftbmlr
** SIG ** MRYwFAYDVQQKFA1BbWViaXMgZC5vLm8uMRYwFAYDVQQD
** SIG ** FA1BbWViaXMgZC5vLm8uMIIBIjANBgkqhkiG9w0BAQEF
** SIG ** AAOCAQ8AMIIBCgKCAQEAl/LoF3DHaSrIaG1pgBmBwDyl
** SIG ** Yt7sRvIuoEdGr/yMhV9RfUIft+xsTPVQOAirvgG+KUbc
** SIG ** E3KMnGH+VuK7Y+vYzRp3dYTLinSQz1NKYAELyTdVzmmY
** SIG ** mU3LX764yk3ABtSZsZwPoiCy+TXE9ZsCkugB2c7Qp9N/
** SIG ** O9EjjQDRwZlUa3nLoY96Y3qNPwkCn04ppYiqPeIXTRz8
** SIG ** XBLs4Nl/bD9wymEuNSV75vzobJ7BUYQwRU7lmNL2SwRY
** SIG ** ENaf0DpdiyFLBsNafHjGYiXQHgNxZUBpj7OoRDNBvMQY
** SIG ** L+LM8OrjhGIK1uGL5CqBD/p81ebeFsAZVxg9hrgnkPVQ
** SIG ** w77U0LZw8wIDAQABo4IBYjCCAV4wCQYDVR0TBAIwADAO
** SIG ** BgNVHQ8BAf8EBAMCB4AwKwYDVR0fBCQwIjAgoB6gHIYa
** SIG ** aHR0cDovL3N2LnN5bWNiLmNvbS9zdi5jcmwwZgYDVR0g
** SIG ** BF8wXTBbBgtghkgBhvhFAQcXAzBMMCMGCCsGAQUFBwIB
** SIG ** FhdodHRwczovL2Quc3ltY2IuY29tL2NwczAlBggrBgEF
** SIG ** BQcCAjAZDBdodHRwczovL2Quc3ltY2IuY29tL3JwYTAT
** SIG ** BgNVHSUEDDAKBggrBgEFBQcDAzBXBggrBgEFBQcBAQRL
** SIG ** MEkwHwYIKwYBBQUHMAGGE2h0dHA6Ly9zdi5zeW1jZC5j
** SIG ** b20wJgYIKwYBBQUHMAKGGmh0dHA6Ly9zdi5zeW1jYi5j
** SIG ** b20vc3YuY3J0MB8GA1UdIwQYMBaAFJY7U/B5M5evfYPv
** SIG ** LivMyreGHnJmMB0GA1UdDgQWBBT3B72WgJotdMR/DD09
** SIG ** J93UkAqfzDANBgkqhkiG9w0BAQsFAAOCAQEAinEvQC+1
** SIG ** yttKEsqAjt2YufpYlul3OQH17YKbUy4AAiKiAsUXWfTu
** SIG ** XRVdkT6CrEYcHyOLaHfe36jVHw8vLIiR2cyEcB3vweyr
** SIG ** JnNpt+Za4I/XZMoG/vvCJmSltOj8C/7PRKWklGgynPNe
** SIG ** HI8+0d1vLzRtK77hFeV7CIMIfnpoYThJKTSLxdr0kn+j
** SIG ** M8otfdLN2aDonnxe0Mf+2rkrX8AFIIHPpIXZj2X2VEmk
** SIG ** ZdyFINgI+KlJVQY/RY9BFMM2htLAIkNcDP1QVzFajhGH
** SIG ** yj+C+UtZQf5PceGYtJHNeq3cm6omjnEfyzi8/NwYFlkW
** SIG ** hvzJEH3woPqKgUramNFFLD0W5zCCBVkwggRBoAMCAQIC
** SIG ** ED141/l2SWCyYX308B7KhiowDQYJKoZIhvcNAQELBQAw
** SIG ** gcoxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2ln
** SIG ** biwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3Qg
** SIG ** TmV0d29yazE6MDgGA1UECxMxKGMpIDIwMDYgVmVyaVNp
** SIG ** Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
** SIG ** eTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMyBQdWJs
** SIG ** aWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
** SIG ** eSAtIEc1MB4XDTEzMTIxMDAwMDAwMFoXDTIzMTIwOTIz
** SIG ** NTk1OVowfzELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5
** SIG ** bWFudGVjIENvcnBvcmF0aW9uMR8wHQYDVQQLExZTeW1h
** SIG ** bnRlYyBUcnVzdCBOZXR3b3JrMTAwLgYDVQQDEydTeW1h
** SIG ** bnRlYyBDbGFzcyAzIFNIQTI1NiBDb2RlIFNpZ25pbmcg
** SIG ** Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
** SIG ** AQCXgx4AFq8ssdIIxNdok1FgHnH24ke021hNI2JqtL9a
** SIG ** G1H3ow0Yd2i72DarLyFQ2p7z518nTgvCl8gJcJOp2lwN
** SIG ** TqQNkaC07BTOkXJULs6j20TpUhs/QTzKSuSqwOg5q1PM
** SIG ** IdDMz3+b5sLMWGqCFe49Ns8cxZcHJI7xe74xLT1u3LWZ
** SIG ** Qp9LYZVfHHDuF33bi+VhiXjHaBuvEXgamK7EVUdT2bMy
** SIG ** 1qEORkDFl5KK0VOnmVuFNVfT6pNiYSAKxzB3JBFNYoO2
** SIG ** untogjHuZcrf+dWNsjXcjCtvanJcYISc8gyUXsBWUgBI
** SIG ** zNP4pX3eL9cT5DiohNVGuBOGwhud6lo43ZvbAgMBAAGj
** SIG ** ggGDMIIBfzAvBggrBgEFBQcBAQQjMCEwHwYIKwYBBQUH
** SIG ** MAGGE2h0dHA6Ly9zMi5zeW1jYi5jb20wEgYDVR0TAQH/
** SIG ** BAgwBgEB/wIBADBsBgNVHSAEZTBjMGEGC2CGSAGG+EUB
** SIG ** BxcDMFIwJgYIKwYBBQUHAgEWGmh0dHA6Ly93d3cuc3lt
** SIG ** YXV0aC5jb20vY3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6
** SIG ** Ly93d3cuc3ltYXV0aC5jb20vcnBhMDAGA1UdHwQpMCcw
** SIG ** JaAjoCGGH2h0dHA6Ly9zMS5zeW1jYi5jb20vcGNhMy1n
** SIG ** NS5jcmwwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF
** SIG ** BwMDMA4GA1UdDwEB/wQEAwIBBjApBgNVHREEIjAgpB4w
** SIG ** HDEaMBgGA1UEAxMRU3ltYW50ZWNQS0ktMS01NjcwHQYD
** SIG ** VR0OBBYEFJY7U/B5M5evfYPvLivMyreGHnJmMB8GA1Ud
** SIG ** IwQYMBaAFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
** SIG ** SIb3DQEBCwUAA4IBAQAThRoeaak396C9pK9+HWFT/p2M
** SIG ** XgymdR54FyPd/ewaA1U5+3GVx2Vap44w0kRaYdtwb9oh
** SIG ** BcIuc7pJ8dGT/l3JzV4D4ImeP3Qe1/c4i6nWz7s1LzNY
** SIG ** qJJW0chNO4LmeYQW/CiwsUfzHaI+7ofZpn+kVqU/rYQu
** SIG ** Kd58vKiqoz0EAeq6k6IOUCIpF0yH5DoRX9akJYmbBWsv
** SIG ** tMkBTCd7C6wZBSKgYBU/2sn7TUyP+3Jnd/0nlMe6NQ6I
** SIG ** Sf6N/SivShK9DbOXBd5EDBX6NisD3MFQAfGhEV0U5eK9
** SIG ** J0tUviuEXg+mw3QFCu+Xw4kisR93873NQ9TxTKk/tYuE
** SIG ** r2Ty0BQhMYIEPDCCBDgCAQEwgZMwfzELMAkGA1UEBhMC
** SIG ** VVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9u
** SIG ** MR8wHQYDVQQLExZTeW1hbnRlYyBUcnVzdCBOZXR3b3Jr
** SIG ** MTAwLgYDVQQDEydTeW1hbnRlYyBDbGFzcyAzIFNIQTI1
** SIG ** NiBDb2RlIFNpZ25pbmcgQ0ECEDB6NnqqPmiBpvlPCMs7
** SIG ** OWQwCQYFKw4DAhoFAKBwMBAGCisGAQQBgjcCAQwxAjAA
** SIG ** MBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG
** SIG ** AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMGCSqGSIb3
** SIG ** DQEJBDEWBBTtnq9nJTyuGwPUm/NL7IROjIWVujANBgkq
** SIG ** hkiG9w0BAQEFAASCAQBFZwe6d/h0FY6FPwyAJvEIjoFa
** SIG ** QzBNIjLHoMLr+qLIqOvAOj07kwp4+eb19gKa4V3ePaH+
** SIG ** g8ZXDLRIMWZEtpEuqKYxW5RnOd/iHg4h+PfVhtU4cixr
** SIG ** NK731fhhcYeDWrzPiAKVWqkdHcHFMSRdFNXrGtbpKWMR
** SIG ** 38T9CeAoC7whXK/N61WhBZOs2WqBn2e2bxsCMLPJzpez
** SIG ** 57mYjk8Zlk1d8DkaxiamkmDkpnzL+eFuKiEZSuvgZ7il
** SIG ** UDmtbdOvpUHTQqdZpNksZSUTGX87TvqGh7wxV5xPV0Bj
** SIG ** kRHYIbDoncD99xleC4H7En7aAS1CPOwsGi6ydHjYr6Mk
** SIG ** XKIxeI6ioYICCzCCAgcGCSqGSIb3DQEJBjGCAfgwggH0
** SIG ** AgEBMHIwXjELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5
** SIG ** bWFudGVjIENvcnBvcmF0aW9uMTAwLgYDVQQDEydTeW1h
** SIG ** bnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIENBIC0g
** SIG ** RzICEA7P9DjI/r81bgTYapgbGlAwCQYFKw4DAhoFAKBd
** SIG ** MBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZI
** SIG ** hvcNAQkFMQ8XDTE2MDQyNjEzMjQ1MlowIwYJKoZIhvcN
** SIG ** AQkEMRYEFOCXzSMTEghkr0AunGczGHuQzCc+MA0GCSqG
** SIG ** SIb3DQEBAQUABIIBAJHp1Wtc6YKicRqFnBN/mw7NsTNB
** SIG ** fYvf1CYHBhl6JX6aRlvehLeXJO4rF46tXV0lSAVONEMs
** SIG ** Cjxc8j2AqEPlHbmL+uiZEwuHquZv+nS1yM1ulNDEiwou
** SIG ** FxUtdRSg3y1KuQ1aTKUhHQ//mxiLhIGzvw8lZcJDqayo
** SIG ** a/0AEkgc8LPbFs5wp+jrNEAxDvTU38ERPjSm6LeCrCeR
** SIG ** pLRkbCAyayCyE+S0Y8dP2Yv1TS0dbPeL5pnBEsr/ym7F
** SIG ** 5DP1tBIm2Rbjl0pxGwTq502wqKGGdJakoxu4wr5xuUXk
** SIG ** BCZCD4OPmggdTYANy+fdmDfv/d0VxgOBmXJKE4nHBGtz
** SIG ** KWx/g/Q=
</signature>
</package>

View File

@@ -23,7 +23,7 @@
// Product version as a single DWORD
// Note: Used for version comparison within C/C++ code.
//
#define ZRCOLA_VERSION 0x01ff0100
#define ZRCOLA_VERSION 0x01ff0600
//
// Product version by components
@@ -33,26 +33,26 @@
//
#define ZRCOLA_VERSION_MAJ 1
#define ZRCOLA_VERSION_MIN 255
#define ZRCOLA_VERSION_REV 1
#define ZRCOLA_VERSION_REV 6
#define ZRCOLA_VERSION_BUILD 0
//
// Human readable product version and build year for UI
//
#define ZRCOLA_VERSION_STR "2.0-alpha1"
#define ZRCOLA_VERSION_STR "2.0-alpha6"
#define ZRCOLA_BUILD_YEAR_STR "2016"
//
// Numerical version presentation for ProductVersion propery in
// MSI packages (syntax: N.N[.N[.N]])
//
#define ZRCOLA_VERSION_INST "1.255.1"
#define ZRCOLA_VERSION_INST "1.255.6"
//
// The product code for ProductCode property in MSI packages
// Replace with new on every version change, regardless how minor it is.
//
#define ZRCOLA_VERSION_GUID "{3A1032A5-E9D0-4603-94A7-C7D31AB4CB89}"
#define ZRCOLA_VERSION_GUID "{D1BCE36B-C032-476A-8129-5F284C1CB405}"
//
// The product vendor and application name for configuration keeping.

View File

@@ -19,6 +19,7 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\language.cpp" />
<ClCompile Include="..\src\mapping.cpp" />
<ClCompile Include="..\src\normalize.cpp" />
<ClCompile Include="..\src\stdafx.cpp">
@@ -31,6 +32,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\zrcola\common.h" />
<ClInclude Include="..\include\zrcola\language.h" />
<ClInclude Include="..\include\zrcola\normalize.h" />
<ClInclude Include="..\include\zrcola\translate.h" />
<ClInclude Include="..\src\stdafx.h" />

View File

@@ -27,6 +27,9 @@
<ClCompile Include="..\src\translate.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\language.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\src\stdafx.h">
@@ -41,6 +44,9 @@
<ClInclude Include="..\include\zrcola\translate.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\zrcola\language.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\res\libZRCola.rc">

View File

@@ -20,6 +20,9 @@
#pragma once
#include <vector>
#ifdef _WIN32
#include <Windows.h>
#endif
///
@@ -44,7 +47,12 @@
///
/// Database IDs
///
#define ZRCOLA_DB_ID (*(ZRCola::recordid_t*)"ZRC")
#define ZRCOLA_DB_ID (*(ZRCola::recordid_t*)"ZRC")
///
/// Unknown language ID
///
#define ZRCOLA_LANG_VOID " "
namespace ZRCola {
@@ -52,6 +60,24 @@ namespace ZRCola {
typedef unsigned __int32 recordsize_t;
///
/// Language ID type
/// Three letter abbreviation, zero terminated
///
typedef char langid_t[4];
#ifdef _WIN32
///
/// Converts language from Windows to ZRCola notation.
///
/// \param[in] lang_win Windows language ID
/// \param[in,out] lang ZRCola language ID
///
void ZRCOLA_API LangConvert(_In_ LANGID lang_win, _Inout_ langid_t &lang);
#endif
///
/// Memory index
///
@@ -168,8 +194,8 @@ namespace ZRCola {
/// \param[out] end Index of the first non-matching element found
///
/// \returns
/// - true if found
/// - false otherwise
/// - \c true if found
/// - \c false otherwise
///
bool find(_In_ const T_data &el, _Out_ size_type &start, _Out_ size_type &end) const
{
@@ -211,15 +237,20 @@ namespace ZRCola {
///
/// Composed-decomposed index transformation mapping
/// Source-destination index transformation mapping
///
class ZRCOLA_NOVTABLE ZRCOLA_API mapping {
public:
size_t cmp; ///< Character index in composed string
size_t decmp; ///< Character index in decomposed string
size_t src; ///< Character index in source string
size_t dst; ///< Character index in destination string
inline mapping() {};
inline mapping(_In_ size_t c, _In_ size_t d) : cmp(c), decmp(d) {}
inline mapping(_In_ size_t s, _In_ size_t d) : src(s), dst(d) {}
///
/// Reverses source and destination indexes
///
inline void invert() { size_t tmp = src; src = dst; dst = tmp; }
};
@@ -229,22 +260,31 @@ namespace ZRCola {
class ZRCOLA_API mapping_vector : public std::vector<mapping> {
public:
///
/// Transforms character index of decomposed to composed string
/// Transforms character index of destination to source
///
/// \param[in] decmp Character index in decomposed string
/// \param[in] decmp Character index in destination string
///
/// \returns Character index in composed string
/// \returns Character index in source string
///
size_t to_composed(_In_ size_t decmp) const;
size_t to_src(_In_ size_t dst) const;
///
/// Transforms destination index to source index
/// Transforms source index to destination index
///
/// \param[in] cmp Character index in composed string
/// \param[in] cmp Character index in source string
///
/// \returns Character index in decomposed string
/// \returns Character index in destination string
///
size_t to_decomposed(_In_ size_t cmp) const;
size_t to_dst(_In_ size_t src) const;
///
/// Reverses source and destination indexes
///
inline void invert()
{
for (iterator i = begin(), iEnd = end(); i != iEnd; ++i)
i->invert();
}
};
};

View File

@@ -0,0 +1,354 @@
/*
Copyright 2015-2016 Amebis
This file is part of ZRCola.
ZRCola is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ZRCola is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ZRCola. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common.h"
#include <stdex/idrec.h>
#include <istream>
#include <vector>
#include <string>
#pragma warning(push)
#pragma warning(disable: 4200)
#pragma warning(disable: 4251)
#pragma warning(disable: 4512)
namespace ZRCola {
///
/// Language Character Database
///
class ZRCOLA_API langchar_db {
public:
#pragma pack(push)
#pragma pack(2)
///
/// Character data
///
struct langchar {
wchar_t chr; ///> Character
langid_t lang; ///< Language ID
};
#pragma pack(pop)
///
/// Character index
///
class indexChar : public index<unsigned __int16, unsigned __int32, langchar>
{
public:
///
/// Constructs the index
///
/// \param[in] h Reference to vector holding the data
///
indexChar(_In_ std::vector<unsigned __int16> &h) : index<unsigned __int16, unsigned __int32, langchar>(h) {}
///
/// Compares two characters by ID (for searching)
///
/// \param[in] a Pointer to first element
/// \param[in] b Pointer to second element
///
/// \returns
/// - <0 when a < b
/// - =0 when a == b
/// - >0 when a > b
///
virtual int compare(_In_ const langchar &a, _In_ const langchar &b) const
{
if (a.chr < b.chr) return -1;
else if (a.chr > b.chr) return 1;
return 0;
}
///
/// Compares two characters by ID (for sorting)
///
/// \param[in] a Pointer to first element
/// \param[in] b Pointer to second element
///
/// \returns
/// - <0 when a < b
/// - =0 when a == b
/// - >0 when a > b
///
virtual int compare_sort(_In_ const langchar &a, _In_ const langchar &b) const
{
if (a.chr < b.chr) return -1;
else if (a.chr > b.chr) return 1;
int r = memcmp(a.lang, b.lang, sizeof(langid_t));
if (r != 0) return r;
return 0;
}
} idxChr; ///< Character index
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
///
/// Character Language Index
///
class indexCharLang : public index<unsigned __int16, unsigned __int32, langchar>
{
public:
///
/// Constructs the index
///
/// \param[in] h Reference to vector holding the data
///
indexCharLang(_In_ std::vector<unsigned __int16> &h) : index<unsigned __int16, unsigned __int32, langchar>(h) {}
///
/// Compares two languages by ID (for searching)
///
/// \param[in] a Pointer to first element
/// \param[in] b Pointer to second element
///
/// \returns
/// - <0 when a < b
/// - =0 when a == b
/// - >0 when a > b
///
virtual int compare(_In_ const langchar &a, _In_ const langchar &b) const
{
int r = memcmp(a.lang, b.lang, sizeof(langid_t));
if (r != 0) return r;
return 0;
}
///
/// Compares two languages by ID (for sorting)
///
/// \param[in] a Pointer to first element
/// \param[in] b Pointer to second element
///
/// \returns
/// - <0 when a < b
/// - =0 when a == b
/// - >0 when a > b
///
virtual int compare_sort(_In_ const langchar &a, _In_ const langchar &b) const
{
int r = memcmp(a.lang, b.lang, sizeof(langid_t));
if (r != 0) return r;
if (a.chr < b.chr) return -1;
else if (a.chr > b.chr) return 1;
return 0;
}
} idxLng; ///< Character language index
#endif
std::vector<unsigned __int16> data; ///< Character data
public:
///
/// Constructs the database
///
inline langchar_db() : idxChr(data)
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
, idxLng(data)
#endif
{}
///
/// Tests presence of character in the given language
///
/// \param[in] chr Character (UTF-16)
/// \param[in] lang Language
///
/// \returns
/// - \c true when character is used in language
/// - \c false otherwise
bool IsLocalCharacter(_In_ wchar_t chr, _In_ langid_t lang) const;
};
typedef ZRCOLA_API stdex::idrec::record<langchar_db, recordid_t, recordsize_t, ZRCOLA_RECORD_ALIGN> langchar_rec;
///
/// Language database
///
class ZRCOLA_API language_db {
public:
#pragma pack(push)
#pragma pack(2)
///
/// Language data
///
struct language {
langid_t id; ///< Language ID
unsigned __int16 name_len; ///< \c name length (in characters)
wchar_t name[]; ///< Language name
};
#pragma pack(pop)
///
/// Language index
///
class indexLang : public index<unsigned __int16, unsigned __int32, language>
{
public:
///
/// Constructs the index
///
/// \param[in] h Reference to vector holding the data
///
indexLang(_In_ std::vector<unsigned __int16> &h) : index<unsigned __int16, unsigned __int32, language>(h) {}
///
/// Compares two languages by ID (for searching)
///
/// \param[in] a Pointer to first element
/// \param[in] b Pointer to second element
///
/// \returns
/// - <0 when a < b
/// - =0 when a == b
/// - >0 when a > b
///
virtual int compare(_In_ const language &a, _In_ const language &b) const
{
int r = memcmp(a.id, b.id, sizeof(langid_t));
if (r != 0) return r;
return 0;
}
///
/// Compares two languages by ID (for sorting)
///
/// \param[in] a Pointer to first element
/// \param[in] b Pointer to second element
///
/// \returns
/// - <0 when a < b
/// - =0 when a == b
/// - >0 when a > b
///
virtual int compare_sort(_In_ const language &a, _In_ const language &b) const
{
int r = memcmp(a.id, b.id, sizeof(langid_t));
if (r != 0) return r;
// As the language ID must not duplicate, further comparison is pointless.
return 0;
}
} idxLng; ///< Language index
std::vector<unsigned __int16> data; ///< Language data
public:
///
/// Constructs the database
///
inline language_db() : idxLng(data) {}
};
typedef ZRCOLA_API stdex::idrec::record<language_db, recordid_t, recordsize_t, ZRCOLA_RECORD_ALIGN> language_rec;
};
const ZRCola::recordid_t stdex::idrec::record<ZRCola::langchar_db, ZRCola::recordid_t, ZRCola::recordsize_t, ZRCOLA_RECORD_ALIGN>::id = *(ZRCola::recordid_t*)"L-C";
const ZRCola::recordid_t stdex::idrec::record<ZRCola::language_db, ZRCola::recordid_t, ZRCola::recordsize_t, ZRCOLA_RECORD_ALIGN>::id = *(ZRCola::recordid_t*)"LNG";
///
/// Reads language character database from a stream
///
/// \param[in] stream Input stream
/// \param[out] db Language character database
///
/// \returns The stream \p stream
///
inline std::istream& operator >>(_In_ std::istream& stream, _Out_ ZRCola::langchar_db &db)
{
unsigned __int32 count;
// Read index count.
stream.read((char*)&count, sizeof(count));
if (!stream.good()) return stream;
// Read character index.
db.idxChr.resize(count);
stream.read((char*)db.idxChr.data(), sizeof(unsigned __int32)*count);
if (!stream.good()) return stream;
#ifdef ZRCOLA_LANGCHAR_LANG_IDX
// Read language index.
db.idxLng.resize(count);
stream.read((char*)db.idxLng.data(), sizeof(unsigned __int32)*count);
if (!stream.good()) return stream;
#endif
// Read data count.
stream.read((char*)&count, sizeof(count));
if (!stream.good()) return stream;
// Read data.
db.data.resize(count);
stream.read((char*)db.data.data(), sizeof(unsigned __int16)*count);
return stream;
}
///
/// Reads language database from a stream
///
/// \param[in] stream Input stream
/// \param[out] db Language database
///
/// \returns The stream \p stream
///
inline std::istream& operator >>(_In_ std::istream& stream, _Out_ ZRCola::language_db &db)
{
unsigned __int32 count;
// Read index count.
stream.read((char*)&count, sizeof(count));
if (!stream.good()) return stream;
// Read language index.
db.idxLng.resize(count);
stream.read((char*)db.idxLng.data(), sizeof(unsigned __int32)*count);
if (!stream.good()) return stream;
// Read data count.
stream.read((char*)&count, sizeof(count));
if (!stream.good()) return stream;
// Read data.
db.data.resize(count);
stream.read((char*)db.data.data(), sizeof(unsigned __int16)*count);
return stream;
}
#pragma warning(pop)

View File

@@ -20,6 +20,7 @@
#pragma once
#include "common.h"
#include "language.h"
#include <stdex/idrec.h>
#include <istream>
@@ -45,6 +46,7 @@ namespace ZRCola {
///
struct translation {
wchar_t chr; ///< Composed character
unsigned __int16 rank; ///< Decomposition rank
unsigned __int16 str_len; ///< \c str length (in characters)
wchar_t str[]; ///< Decomposed string
@@ -94,8 +96,8 @@ namespace ZRCola {
///
/// Compares two transformations by string (for searching)
///
/// \param[in] a Pointer to key sequence
/// \param[in] b Pointer to second key sequence
/// \param[in] a Pointer to first element
/// \param[in] b Pointer to second element
///
/// \returns
/// - <0 when a < b
@@ -150,8 +152,8 @@ namespace ZRCola {
///
/// Compares two transformations by character (for searching)
///
/// \param[in] a Pointer to key sequence
/// \param[in] b Pointer to second key sequence
/// \param[in] a Pointer to first element
/// \param[in] b Pointer to second element
///
/// \returns
/// - <0 when a < b
@@ -182,6 +184,9 @@ namespace ZRCola {
if (a.chr < b.chr) return -1;
else if (a.chr > b.chr) return +1;
if (a.rank < b.rank) return -1;
else if (a.rank > b.rank) return +1;
int r = translation::CompareString(a.str, a.str_len, b.str, b.str_len);
if (r != 0) return r;
@@ -216,7 +221,22 @@ namespace ZRCola {
/// \param[out] output Output string (UTF-16)
/// \param[out] map The vector of source to destination index mappings (optional)
///
void Decompose(_In_z_count_(inputMax) const wchar_t* input, _In_ size_t inputMax, _Out_ std::wstring &output, _Out_opt_ std::vector<mapping>* map = NULL) const;
inline void Decompose(_In_z_count_(inputMax) const wchar_t* input, _In_ size_t inputMax, _Out_ std::wstring &output, _Out_opt_ std::vector<mapping>* map = NULL) const
{
Decompose(input, inputMax, NULL, ZRCOLA_LANG_VOID, output, map);
}
///
/// Decomposes string according ommiting language specific characters
///
/// \param[in] input Input string (UTF-16)
/// \param[in] inputMax Length of the input string in characters. Can be (size_t)-1 if \p input is zero terminated.
/// \param[in] lc_db Language character database
/// \param[in] lang Language ID
/// \param[out] output Output string (UTF-16)
/// \param[out] map The vector of source to destination index mappings (optional)
///
void Decompose(_In_z_count_(inputMax) const wchar_t* input, _In_ size_t inputMax, _In_opt_ const langchar_db *lc_db, _In_opt_ langid_t lang, _Out_ std::wstring &output, _Out_opt_ std::vector<mapping>* map = NULL) const;
};

View File

@@ -0,0 +1,97 @@
/*
Copyright 2015-2016 Amebis
This file is part of ZRCola.
ZRCola is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ZRCola is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ZRCola. If not, see <http://www.gnu.org/licenses/>.
*/
#include "stdafx.h"
#ifdef _WIN32
void ZRCola::LangConvert(_In_ LANGID lang_win, _Inout_ ZRCola::langid_t &lang)
{
switch (PRIMARYLANGID(lang_win)) {
case LANG_BELARUSIAN : memcpy(lang, "bel", sizeof(lang)); break;
case LANG_CZECH : memcpy(lang, "cze", sizeof(lang)); break;
case LANG_DANISH : memcpy(lang, "dan", sizeof(lang)); break;
case LANG_GERMAN : memcpy(lang, "deu", sizeof(lang)); break;
case LANG_ENGLISH : memcpy(lang, "eng", sizeof(lang)); break;
case LANG_ESTONIAN : memcpy(lang, "est", sizeof(lang)); break;
case LANG_FRENCH : memcpy(lang, "fra", sizeof(lang)); break;
case LANG_IRISH : memcpy(lang, "gle", sizeof(lang)); break;
case LANG_HUNGARIAN : memcpy(lang, "hun", sizeof(lang)); break;
case LANG_LATVIAN : memcpy(lang, "lav", sizeof(lang)); break;
case LANG_LITHUANIAN : memcpy(lang, "lit", sizeof(lang)); break;
case LANG_MACEDONIAN : memcpy(lang, "mkd", sizeof(lang)); break;
case LANG_MALTESE : memcpy(lang, "mlt", sizeof(lang)); break;
case LANG_NORWEGIAN : memcpy(lang, "nor", sizeof(lang)); break;
case LANG_POLISH : memcpy(lang, "pol", sizeof(lang)); break;
case LANG_PORTUGUESE : memcpy(lang, "por", sizeof(lang)); break;
case LANG_ROMANIAN : memcpy(lang, "rum", sizeof(lang)); break;
case LANG_RUSSIAN : memcpy(lang, "rus", sizeof(lang)); break;
case LANG_SLOVAK : memcpy(lang, "slk", sizeof(lang)); break;
case LANG_SLOVENIAN : memcpy(lang, "slv", sizeof(lang)); break;
case LANG_SPANISH : memcpy(lang, "spa", sizeof(lang)); break;
case LANG_ALBANIAN : memcpy(lang, "sqi", sizeof(lang)); break;
case LANG_SWEDISH : memcpy(lang, "swe", sizeof(lang)); break;
case LANG_TURKISH : memcpy(lang, "tur", sizeof(lang)); break;
case LANG_UKRAINIAN : memcpy(lang, "ukr", sizeof(lang)); break;
case LANG_CROATIAN : // LANG_BOSNIAN, and LANG_SERBIAN
switch (SUBLANGID(lang_win)) {
case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN : memcpy(lang, "bos", sizeof(lang)); break;
case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC : memcpy(lang, "boz", sizeof(lang)); break;
case SUBLANG_CROATIAN_CROATIA :
case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN : memcpy(lang, "hrv", sizeof(lang)); break;
case SUBLANG_SERBIAN_LATIN :
case SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN :
case SUBLANG_SERBIAN_MONTENEGRO_LATIN :
case SUBLANG_SERBIAN_SERBIA_LATIN : memcpy(lang, "srp", sizeof(lang)); break;
case SUBLANG_SERBIAN_CYRILLIC :
case SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC :
case SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC :
case SUBLANG_SERBIAN_SERBIA_CYRILLIC : memcpy(lang, "srz", sizeof(lang)); break;
}
break;
}
}
#endif
bool ZRCola::langchar_db::IsLocalCharacter(_In_ wchar_t chr, _In_ ZRCola::langid_t lang) const
{
for (size_t l = 0, r = idxChr.size(); l < r; ) {
// Test the character in the middle of the search area.
size_t m = (l + r) / 2;
const langchar &lc = idxChr[m];
// Do the bisection test on character.
if (chr < lc.chr) r = m;
else if (lc.chr < chr ) l = m + 1;
else {
// Do the bisection test on language.
int res = memcmp(lang, lc.lang, sizeof(langid_t));
if (res < 0) r = m;
else if (res > 0) l = m + 1;
else {
// Match found.
return true;
}
}
}
return false;
}

View File

@@ -20,51 +20,63 @@
#include "stdafx.h"
size_t ZRCola::mapping_vector::to_composed(_In_ size_t decmp) const
size_t ZRCola::mapping_vector::to_src(_In_ size_t dst) const
{
if (empty()) {
// One-to-one mapping.
return dst;
}
for (size_type l = 0, r = size();;) {
if (l < r) {
size_type m = (l + r) / 2;
const mapping &el = (*this)[m];
if (decmp < el.decmp) r = m;
else if (el.decmp < decmp) l = m + 1;
if ( dst < el.dst) r = m;
else if (el.dst < dst) l = m + 1;
else {
// An exact match found.
return el.cmp;
return el.src;
}
} else if (l) {
// We found a map interval.
const mapping &el = (*this)[l - 1];
return el.cmp + (decmp - el.decmp);
return el.src + (dst - el.dst);
} else {
// The decomposed character index is far left.
return decmp;
// The destination character index is left of the first transformation.
const mapping &el = (*this)[0];
return std::min<size_t>(dst, el.src);
}
}
}
size_t ZRCola::mapping_vector::to_decomposed(_In_ size_t cmp) const
size_t ZRCola::mapping_vector::to_dst(_In_ size_t src) const
{
if (empty()) {
// One-to-one mapping.
return src;
}
for (size_type l = 0, r = size();;) {
if (l < r) {
size_type m = (l + r) / 2;
const mapping &el = (*this)[m];
if (cmp < el.cmp) r = m;
else if (el.cmp < cmp) l = m + 1;
if ( src < el.src) r = m;
else if (el.src < src) l = m + 1;
else {
// An exact match found.
return el.decmp;
return el.dst;
}
} else if (l) {
// We found a map interval.
const mapping &el = (*this)[l - 1];
return el.decmp + (cmp - el.cmp);
return el.dst + (src - el.src);
} else {
// The composed character index is far left.
return cmp;
// The source character index is left of the first transformation.
const mapping &el = (*this)[0];
return std::min<size_t>(src, el.dst);
}
}
}

View File

@@ -20,6 +20,6 @@
#include "stdafx.h"
void ZRCOLA_API ZRCola::Normalize(_In_z_count_(inputMax) const wchar_t* input, _In_ size_t inputMax, _Out_ std::wstring &output, _Out_opt_ std::vector<mapping>* map)
void ZRCola::Normalize(_In_z_count_(inputMax) const wchar_t* input, _In_ size_t inputMax, _Out_ std::wstring &output, _Out_opt_ std::vector<mapping>* map)
{
}

View File

@@ -20,7 +20,9 @@
#pragma once
#include "../../../include/zrcola.h"
#include "../include/zrcola/translate.h"
#include "../include/zrcola/language.h"
#include "../include/zrcola/normalize.h"
#include "../include/zrcola/translate.h"
#include <assert.h>

View File

@@ -37,90 +37,72 @@ void ZRCola::translation_db::Compose(_In_z_count_(inputMax) const wchar_t* input
indexComp::size_type compositionsCount = idxComp.size();
for (size_t i = 0; i < inputMax;) {
// Start with the full search area at i-th character.
for (size_t l = 0, r = compositionsCount, ii = i, j = 0;; ii++, j++) {
if (ii < inputMax) {
size_t l_prev = l;
wchar_t c = input[ii];
while (l < r) {
// Test the composition in the middle of the search area.
size_t m = (l + r) / 2;
// Find the longest matching composition at i-th character.
size_t l_match = (size_t)-1;
for (size_t l = 0, r = compositionsCount, ii = i, j = 0; ii < inputMax && l < r; ii++, j++) {
wchar_t c = input[ii];
while (l < r) {
// Test the composition in the middle of the search area.
size_t m = (l + r) / 2;
// Get the j-th character of the composition.
// All compositions that get short on characters are lexically ordered before.
// Thus the j-th character is considered 0.
const translation &trans = idxComp[m];
wchar_t s = j < trans.str_len ? trans.str[j] : 0;
// Get the j-th character of the composition.
// All compositions that get short on characters are lexically ordered before.
// Thus the j-th character is considered 0.
const translation &trans = idxComp[m];
wchar_t s = j < trans.str_len ? trans.str[j] : 0;
// Do the bisection test.
if (c < s) r = m;
else if (s < c) l = m + 1;
else {
// Character found.
// Do the bisection test.
if (c < s) r = m;
else if (s < c) l = m + 1;
else {
// Character found.
// Narrow the search area on the left to start at the first composition in the run.
for (size_t rr = m; l < rr;) {
size_t m = (l + rr) / 2;
const translation &trans = idxComp[m];
wchar_t s = j < trans.str_len ? trans.str[j] : 0;
if (c <= s) rr = m; else l = m + 1;
}
// Narrow the search area on the right to end at the first composition not in the run.
for (size_t ll = m + 1; ll < r;) {
size_t m = (ll + r) / 2;
const translation &trans = idxComp[m];
wchar_t s = j < trans.str_len ? trans.str[j] : 0;
if (s <= c) ll = m + 1; else r = m;
}
break;
// Narrow the search area on the left to start at the first composition in the run.
for (size_t rr = m; l < rr;) {
size_t m = (l + rr) / 2;
const translation &trans = idxComp[m];
wchar_t s = j < trans.str_len ? trans.str[j] : 0;
if (c <= s) rr = m; else l = m + 1;
}
}
if (l >= r) {
// The search area is empty.
const translation &trans = idxComp[l_prev];
if (j && l_prev < compositionsCount && j == trans.str_len) {
// The first composition of the previous run was a match.
output += trans.chr;
i = ii;
if (j > 1 && map) {
// Mapping changed.
map->push_back(ZRCola::mapping(output.length(), i));
}
} else {
// The exact match was not found.
output += input[i];
i++;
// Narrow the search area on the right to end at the first composition not in the run.
for (size_t ll = m + 1; ll < r;) {
size_t m = (ll + r) / 2;
const translation &trans = idxComp[m];
wchar_t s = j < trans.str_len ? trans.str[j] : 0;
if (s <= c) ll = m + 1; else r = m;
}
const translation &trans = idxComp[l];
if (j + 1 == trans.str_len) {
// The first composition of the run was a match (thus far). Save it.
l_match = l;
}
break;
}
} else {
// End of input reached.
const translation &trans = idxComp[l];
if (l < compositionsCount && j == trans.str_len) {
// The first composition of the previous run was a match.
output += trans.chr;
i = ii;
if (j > 1 && map) {
// Mapping changed.
map->push_back(ZRCola::mapping(output.length(), i));
}
} else {
output += input[i];
i++;
}
break;
}
}
if (l_match < compositionsCount) {
// The saved composition was an exact match.
const translation &trans = idxComp[l_match];
output += trans.chr;
i += trans.str_len;
if (trans.str_len > 1 && map) {
// Mapping changed.
map->push_back(ZRCola::mapping(i, output.length()));
}
} else {
// The match was not found.
output += input[i];
i++;
}
}
}
void ZRCOLA_API ZRCola::translation_db::Decompose(_In_z_count_(inputMax) const wchar_t* input, _In_ size_t inputMax, _Out_ std::wstring &output, _Out_opt_ std::vector<mapping>* map) const
void ZRCola::translation_db::Decompose(_In_z_count_(inputMax) const wchar_t* input, _In_ size_t inputMax, _In_ const langchar_db *lc_db, _In_ langid_t lang, _Out_ std::wstring &output, _Out_opt_ std::vector<mapping>* map) const
{
assert(input || inputMax == 0);
@@ -149,11 +131,28 @@ void ZRCOLA_API ZRCola::translation_db::Decompose(_In_z_count_(inputMax) const w
else if (decompSrc < c) l = m + 1;
else {
// Character found.
output.append(trans.str, trans.str_len);
i++;
if (map) {
// Mapping changed.
map->push_back(ZRCola::mapping(i, output.length()));
// Narrow the search area on the left to start at the first decomposition in the run (first by rank).
for (size_t rr = m; l < rr;) {
size_t m = (l + rr) / 2;
const translation &trans = idxDecomp[m];
wchar_t decompSrc = trans.chr;
if (c <= decompSrc) rr = m; else l = m + 1;
}
const translation &trans = idxDecomp[l];
if (trans.str_len && trans.str[0] != L'#' && (!lc_db || !lc_db->IsLocalCharacter(c, lang))) {
// Append decomposed sequence.
output.append(trans.str, trans.str_len);
i++;
if (map) {
// Mapping changed.
map->push_back(ZRCola::mapping(i, output.length()));
}
} else {
// Character is inhibited to decompose.
output += c;
i++;
}
break;
}

Binary file not shown.

View File

@@ -0,0 +1,116 @@
msgid ""
msgstr ""
"Project-Id-Version: ZRCola.zrcdb\n"
"Language: en\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: ZRColaCompile 2.0-alpha5\n"
msgid "Albanian"
msgstr ""
msgid "Belarusian"
msgstr ""
msgid "Bosnian Cyrillic"
msgstr ""
msgid "Bosnian Latinic"
msgstr ""
msgid "Croatian"
msgstr ""
msgid "Czech"
msgstr ""
msgid "Danish"
msgstr ""
msgid "English"
msgstr ""
msgid "Estonian"
msgstr ""
msgid "French"
msgstr ""
msgid "Friulian"
msgstr ""
msgid "German"
msgstr ""
msgid "Hungarian"
msgstr ""
msgid "Irish Gaelic"
msgstr ""
msgid "Kashubian"
msgstr ""
msgid "Latin"
msgstr ""
msgid "Latvian"
msgstr ""
msgid "Lithuanian"
msgstr ""
msgid "Macedonian"
msgstr ""
msgid "Maltese"
msgstr ""
msgid "Moldavian Cyrillic"
msgstr ""
msgid "Moldavian Latinic"
msgstr ""
msgid "Norwegian"
msgstr ""
msgid "Polish"
msgstr ""
msgid "Portuguese"
msgstr ""
msgid "Romanian"
msgstr ""
msgid "Russian"
msgstr ""
msgid "Serbian Cyrillic"
msgstr ""
msgid "Serbian Latinic"
msgstr ""
msgid "Slovak"
msgstr ""
msgid "Slovenian"
msgstr ""
msgid "Sorbian"
msgstr ""
msgid "Spanish"
msgstr ""
msgid "Swedish"
msgstr ""
msgid "Turkish"
msgstr ""
msgid "Ukrainian"
msgstr ""

Binary file not shown.

View File

@@ -0,0 +1,123 @@
msgid ""
msgstr ""
"Project-Id-Version: ZRCola.zrcdb\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
"Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n"
"Language-Team: Amebis, d. o. o., Kamnik <info@amebis.si>\n"
"Language: sl_SI\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.7\n"
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n"
"%100==4 ? 2 : 3);\n"
"X-Poedit-SourceCharset: UTF-8\n"
msgid "Albanian"
msgstr "albanščina"
msgid "Belarusian"
msgstr "beloruščina"
msgid "Bosnian Cyrillic"
msgstr "bosanščina cirilica"
msgid "Bosnian Latinic"
msgstr "bosanščina latinica"
msgid "Croatian"
msgstr "hrvaščina"
msgid "Czech"
msgstr "češčina"
msgid "Danish"
msgstr "danščina"
msgid "English"
msgstr "angleščina"
msgid "Estonian"
msgstr "estonščina"
msgid "French"
msgstr "francoščina"
msgid "Friulian"
msgstr "furlanščina"
msgid "German"
msgstr "nemščina"
msgid "Hungarian"
msgstr "madžarščina"
msgid "Irish Gaelic"
msgstr "irščina"
msgid "Kashubian"
msgstr "kašubščina"
msgid "Latin"
msgstr "latinščina"
msgid "Latvian"
msgstr "letonščina"
msgid "Lithuanian"
msgstr "litovščina"
msgid "Macedonian"
msgstr "makedonščina"
msgid "Maltese"
msgstr "malteščina"
msgid "Moldavian Cyrillic"
msgstr "moldavščina cirilica"
msgid "Moldavian Latinic"
msgstr "moldavščina latinica"
msgid "Norwegian"
msgstr "norveščina"
msgid "Polish"
msgstr "poljščina"
msgid "Portuguese"
msgstr "portugalščina"
msgid "Romanian"
msgstr "romunščina"
msgid "Russian"
msgstr "ruščina"
msgid "Serbian Cyrillic"
msgstr "srbščina cirilica"
msgid "Serbian Latinic"
msgstr "srbščina latinica"
msgid "Slovak"
msgstr "slovaščina"
msgid "Slovenian"
msgstr "slovenščina"
msgid "Sorbian"
msgstr "lužiščini"
msgid "Spanish"
msgstr "španščina"
msgid "Swedish"
msgstr "švedščina"
msgid "Turkish"
msgstr "turščina"
msgid "Ukrainian"
msgstr "ukrajinščina"

Binary file not shown.

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: wxWidgets 3.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-02-02 15:21+0100\n"
"PO-Revision-Date: 2016-03-14 17:12+0100\n"
"PO-Revision-Date: 2016-04-08 13:05+0200\n"
"Last-Translator: Simon Rozman <simon.rozman@amebis.si>\n"
"Language-Team: Simon Rozman <simon.rozman@amebis.si>\n"
"Language: sl_SI\n"
@@ -2955,7 +2955,7 @@ msgstr "Izreži"
# generic/dirdlgg.cpp:191
#: ../src/common/stockitem.cpp:259
msgid "Cut selection"
msgstr "Prilepi izbor"
msgstr "Izreži izbor"
#: ../src/common/fmapbase.cpp:152
msgid "Cyrillic (ISO-8859-5)"