diff --git a/.github/multi-labeler.yml b/.github/multi-labeler.yml index ffab4f5572..b2e84bec10 100644 --- a/.github/multi-labeler.yml +++ b/.github/multi-labeler.yml @@ -95,3 +95,7 @@ labels: - label: 'epic-ldml' matcher: branch: '.*epic-ldml.*' # anywhere in the branch name, e.g. feat/epic-ldml/developer/... or feat/developer/foo-epic-ldml + + - label: 'epic-kmcompx' + matcher: + branch: '.*epic-kmcompx.*' diff --git a/.gitignore b/.gitignore index cb0de77c31..0abec10c3b 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ /common/windows/delphi/**/*.bpl /common/windows/delphi/**/*.map /common/windows/delphi/**/*.tds +/common/windows/delphi/**/*.identcache # Temp files generated during release build /windows/src/buildtools/inst/copydebug.mak @@ -190,3 +191,10 @@ lcov.info /keyman*.buildinfo /keyman*.changes /keyman*.tar.?z + +#Sabine: +# /common/test/keyboards/invalid/source/*.kmx +# /developer/src/test/auto/kmcomp/*.kmn +# /developer/src/test/auto/kmcomp/*.kvk +# /developer/src/test/auto/kmcomp/*.kvk* +# /developer/src/test/auto/kmcomp/*.txt diff --git a/common/include/km_types.h b/common/include/km_types.h index bf25b354b5..d81f267238 100644 --- a/common/include/km_types.h +++ b/common/include/km_types.h @@ -1,4 +1,5 @@ #pragma once +#include #include @@ -21,30 +22,31 @@ #define KMX_64BIT #endif -typedef uint32_t KMX_DWORD; -typedef int32_t KMX_BOOL; -typedef uint8_t KMX_BYTE; -typedef uint16_t KMX_WORD; +typedef uint32_t KMX_DWORD; +typedef int32_t KMX_BOOL; +typedef uint8_t KMX_BYTE; +typedef uint16_t KMX_WORD; #if defined(__cplusplus) typedef char16_t km_kbp_cp; typedef char32_t km_kbp_usv; #else -typedef uint16_t km_kbp_cp; // code point -typedef uint32_t km_kbp_usv; // Unicode Scalar Value +typedef uint16_t km_kbp_cp; // code point +typedef uint32_t km_kbp_usv; // Unicode Scalar Value #endif -typedef km_kbp_cp KMX_WCHAR; // wc, 16-bit UNICODE character -typedef KMX_WCHAR *PKMX_WCHAR; +typedef km_kbp_cp KMX_WCHAR; // wc, 16-bit UNICODE character +typedef KMX_WCHAR* PKMX_WCHAR; -typedef char KMX_CHAR; -typedef KMX_CHAR *PKMX_CHAR; +typedef char KMX_CHAR; +typedef char* PKMX_STR; +typedef KMX_CHAR* PKMX_CHAR; -typedef uint32_t KMX_UINT; +typedef uint32_t KMX_UINT; -typedef KMX_BYTE *PKMX_BYTE; -typedef KMX_WORD *PKMX_WORD; -typedef KMX_DWORD *PKMX_DWORD; +typedef KMX_BYTE* PKMX_BYTE; +typedef KMX_WORD* PKMX_WORD; +typedef KMX_DWORD* PKMX_DWORD; #ifndef FALSE #define FALSE 0 diff --git a/common/include/kmx_file.h b/common/include/kmx_file.h index 4519e0ccef..998c978007 100644 --- a/common/include/kmx_file.h +++ b/common/include/kmx_file.h @@ -64,6 +64,8 @@ namespace kmx { // Different begin types #define BEGIN_ANSI 0 #define BEGIN_UNICODE 1 +#define BEGIN_NEWCONTEXT 2 +#define BEGIN_POSTKEYSTROKE 3 #define TSS_NONE 0 #define TSS_BITMAP 1 @@ -302,6 +304,7 @@ struct COMP_STORE { struct COMP_KEY { KMX_WORD Key; + KMX_WORD _reserved; KMX_DWORD Line; KMX_DWORD ShiftFlags; KMX_DWORD dpOutput; diff --git a/common/test/keyboards/build.sh b/common/test/keyboards/build.sh index 0a8d1782a5..cbf5863e37 100755 --- a/common/test/keyboards/build.sh +++ b/common/test/keyboards/build.sh @@ -29,7 +29,9 @@ display_usage() { for d in "$THIS_DIR/"*/; do d="$(basename "$d")" - echo " $d" + if [ "$d" != "invalid" ]; then + echo " $d" + fi done echo @@ -122,7 +124,9 @@ fi if [ ${#TARGETS[@]} == 0 ]; then for d in "$THIS_DIR/"*/; do d="$(basename "$d")" - TARGETS+=("$d") + if [ "$d" != "invalid" ]; then + TARGETS+=("$d") + fi done fi diff --git a/common/test/keyboards/invalid/README.md b/common/test/keyboards/invalid/README.md new file mode 100644 index 0000000000..a1a1b5e3ab --- /dev/null +++ b/common/test/keyboards/invalid/README.md @@ -0,0 +1,163 @@ +# **Tests for kmcompxtest()** +
+ +This folder contains several kmn-files that are used for testing resulting error codes. + +Most of these tests are copied from balochi_phonetic and contain alterations of the data to produce (at least) 1 error. +
+
+ +## Naming Convention of kmn-files for using with kmcompxtest() + + CERR_404D_balochi_phonetic.kmn + + +The naming convention of the files is as follows: + +* All Files **MUST** start with CERR_ followed by 4 characters and an underscore. + +* After the second underscore all combination of char can be used. + +* The 4 characters following CERR_ correspond to the last 4 digits of the error code which is expected to be produced by this file. + + ( e.g. CERR_404D_balochi_phonetic.kmn should produce error 0x0000404D). + +
+
+ +While running, kmcompxtest extracts those 4 characters from the Filename (e.g. 404D for CERR_404D_balochi_phonetic) and compares those to the actual error found. + +* If these 4 characters correspond to the actual error given, the test will be marked as OK. (Code 0) +
+* If these 4 characters signify an error but **no error** does occur, the test will be marked as FAILED (Code 1) +
+* If these 4 characters signify an error but this **specific error** does not occur, the test will be marked as FAILED (Code 4) +
+* If these 4 characters signify an error number that is **not correct**, the test will be marked as FAILED (Code 5) +
+* If more than 1 error is produced, only the error coded in the Filename will be detected + +
+
+ +### Tests are available for the following CERR_: + + +| | Error Number | CERR_ +| :-: | :-----------:| :------------------------------------- +| | 00000800 | CERR_LEXICAL_MODEL_MIN +| | 000008FF | CERR_LEXICAL_MODEL_MAX +| | 00000800 | CERR_LEXICAL_MODEL_MIN +| | 000008FF | CERR_LEXICAL_MODEL_MAX +| | 00000000 | CERR_None +| | 00000001 | CERR_EndOfFile +| | 00008002 | CERR_BadCallParams +| | 00008004 | CERR_CannotAllocateMemory +| | 00008005 | CERR_InfileNotExist +| | 00008006 | CERR_CannotCreateOutfile +| | 00008007 | CERR_UnableToWriteFully +| | 00008008 | CERR_CannotReadInfile +| | 00008009 | CERR_SomewhereIGotItWrong +|**X**| 0000400A | CERR_InvalidToken +| | 0000400B | CERR_InvalidBegin +| | 0000400C | CERR_InvalidName +|**X**| 0000400D | CERR_InvalidVersion +|**X**| 0000400E | CERR_InvalidLanguageLine +| | 0000400F | CERR_LayoutButNoLanguage +| | 00004010 | CERR_InvalidLayoutLine +| | 00004011 | CERR_NoVersionLine +| | 00004012 | CERR_InvalidGroupLine +|**X**| 00004013 | CERR_InvalidStoreLine +| | 00004014 | CERR_InvalidCodeInKeyPartOfRule +|**X**| 00004015 | CERR_InvalidDeadkey +|**X**| 00004016 | CERR_InvalidValue +|**X**| 00004017 | CERR_ZeroLengthString +| | 00004018 | CERR_TooManyIndexToKeyRefs +|**X**| 00004019 | CERR_UnterminatedString +| | 0000401A | CERR_StringInVirtualKeySection +| | 0000401B | CERR_AnyInVirtualKeySection +| | 0000401C | CERR_InvalidAny +|**X**| 0000401D | CERR_StoreDoesNotExist +| | 0000401E | CERR_BeepInVirtualKeySection +| | 0000401F | CERR_IndexInVirtualKeySection +| | 00004020 | CERR_InvalidIndex +| | 00004021 | CERR_OutsInVirtualKeySection +| | 00004022 | CERR_InvalidOuts +| | 00004024 | CERR_ContextInVirtualKeySection +| | 00004025 | CERR_InvalidUse +|**X**| 00004026 | CERR_GroupDoesNotExist +| | 00004027 | CERR_VirtualKeyNotAllowedHere +| | 00004028 | CERR_InvalidSwitch +|**X**| 00004029 | CERR_NoTokensFound +| | 0000402A | CERR_InvalidLineContinuation +|**X**| 0000402B | CERR_LineTooLong +| | 0000402C | CERR_InvalidCopyright +|**X**| 0000402D | CERR_CodeInvalidInThisSection +| | 0000402E | CERR_InvalidMessage +| | 0000402F | CERR_InvalidLanguageName +| | 00004030 | CERR_InvalidBitmapLine +|**X**| 00004031 | CERR_CannotReadBitmapFile +| | 00004032 | CERR_IndexDoesNotPointToAny +| | 00004033 | CERR_ReservedCharacter +|**X**| 00004034 | CERR_InvalidCharacter +| | 00004035 | CERR_InvalidCall +| | 00004036 | CERR_CallInVirtualKeySection +| | 00004037 | CERR_CodeInvalidInKeyStore +|**X**| 00004038 | CERR_CannotLoadIncludeFile +|**X**| 00004039 | CERR_60FeatureOnly_EthnologueCode +|**X**| 0000403A | CERR_60FeatureOnly_MnemonicLayout +| | 0000403B | CERR_60FeatureOnly_OldCharPosMatching +| | 0000403C | CERR_60FeatureOnly_NamedCodes +| | 0000403D | CERR_60FeatureOnly_Contextn +|**X**| 0000403E | CERR_501FeatureOnly_Call +| | 0000403F | CERR_InvalidNamedCode +|**X**| 00004040 | CERR_InvalidSystemStore +|**X**| 00004044 | CERR_60FeatureOnly_VirtualCharKey +|**X**| 00004045 | CERR_VersionAlreadyIncluded +|**X**| 00004046 | CERR_70FeatureOnly +|**X**| 00004047 | CERR_80FeatureOnly +| | 00004048 | CERR_InvalidInVirtualKeySection +|**X**| 00004049 | CERR_InvalidIf +|**X**| 0000404A | CERR_InvalidReset +|**X**| 0000404B | CERR_InvalidSet +|**X**| 0000404C | CERR_InvalidSave +|**X**| 0000404D | CERR_InvalidEthnologueCode +| | 0000804E | CERR_CannotCreateTempfile +|**X**| 0000404F | CERR_90FeatureOnly_IfSystemStores +| | 00004050 | CERR_IfSystemStore_NotFound +| | 00004051 | CERR_90FeatureOnly_SetSystemStores +| | 00004052 | CERR_SetSystemStore_NotFound +| | 00004053 | CERR_90FeatureOnlyVirtualKeyDictionary +| | 00004054 | CERR_NotSupportedInKeymanWebContext +| | 00004055 | CERR_NotSupportedInKeymanWebOutput +| | 00004056 | CERR_NotSupportedInKeymanWebStore +| | 00004057 | CERR_VirtualCharacterKeysNotSupportedInKeymanWeb +| | 00004058 | CERR_VirtualKeysNotValidForMnemonicLayouts +| | 00004059 | CERR_InvalidTouchLayoutFile +| | 0000405A | CERR_TouchLayoutInvalidIdentifier +| | 0000405B | CERR_InvalidKeyCode +|**X**| 0000405C | CERR_90FeatureOnlyLayoutFile +|**X**| 0000405D | CERR_90FeatureOnlyKeyboardVersion +|**X**| 0000405E | CERR_KeyboardVersionFormatInvalid +| | 0000405F | CERR_ContextExHasInvalidOffset +|**X**| 00004060 | CERR_90FeatureOnlyEmbedCSS +|**X**| 00004061 | CERR_90FeatureOnlyTargets +| | 00004062 | CERR_ContextAndIndexInvalidInMatchNomatch +| | 00004063 | CERR_140FeatureOnlyContextAndNotAnyWeb +|**X**| 00004064 | CERR_ExpansionMustFollowCharacterOrVKey +|**X**| 00004065 | CERR_VKeyExpansionMustBeFollowedByVKey +|**X**| 00004066 | CERR_CharacterExpansionMustBeFollowedByCharacter +|**X**| 00004067 | CERR_VKeyExpansionMustUseConsistentShift +|**X**| 00004068 | CERR_ExpansionMustBePositive +|**X**| 00004069 | CERR_CasedKeysMustContainOnlyVirtualKeys +|**X**| 0000406A | CERR_CasedKeysMustNotIncludeShiftStates +|**X**| 0000406B | CERR_CasedKeysNotSupportedWithMnemonicLayout +|**X**| 0000406C | CERR_CannotUseReadWriteGroupFromReadonlyGroup +| | 0000406D | CERR_StatementNotPermittedInReadonlyGroup +|**X**| 0000406E | CERR_OutputInReadonlyGroup +|**X**| 0000406F | CERR_NewContextGroupMustBeReadonly +|**X**| 00004070 | CERR_PostKeystrokeGroupMustBeReadonly +|**X**| 00004071 | CERR_DuplicateGroup +|**X**| 00004072 | CERR_DuplicateStore +|**X**| 00004073 | CERR_RepeatedBegin +|**X**| 000080C0 | CERR_BufferOverflow diff --git a/common/test/keyboards/invalid/source/CERR_400A_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_400A_balochi_phonetic.kmn new file mode 100644 index 0000000000..0b7f2ffb0a --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_400A_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' +c ***** CERR_InvalidToken 0x0000400A ******************************** ++ [CTRL B10] > L'1234' +c ******************************************************************* ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' diff --git a/common/test/keyboards/invalid/source/CERR_400D_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_400D_balochi_phonetic.kmn new file mode 100644 index 0000000000..ade9793ed4 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_400D_balochi_phonetic.kmn @@ -0,0 +1,130 @@ + c ***** CERR_InvalidVersion 0x0000400D ***************************** +store(&VERSION) '127.0' +c ******************************************************************* +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_400E_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_400E_balochi_phonetic.kmn new file mode 100644 index 0000000000..ced7892f05 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_400E_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + c ***** CERR_InvalidLanguageLine 0x0000400E ************************ +store(&LANGUAGE) 'abc123' +c ******************************************************************* +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4013_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4013_balochi_phonetic.kmn new file mode 100644 index 0000000000..cd838e3682 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4013_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +c ***** CERR_InvalidStoreLine 0x00004013 *************************** +store(&VERSION '10.0' +c ****************************************************************** +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4015_k_014___groups_and_virtual_keys.kmn b/common/test/keyboards/invalid/source/CERR_4015_k_014___groups_and_virtual_keys.kmn new file mode 100644 index 0000000000..da26166e5c --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4015_k_014___groups_and_virtual_keys.kmn @@ -0,0 +1,30 @@ +store(&NAME) '014 - groups and virtual keys' +c Description: Tests multiple groups and virtual keys with mnemonic layout +c keys: [K_A][SHIFT K_2][K_A][LCTRL K_2][K_A] +c expected: \u03B1\u1FB0\u1FB1 + +store(&VERSION) '9.0' + +begin Unicode > use(UMain) + +store(&MnemonicLayout) "0" + +c ---------------------------------------------- + +group(UMain) using keys + + [K_A] > U+03B1 + +c ***** CERR_InvalidDeadkey 0x00004015 ****************************** + + [CTRL K_q] > deadkey('–') +c ******************************************************************* + + + [ALT K_2] > deadkey(MacronBug) + + [SHIFT K_2] > deadkey(BreveBug) + + match > use(DK1) + +c ---------------------------------------------- + +group(DK1) + deadkey(MacronBug) U+03B1 > U+1FB1 c won't work + deadkey(BreveBug) U+03B1 > U+1FB0 c works \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4016_k_014___groups_and_virtual_keys.kmn b/common/test/keyboards/invalid/source/CERR_4016_k_014___groups_and_virtual_keys.kmn new file mode 100644 index 0000000000..9a07e0b058 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4016_k_014___groups_and_virtual_keys.kmn @@ -0,0 +1,29 @@ +store(&NAME) '014 - groups and virtual keys' +c Description: Tests multiple groups and virtual keys with mnemonic layout +c keys: [K_A][SHIFT K_2][K_A][LCTRL K_2][K_A] +c expected: \u03B1\u1FB0\u1FB1 + +store(&VERSION) '9.0' + +begin Unicode > use(UMain) + +store(&MnemonicLayout) "0" + +c ---------------------------------------------- + +group(UMain) using keys + + [K_A] > U+03B1 + + [CTRL K_2] > deadkey(MacronBug) + + [ALT K_2] > deadkey(MacronBug) + + [SHIFT K_2] > deadkey(BreveBug) + + match > use(DK1) + +c ---------------------------------------------- + +group(DK1) + deadkey(MacronBug) U+03B1 > U+1FB1 c won't work + + c ***** CERR_InvalidValue 0x00004016 ***************************** + deXadkey(BreveBug) U+03B1 > U+1FB0 c works +c ******************************************************************* \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4017_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4017_balochi_phonetic.kmn new file mode 100644 index 0000000000..ddc33aeb05 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4017_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.bmp' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' +c ***** CERR_ZeroLengthString 0x00004017 *************************** ++ [CTRL B10] > +c ****************************************************************** ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4019_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4019_balochi_phonetic.kmn new file mode 100644 index 0000000000..48f978a1eb --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4019_balochi_phonetic.kmn @@ -0,0 +1,129 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +c ***** CERR_UnterminatedString 0x00004019 ************************* +store(&BITMAP)CERR__balochi_phonetic.ico' +c ****************************************************************** +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_401D_k_034___options_double_set_reset.kmn b/common/test/keyboards/invalid/source/CERR_401D_k_034___options_double_set_reset.kmn new file mode 100644 index 0000000000..31876eeeef --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_401D_k_034___options_double_set_reset.kmn @@ -0,0 +1,22 @@ +store(&NAME) '034 - options double set reset' +c Description: Tests basic option rules with save reset+set+reset +c keys: [K_A][K_A] +c expected: foo.foo. +c context: +c option: foo=1 +c expected option: foo=1 + +store(&version) '10.0' + +store(foo) '0' + +begin Unicode > use(Main) + +group(Main) using keys + +c ***** CERR_StoreDoesNotExist 0x0000401D *********************************** +if(foo = '1') + 'a' > 'foo.' set(foo='2') reset(ffoo) set(foo='3') reset(foo) +c ******************************************************************* +if(foo = '2') + 'a' > 'bar.' +if(foo = '3') + 'a' > 'baz.' +if(foo = '0') + 'a' > 'no foo.' diff --git a/common/test/keyboards/invalid/source/CERR_4026_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4026_balochi_phonetic.kmn new file mode 100644 index 0000000000..6fb2c649de --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4026_balochi_phonetic.kmn @@ -0,0 +1,17 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +c ***** CERR_GroupDoesNotExist 0x00004026 ************************** + +c ****************************************************************** \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4029_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4029_balochi_phonetic.kmn new file mode 100644 index 0000000000..3d093c36d4 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4029_balochi_phonetic.kmn @@ -0,0 +1,128 @@ +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +c ***** CERR_NoTokensFound 0x00004029 ******************************* +begin +c ******************************************************************* +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '§' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' diff --git a/common/test/keyboards/invalid/source/CERR_402B_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_402B_balochi_phonetic.kmn new file mode 100644 index 0000000000..7da903abe3 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_402B_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +c ***** CERR_LineTooLong 0x0000402B ******************************** +store(©RIGHT) '© 2017-2021 SIL InternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' +c ****************************************************************** +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_402D_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_402D_balochi_phonetic.kmn new file mode 100644 index 0000000000..37755739b9 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_402D_balochi_phonetic.kmn @@ -0,0 +1,129 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) +c ***** CERR_CodeInvalidInThisSection 0x0000402D ******************* + +c ****************************************************************** ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4031_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4031_balochi_phonetic.kmn new file mode 100644 index 0000000000..b9b62c3a42 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4031_balochi_phonetic.kmn @@ -0,0 +1,129 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +c ***** CERR_CannotReadBitmapFile 0x00004031 *********************** +store(&BITMAP) 'balochi_phonetic.ico' +c ****************************************************************** +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4034_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4034_balochi_phonetic.kmn new file mode 100644 index 0000000000..c5c8306d37 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4034_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +c ***** CERR_InvalidCharacter 0x00004034 *************************** +store(©RIGHT) ' 2012 U+1234 -2020 SIL International' +c ****************************************************************** +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4038_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4038_balochi_phonetic.kmn new file mode 100644 index 0000000000..7e6eaedb1f --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4038_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' +c ***** CERR_CannotLoadIncludeFile 0x00004038 ********************** +store(&INCLUDECODES) 'XX.txt' +c ****************************************************************** +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4039_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4039_balochi_phonetic.kmn new file mode 100644 index 0000000000..7eb9571a14 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4039_balochi_phonetic.kmn @@ -0,0 +1,137 @@ +c ***** This test will produce XXXX Error: *************************** +c ***** 1) it will be marked as FAIL when run in kmcompxtest ******* +c ***** as a XXXXXXX non-existing ErrorNr (0x00040733) is specified ***** +c ******************************************************************store(&VERSION) '10.0' + +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +c ***** CERR_60FeatureOnly_EthnologueCode 0x00004039 **************** +store(&version) '3.0' +store(ÐNOLOGUECODE) 'eng' +c ******************************************************************* + +begin Unicode > use(main) + +group (main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '§' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' diff --git a/common/test/keyboards/invalid/source/CERR_403A_014_groups_and_virtual_keys.kmn b/common/test/keyboards/invalid/source/CERR_403A_014_groups_and_virtual_keys.kmn new file mode 100644 index 0000000000..43981238d7 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_403A_014_groups_and_virtual_keys.kmn @@ -0,0 +1,34 @@ +c RegressionTest: Multiple groups and virtual keys +c Font: Arial Unicode MS +c Encoding: Unicode +c Description: Tests multiple groups and virtual keys -- bug Ixxx +c Procedure: Press A, Shift+2, A, Ctrl+2, A +c AutoProc: K_A S+ K_2 S- K_A C+ K_2 C- K_A +c FinalOutput: U+03B1 U+1FB0 U+1FB1 + +c ***** CERR_60FeatureOnly_MnemonicLayout 0x0000403A **************** +store(&VERSION) '3.0' +c ******************************************************************* + +NAME "AltGr Deadkeys Test" + +begin Unicode > use(UMain) c Substitute UMain1 or UMain2 + +c ***** CERR_60FeatureOnly_MnemonicLayout 0x0000403A **************** +store(&MnemonicLayout) "1" +c ******************************************************************* + + +c ---------------------------------------------- +group(UMain) using keys + + ['a'] > U+03B1 + + [CTRL '2'] > deadkey(MacronBug) + + [ALT '2'] > deadkey(MacronBug) + + [SHIFT '2'] > deadkey(BreveBug) + match > use(DK1) + +c ---------------------------------------------- + +group(DK1) + deadkey(MacronBug) U+03B1 > U+1FB1 c won't work + deadkey(BreveBug) U+03B1 > U+1FB0 c works diff --git a/common/test/keyboards/invalid/source/CERR_403E_imsample.kmn b/common/test/keyboards/invalid/source/CERR_403E_imsample.kmn new file mode 100644 index 0000000000..93c90cfcea --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_403E_imsample.kmn @@ -0,0 +1,17 @@ +c ***** CERR_501FeatureOnly_Call 0x0000403E ************************* +store(&VERSION) '3.0' +c ******************************************************************* +store(&NAME) 'IMTest' +store(DLLFunction) "imsample.dll:DF" + +begin Unicode > use(main) + +group(main) using keys + +c ***** CERR_501FeatureOnly_Call 0x0000403E ************************* + ++ [K_BKSP] > call(DLLFunction) ++ [K_ESC] > call(DLLFunction) + +nomatch > call(DLLFunction) +c ******************************************************************* \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4040_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4040_balochi_phonetic.kmn new file mode 100644 index 0000000000..4e6e7b41e3 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4040_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +c ***** CERR_InvalidSystemStore 0x00004040 ************************* +store(&NXXAME) 'Balochi Phonetic' +c ****************************************************************** +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4044_014_groups_and_virtual_keys.kmn b/common/test/keyboards/invalid/source/CERR_4044_014_groups_and_virtual_keys.kmn new file mode 100644 index 0000000000..42a0f87ee0 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4044_014_groups_and_virtual_keys.kmn @@ -0,0 +1,33 @@ +c RegressionTest: Multiple groups and virtual keys +c Font: Arial Unicode MS +c Encoding: Unicode +c Description: Tests multiple groups and virtual keys -- bug Ixxx +c Procedure: Press A, Shift+2, A, Ctrl+2, A +c AutoProc: K_A S+ K_2 S- K_A C+ K_2 C- K_A +c FinalOutput: U+03B1 U+1FB0 U+1FB1 + +c ***** CERR_501FeatureOnly_Call 0x0000403E ************************* +store(&VERSION) '3.0' +c ******************************************************************* + +NAME "AltGr Deadkeys Test" + +begin Unicode > use(UMain) c Substitute UMain1 or UMain2 + +store(&MnemonicLayout) "1" + +c ---------------------------------------------- +c ***** CERR_60FeatureOnly_VirtualCharKey 0x00004044 **************** +group(UMain) using keys + + ['a'] > U+03B1 + + [CTRL '2'] > deadkey(MacronBug) + + [ALT '2'] > deadkey(MacronBug) + + [SHIFT '2'] > deadkey(BreveBug) +c ******************************************************************* + match > use(DK1) + +c ---------------------------------------------- + +group(DK1) + deadkey(MacronBug) U+03B1 > U+1FB1 c won't work + deadkey(BreveBug) U+03B1 > U+1FB0 c works diff --git a/common/test/keyboards/invalid/source/CERR_4045_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4045_balochi_phonetic.kmn new file mode 100644 index 0000000000..b50a62ced3 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4045_balochi_phonetic.kmn @@ -0,0 +1,134 @@ +store(&VERSION) '10.0' + +c ***** CERR_VersionAlreadyIncluded 0x00004045 ****************************** +store(&VERSION) '110.0' +c ******************************************************************* + +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' diff --git a/common/test/keyboards/invalid/source/CERR_4046_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4046_balochi_phonetic.kmn new file mode 100644 index 0000000000..69b4ce96f6 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4046_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +c ***** CERR_70FeatureOnly 0x00004046 ****************************** +store(&VERSION) '4.0' +c ****************************************************************** +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4047_k_022___options_with_preset.kmn b/common/test/keyboards/invalid/source/CERR_4047_k_022___options_with_preset.kmn new file mode 100644 index 0000000000..174a768ee5 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4047_k_022___options_with_preset.kmn @@ -0,0 +1,26 @@ +store(&NAME) '022 - options with preset' +c Description: Tests basic option rules with a preset supplied +c keys: [K_A][K_1][K_A][K_0][K_A] +c expected: foo.foo.no foo. +c context: +c option: foo=1 +c expected option: foo=0 +c saved option: foo=0 + +c ***** CERR_80FeatureOnly 0x00004047 ******************************* +store(&VERSION) '3.0' +c ******************************************************************* + +store(foo) '0' + +begin Unicode > use(Main) + +group(Main) using keys + +if(foo = '1') + 'a' > 'foo.' +if(foo = '0') + 'a' > 'no foo.' + +c ***** CERR_80FeatureOnly 0x00004047 ******************************* ++ '1' > set(foo = '1') save(foo) ++ '0' > set(foo = '0') save(foo) +c ******************************************************************* \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4049_k_022___options_with_preset.kmn b/common/test/keyboards/invalid/source/CERR_4049_k_022___options_with_preset.kmn new file mode 100644 index 0000000000..ea423987a4 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4049_k_022___options_with_preset.kmn @@ -0,0 +1,24 @@ +store(&NAME) '022 - options with preset' +c Description: Tests basic option rules with a preset supplied +c keys: [K_A][K_1][K_A][K_0][K_A] +c expected: foo.foo.no foo. +c context: +c option: foo=1 +c expected option: foo=0 +c saved option: foo=0 + +store(&VERSION) '8.0' + +store(foo) '0' + +begin Unicode > use(Main) + +group(Main) using keys + +c ***** CERR_InvalidIf 0x00004049 *********************************** +if(foo '1') + 'a' > 'foo.' +c ******************************************************************* +if(foo = '0') + 'a' > 'no foo.' + ++ '1' > set(foo = '1') save(foo) ++ '0' > set(foo = '0') save(foo) \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_404A_k_025___options_with_reset.kmn b/common/test/keyboards/invalid/source/CERR_404A_k_025___options_with_reset.kmn new file mode 100644 index 0000000000..9dea1a51e4 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_404A_k_025___options_with_reset.kmn @@ -0,0 +1,23 @@ +store(&NAME) '025 - options with reset' +c Description: Tests basic option rules with reset +c keys: [K_A][K_1][K_A][K_0][K_A][K_3] +c expected: foo.foo.no foo. +c context: +c option: foo=1 +c expected option: foo=1 + +store(&version) '10.0' + +store(foo) '0' + +begin Unicode > use(Main) + +group(Main) using keys + +if(foo = '1') + 'a' > 'foo.' +if(foo = '0') + 'a' > 'no foo.' ++ '1' > set(foo = '1') ++ '0' > set(foo = '0') +c ***** CERR_InvalidReset 0x0000404A ******************************** ++ '3' > reset +c ******************************************************************* diff --git a/common/test/keyboards/invalid/source/CERR_404B_k_025___options_with_reset.kmn b/common/test/keyboards/invalid/source/CERR_404B_k_025___options_with_reset.kmn new file mode 100644 index 0000000000..70b534fc7e --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_404B_k_025___options_with_reset.kmn @@ -0,0 +1,25 @@ +store(&NAME) '025 - options with reset' +c Description: Tests basic option rules with reset +c keys: [K_A][K_1][K_A][K_0][K_A][K_3] +c expected: foo.foo.no foo. +c context: +c option: foo=1 +c expected option: foo=1 + +store(&version) '10.0' + +store(foo) '0' + +begin Unicode > use(Main) + +group(Main) using keys + +if(foo = '1') + 'a' > 'foo.' +if(foo = '0') + 'a' > 'no foo.' + +c ***** CERR_InvalidReset 0x0000404B ******************************** ++ '1' > set( ++ '0' > set +c ******************************************************************* + ++ '3' > reset(foo) diff --git a/common/test/keyboards/invalid/source/CERR_404C_k_023___options_with_save.kmn b/common/test/keyboards/invalid/source/CERR_404C_k_023___options_with_save.kmn new file mode 100644 index 0000000000..a160ace737 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_404C_k_023___options_with_save.kmn @@ -0,0 +1,23 @@ +store(&NAME) '023 - options with save' +c Description: Tests basic option rules with save +c keys: [K_A][K_1][K_A][K_0][K_A][K_2] +c expected: no foo.foo.no foo. +c context: +c expected option: foo=0 +c saved option: foo=0 + +store(&version) '10.0' + +store(foo) '0' + +begin Unicode > use(Main) + +group(Main) using keys + +if(foo = '1') + 'a' > 'foo.' +if(foo = '0') + 'a' > 'no foo.' ++ '1' > set(foo = '1') ++ '0' > set(foo = '0') +c ***** CERR_InvalidSave 0x0000404C ********************************* ++ '2' > save +c ******************************************************************* diff --git a/common/test/keyboards/invalid/source/CERR_404D_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_404D_balochi_phonetic.kmn new file mode 100644 index 0000000000..7aadf55672 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_404D_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' +c ***** CERR_InvalidEthnologueCode 0x0000404D ********************** +store(&EthnologueCode) "xxxx" +c ****************************************************************** +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_404F_k_026___system_stores.kmn b/common/test/keyboards/invalid/source/CERR_404F_k_026___system_stores.kmn new file mode 100644 index 0000000000..e336ac5d78 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_404F_k_026___system_stores.kmn @@ -0,0 +1,29 @@ +store(&NAME) '026 - system stores' +c Description: Tests platform and baselayout system store rules +c keys: [K_1][K_2][K_3][K_4][K_A][K_B] +c expected: windows.desktop.hardware.native.en-US.kbdus.dll. +c context: +c (default) option: &platform=windows desktop hardware native <-- ignored by test +c (default) option: &baseLayout=kbdus.dll <-- ignored by test +c (default) option: &baseLayoutAlt=en-US <-- ignored by test + +c ***** CERR_90FeatureOnly_IfSystemStores 0x0000404F **************** +store(&version) '3.0' +c ******************************************************************* + +store(digit) '1234567890' +store(letter) 'abcdefghij' + +begin Unicode > use(Main) + +group(Main) using keys + +platform('windows') + '1' > 'windows.' +platform('desktop') + '2' > 'desktop.' +platform('hardware') + '3' > 'hardware.' +platform('native') + '4' > 'native.' ++ any(digit) > 'platform-fail.' + +baselayout('en-US') + 'a' > 'en-US.' +baselayout('kbdus.dll') + 'b' > 'kbdus.dll.' ++ any(letter) > 'baselayout-fail.' diff --git a/common/test/keyboards/invalid/source/CERR_405C_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_405C_balochi_phonetic.kmn new file mode 100644 index 0000000000..ad77761603 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_405C_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +c ***** CERR_90FeatureOnlyLayoutFile 0x0000405C ******************** +store(&VERSION) '4.0' +c ****************************************************************** +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_405D_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_405D_balochi_phonetic.kmn new file mode 100644 index 0000000000..e1224961dd --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_405D_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +c ***** CERR_90FeatureOnlyKeyboardVersion 0x0000405D *************** +store(&VERSION) '4.0' +c ****************************************************************** +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_405E_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_405E_balochi_phonetic.kmn new file mode 100644 index 0000000000..c255c0f5e7 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_405E_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +c ***** CERR_KeyboardVersionFormatInvalid 0x0000405E *************** +store(&KEYBOARDVERSION) 'abc' +c ****************************************************************** +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4060_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4060_balochi_phonetic.kmn new file mode 100644 index 0000000000..6fc5ebe1ae --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4060_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +store(&VERSION) '4.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' +c ***** CERR_90FeatureOnlyEmbedCSS 0x00004060 ********************** +store(&KMW_EMBEDCSS) 'naijatype.css' +c ****************************************************************** +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4061_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4061_balochi_phonetic.kmn new file mode 100644 index 0000000000..47b224d2c6 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4061_balochi_phonetic.kmn @@ -0,0 +1,130 @@ +c ***** CERR_90FeatureOnlyTargets 0x00004061 *********************** +store(&VERSION) '4.0' +c ****************************************************************** +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' \ No newline at end of file diff --git a/common/test/keyboards/invalid/source/CERR_4064_caps_lock_layer_3620.kmn b/common/test/keyboards/invalid/source/CERR_4064_caps_lock_layer_3620.kmn new file mode 100644 index 0000000000..dbc3b65a80 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4064_caps_lock_layer_3620.kmn @@ -0,0 +1,22 @@ +c caps_lock_layer_3620 generated from template at 2021-11-30 14:58:52 +c with name "Caps Lock Layer 3620" +store(&VERSION) '10.0' +store(&NAME) 'Caps Lock Layer 3620' +store(©RIGHT) '©' +store(&KEYBOARDVERSION) '1.0' +store(&TARGETS) 'any' +store(&VISUALKEYBOARD) 'caps_lock_layer_3620.kvks' +store(&LAYOUTFILE) 'caps_lock_layer_3620.keyman-touch-layout' + +begin Unicode > use(main) + +store(key) [K_A] .. [K_Z] [SHIFT K_A] .. [SHIFT K_Z] +c ***** CERR_ExpansionMustFollowCharacterOrVKey 0x00004064 ********** +store(out) .. 'z' 'A' .. 'Z' +c ******************************************************************* +store(&CasedKeys) [K_A] .. [K_Z] + +group(main) using keys + ++ any(key) > index(out, 1) + diff --git a/common/test/keyboards/invalid/source/CERR_4065_test_expansion_invalid.kmn b/common/test/keyboards/invalid/source/CERR_4065_test_expansion_invalid.kmn new file mode 100644 index 0000000000..b721946537 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4065_test_expansion_invalid.kmn @@ -0,0 +1,34 @@ +c This file tests that invalid expansions are caught +store(&NAME) 'Test Invalid Expansions' +begin Unicode > use(main) + +group(main) using keys + +c Backward ranges + +store(char_range_backward) 'c' .. 'a' +store(key_range_backward) [K_E] .. [K_A] + +store(char_range_empty) 'c' .. 'c' +store(key_range_empty) [K_E] .. [K_E] + +c Incomplete ranges + +store(range_open) .. +store(char_range_open_end) 'a' .. +store(char_range_open_start) .. 'z' + +store(key_range_open_end) [K_A] .. +store(key_range_open_start) .. [K_Z] + +c Inconsistent ranges + +store(char_range_to_key) 'a' .. [K_Z] +store(key_range_to_char) [K_A] .. 'z' + +store(char_range_to_statement) 'a' .. nul +store(key_range_to_statement) [K_A] .. nul +store(char_range_from_statement) nul .. 'a' +store(key_range_from_statement) nul .. [K_A] + +store(key_range_shift_inconsistent) [SHIFT K_A] .. [K_Z] diff --git a/common/test/keyboards/invalid/source/CERR_4066_test_expansion_invalid.kmn b/common/test/keyboards/invalid/source/CERR_4066_test_expansion_invalid.kmn new file mode 100644 index 0000000000..b721946537 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4066_test_expansion_invalid.kmn @@ -0,0 +1,34 @@ +c This file tests that invalid expansions are caught +store(&NAME) 'Test Invalid Expansions' +begin Unicode > use(main) + +group(main) using keys + +c Backward ranges + +store(char_range_backward) 'c' .. 'a' +store(key_range_backward) [K_E] .. [K_A] + +store(char_range_empty) 'c' .. 'c' +store(key_range_empty) [K_E] .. [K_E] + +c Incomplete ranges + +store(range_open) .. +store(char_range_open_end) 'a' .. +store(char_range_open_start) .. 'z' + +store(key_range_open_end) [K_A] .. +store(key_range_open_start) .. [K_Z] + +c Inconsistent ranges + +store(char_range_to_key) 'a' .. [K_Z] +store(key_range_to_char) [K_A] .. 'z' + +store(char_range_to_statement) 'a' .. nul +store(key_range_to_statement) [K_A] .. nul +store(char_range_from_statement) nul .. 'a' +store(key_range_from_statement) nul .. [K_A] + +store(key_range_shift_inconsistent) [SHIFT K_A] .. [K_Z] diff --git a/common/test/keyboards/invalid/source/CERR_4067_test_expansion_invalid.kmn b/common/test/keyboards/invalid/source/CERR_4067_test_expansion_invalid.kmn new file mode 100644 index 0000000000..b721946537 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4067_test_expansion_invalid.kmn @@ -0,0 +1,34 @@ +c This file tests that invalid expansions are caught +store(&NAME) 'Test Invalid Expansions' +begin Unicode > use(main) + +group(main) using keys + +c Backward ranges + +store(char_range_backward) 'c' .. 'a' +store(key_range_backward) [K_E] .. [K_A] + +store(char_range_empty) 'c' .. 'c' +store(key_range_empty) [K_E] .. [K_E] + +c Incomplete ranges + +store(range_open) .. +store(char_range_open_end) 'a' .. +store(char_range_open_start) .. 'z' + +store(key_range_open_end) [K_A] .. +store(key_range_open_start) .. [K_Z] + +c Inconsistent ranges + +store(char_range_to_key) 'a' .. [K_Z] +store(key_range_to_char) [K_A] .. 'z' + +store(char_range_to_statement) 'a' .. nul +store(key_range_to_statement) [K_A] .. nul +store(char_range_from_statement) nul .. 'a' +store(key_range_from_statement) nul .. [K_A] + +store(key_range_shift_inconsistent) [SHIFT K_A] .. [K_Z] diff --git a/common/test/keyboards/invalid/source/CERR_4068_test_expansion_invalid.kmn b/common/test/keyboards/invalid/source/CERR_4068_test_expansion_invalid.kmn new file mode 100644 index 0000000000..b721946537 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4068_test_expansion_invalid.kmn @@ -0,0 +1,34 @@ +c This file tests that invalid expansions are caught +store(&NAME) 'Test Invalid Expansions' +begin Unicode > use(main) + +group(main) using keys + +c Backward ranges + +store(char_range_backward) 'c' .. 'a' +store(key_range_backward) [K_E] .. [K_A] + +store(char_range_empty) 'c' .. 'c' +store(key_range_empty) [K_E] .. [K_E] + +c Incomplete ranges + +store(range_open) .. +store(char_range_open_end) 'a' .. +store(char_range_open_start) .. 'z' + +store(key_range_open_end) [K_A] .. +store(key_range_open_start) .. [K_Z] + +c Inconsistent ranges + +store(char_range_to_key) 'a' .. [K_Z] +store(key_range_to_char) [K_A] .. 'z' + +store(char_range_to_statement) 'a' .. nul +store(key_range_to_statement) [K_A] .. nul +store(char_range_from_statement) nul .. 'a' +store(key_range_from_statement) nul .. [K_A] + +store(key_range_shift_inconsistent) [SHIFT K_A] .. [K_Z] diff --git a/common/test/keyboards/invalid/source/CERR_4069_test_casedkeys_invalid_1.kmn b/common/test/keyboards/invalid/source/CERR_4069_test_casedkeys_invalid_1.kmn new file mode 100644 index 0000000000..8bc65cced6 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4069_test_casedkeys_invalid_1.kmn @@ -0,0 +1,10 @@ +c Tests cased keys - invalid codes +store(&NAME) 'Test &CasedKeys' +begin Unicode > use(main) + +group(main) using keys + +store(&CasedKeys) U+1000 + ++ [K_A] > 'aaah' ++ [SHIFT K_A] > 'AAAH' diff --git a/common/test/keyboards/invalid/source/CERR_406A_test_casedkeys_invalid_2.kmn b/common/test/keyboards/invalid/source/CERR_406A_test_casedkeys_invalid_2.kmn new file mode 100644 index 0000000000..508466c07e --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_406A_test_casedkeys_invalid_2.kmn @@ -0,0 +1,10 @@ +c Tests cased keys - invalid codes +store(&NAME) 'Test &CasedKeys' +begin Unicode > use(main) + +group(main) using keys + +store(&CasedKeys) [SHIFT K_1] + ++ [K_A] > 'aaah' ++ [SHIFT K_A] > 'AAAH' diff --git a/common/test/keyboards/invalid/source/CERR_406B_test_casedkeys_mnemonic_1.kmn b/common/test/keyboards/invalid/source/CERR_406B_test_casedkeys_mnemonic_1.kmn new file mode 100644 index 0000000000..40b0bbb966 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_406B_test_casedkeys_mnemonic_1.kmn @@ -0,0 +1,11 @@ +c Tests cased keys - invalid with mnemonic layout +store(&NAME) 'Test &CasedKeys' +store(&mnemoniclayout) '1' +begin Unicode > use(main) + +group(main) using keys + +store(&CasedKeys) [K_A] [K_E] [K_I] [K_O] [K_U] [K_1] .. [K_4] + ++ [K_A] > 'aaah' ++ [SHIFT K_A] > 'AAAH' diff --git a/common/test/keyboards/invalid/source/CERR_406C_test_5963_readonlygroup_usenonreadonly.kmn b/common/test/keyboards/invalid/source/CERR_406C_test_5963_readonlygroup_usenonreadonly.kmn new file mode 100644 index 0000000000..8ced461fc7 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_406C_test_5963_readonlygroup_usenonreadonly.kmn @@ -0,0 +1,12 @@ +c should fail to compile, readonly group uses() non-readonly group + +begin Unicode > use(main) + +group(main) using keys + +group(foo) readonly + +'a' > use(bar) + +group(bar) + diff --git a/common/test/keyboards/invalid/source/CERR_406E_test_5963_readonlygroup_misplacedcontext.kmn b/common/test/keyboards/invalid/source/CERR_406E_test_5963_readonlygroup_misplacedcontext.kmn new file mode 100644 index 0000000000..251a3d1033 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_406E_test_5963_readonlygroup_misplacedcontext.kmn @@ -0,0 +1,11 @@ +c Should fail to compile, `context` must be omitted or first statement in output + +begin Unicode > use(main) + +group(main) using keys + +group(foo) readonly + +'a' > use(bar) context + +group(bar) readonly diff --git a/common/test/keyboards/invalid/source/CERR_406F_test_5963_newcontext_2.kmn b/common/test/keyboards/invalid/source/CERR_406F_test_5963_newcontext_2.kmn new file mode 100644 index 0000000000..a2916de43a --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_406F_test_5963_newcontext_2.kmn @@ -0,0 +1,9 @@ +c Should fail to compile, group is not readonly + +begin Unicode > use(main) +begin NewContext > use(NewContext) + +group(NewContext) + +group(main) using keys + diff --git a/common/test/keyboards/invalid/source/CERR_4070_test_5963_postkeystroke_2.kmn b/common/test/keyboards/invalid/source/CERR_4070_test_5963_postkeystroke_2.kmn new file mode 100644 index 0000000000..12bb366150 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4070_test_5963_postkeystroke_2.kmn @@ -0,0 +1,8 @@ +c Should fail to compile, group is not readonly + +begin Unicode > use(main) +begin PostKeystroke > use(PostKeystroke) + +group(PostKeystroke) + +group(main) using keys diff --git a/common/test/keyboards/invalid/source/CERR_4071_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4071_balochi_phonetic.kmn new file mode 100644 index 0000000000..68a8a54246 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4071_balochi_phonetic.kmn @@ -0,0 +1,131 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +c ***** CERR_DuplicateGroup 0x00004071 ****************************** +group(main) using keys +c ******************************************************************* +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' diff --git a/common/test/keyboards/invalid/source/CERR_4072_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4072_balochi_phonetic.kmn new file mode 100644 index 0000000000..ca9f15d3f3 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4072_balochi_phonetic.kmn @@ -0,0 +1,133 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' + +c ***** DuplicateStore 0x00004072 *********************************** +store(©RIGHT) '© ABC' +c ******************************************************************* + +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' diff --git a/common/test/keyboards/invalid/source/CERR_4073_balochi_phonetic.kmn b/common/test/keyboards/invalid/source/CERR_4073_balochi_phonetic.kmn new file mode 100644 index 0000000000..9483a2196d --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_4073_balochi_phonetic.kmn @@ -0,0 +1,132 @@ +store(&VERSION) '10.0' +store(&NAME) 'Balochi Phonetic' +store(&TARGETS) 'any' +store(&KMW_RTL) '1' +store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.4.2' +store(©RIGHT) '© 2017-2021 SIL International' +store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' +store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' +store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' +store(&BITMAP) 'CERR__balochi_phonetic.ico' + +begin Unicode > use(main) + +c ***** CERR_RepeatedBegin 0x00004073 ******************************* +begin Unicode > use(main) +c ******************************************************************* + +group(main) using keys ++ [CTRL B08] > '‎' ++ [CTRL B09] > '‏' ++ [CTRL B10] > '–' ++ [SHIFT CTRL E11] > '“' ++ [SHIFT CTRL E12] > '”' ++ [CTRL E11] > '‘' ++ [CTRL E12] > '’' ++ [CTRL K_K] > 'ء' ++ [CTRL K_D] > 'ذ' ++ [K_EQUAL] > '=' ++ [SHIFT K_8] > '*' ++ [SHIFT K_7] > '&' ++ [SHIFT K_5] > '%' ++ [SHIFT K_4] > '$' ++ [SHIFT K_3] > '#' ++ [SHIFT K_2] > '@' ++ [SHIFT K_1] > '!' ++ [SHIFT K_N] > 'ں' ++ [K_BKSLASH] > '۔' ++ [K_LBRKT] > ']' ++ [K_RBRKT] > '[' ++ [K_F] > 'َ' ++ [K_V] > 'ِ' ++ [K_X] > 'ش' ++ [SHIFT K_H] > 'ح' ++ [SHIFT K_G] > 'ص' ++ [SHIFT K_Y] > 'ي' ++ [CTRL K_0] > '۰' ++ [CTRL K_9] > '۹' ++ [CTRL K_8] > '۸' ++ [CTRL K_7] > '۷' ++ [CTRL K_6] > '۶' ++ [CTRL K_5] > '۵' ++ [CTRL K_4] > '۴' ++ [CTRL K_3] > '۳' ++ [CTRL K_2] > '۲' ++ [CTRL K_1] > '۱' ++ [K_SLASH] > '/' ++ [K_HYPHEN] > '-' ++ [SHIFT K_COLON] > ':' ++ [SHIFT K_QUOTE] > '"' ++ [K_QUOTE] > U+0027 ++ [K_O] > 'ُ' ++ [SHIFT K_O] > 'ْ' ++ [K_BKQUOTE] > 'ء' ++ [SHIFT K_W] > 'أ' ++ [SHIFT K_P] > 'ّ' ++ [SHIFT K_BKQUOTE] > 'ٔ' ++ [SHIFT K_J] > 'ض' ++ [SHIFT K_9] > ')' ++ [SHIFT K_RBRKT] > '{' ++ [SHIFT K_LBRKT] > '}' ++ [SHIFT K_0] > '(' ++ [SHIFT K_SLASH] > '؟' ++ [SHIFT K_K] > 'ع' ++ [SHIFT K_EQUAL] > '«' ++ [SHIFT K_HYPHEN] > '»' ++ [SHIFT K_I] > 'ً' + ++ [SHIFT K_PERIOD] > '‹' ++ [SHIFT K_COMMA] > '›' ++ [SHIFT K_L] > 'ـ' ++ [SHIFT K_U] > 'ۀ' ++ [SHIFT K_B] > 'ة' ++ [SHIFT K_M] > 'غ' ++ [SHIFT K_F] > 'ف' ++ [SHIFT K_E] > 'ۓ' ++ [SHIFT K_Q] > 'ق' ++ [K_0] > '0' ++ [K_9] > '9' ++ [K_8] > '8' ++ [K_7] > '7' ++ [K_6] > '6' ++ [K_5] > '5' ++ [K_4] > '4' ++ [K_3] > '3' ++ [K_2] > '2' ++ [K_1] > '1' ++ [K_I] > 'ێ' ++ [SHIFT K_D] > 'ڈ' ++ [K_G] > 'گ' ++ [K_U] > 'ۆ' ++ [SHIFT K_R] > 'ڑ' ++ [SHIFT K_6] > '‌' ++ [SHIFT K_T] > 'ٹ' ++ [SHIFT K_V] > 'ظ' ++ [SHIFT K_C] > 'ط' ++ [SHIFT K_X] > 'خ' ++ [SHIFT K_Z] > 'ژ' ++ [SHIFT K_S] > 'ث' ++ [SHIFT K_A] > 'آ' ++ [K_PERIOD] > '.' ++ [K_COMMA] > '،' ++ [K_M] > 'م' ++ [K_N] > 'ن' ++ [K_B] > 'ب' ++ [K_C] > 'چ' ++ [K_Z] > 'ز' ++ [K_P] > 'پ' ++ [K_Y] > 'ی' ++ [K_T] > 'ت' ++ [K_R] > 'ر' ++ [K_E] > 'ے' ++ [K_W] > 'و' ++ [K_Q] > 'ئ' ++ [K_COLON] > '؛' ++ [K_L] > 'ل' ++ [K_K] > 'ک' ++ [K_J] > 'ج' ++ [K_H] > 'ه' ++ [K_D] > 'د' ++ [K_S] > 'س' ++ [K_A] > 'ا' diff --git a/common/test/keyboards/invalid/source/CERR_80C0_test_expansion_absurd.kmn b/common/test/keyboards/invalid/source/CERR_80C0_test_expansion_absurd.kmn new file mode 100644 index 0000000000..905093bc87 --- /dev/null +++ b/common/test/keyboards/invalid/source/CERR_80C0_test_expansion_absurd.kmn @@ -0,0 +1,7 @@ +c This file tests absurdly long expansions +store(&NAME) 'Test Expansions' +begin Unicode > use(main) + +group(main) using keys + +store(schar_range) U+0020 .. U+10FFFF diff --git a/common/test/keyboards/invalid/source/CERR__balochi_phonetic.ico b/common/test/keyboards/invalid/source/CERR__balochi_phonetic.ico new file mode 100644 index 0000000000..3fc6a22429 Binary files /dev/null and b/common/test/keyboards/invalid/source/CERR__balochi_phonetic.ico differ diff --git a/common/windows/cpp/include/keymanversion_build.in b/common/windows/cpp/include/keymanversion_build.in index a6a9ee010b..85666ce89c 100644 --- a/common/windows/cpp/include/keymanversion_build.in +++ b/common/windows/cpp/include/keymanversion_build.in @@ -12,6 +12,7 @@ #define KEYMAN_VersionWin "$VersionWin" #define KEYMAN_VersionWin_W L"$VersionWin" +#define KEYMAN_VersionWin_W16 u"$VersionWin" #define KEYMAN_VersionRelease "$VersionRelease" #define KEYMAN_VersionRelease_W L"$VersionRelease" diff --git a/common/windows/cpp/include/legacy_kmx_file.h b/common/windows/cpp/include/legacy_kmx_file.h index eddbf23341..ae18543312 100644 --- a/common/windows/cpp/include/legacy_kmx_file.h +++ b/common/windows/cpp/include/legacy_kmx_file.h @@ -346,6 +346,7 @@ static_assert(sizeof(COMP_STORE) == KEYBOARDFILESTORE_SIZE, "COMP_STORE must be struct COMP_KEY { WORD Key; + WORD _reserved; DWORD Line; DWORD ShiftFlags; DWORD dpOutput; @@ -404,9 +405,18 @@ typedef COMP_STORE *PCOMP_STORE; typedef COMP_KEY *PCOMP_KEY; typedef COMP_GROUP *PCOMP_GROUP; + +typedef struct _COMPILER_OPTIONS { + DWORD dwSize; + BOOL ShouldAddCompilerVersion; + BOOL UseKmcmpLib; +} COMPILER_OPTIONS; + +typedef COMPILER_OPTIONS *PCOMPILER_OPTIONS; + typedef int (CALLBACK *CompilerMessageProc)(int line, DWORD dwMsgCode, LPSTR szText); -extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL FSaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc); // I4865 // I4866 +//extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL FSaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc); // I4865 // I4866 #endif // _COMPILER_H diff --git a/common/windows/cpp/include/vkeys.h b/common/windows/cpp/include/vkeys.h index 47a1daf301..6aa71cc497 100644 --- a/common/windows/cpp/include/vkeys.h +++ b/common/windows/cpp/include/vkeys.h @@ -1,4 +1,12 @@ #pragma once -extern PCWSTR VKeyNames[256]; -extern PCWSTR VKeyISO9995Names[256]; +#ifdef USE_CHAR16_T +#include +#define VKEY_CHAR KMX_UCHAR +#else +#define VKEY_CHAR WCHAR +#define lpuch(x) L ## x +#endif + +extern const VKEY_CHAR* VKeyNames[256]; +extern const VKEY_CHAR* VKeyISO9995Names[256]; diff --git a/common/windows/cpp/src/vkeys.cpp b/common/windows/cpp/src/vkeys.cpp index 4b4710baa9..5bf249b3dd 100644 --- a/common/windows/cpp/src/vkeys.cpp +++ b/common/windows/cpp/src/vkeys.cpp @@ -17,10 +17,9 @@ */ #include "pch.h" +#include "../include/vkeys.h" -#define lpuch(x) L ## x - -PCWSTR VKeyNames[256] = { +const VKEY_CHAR* VKeyNames[256] = { // Key Codes lpuch("K_?00"), // &H0 lpuch("K_LBUTTON"), // &H1 @@ -292,7 +291,7 @@ PCWSTR VKeyNames[256] = { lpuch("K_?FF") // &HFF }; -PCWSTR VKeyISO9995Names[256] = { +const VKEY_CHAR* VKeyISO9995Names[256] = { // Key Codes lpuch(""), // lpuch("K_?00"), // &H0 lpuch(""), // lpuch("K_LBUTTON"), // &H1 diff --git a/common/windows/delphi/components/common_components.identcache b/common/windows/delphi/components/common_components.identcache deleted file mode 100644 index e216a30819..0000000000 Binary files a/common/windows/delphi/components/common_components.identcache and /dev/null differ diff --git a/common/windows/delphi/general/RegistryKeys.pas b/common/windows/delphi/general/RegistryKeys.pas index fcb51ec7d0..57f865f9b2 100644 --- a/common/windows/delphi/general/RegistryKeys.pas +++ b/common/windows/delphi/general/RegistryKeys.pas @@ -393,6 +393,8 @@ const SRegValue_IDEOptAutoSaveBeforeCompiling = 'auto save before compiling'; // CU SRegValue_IDEOptOSKAutoSaveBeforeImporting = 'osk auto save before importing'; // CU + SRegValue_IDEOptUseLegacyCompiler = 'use legacy compiler'; // CU + // Note: keeping 'web host port' reg value name to ensure settings maintained // from version 14.0 and earlier of Keyman Developer. Other values are // new with Keyman Developer 15.0 diff --git a/core/.gitignore b/core/.gitignore index e71a856da3..b02aacc473 100644 --- a/core/.gitignore +++ b/core/.gitignore @@ -1,6 +1,7 @@ .vs/ build/ configure/ +resources/ # cross-compile for meson wasm, built from wasm.build..in wasm.build @@ -10,8 +11,6 @@ TIER.md VERSION.md shellHelperFunctions.sh -src/rust/keyman_keyboard_processor/target/ - # The following files/subdirs are generated by autotools when building ibus-keyman. # They can be removed after we convert ibus-keyman to use meson. .deps/ diff --git a/core/build.sh b/core/build.sh index caaeafb929..3b450d604f 100755 --- a/core/build.sh +++ b/core/build.sh @@ -121,6 +121,14 @@ builder_describe_outputs \ build:arch /core/build/arch/$CONFIGURATION/src/libkmnkbp0.a \ build:wasm /core/build/wasm/$CONFIGURATION/src/libkmnkbp0.a +# Import our standard compiler defines; this is copied from +# /resources/build/meson/standard.meson.build by build.sh, because meson doesn't +# allow us to reference a file outside its root +if builder_has_action configure; then + mkdir -p "$THIS_SCRIPT_PATH/resources" + cp "$KEYMAN_ROOT/resources/build/meson/standard.meson.build" "$THIS_SCRIPT_PATH/resources/meson.build" +fi + # Iterate through all possible targets; note that targets that cannot be built # on the current platform have already been excluded through the archtargets # settings above diff --git a/core/meson.build b/core/meson.build index 47b8860389..81d994124c 100644 --- a/core/meson.build +++ b/core/meson.build @@ -14,27 +14,19 @@ project('keyboardprocessor', 'cpp', 'c', 'warning_level=2'], meson_version: '>=0.53.0') -compiler = meson.get_compiler('cpp') +# Import our standard compiler defines; this is copied from +# /resources/build/standard.meson.build by build.sh, because +# meson doesn't allow us to reference a file outside its root +subdir('resources') lib_version = '0.0.0' py = import('python') python = py.find_installation() -# Once we can assume meson 0.60 we can delete this -# (https://mesonbuild.com/Release-notes-for-0-60-0.html#msvc-compiler-now-assumes-utf8-source-code-by-default) -if compiler.get_id() == 'msvc' - add_global_arguments('/source-charset:utf-8', language: ['c', 'cpp']) -endif - -message('host_machine.system(): ' + host_machine.system()) -message('compiler.get_id(): ' + compiler.get_id()) - -cc = meson.get_compiler('c') - # TODO: Shared includes may use namespaces, etc which need future tidyup. # For now, we use KMN_KBP to inject the km::kbp::kmx namespace -defns = ['-DKMN_KBP'] +defns += ['-DKMN_KBP'] # #define DEBUG when we are on a debug build if get_option('buildtype') == 'debug' diff --git a/core/src/meson.build b/core/src/meson.build index 4694a0b8d7..97b9291646 100644 --- a/core/src/meson.build +++ b/core/src/meson.build @@ -4,58 +4,21 @@ # Authors: Tim Eves (TSE) # -defns += ['-DKMN_KBP_EXPORTING'] version_res = [] -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' - warns = [ - '-Wctor-dtor-privacy', - '-Wdouble-promotion', - '-Wendif-labels', - '-Wno-unknown-pragmas', - '-Wno-missing-field-initializers', - '-Wnon-virtual-dtor', - '-Wshadow' - ] - flags = [ - '-fvisibility=hidden', - '-fvisibility-inlines-hidden' - ] - links = [] - - if compiler.get_id() == 'clang' - warns += [ - '-Wimplicit-fallthrough', - '-Wno-double-promotion', - '-Wshorten-64-to-32' - ] - endif - - if host_machine.system() == 'darwin' - warns += ['-Wno-ctor-dtor-privacy', '-Wno-non-virtual-dtor'] - endif -endif - -if compiler.get_id() == 'msvc' - warns = [] - flags = [] - defns += [ - '-D_SCL_SECURE_NO_WARNINGS', - '-D_CRT_SECURE_NO_WARNINGS', - '-DUNICODE' - ] - links = [] +# TODO: shouldn't this be defined only for dylib and not static lib? +defns += ['-DKMN_KBP_EXPORTING'] +if cpp_compiler.get_id() == 'msvc' + defns += ['-DUNICODE'] # /n = append null # /c65001 = utf-8 file format version_res += import('windows').compile_resources('version.rc', args:['/n','/c65001']) endif -if compiler.get_id() == 'emscripten' - warns = [] - flags = [] - defns = ['-DKMN_KBP'] - links = [] +if cpp_compiler.get_id() == 'emscripten' + # TODO: why do we need this defn here? + defns += ['-DKMN_KBP'] endif kmx_files = files( diff --git a/core/tests/kmx_test_source/meson.build b/core/tests/kmx_test_source/meson.build index 4cfdd5661d..691839047f 100644 --- a/core/tests/kmx_test_source/meson.build +++ b/core/tests/kmx_test_source/meson.build @@ -1,4 +1,6 @@ -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' or compiler.get_id() == 'emscripten' + +# TODO -- why are these differing from the standard.meson.build flags? +if cpp_compiler.get_id() == 'gcc' or cpp_compiler.get_id() == 'clang' or cpp_compiler.get_id() == 'emscripten' warns = [ '-Wno-missing-field-initializers', '-Wno-unused-parameter' diff --git a/core/tests/meson.build b/core/tests/meson.build index 1d37806947..e2e2997582 100644 --- a/core/tests/meson.build +++ b/core/tests/meson.build @@ -22,7 +22,7 @@ if get_option('keyman_core_tests') if get_option('default_library') != 'static' ctypes_void_p_size = ['-c', 'import ctypes; print(ctypes.sizeof(ctypes.c_void_p))'] r = run_command(python, ctypes_void_p_size) - python_ctypes_compatible = r.stdout().to_int() == compiler.sizeof('void *') + python_ctypes_compatible = r.stdout().to_int() == cpp_compiler.sizeof('void *') if not python_ctypes_compatible message('Python ctypes is incompatible with built shared object. Disabling some tests.') endif diff --git a/core/tests/unit/json/meson.build b/core/tests/unit/json/meson.build index 42106976cd..6289d7db0c 100644 --- a/core/tests/unit/json/meson.build +++ b/core/tests/unit/json/meson.build @@ -4,7 +4,7 @@ # Authors: Tim Eves (TSE) # -if compiler.get_id() == 'emscripten' +if cpp_compiler.get_id() == 'emscripten' tests_flags = ['-lnodefs.js'] else tests_flags = [] diff --git a/core/tests/unit/kmnkbd/debug_api.cpp b/core/tests/unit/kmnkbd/debug_api.cpp index b8c5b4c6ec..794b6f86bd 100644 --- a/core/tests/unit/kmnkbd/debug_api.cpp +++ b/core/tests/unit/kmnkbd/debug_api.cpp @@ -312,11 +312,11 @@ void test_store_offsets() { km_kbp_state_debug_item{KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_FLAG_UNICODE, {KM_KBP_VKEY_B, 0, 'b'}}, km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_ENTER, 0, {}, {u"", &gp}}, - // store_offsets: 6 = store #, 1 = index into store, 6 = store #, 0 = index into store + // store_offsets: 5 = store #, 1 = index into store, 6 = store #, 0 = index into store // store: store(diaeresisBase) 'ae' // context: exay - km_kbp_state_debug_item{KM_KBP_DEBUG_RULE_ENTER, 0, {}, {u"exay", &gp, &kpb, {6, 1, 6, 0, 0xFFFF}}}, - km_kbp_state_debug_item{KM_KBP_DEBUG_RULE_EXIT, 0, {}, {u"exay", &gp, &kpb, {6, 1, 6, 0, 0xFFFF}, 6}}, + km_kbp_state_debug_item{KM_KBP_DEBUG_RULE_ENTER, 0, {}, {u"exay", &gp, &kpb, {5, 1, 5, 0, 0xFFFF}}}, + km_kbp_state_debug_item{KM_KBP_DEBUG_RULE_EXIT, 0, {}, {u"exay", &gp, &kpb, {5, 1, 5, 0, 0xFFFF}, 6}}, km_kbp_state_debug_item{KM_KBP_DEBUG_GROUP_EXIT, 0, {}, {u"", &gp, nullptr, {}, 6}}, km_kbp_state_debug_item{KM_KBP_DEBUG_END, 0, {}, {u"", nullptr, nullptr, {}, 6}}, diff --git a/core/tests/unit/kmnkbd/meson.build b/core/tests/unit/kmnkbd/meson.build index 16884298e5..9cf3cdb240 100644 --- a/core/tests/unit/kmnkbd/meson.build +++ b/core/tests/unit/kmnkbd/meson.build @@ -4,7 +4,8 @@ # Authors: Tim Eves (TSE) # -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' or compiler.get_id() == 'emscripten' +# TODO -- why are these differing from the standard.meson.build flags? +if cpp_compiler.get_id() == 'gcc' or cpp_compiler.get_id() == 'clang' or cpp_compiler.get_id() == 'emscripten' warns = [ '-Wno-missing-field-initializers', '-Wno-unused-parameter' @@ -13,7 +14,7 @@ else warns = [] endif -defns+=['-DKMN_KBP_STATIC'] +local_defns = ['-DKMN_KBP_STATIC'] tests = [ ['context-api', 'context_api.cpp'], ['keyboard-api', 'keyboard_api.cpp'], @@ -24,7 +25,7 @@ tests = [ ['kmx_context', 'test_kmx_context.cpp'], ] -if compiler.get_id() == 'emscripten' +if cpp_compiler.get_id() == 'emscripten' tests_flags = ['--embed-file', join_paths(meson.current_source_dir(),'..','kmx','@/')] source_path = '/' test_path = '/' @@ -36,7 +37,7 @@ endif foreach t : tests bin = executable(t[0], t[1], - cpp_args: defns + warns, + cpp_args: local_defns + defns + warns, include_directories: [inc, libsrc], link_args: links + tests_flags, objects: lib.extract_all_objects(recursive: false)) diff --git a/core/tests/unit/kmx/000 - null keyboard.kmx b/core/tests/unit/kmx/000 - null keyboard.kmx index f0e9da6bcc..a4bdc1b835 100644 Binary files a/core/tests/unit/kmx/000 - null keyboard.kmx and b/core/tests/unit/kmx/000 - null keyboard.kmx differ diff --git a/core/tests/unit/kmx/001 - basic input UnicodeI.kmx b/core/tests/unit/kmx/001 - basic input UnicodeI.kmx index fc59fa6a2d..08319803ce 100644 Binary files a/core/tests/unit/kmx/001 - basic input UnicodeI.kmx and b/core/tests/unit/kmx/001 - basic input UnicodeI.kmx differ diff --git a/core/tests/unit/kmx/002 - basic input Unicode.kmx b/core/tests/unit/kmx/002 - basic input Unicode.kmx index 0d2539a641..52a337a2c4 100644 Binary files a/core/tests/unit/kmx/002 - basic input Unicode.kmx and b/core/tests/unit/kmx/002 - basic input Unicode.kmx differ diff --git a/core/tests/unit/kmx/003 - nul.kmx b/core/tests/unit/kmx/003 - nul.kmx index 79046c521a..502012d2c5 100644 Binary files a/core/tests/unit/kmx/003 - nul.kmx and b/core/tests/unit/kmx/003 - nul.kmx differ diff --git a/core/tests/unit/kmx/004 - basic input (shift 2).kmx b/core/tests/unit/kmx/004 - basic input (shift 2).kmx index a31840fa24..583b631a61 100644 Binary files a/core/tests/unit/kmx/004 - basic input (shift 2).kmx and b/core/tests/unit/kmx/004 - basic input (shift 2).kmx differ diff --git a/core/tests/unit/kmx/005 - nul with initial context.kmx b/core/tests/unit/kmx/005 - nul with initial context.kmx index 79046c521a..502012d2c5 100644 Binary files a/core/tests/unit/kmx/005 - nul with initial context.kmx and b/core/tests/unit/kmx/005 - nul with initial context.kmx differ diff --git a/core/tests/unit/kmx/006 - vkey input (shift ctrl).kmx b/core/tests/unit/kmx/006 - vkey input (shift ctrl).kmx index 5320c4405c..4cc728fa2a 100644 Binary files a/core/tests/unit/kmx/006 - vkey input (shift ctrl).kmx and b/core/tests/unit/kmx/006 - vkey input (shift ctrl).kmx differ diff --git a/core/tests/unit/kmx/007 - vkey input (ctrl alt).kmx b/core/tests/unit/kmx/007 - vkey input (ctrl alt).kmx index a76e77d6d4..35538a053f 100644 Binary files a/core/tests/unit/kmx/007 - vkey input (ctrl alt).kmx and b/core/tests/unit/kmx/007 - vkey input (ctrl alt).kmx differ diff --git a/core/tests/unit/kmx/008 - vkey input (ctrl alt 2).kmx b/core/tests/unit/kmx/008 - vkey input (ctrl alt 2).kmx index c197fa727a..c145a31fdd 100644 Binary files a/core/tests/unit/kmx/008 - vkey input (ctrl alt 2).kmx and b/core/tests/unit/kmx/008 - vkey input (ctrl alt 2).kmx differ diff --git a/core/tests/unit/kmx/012 - ralt.kmx b/core/tests/unit/kmx/012 - ralt.kmx index cbab878a8a..a4937e1415 100644 Binary files a/core/tests/unit/kmx/012 - ralt.kmx and b/core/tests/unit/kmx/012 - ralt.kmx differ diff --git a/core/tests/unit/kmx/013 - deadkeys.kmx b/core/tests/unit/kmx/013 - deadkeys.kmx index 68d8f4a313..bc49a108eb 100644 Binary files a/core/tests/unit/kmx/013 - deadkeys.kmx and b/core/tests/unit/kmx/013 - deadkeys.kmx differ diff --git a/core/tests/unit/kmx/014 - groups and virtual keys.kmx b/core/tests/unit/kmx/014 - groups and virtual keys.kmx index 5a24d0909e..b269edcb01 100644 Binary files a/core/tests/unit/kmx/014 - groups and virtual keys.kmx and b/core/tests/unit/kmx/014 - groups and virtual keys.kmx differ diff --git a/core/tests/unit/kmx/015 - ralt 2.kmx b/core/tests/unit/kmx/015 - ralt 2.kmx index f565b4fee4..dcbd1ce1cd 100644 Binary files a/core/tests/unit/kmx/015 - ralt 2.kmx and b/core/tests/unit/kmx/015 - ralt 2.kmx differ diff --git a/core/tests/unit/kmx/017 - space mnemonic kbd.kmx b/core/tests/unit/kmx/017 - space mnemonic kbd.kmx index 797014bda1..a3acc86a9a 100644 Binary files a/core/tests/unit/kmx/017 - space mnemonic kbd.kmx and b/core/tests/unit/kmx/017 - space mnemonic kbd.kmx differ diff --git a/core/tests/unit/kmx/018 - nul testing.kmx b/core/tests/unit/kmx/018 - nul testing.kmx index 13204ad251..b8148492ae 100644 Binary files a/core/tests/unit/kmx/018 - nul testing.kmx and b/core/tests/unit/kmx/018 - nul testing.kmx differ diff --git a/core/tests/unit/kmx/019 - multiple deadkeys.kmx b/core/tests/unit/kmx/019 - multiple deadkeys.kmx index 44113e2d35..05f030c9fc 100644 Binary files a/core/tests/unit/kmx/019 - multiple deadkeys.kmx and b/core/tests/unit/kmx/019 - multiple deadkeys.kmx differ diff --git a/core/tests/unit/kmx/020 - deadkeys and backspace.kmx b/core/tests/unit/kmx/020 - deadkeys and backspace.kmx index 3c245041b0..9cc5703d18 100644 Binary files a/core/tests/unit/kmx/020 - deadkeys and backspace.kmx and b/core/tests/unit/kmx/020 - deadkeys and backspace.kmx differ diff --git a/core/tests/unit/kmx/021 - options.kmx b/core/tests/unit/kmx/021 - options.kmx index c5550c1018..30a0af13f5 100644 Binary files a/core/tests/unit/kmx/021 - options.kmx and b/core/tests/unit/kmx/021 - options.kmx differ diff --git a/core/tests/unit/kmx/022 - options with preset.kmx b/core/tests/unit/kmx/022 - options with preset.kmx index 57f3720de7..56e5f132c8 100644 Binary files a/core/tests/unit/kmx/022 - options with preset.kmx and b/core/tests/unit/kmx/022 - options with preset.kmx differ diff --git a/core/tests/unit/kmx/023 - options with save.kmx b/core/tests/unit/kmx/023 - options with save.kmx index f6689ce47e..fae122dc48 100644 Binary files a/core/tests/unit/kmx/023 - options with save.kmx and b/core/tests/unit/kmx/023 - options with save.kmx differ diff --git a/core/tests/unit/kmx/024 - options with save and preset.kmx b/core/tests/unit/kmx/024 - options with save and preset.kmx index 029a136f78..66f4375a70 100644 Binary files a/core/tests/unit/kmx/024 - options with save and preset.kmx and b/core/tests/unit/kmx/024 - options with save and preset.kmx differ diff --git a/core/tests/unit/kmx/025 - options with reset.kmx b/core/tests/unit/kmx/025 - options with reset.kmx index e1595c8466..2278476e80 100644 Binary files a/core/tests/unit/kmx/025 - options with reset.kmx and b/core/tests/unit/kmx/025 - options with reset.kmx differ diff --git a/core/tests/unit/kmx/026 - system stores.kmx b/core/tests/unit/kmx/026 - system stores.kmx index da2e0b30c0..04bca4f2f1 100644 Binary files a/core/tests/unit/kmx/026 - system stores.kmx and b/core/tests/unit/kmx/026 - system stores.kmx differ diff --git a/core/tests/unit/kmx/027 - system stores 2.kmx b/core/tests/unit/kmx/027 - system stores 2.kmx index 43d58aaa2b..1109fcec8e 100644 Binary files a/core/tests/unit/kmx/027 - system stores 2.kmx and b/core/tests/unit/kmx/027 - system stores 2.kmx differ diff --git a/core/tests/unit/kmx/028 - smp.kmx b/core/tests/unit/kmx/028 - smp.kmx index da89544b3e..4fa3be656c 100644 Binary files a/core/tests/unit/kmx/028 - smp.kmx and b/core/tests/unit/kmx/028 - smp.kmx differ diff --git a/core/tests/unit/kmx/029 - beep.kmx b/core/tests/unit/kmx/029 - beep.kmx index 1e809bdb33..112e411793 100644 Binary files a/core/tests/unit/kmx/029 - beep.kmx and b/core/tests/unit/kmx/029 - beep.kmx differ diff --git a/core/tests/unit/kmx/030 - multiple groups.kmx b/core/tests/unit/kmx/030 - multiple groups.kmx index 9b75bfca40..5b69b1ff9a 100644 Binary files a/core/tests/unit/kmx/030 - multiple groups.kmx and b/core/tests/unit/kmx/030 - multiple groups.kmx differ diff --git a/core/tests/unit/kmx/031 - caps lock.kmx b/core/tests/unit/kmx/031 - caps lock.kmx index e317f13349..dfa7f88b9d 100644 Binary files a/core/tests/unit/kmx/031 - caps lock.kmx and b/core/tests/unit/kmx/031 - caps lock.kmx differ diff --git a/core/tests/unit/kmx/032 - caps control.kmx b/core/tests/unit/kmx/032 - caps control.kmx index 67d7ac2102..a2b7b8eb6c 100644 Binary files a/core/tests/unit/kmx/032 - caps control.kmx and b/core/tests/unit/kmx/032 - caps control.kmx differ diff --git a/core/tests/unit/kmx/033 - caps always off.kmx b/core/tests/unit/kmx/033 - caps always off.kmx index 08bd6521fe..3fb585f6f1 100644 Binary files a/core/tests/unit/kmx/033 - caps always off.kmx and b/core/tests/unit/kmx/033 - caps always off.kmx differ diff --git a/core/tests/unit/kmx/034 - options double set reset.kmx b/core/tests/unit/kmx/034 - options double set reset.kmx index 92ef0da0ad..fc10961e66 100644 Binary files a/core/tests/unit/kmx/034 - options double set reset.kmx and b/core/tests/unit/kmx/034 - options double set reset.kmx differ diff --git a/core/tests/unit/kmx/035 - options double set staged.kmx b/core/tests/unit/kmx/035 - options double set staged.kmx index 61970709ea..59425f3ef1 100644 Binary files a/core/tests/unit/kmx/035 - options double set staged.kmx and b/core/tests/unit/kmx/035 - options double set staged.kmx differ diff --git a/core/tests/unit/kmx/036 - options - double reset staged.kmx b/core/tests/unit/kmx/036 - options - double reset staged.kmx index 2cc4b21993..31b1a4ae69 100644 Binary files a/core/tests/unit/kmx/036 - options - double reset staged.kmx and b/core/tests/unit/kmx/036 - options - double reset staged.kmx differ diff --git a/core/tests/unit/kmx/037 - options - double reset.kmx b/core/tests/unit/kmx/037 - options - double reset.kmx index 2e8120f6e5..ae5159921f 100644 Binary files a/core/tests/unit/kmx/037 - options - double reset.kmx and b/core/tests/unit/kmx/037 - options - double reset.kmx differ diff --git a/core/tests/unit/kmx/038 - punctkeys.kmx b/core/tests/unit/kmx/038 - punctkeys.kmx index 2b892d51b8..e891f0e0ea 100644 Binary files a/core/tests/unit/kmx/038 - punctkeys.kmx and b/core/tests/unit/kmx/038 - punctkeys.kmx differ diff --git a/core/tests/unit/kmx/039 - generic ctrlalt.kmx b/core/tests/unit/kmx/039 - generic ctrlalt.kmx index 897c02624d..2973cd654a 100644 Binary files a/core/tests/unit/kmx/039 - generic ctrlalt.kmx and b/core/tests/unit/kmx/039 - generic ctrlalt.kmx differ diff --git a/core/tests/unit/kmx/040 - long context.kmx b/core/tests/unit/kmx/040 - long context.kmx index c6025add0a..af2d7ccd75 100644 Binary files a/core/tests/unit/kmx/040 - long context.kmx and b/core/tests/unit/kmx/040 - long context.kmx differ diff --git a/core/tests/unit/kmx/041 - long context and deadkeys.kmx b/core/tests/unit/kmx/041 - long context and deadkeys.kmx index d92dbb46ee..99cf960488 100644 Binary files a/core/tests/unit/kmx/041 - long context and deadkeys.kmx and b/core/tests/unit/kmx/041 - long context and deadkeys.kmx differ diff --git a/core/tests/unit/kmx/042 - long context and split deadkeys.kmx b/core/tests/unit/kmx/042 - long context and split deadkeys.kmx index 49b539ffb1..ae9fbdbacb 100644 Binary files a/core/tests/unit/kmx/042 - long context and split deadkeys.kmx and b/core/tests/unit/kmx/042 - long context and split deadkeys.kmx differ diff --git a/core/tests/unit/kmx/043 - output and keystroke.kmx b/core/tests/unit/kmx/043 - output and keystroke.kmx index 120b42e2bc..5df945b1d6 100644 Binary files a/core/tests/unit/kmx/043 - output and keystroke.kmx and b/core/tests/unit/kmx/043 - output and keystroke.kmx differ diff --git a/core/tests/unit/kmx/044 - if and context.kmx b/core/tests/unit/kmx/044 - if and context.kmx index ae70c6ab81..480e68693e 100644 Binary files a/core/tests/unit/kmx/044 - if and context.kmx and b/core/tests/unit/kmx/044 - if and context.kmx differ diff --git a/core/tests/unit/kmx/045 - deadkey and context.kmx b/core/tests/unit/kmx/045 - deadkey and context.kmx index 2ae9ff2eb6..725dd101a4 100644 Binary files a/core/tests/unit/kmx/045 - deadkey and context.kmx and b/core/tests/unit/kmx/045 - deadkey and context.kmx differ diff --git a/core/tests/unit/kmx/046 - deadkey and contextex.kmx b/core/tests/unit/kmx/046 - deadkey and contextex.kmx index 8a1a97b556..2fb81f9a0c 100644 Binary files a/core/tests/unit/kmx/046 - deadkey and contextex.kmx and b/core/tests/unit/kmx/046 - deadkey and contextex.kmx differ diff --git a/core/tests/unit/kmx/047 - caps always off initially on.kmx b/core/tests/unit/kmx/047 - caps always off initially on.kmx index a890017c4c..3a91117bc0 100644 Binary files a/core/tests/unit/kmx/047 - caps always off initially on.kmx and b/core/tests/unit/kmx/047 - caps always off initially on.kmx differ diff --git a/core/tests/unit/kmx/048 - modifier keys keep context.kmx b/core/tests/unit/kmx/048 - modifier keys keep context.kmx index 52c70f61e0..0cfbea883b 100644 Binary files a/core/tests/unit/kmx/048 - modifier keys keep context.kmx and b/core/tests/unit/kmx/048 - modifier keys keep context.kmx differ diff --git a/core/tests/unit/kmx/fixtures/binary/meson.build b/core/tests/unit/kmx/fixtures/binary/meson.build index 5998a3b1e9..da509ff619 100644 --- a/core/tests/unit/kmx/fixtures/binary/meson.build +++ b/core/tests/unit/kmx/fixtures/binary/meson.build @@ -9,7 +9,7 @@ # Build all binary test keyboards -if compiler.get_id() == 'emscripten' +if cpp_compiler.get_id() == 'emscripten' binary_test_path = '/' else binary_test_path = meson.current_build_dir() diff --git a/core/tests/unit/kmx/kmx_imsample.kmx b/core/tests/unit/kmx/kmx_imsample.kmx index 754c0985ae..544c0c85f4 100644 Binary files a/core/tests/unit/kmx/kmx_imsample.kmx and b/core/tests/unit/kmx/kmx_imsample.kmx differ diff --git a/core/tests/unit/kmx/kmx_imx.cpp b/core/tests/unit/kmx/kmx_imx.cpp index 2afb9c63bc..dbfa2fbf7e 100644 --- a/core/tests/unit/kmx/kmx_imx.cpp +++ b/core/tests/unit/kmx/kmx_imx.cpp @@ -31,10 +31,10 @@ km_kbp_option_item test_env_opts[] = KM_KBP_OPTIONS_END }; -std::map expected_imx_map { {4, "imsample.dll:DF"}, - {5, "imsample.dll:func2"}, - {6, "another.dll:func3"}, - {7, "another.dll:func4"}, +std::map expected_imx_map { {3, "imsample.dll:DF"}, + {4, "imsample.dll:func2"}, + {5, "another.dll:func3"}, + {6, "another.dll:func4"}, }; std::map g_extract_imx_map; @@ -97,7 +97,9 @@ uint8_t test_imx_callback(km_kbp_state *state, uint32_t imx_id, void *callback_o std::cout << "test_imx_callback function name: " << it->second << std::endl; km_kbp_action_item *a_items = new km_kbp_action_item[10]; switch (imx_id) { - case 4: + // this corresponds to store index; if these change, the values + // here will need updating + case 3: a_items[0].type = KM_KBP_IT_CHAR; a_items[0].character = km_kbp_usv('X'); @@ -105,7 +107,7 @@ uint8_t test_imx_callback(km_kbp_state *state, uint32_t imx_id, void *callback_o a_items[2].type = KM_KBP_IT_END; km_kbp_state_queue_action_items(state, a_items); break; - case 5: + case 4: a_items[0].type = KM_KBP_IT_CHAR; a_items[0].character = km_kbp_usv('Y'); @@ -116,7 +118,7 @@ uint8_t test_imx_callback(km_kbp_state *state, uint32_t imx_id, void *callback_o a_items[3].type = KM_KBP_IT_END; km_kbp_state_queue_action_items(state, a_items); break; - case 6: + case 5: a_items[0].type = KM_KBP_IT_BACK; a_items[0].backspace.expected_type = KM_KBP_BT_CHAR; a_items[0].backspace.expected_value = km_kbp_usv('A'); @@ -125,7 +127,7 @@ uint8_t test_imx_callback(km_kbp_state *state, uint32_t imx_id, void *callback_o a_items[2].type = KM_KBP_IT_END; km_kbp_state_queue_action_items(state, a_items); break; - case 7: { + case 6: { a_items[0].type = KM_KBP_IT_INVALIDATE_CONTEXT; a_items[1].type = KM_KBP_IT_END; km_kbp_state_queue_action_items(state, a_items); diff --git a/core/tests/unit/kmx/kmx_key_list.kmx b/core/tests/unit/kmx/kmx_key_list.kmx index efb6540fce..12a2bf8fc4 100644 Binary files a/core/tests/unit/kmx/kmx_key_list.kmx and b/core/tests/unit/kmx/kmx_key_list.kmx differ diff --git a/core/tests/unit/kmx/meson.build b/core/tests/unit/kmx/meson.build index 048b888011..f4ededbf95 100644 --- a/core/tests/unit/kmx/meson.build +++ b/core/tests/unit/kmx/meson.build @@ -5,7 +5,8 @@ # History: 19 Oct 2018 - TSE - Added test for context API functions. # -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' or compiler.get_id() == 'emscripten' +# TODO -- why are these differing from the standard.meson.build flags? +if cpp_compiler.get_id() == 'gcc' or cpp_compiler.get_id() == 'clang' or cpp_compiler.get_id() == 'emscripten' warns = [ '-Wno-missing-field-initializers', '-Wno-unused-parameter' @@ -15,7 +16,7 @@ else endif -if compiler.get_id() == 'emscripten' +if cpp_compiler.get_id() == 'emscripten' tests_flags = ['--embed-file', join_paths(meson.current_source_dir(),'@/')] # we have to link in files from the binary folder also as the binary tests # use the kmx test runner. @@ -108,7 +109,7 @@ else cat_cmd = [find_program('cat', required: true)] endif -if compiler.get_id() == 'emscripten' +if cpp_compiler.get_id() == 'emscripten' # The .kmx files are linked in to the unit test, # so kmcomp is too late here kmcomp = disabler() @@ -206,7 +207,7 @@ if kmcomp.found() endforeach else foreach kbd : tests - if compiler.get_id() == 'emscripten' + if cpp_compiler.get_id() == 'emscripten' kbd_basename = kbd else kbd_basename = 'k_' + kbd.underscorify().to_lower() diff --git a/core/tests/unit/ldml/meson.build b/core/tests/unit/ldml/meson.build index 6ef36cc5e8..8a0c3c4ec4 100644 --- a/core/tests/unit/ldml/meson.build +++ b/core/tests/unit/ldml/meson.build @@ -4,7 +4,8 @@ # Authors: Marc Durdin # -if compiler.get_id() == 'gcc' or compiler.get_id() == 'clang' or compiler.get_id() == 'emscripten' +# TODO -- why are these differing from the standard.meson.build flags? +if cpp_compiler.get_id() == 'gcc' or cpp_compiler.get_id() == 'clang' or cpp_compiler.get_id() == 'emscripten' warns = [ '-Wno-missing-field-initializers', '-Wno-unused-parameter' @@ -37,7 +38,7 @@ endif # Build ldml test executable -if compiler.get_id() == 'emscripten' +if cpp_compiler.get_id() == 'emscripten' tests_flags = ['--embed-file', join_paths(meson.current_build_dir(),'keyboards','@')] tests_flags += ['--embed-file', join_paths(meson.current_build_dir(),'invalid-keyboards','@')] test_path = '/' diff --git a/developer/src/Makefile b/developer/src/Makefile index b2059a0cd9..6f9efcca7b 100644 --- a/developer/src/Makefile +++ b/developer/src/Makefile @@ -3,9 +3,9 @@ # !ifdef NODELPHI -TARGETS=build-tools kmcmpdll kmanalyze kmdecomp server kmc +TARGETS=build-tools kmcmplib kmcmpdll kmanalyze kmdecomp server kmc !else -TARGETS=build-tools kmcmpdll kmcomp kmanalyze kmconvert tike samples setup inst kmdecomp server kmc +TARGETS=build-tools kmcmplib kmcmpdll kmcomp kmanalyze kmconvert tike samples setup inst kmdecomp server kmc !endif EXCLUDEPATHDEFINES=1 @@ -29,7 +29,11 @@ imsample: .virtual cd $(DEVELOPER_ROOT)\src\imsample $(MAKE) $(TARGET) -kmcmpdll: .virtual +kmcmplib: global-versions .virtual + cd $(DEVELOPER_ROOT)\src\kmcmplib + $(MAKE) $(TARGET) + +kmcmpdll: kmcmplib .virtual cd $(DEVELOPER_ROOT)\src\kmcmpdll $(MAKE) $(TARGET) diff --git a/developer/src/common/delphi/compiler/compile.pas b/developer/src/common/delphi/compiler/compile.pas index ba136af973..9b304b39d8 100644 --- a/developer/src/common/delphi/compiler/compile.pas +++ b/developer/src/common/delphi/compiler/compile.pas @@ -64,7 +64,7 @@ type FILE_KEY = record Key: WCHAR; // WCHAR -- actually a WORD - packing: WORD; + LineStoreIndex: WORD; Line: DWORD; ShiftFlags: DWORD; dpOutput: PWideChar; // from start of key structure @@ -174,6 +174,7 @@ type TCompilerOptions = record dwSize: DWORD; ShouldAddCompilerVersion: BOOL; + UseKmcmpLib: BOOL; end; COMPILER_OPTIONS = TCompilerOptions; diff --git a/developer/src/ext/json-schema-validator/json-validator.cpp b/developer/src/ext/json-schema-validator/json-validator.cpp index 8e8ffaee68..28988f37b5 100644 --- a/developer/src/ext/json-schema-validator/json-validator.cpp +++ b/developer/src/ext/json-schema-validator/json-validator.cpp @@ -683,8 +683,8 @@ void json_validator::validate_object(const json &instance, const json &schema, c static std::size_t utf8_length(const std::string &s) { size_t len = 0; - for (const unsigned char &c : s) - if ((c & 0xc0) != 0x80) + for (const char &c : s) + if (((unsigned char)c & 0xc0) != 0x80) len++; return len; } diff --git a/developer/src/kmcmpdll/Compiler.cpp b/developer/src/kmcmpdll/Compiler.cpp index 6289f95d11..ae522b987a 100644 --- a/developer/src/kmcmpdll/Compiler.cpp +++ b/developer/src/kmcmpdll/Compiler.cpp @@ -90,6 +90,20 @@ #include "UnreachableRules.h" #include "CheckForDuplicates.h" +/* + Following kmcmplib definitions are translated to Windows types + because we can't import the kmcmplib headers. The structure + sizes and alignments have been manually verified. +*/ + + +#include "../kmcmplib/include/kmcmplibapi.h" +/*typedef int (*kmcmp_CompilerMessageProc)(int line, KMX_DWORD dwMsgCode, PKMX_STR szText, void* context); +extern "C" BOOL kmcmp_CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL FSaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgProc, void* context); // I4865 // I4866 +extern "C" BOOL kmcmp_CompileKeyboardFileToBuffer(PSTR pszInfile, void* pfkBuffer, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgProc, void* context, int Target); // I4865 // I4866 +extern "C" void kmcmp_Keyman_Diagnostic(int mode) ; +extern "C" BOOL kmcmp_SetCompilerOptions(PCOMPILER_OPTIONS options);*/ + int xatoi(PWSTR *p); int atoiW(PWSTR p); void safe_wcsncpy(PWSTR out, PWSTR in, int cbMax); @@ -214,6 +228,7 @@ BOOL FSaveDebug, FCompilerWarningsAsErrors, FWarnDeprecatedCode; // I4865 // BOOL FShouldAddCompilerVersion = TRUE; BOOL FOldCharPosMatching = FALSE, FMnemonicLayout = FALSE; NamedCodeConstants *CodeConstants = NULL; + int BeginLine[4]; /* Compile target */ @@ -288,21 +303,33 @@ BOOL AddCompileMessage(DWORD msg) return FALSE; } -typedef struct _COMPILER_OPTIONS { - DWORD dwSize; - BOOL ShouldAddCompilerVersion; -} COMPILER_OPTIONS; - -typedef COMPILER_OPTIONS *PCOMPILER_OPTIONS; +bool flag_use_new_kmcomp = true; // flag to switch to new kmcompx extern "C" BOOL __declspec(dllexport) SetCompilerOptions(PCOMPILER_OPTIONS options) { if(!options || options->dwSize < sizeof(COMPILER_OPTIONS)) { return FALSE; } + + flag_use_new_kmcomp = options->UseKmcmpLib; + + //printf("\n---> started in SetCompilerOptions() of kmcmpdll\n"); + if ( flag_use_new_kmcomp ) + { + KMCMP_COMPILER_OPTIONS kmcmp_options = {0}; + kmcmp_options.dwSize = sizeof(KMCMP_COMPILER_OPTIONS); + kmcmp_options.ShouldAddCompilerVersion = options->ShouldAddCompilerVersion; + return kmcmp_SetCompilerOptions(&kmcmp_options); + } + //printf("---> stayed in SetCompilerOptions() of kmcmpdll\n"); + FShouldAddCompilerVersion = options->ShouldAddCompilerVersion; return TRUE; } +int kmcmpMsgproc(int line, uint32_t dwMsgCode, char* szText, void* context) { + return static_cast(context)(line, dwMsgCode, szText); +} + extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL ASaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc) // I4865 // I4866 { HANDLE hInfile = INVALID_HANDLE_VALUE, hOutfile = INVALID_HANDLE_VALUE; @@ -310,6 +337,15 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR p DWORD len; char str[260]; + //printf("\n---> started in CompileKeyboardFile() of kmcmpdll\n"); + + if ( flag_use_new_kmcomp ) + { + return kmcmp_CompileKeyboardFile(pszInfile, pszOutfile, ASaveDebug, ACompilerWarningsAsErrors,AWarnDeprecatedCode, kmcmpMsgproc, (void*) pMsgProc); + } + + //printf("---> stayed in CompileKeyboardFile() of kmcmpdll\n"); + FSaveDebug = ASaveDebug; FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865 FWarnDeprecatedCode = AWarnDeprecatedCode; // I4866 @@ -331,6 +367,8 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR p currentLine = 0; nErrors = 0; + AddCompileString("NOTE: Using legacy compiler"); + hInfile = CreateFileA(pszInfile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hInfile == INVALID_HANDLE_VALUE) SetError(CERR_InfileNotExist); @@ -392,6 +430,15 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFileToBuffer(PSTR pszInfile DWORD len; char str[260]; + //printf("\n---> started in CompileKeyboardFileToBuffer() of kmcmpdll\n"); + if ( flag_use_new_kmcomp ) + { + return kmcmp_CompileKeyboardFileToBuffer( pszInfile, (void*) pfkBuffer, ACompilerWarningsAsErrors, AWarnDeprecatedCode, kmcmpMsgproc, (void*) pMsgProc, Target); + } + + //printf("---> stayed in CompileKeyboardFileToBuffer() of kmcmpdll\n"); + + FSaveDebug = TRUE; // I3681 FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865 FWarnDeprecatedCode = AWarnDeprecatedCode; // I4866 @@ -413,6 +460,8 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFileToBuffer(PSTR pszInfile currentLine = 0; nErrors = 0; + AddCompileString("NOTE: Using legacy compiler"); + hInfile = CreateFileA(pszInfile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hInfile == INVALID_HANDLE_VALUE) SetError(CERR_InfileNotExist); @@ -611,7 +660,6 @@ DWORD ProcessBeginLine(PFILE_KEYBOARD fk, PWSTR p) if(BeginLine[BeginMode] != -1) { return CERR_RepeatedBegin; } - BeginLine[BeginMode] = currentLine; if ((msg = GetRHS(fk, p, tstr, 80, (int)(INT_PTR)(p - pp), FALSE)) != CERR_None) return msg; @@ -942,10 +990,23 @@ int cmpkeys(const void *key, const void *elem) { if (akey->Line < aelem->Line) return -1; if (akey->Line > aelem->Line) return 1; - return 0; + if(akey->Key == aelem->Key) { + if(akey->ShiftFlags == aelem->ShiftFlags) { + return akey->LineStoreIndex - aelem->LineStoreIndex; + } + return akey->ShiftFlags - aelem->ShiftFlags; + } + return akey->Key - aelem->Key; } if (l1 < l2) return 1; if (l1 > l2) return -1; + if(akey->Key == aelem->Key) { + if(akey->ShiftFlags == aelem->ShiftFlags) { + return akey->LineStoreIndex - aelem->LineStoreIndex; + } + return akey->ShiftFlags - aelem->ShiftFlags; + } + return akey->Key - aelem->Key; } return(char_key - char_elem); // akey->Key - aelem->Key); } @@ -1728,6 +1789,7 @@ CheckOutputIsReadonly(const PFILE_KEYBOARD fk, const PWSTR output) { // I4867 wcscpy_s(kp->dpContext, wcslen(pklIn) + 1, pklIn); // I3481 kp->Line = currentLine; + kp->LineStoreIndex = 0; // Finished if we are not using keys @@ -1869,6 +1931,7 @@ DWORD ExpandKp(PFILE_KEYBOARD fk, PFILE_KEY kpp, DWORD storeIndex) k->ShiftFlags = 0; } k->Line = kpp->Line; + k->LineStoreIndex = (WORD)n; ExpandKp_ReplaceIndex(fk, k, keyIndex, n); } @@ -3315,6 +3378,7 @@ DWORD WriteCompiledKeyboard(PFILE_KEYBOARD fk, HANDLE hOutfile) offset += gp->cxKeyArray * sizeof(COMP_KEY); for (j = 0; j < gp->cxKeyArray; j++, kp++, fkp++) { + kp->_reserved = 0; kp->Key = fkp->Key; if (FSaveDebug) kp->Line = fkp->Line; else kp->Line = 0; kp->ShiftFlags = fkp->ShiftFlags; diff --git a/developer/src/kmcmpdll/Compiler.rc b/developer/src/kmcmpdll/Compiler.rc index d5b2e5289f..b1922ac9b4 100644 --- a/developer/src/kmcmpdll/Compiler.rc +++ b/developer/src/kmcmpdll/Compiler.rc @@ -91,12 +91,6 @@ END STRINGTABLE BEGIN CERR_InvalidSystemStore "Invalid system store name found" - CERR_CallIsProfessionalFeature - "Call() is only available in Keyman Developer Professional" - CERR_IncludeCodesIsProfessionalFeature - "&IncludeCodes is only available in Keyman Developer Professional" - CERR_MnemonicLayoutIsProfessionalFeature - "&MnemonicLayout is only available in Keyman Developer Professional" CERR_60FeatureOnly_VirtualCharKey "Virtual character keys require VERSION 6.0" CERR_VersionAlreadyIncluded diff --git a/developer/src/kmcmpdll/UnreachableRules.cpp b/developer/src/kmcmpdll/UnreachableRules.cpp index a5c6519ef3..84bff8752c 100644 --- a/developer/src/kmcmpdll/UnreachableRules.cpp +++ b/developer/src/kmcmpdll/UnreachableRules.cpp @@ -16,7 +16,8 @@ std::wstring MakeHashKeyFromFileKey(PFILE_KEY kp) { std::wstringstream key; key << kp->Key << "," << kp->ShiftFlags << ","; - if (kp->dpContext) key << kp->dpContext; + if (kp->dpContext) + key << kp->dpContext; return key.str(); } diff --git a/developer/src/kmcmpdll/comperr.h b/developer/src/kmcmpdll/comperr.h index 258825dab4..3d1658af0e 100644 --- a/developer/src/kmcmpdll/comperr.h +++ b/developer/src/kmcmpdll/comperr.h @@ -101,9 +101,6 @@ #define CERR_InvalidNamedCode 0x0000403F #define CERR_InvalidSystemStore 0x00004040 -#define CERR_CallIsProfessionalFeature 0x00004041 -#define CERR_IncludeCodesIsProfessionalFeature 0x00004042 -#define CERR_MnemonicLayoutIsProfessionalFeature 0x00004043 #define CERR_60FeatureOnly_VirtualCharKey 0x00004044 #define CERR_VersionAlreadyIncluded 0x00004045 diff --git a/developer/src/kmcmpdll/compfile.h b/developer/src/kmcmpdll/compfile.h index f58e041830..4fd6e68eb5 100644 --- a/developer/src/kmcmpdll/compfile.h +++ b/developer/src/kmcmpdll/compfile.h @@ -86,6 +86,7 @@ typedef FILE_STORE *PFILE_STORE; struct FILE_KEY { WCHAR Key; // WCHAR for consistency; only a byte used however + WORD LineStoreIndex; DWORD Line; DWORD ShiftFlags; PWSTR dpOutput; // from start of key structure diff --git a/developer/src/kmcmpdll/json-validation.cpp b/developer/src/kmcmpdll/json-validation.cpp index 9516925ad0..c69dcbbb5e 100644 --- a/developer/src/kmcmpdll/json-validation.cpp +++ b/developer/src/kmcmpdll/json-validation.cpp @@ -4,6 +4,11 @@ #include +typedef bool (*kmcmp_ValidateJsonMessageProc)(int64_t offset, const char* szText, void* context); +extern "C" bool kmcmp_ValidateJsonFile(std::fstream& f, std::fstream& fd, kmcmp_ValidateJsonMessageProc MessageProc, void* context); + +extern bool flag_use_new_kmcomp; + using nlohmann::json; using nlohmann::json_uri; using nlohmann::json_schema_draft4::json_validator; @@ -24,7 +29,19 @@ static void loader(const json_uri &uri, json &schema) } } +bool kmcmpMessageProc(int64_t offset, const char* szText, void* context) { + return ((ValidateJsonMessageProc)context)(offset, szText); +} + extern "C" BOOL __declspec(dllexport) ValidateJsonFile(PWSTR pwszSchemaFile, PWSTR pwszJsonFile, ValidateJsonMessageProc MessageProc) { + + if ( flag_use_new_kmcomp ) + { + std::fstream f(pwszSchemaFile); + std::fstream fd(pwszJsonFile); + return kmcmp_ValidateJsonFile(f, fd, kmcmpMessageProc, (void*)MessageProc); + } + std::fstream f(pwszSchemaFile); if (!f.good()) { MessageProc(-1, "Schema file could not be loaded."); diff --git a/developer/src/kmcmpdll/kmcmpdll.vcxproj b/developer/src/kmcmpdll/kmcmpdll.vcxproj index 9d6a5f1921..384487cfcd 100644 --- a/developer/src/kmcmpdll/kmcmpdll.vcxproj +++ b/developer/src/kmcmpdll/kmcmpdll.vcxproj @@ -89,21 +89,25 @@ $(VC_IncludePath);$(WindowsSDK_IncludePath);$(KEYMAN_ROOT)\developer\src\ext\json;$(KEYMAN_ROOT)\developer\src\ext\json-schema-validator $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(KEYMAN_ROOT)\developer\src\kmcmplib\build\x86\$(Configuration)\src;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) $(VC_IncludePath);$(WindowsSDK_IncludePath);$(KEYMAN_ROOT)\developer\src\ext\json;$(KEYMAN_ROOT)\developer\src\ext\json-schema-validator $(ProjectDir)obj\$(Platform)\$(Configuration)\ $(ProjectName).x64 $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(KEYMAN_ROOT)\developer\src\kmcmplib\build\x64\$(Configuration)\src;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) $(VC_IncludePath);$(WindowsSDK_IncludePath);$(KEYMAN_ROOT)\developer\src\ext\json;$(KEYMAN_ROOT)\developer\src\ext\json-schema-validator + $(KEYMAN_ROOT)\developer\src\kmcmplib\build\x86\$(Configuration)\src;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86) $(VC_IncludePath);$(WindowsSDK_IncludePath);$(KEYMAN_ROOT)\developer\src\ext\json;$(KEYMAN_ROOT)\developer\src\ext\json-schema-validator $(ProjectDir)obj\$(Platform)\$(Configuration)\ $(ProjectName).x64 $(ProjectDir)bin\$(Platform)\$(Configuration)\ + $(KEYMAN_ROOT)\developer\src\kmcmplib\build\x64\$(Configuration)\src;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64) @@ -138,7 +142,7 @@ $(KEYMAN_ROOT)\windows\src\global\inc - version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies) + libkmcmplib.a;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies) true true @@ -186,7 +190,7 @@ $(KEYMAN_ROOT)\windows\src\global\inc - version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies) + libkmcmplib.a;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies) true true Windows @@ -229,7 +233,7 @@ $(KEYMAN_ROOT)\windows\src\global\inc - version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies) + libkmcmplib.a;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies) true true true @@ -273,7 +277,7 @@ $(KEYMAN_ROOT)\windows\src\global\inc - version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies) + libkmcmplib.a;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies) true true true diff --git a/developer/src/kmcmpdll/pch.h b/developer/src/kmcmpdll/pch.h index 473c0799a2..dcba976ea7 100644 --- a/developer/src/kmcmpdll/pch.h +++ b/developer/src/kmcmpdll/pch.h @@ -11,12 +11,12 @@ #include #include -#include "../../../../common/windows/cpp/include/legacy_kmx_file.h" -#include "../../../../common/windows/cpp/include/xstring.h" +#include "../../../common/windows/cpp/include/legacy_kmx_file.h" +#include "../../../common/windows/cpp/include/xstring.h" -#include "../../../../common/windows/cpp/include/registry.h" -#include "../../../../common/windows/cpp/include/unicode.h" -#include "../../../../common/windows/cpp/include/crc32.h" +#include "../../../common/windows/cpp/include/registry.h" +#include "../../../common/windows/cpp/include/unicode.h" +#include "../../../common/windows/cpp/include/crc32.h" #include #include diff --git a/developer/src/kmcmplib/.gitignore b/developer/src/kmcmplib/.gitignore new file mode 100644 index 0000000000..9418ac1e3e --- /dev/null +++ b/developer/src/kmcmplib/.gitignore @@ -0,0 +1,4 @@ +build/ +wasm.build +tests/keyboards/ +resources/ \ No newline at end of file diff --git a/developer/src/kmcmplib/Makefile b/developer/src/kmcmplib/Makefile new file mode 100644 index 0000000000..4acc7d3cfb --- /dev/null +++ b/developer/src/kmcmplib/Makefile @@ -0,0 +1,39 @@ +# +# KMCmpLib Makefile +# + +!include ..\Defines.mak + +!ifdef GIT_BASH_FOR_KEYMAN +CALLER=$(GIT_BASH_FOR_KEYMAN) +!else +CALLER=start /wait +!endif +!ifdef DEBUG +BUILD_DEBUG=-d +!else +BUILD_DEBUG= +!endif + +build: .virtual + $(CALLER) ./build.sh clean configure build $(BUILD_DEBUG) + +clean: + $(CALLER) ./build.sh clean $(BUILD_DEBUG) + +signcode: + @rem Not required + +wrap-symbols: + @rem Not required + +test-manifest: + @rem This target needed as dependency for TIKE and KMCMPDLL + +test: + $(CALLER) ./build.sh test $(BUILD_DEBUG) + +install: + @rem Not required + +!include ..\Target.mak diff --git a/developer/src/kmcmplib/build.bat b/developer/src/kmcmplib/build.bat new file mode 100644 index 0000000000..7b5dcf110d --- /dev/null +++ b/developer/src/kmcmplib/build.bat @@ -0,0 +1,121 @@ +@echo off +rem **************************************************************** +rem Run build.sh, not this file directly, to build on Windows. +rem **************************************************************** +setlocal enabledelayedexpansion + +if "%1"=="" goto help +if "%1"=="all" goto all +if "%1"=="x86" goto build +if "%1"=="x64" goto build + +echo "Invalid parameter." +goto help + +rem ---------------------------------- + +:help +echo Usage: %0 x86^|x64^|all debug^|release [configure] [build] [test] [additional params for meson/ninja] +echo or +echo Usage: %0 x86^|x64 -c +echo -c will leave your environment configured for Visual Studio for selected platform. +echo. +echo Otherwise, %0 is intended to be used by build.sh, not directly. +echo At least one of 'configure', 'build', or 'test' is required. +goto :eof + +rem ---------------------------------- + +:all + +setlocal +cd %KEYMAN_ROOT%\developer\src\kmcmplib +cmd /c build.bat x86 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! + +cd %KEYMAN_ROOT%\developer\src\kmcmplib +cmd /c build.bat x64 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! + +goto :eof + +rem ---------------------------------- + +:build + +set ARCH=%1 +shift + +if "%1"=="-c" goto :setup + +echo === Locating Visual Studio === + +rem From https://github.com/microsoft/vswhere +for /f "usebackq delims=#" %%a in (`"%programfiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -property installationPath`) do ( + set VsDevCmd_Path=%%a\Common7\Tools\VsDevCmd.bat +) + +if errorlevel 1 ( + echo vswhere failed [!errorlevel!] + exit /b !errorlevel! +) + +if not exist "!VsDevCmd_Path!" ( + echo Could not find vsdevcmd.bat [!VsDevCmd_Path!] + exit /b 1 +) + +echo === Configuring VC++ === +set VSCMD_SKIP_SENDTELEMETRY=1 +call "!VsDevCmd_Path!" -arch=!ARCH! -no_logo -startdir=none || exit !errorlevel! + +cd %KEYMAN_ROOT%\developer\src\kmcmplib + +set BUILDTYPE=%1 +shift + +set STATIC_LIBRARY=--default-library both + +set COMMAND=%1 +shift + +if "!COMMAND!" == "configure" ( + echo === Configuring Keyman KMX Compiler for Windows !ARCH! !BUILDTYPE! === + if exist build\!ARCH!\!BUILDTYPE! rd /s/q build\!ARCH!\!BUILDTYPE! + meson setup build\!ARCH!\!BUILDTYPE! !STATIC_LIBRARY! --buildtype !BUILDTYPE! --werror %1 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! + shift +) + +if "!COMMAND!" == "build" ( + echo === Building Keyman KMX Compiler for Windows !ARCH! !BUILDTYPE! === + cd build\!ARCH!\!BUILDTYPE! || exit !errorlevel! + ninja %1 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! + cd ..\..\.. + shift +) + +if "!COMMAND!" == "test" ( + echo === Testing Keyman KMX Compiler for Windows !ARCH! !BUILDTYPE! === + cd build\!ARCH!\!BUILDTYPE! || exit !errorlevel! + meson test --print-errorlogs %1 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! + cd ..\..\.. + shift +) + +goto :eof + +rem ---------------------------------- + +:setup + +rem Standalone build, so we'll make the environment available to the caller +rem Also setup +rem Note: Visual Studio 2022 doesn't provide vcvarsall.bat, so we'll have to find a different solution +endlocal +for /f "usebackq delims=#" %%a in (`"%programfiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -property installationPath`) do ( + set VsDevCmd_Path=%%a\Common7\Tools\VsDevCmd.bat +) + +set VSCMD_SKIP_SENDTELEMETRY=1 +"!VsDevCmd_Path!" -arch=!ARCH! -no_logo -startdir=none +goto :eof + +rem ---------------------------------- diff --git a/developer/src/kmcmplib/build.sh b/developer/src/kmcmplib/build.sh new file mode 100755 index 0000000000..c4e7d05ed2 --- /dev/null +++ b/developer/src/kmcmplib/build.sh @@ -0,0 +1,119 @@ +#!/usr/bin/env bash + +set -e +set -u + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$THIS_SCRIPT_PATH/checkout-keyboards.inc.sh" +. "$THIS_SCRIPT_PATH/commands.inc.sh" + +cd "$THIS_SCRIPT_PATH" + +################################ Main script ################################ + +# +# Restrict available targets to those that can be built on the current system +# + +archtargets=(":wasm WASM build") + +case $BUILDER_OS in + win) + archtargets+=( + ":x86 32-bit Windows (x86) build" + ":x64 64-bit Windows (x64) build" + ) + ;; + mac|linux) + archtargets+=( + ":arch Linux or mac build -- current architecture" + ) + ;; +esac + +# TODO: consider using "linux" and "mac" instead of "arch"? +# ":linux Build for current Linux architecture" +# ":mac Build for current macOS architecture" + +builder_describe \ + "Build Keyman KMX Compiler Static Library +Libraries will be built in 'build///src'. + * : 'debug' or 'release' (see --debug flag) + * All parameters after '--' are passed to meson or ninja +" \ + "clean" \ + "configure" \ + "build" \ + "test" \ + "${archtargets[@]}" \ + "--debug,-d configuration is 'debug', not 'release'" \ + "--test=opt_tests,-t test[s] to run (space separated)" + +builder_parse "$@" + +if builder_has_option --debug; then + CONFIGURATION=debug +else + CONFIGURATION=release +fi + +builder_describe_outputs \ + configure:x86 build/x86/$CONFIGURATION/build.ninja \ + configure:x64 build/x64/$CONFIGURATION/build.ninja \ + configure:arch build/arch/$CONFIGURATION/build.ninja \ + configure:wasm build/wasm/$CONFIGURATION/build.ninja \ + build:x86 build/x86/$CONFIGURATION/src/libkmcmplib.a \ + build:x64 build/x64/$CONFIGURATION/src/libkmcmplib.a \ + build:arch build/arch/$CONFIGURATION/src/libkmcmplib.a \ + build:wasm build/wasm/$CONFIGURATION/src/libkmcmplib.a + +TARGET_PATH="$THIS_SCRIPT_PATH/build" + +# Iterate through all possible targets; note that targets that cannot be built +# on the current platform have already been excluded through the archtargets +# settings above +targets=(wasm x86 x64 arch) + +do_action() { + local action_function=do_$1 + for target in "${targets[@]}"; do + MESON_PATH="$TARGET_PATH/$target/$CONFIGURATION" + $action_function $target + done +} + +locate_keyboards_repo + +# Note, we have a 'global' clean and also a per-arch clean +if builder_start_action clean; then + rm -rf "$THIS_SCRIPT_PATH/tests/keyboards" + builder_finish_action success clean +fi + +do_action clean + +# Note, we have a 'global' configure and also a per-arch configure +if builder_start_action configure; then + # Import our standard compiler defines; this is copied from + # /resources/build/meson/standard.meson.build by build.sh, because meson doesn't + # allow us to reference a file outside its root + mkdir -p "$THIS_SCRIPT_PATH/resources" + cp "$KEYMAN_ROOT/resources/build/meson/standard.meson.build" "$THIS_SCRIPT_PATH/resources/meson.build" + + # We have to checkout the keyboards repo in a 'configure' action because + # otherwise meson will not get the right list of keyboard source files, + # even though we only use it in the 'test' action + checkout_keyboards + builder_finish_action success configure +fi + +do_action configure + +do_action build +do_action test diff --git a/developer/src/kmcmplib/checkout-keyboards.inc.sh b/developer/src/kmcmplib/checkout-keyboards.inc.sh new file mode 100644 index 0000000000..defcb479ef --- /dev/null +++ b/developer/src/kmcmplib/checkout-keyboards.inc.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# +# Look for the keyboards repo, either at $KEYBOARDS_ROOT, or, if that is not +# set, prepare to clone from GitHub. It will always be cloned to ./keyboards/ +# +function locate_keyboards_repo() { + if [[ ! -f "$THIS_SCRIPT_PATH/tests/keyboards_commit_ref.txt" ]]; then + builder_die "keyboards_commit_ref.txt does not exist, run prep.sh" + fi + + if [[ ! -d "$THIS_SCRIPT_PATH/tests/fixtures" ]]; then + builder_die "fixtures folder does not exist, run prep.sh" + fi + + if [[ -z "${KEYBOARDS_ROOT+x}" ]]; then + # KEYBOARDS_ROOT is not set, so we'll clone from GitHub + export KEYBOARDS_SOURCE_REPO=https://github.com/keymanapp/keyboards + builder_echo warning "\$KEYBOARDS_ROOT variable not set, using $KEYBOARDS_SOURCE_REPO" + builder_echo warning "For faster test builds, setup a local clone of that repo and set" + builder_echo warning "\$KEYBOARDS_ROOT to point to it" + else + builder_echo "\$KEYBOARDS_ROOT variable is $KEYBOARDS_ROOT" + export KEYBOARDS_SOURCE_REPO="$KEYBOARDS_ROOT" + fi +} + +# +# Shallow-clone of keyboards repo at commit found in keyboards_commit_ref.txt +# +function checkout_keyboards() { + local KEYBOARDS_COMMIT=$(cat $THIS_SCRIPT_PATH/tests/keyboards_commit_ref.txt) + + mkdir -p "$THIS_SCRIPT_PATH/tests/keyboards" + pushd "$THIS_SCRIPT_PATH/tests/keyboards" > /dev/null + + if [[ ! -f "build.sh" ]]; then + # We'll have to init the folder and clone the repo + builder_echo "Checking out keyboards repository at $THIS_SCRIPT_PATH/tests/keyboards" + git init + git remote add origin "$KEYBOARDS_SOURCE_REPO" + fi + + # Make sure we have fetched the commit, as it may have changed + # from a previous build + builder_echo "Fetching commit $KEYBOARDS_COMMIT in repo at $THIS_SCRIPT_PATH/tests/keyboards" + git fetch --depth=1 --no-tags origin "$KEYBOARDS_COMMIT" + git reset --hard "$KEYBOARDS_COMMIT" + + popd > /dev/null +} diff --git a/developer/src/kmcmplib/commands.inc.sh b/developer/src/kmcmplib/commands.inc.sh new file mode 100644 index 0000000000..3bc7881621 --- /dev/null +++ b/developer/src/kmcmplib/commands.inc.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash + +# ---------------------------------------------------------------------------- +# clean +# ---------------------------------------------------------------------------- + +do_clean() { + # clean: note build/ will be left, but build// should be gone + local target=$1 + builder_start_action clean:$target || return 0 + + rm -rf "$MESON_PATH" + builder_finish_action success clean:$target +} + +# ---------------------------------------------------------------------------- +# configure +# ---------------------------------------------------------------------------- + +do_configure() { + local target=$1 + builder_start_action configure:$target || return 0 + + local STANDARD_MESON_ARGS= + + if [[ $target == wasm ]]; then + # do_configure_wasm + locate_emscripten + build_meson_cross_file_for_wasm + STANDARD_MESON_ARGS="--cross-file wasm.defs.build --cross-file wasm.build --default-library static" + fi + + if [[ $target =~ ^(x86|x64)$ ]]; then + cmd //C build.bat $target $CONFIGURATION configure "${builder_extra_params[@]}" + else + pushd "$THIS_SCRIPT_PATH" > /dev/null + # Additional arguments are used by Linux build, e.g. -Dprefix=${INSTALLDIR} + meson setup "$MESON_PATH" --werror --buildtype $CONFIGURATION $STANDARD_MESON_ARGS "${builder_extra_params[@]}" + popd > /dev/null + fi + builder_finish_action success configure:$target +} + +# ---------------------------------------------------------------------------- +# build +# ---------------------------------------------------------------------------- + +do_build() { + local target=$1 + builder_start_action build:$target || return 0 + + if [[ $target =~ ^(x86|x64)$ ]]; then + # Build the meson targets, both x86 and x64 also + # We need to use a batch file here so we can get + # the Visual Studio build environment with vcvarsall.bat + # TODO: if PATH is the only variable required, let's try and + # eliminate this difference in the build process + cmd //C build.bat $target $CONFIGURATION build "${builder_extra_params[@]}" + else + pushd "$MESON_PATH" > /dev/null + ninja + popd > /dev/null + fi + builder_finish_action success build:$target +} + +# ---------------------------------------------------------------------------- +# test +# ---------------------------------------------------------------------------- + +do_test() { + local target=$1 + builder_start_action test:$target || return 0 + + # Works on a local clone of keyboards repository, to avoid clobbering + # user's existing keyboards repo, if present + checkout_keyboards + + if [[ $target =~ ^(x86|x64)$ ]]; then + cmd //C build.bat $target $CONFIGURATION test "${builder_extra_params[@]}" + else + pushd "$MESON_PATH" > /dev/null + meson test "${builder_extra_params[@]}" + popd > /dev/null + fi + builder_finish_action success test:$target +} + +# ---------------------------------------------------------------------------- +# install and uninstall +# ---------------------------------------------------------------------------- + +do_install() { + do_command install $1 +} + +do_uninstall() { + do_command uninstall $1 +} + +do_command() { + local command=$1 + local target=$2 + builder_start_action $command:$target || return 0 + pushd "$MESON_PATH" > /dev/null + ninja $command + popd > /dev/null + builder_finish_action success $command:$target +} + +# ---------------------------------------------------------------------------- +# utility functions +# ---------------------------------------------------------------------------- + +# +# We don't want to rely on emcc being on the path, because Emscripten puts far +# too many things onto the path (in particular for us, node). +# +# The following comment suggests that we don't need emcc on the path. +# https://github.com/emscripten-core/emscripten/issues/4848#issuecomment-1097357775 +# +# So we try and locate emcc in common locations ourselves. The search pattern +# is: +# +# 1. Look for $EMSCRIPTEN_BASE (our primary emscripten variable), which should +# point to the folder that emcc is located in +# 2. Look for $EMCC which should point to the emcc executable +# 3. Look for emcc on the path +# +locate_emscripten() { + if [[ -z ${EMSCRIPTEN_BASE+x} ]]; then + if [[ -z ${EMCC+x} ]]; then + local EMCC=`which emcc` + [[ -z $EMCC ]] && fail "locate_emscripten: Could not locate emscripten (emcc) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" + fi + [[ -x $EMCC ]] || fail "locate_emscripten: Variable EMCC ($EMCC) does not point to a valid executable emcc" + EMSCRIPTEN_BASE="$(dirname "$EMCC")" + fi + + [[ -x ${EMSCRIPTEN_BASE}/emcc ]] || fail "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to emcc's folder" +} + +build_meson_cross_file_for_wasm() { + if [ $BUILDER_OS == win ]; then + local R=$(cygpath -w $(echo $EMSCRIPTEN_BASE) | sed 's_\\_\\\\_g') + else + local R=$(echo $EMSCRIPTEN_BASE | sed 's_/_\\/_g') + fi + sed -e "s/\$EMSCRIPTEN_BASE/$R/g" wasm.build.$BUILDER_OS.in > wasm.build +} \ No newline at end of file diff --git a/developer/src/kmcmplib/getversion.bat b/developer/src/kmcmplib/getversion.bat new file mode 100644 index 0000000000..dcab02e4d9 --- /dev/null +++ b/developer/src/kmcmplib/getversion.bat @@ -0,0 +1,3 @@ +@echo off +REM Get the version number from VERSION.md +more ..\..\..\VERSION.md diff --git a/developer/src/kmcmplib/getversion.sh b/developer/src/kmcmplib/getversion.sh new file mode 100755 index 0000000000..cd02c07929 --- /dev/null +++ b/developer/src/kmcmplib/getversion.sh @@ -0,0 +1,4 @@ +#!/bin/bash +# Get the version number from VERSION.md +VERSIONFILE=../../../VERSION.md +cat $VERSIONFILE diff --git a/developer/src/kmcmplib/include/keyman_version.h.in b/developer/src/kmcmplib/include/keyman_version.h.in new file mode 100644 index 0000000000..e55e7b70c7 --- /dev/null +++ b/developer/src/kmcmplib/include/keyman_version.h.in @@ -0,0 +1,9 @@ +#define keyman_version_stringify(x) keyman_version_to_string(x) +#define keyman_version_to_string(x) #x + +// Product versioning + +#define KEYMAN_VERSION_MAJOR @majorver@ +#define KEYMAN_VERSION_MINOR @minorver@ +#define KEYMAN_VERSION_PATCH @patchver@ +#define KEYMAN_VERSION_STRING keyman_version_stringify(@majorver@ ## . ## @minorver@ ## . ## @patchver@ ## .0) diff --git a/developer/src/kmcmplib/include/kmcmplibapi.h b/developer/src/kmcmplib/include/kmcmplibapi.h new file mode 100644 index 0000000000..c3e43f2574 --- /dev/null +++ b/developer/src/kmcmplib/include/kmcmplibapi.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +typedef struct _KMCMP_COMPILER_OPTIONS { + uint32_t dwSize; + bool ShouldAddCompilerVersion; +} KMCMP_COMPILER_OPTIONS; + +extern "C" bool kmcmp_SetCompilerOptions( + KMCMP_COMPILER_OPTIONS* options +); + +typedef int (*kmcmp_CompilerMessageProc)(int line, uint32_t dwMsgCode, char* szText, void* context); + +extern "C" uint32_t kmcmp_CompileKeyboardFile( + char* pszInfile, + char* pszOutfile, + bool ASaveDebug, + bool ACompilerWarningsAsErrors, + bool AWarnDeprecatedCode, + kmcmp_CompilerMessageProc pMsgproc, + void* AmsgprocContext +); + +extern "C" uint32_t kmcmp_CompileKeyboardFileToBuffer( + char* pszInfile, + void* pfkBuffer, + bool ACompilerWarningsAsErrors, + bool AWarnDeprecatedCode, + kmcmp_CompilerMessageProc pMsgproc, + void* AmsgprocContext, + int Target +); + +typedef bool (*kmcmp_ValidateJsonMessageProc)(int64_t offset, const char* szText, void* context); + +extern "C" bool kmcmp_ValidateJsonFile( + std::fstream& f, + std::fstream& fd, + kmcmp_ValidateJsonMessageProc MessageProc, + void* context +); diff --git a/developer/src/kmcmplib/include/kmcompx.h b/developer/src/kmcmplib/include/kmcompx.h new file mode 100644 index 0000000000..33a76beb74 --- /dev/null +++ b/developer/src/kmcmplib/include/kmcompx.h @@ -0,0 +1,49 @@ +#pragma once +#include + +// TODO: merge with kmcmplib.h + +typedef wchar_t KMX_WCHART; +typedef KMX_DWORD * PKMX_DWORD; +typedef char * PKMX_STR; +typedef KMX_WCHAR* PKMX_WCHAR ; + +// TODO: these defines are copied out of unicode.h, because unicode.h still +// has windows-specific types. These should be remerged at a future date + +#define Uni_IsSurrogate1(ch) ((ch) >= 0xD800 && (ch) <= 0xDBFF) +#define Uni_IsSurrogate2(ch) ((ch) >= 0xDC00 && (ch) <= 0xDFFF) +#define Uni_IsSMP(ch) ((ch) >= 0x10000) + +#define Uni_SurrogateToUTF32(ch, cl) (((ch) - 0xD800) * 0x400 + ((cl) - 0xDC00) + 0x10000) + +#define Uni_UTF32ToSurrogate1(ch) (((ch) - 0x10000) / 0x400 + 0xD800) +#define Uni_UTF32ToSurrogate2(ch) (((ch) - 0x10000) % 0x400 + 0xDC00) + +#define Uni_UTF16ToUTF32(p) (Uni_IsSurrogate1(*(p)) && Uni_IsSurrogate2(*((p)+1)) ? Uni_SurrogateToUTF32(*(p), *((p)+1)) : *(p)) + +// +// C++17 definition of Windows _countof +// TODO: remove use of _countof throughout +// + +#ifndef _MSC_VER +#include + +template < typename T, size_t N > +size_t _countof( T ( & arr )[ N ] ) +{ + return std::extent< T[ N ] >::value; +} + +#endif + +// For MSVC, we want to use the std CRT library functions +// and ignore security warnings at this time, so we are +// not forced to use the non-portable _s variants. +#define _CRT_SECURE_NO_DEPRECATE + +// strtok_s on MSVC works the same as strtok_r +#ifdef _MSC_VER +#define strtok_r strtok_s +#endif \ No newline at end of file diff --git a/developer/src/kmcmplib/include/meson.build b/developer/src/kmcmplib/include/meson.build new file mode 100644 index 0000000000..6da3128763 --- /dev/null +++ b/developer/src/kmcmplib/include/meson.build @@ -0,0 +1,25 @@ +# +# Keyman is copyright (C) SIL International. MIT License. +# +# Cross platform build script to build headers +# + +project_ver = meson.project_version().split('.') + +cfg = configuration_data() +cfg.set('majorver', project_ver[0]) +cfg.set('minorver', project_ver[1]) +cfg.set('patchver', project_ver[2]) + +configure_file( + configuration: cfg, + input: 'keyman_version.h.in', + output: 'keyman_version.h', +) + +inc = include_directories( # '.', is_system: true) + '.', + '../../../../common/include', + '../../ext/json', + '../../ext/json-schema-validator' +) diff --git a/developer/src/kmcmplib/meson.build b/developer/src/kmcmplib/meson.build new file mode 100644 index 0000000000..ae8fd6ac62 --- /dev/null +++ b/developer/src/kmcmplib/meson.build @@ -0,0 +1,24 @@ +# +# Keyman is copyright (C) SIL International. MIT License. +# +# Cross platform build script to compile kmcmplib and tests +# + +project('kmcmplib', 'cpp', 'c', + version: run_command(find_program('getversion.bat', 'getversion.sh')).stdout().strip(), + license: 'MIT', + default_options : ['buildtype=release', + 'cpp_std=c++14', + 'b_vscrt=static_from_buildtype', + 'default_library=static']) + +# Import our standard compiler defines; this is copied from +# /resources/build/standard.meson.build by build.sh, because +# meson doesn't allow us to reference a file outside its root +subdir('resources') + +# ------------------------------------------------------------ + +subdir('include') +subdir('src') +subdir('tests') diff --git a/developer/src/kmcmplib/src/CasedKeys.cpp b/developer/src/kmcmplib/src/CasedKeys.cpp new file mode 100644 index 0000000000..d832c4408c --- /dev/null +++ b/developer/src/kmcmplib/src/CasedKeys.cpp @@ -0,0 +1,154 @@ + +#include "pch.h" + +#include "compfile.h" +#include "comperr.h" +#include "../../../../common/windows/cpp/include/vkeys.h" +#include "kmcmplib.h" + +#include "CharToKeyConversion.h" +#include "kmx_u16.h" +#include "xstring.h" + +namespace kmcmp { + extern KMX_BOOL FMnemonicLayout; // TODO: these globals should be consolidated one day +} + +KMX_DWORD ExpandCapsRule(PFILE_GROUP gp, PFILE_KEY kpp, PFILE_STORE sp); + +KMX_DWORD VerifyCasedKeys(PFILE_STORE sp) { + assert(sp != NULL); + + if (kmcmp::FMnemonicLayout) { + // The &CasedKeys system store is not supported for + // mnemonic layouts in 14.0 + return CERR_CasedKeysNotSupportedWithMnemonicLayout; + } + + // We will rewrite this store with virtual keys + + PKMX_WCHAR p = sp->dpString; + PKMX_WCHAR buf = new KMX_WCHAR[u16len(p) * 5 + 1]; // extended keys are 5 units long, so this is the max length + PKMX_WCHAR q = buf; + + while (*p) { + KMX_UINT key = 0, shift = 0; + if (*p != UC_SENTINEL) { + if (!kmcmp::MapUSCharToVK(*p, &key, &shift)) { + return CERR_CasedKeysMustContainOnlyVirtualKeys; + } + if (shift & K_SHIFTFLAG) { + return CERR_CasedKeysMustNotIncludeShiftStates; + } + } + else { + if (*(p + 1) != CODE_EXTENDED) { + return CERR_CasedKeysMustContainOnlyVirtualKeys; + } + shift = *(p + 2); + key = *(p + 3); + if (shift != ISVIRTUALKEY) { + return CERR_CasedKeysMustNotIncludeShiftStates; + } + } + *q++ = UC_SENTINEL; + *q++ = CODE_EXTENDED; + *q++ = shift; + *q++ = key; + *q++ = UC_SENTINEL_EXTENDEDEND; + *q = 0; + + p = incxstr(p); + } + + delete[] sp->dpString; + sp->dpString = buf; + + return CERR_None; +} + +KMX_DWORD ExpandCapsRulesForGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) { + assert(fk != NULL); + assert(gp != NULL); + + if (kmcmp::FMnemonicLayout) { + // The &CasedKeys system store is not supported for + // mnemonic layouts in 14.0 + return CERR_None; + } + + PFILE_STORE sp = FindSystemStore(fk, TSS_CASEDKEYS); + if (!sp) { + // If there is no &CasedKeys system store, then we do not + // process the key + return CERR_None; + } + + KMX_DWORD msg; + // ExpandCapsRule may add extra rules at the end of gp->dpKeyArray, + // reallocating it, so we (a) cache the original length, and (b) + // dereference the array every call + int cxKeyArray = gp->cxKeyArray; + for (int i = 0; i < cxKeyArray; i++) { + if ((msg = ExpandCapsRule(gp, &gp->dpKeyArray[i], sp)) != CERR_None) { + return msg; + } + } + return CERR_None; +} + +KMX_DWORD ExpandCapsRule(PFILE_GROUP gp, PFILE_KEY kpp, PFILE_STORE sp) { + KMX_UINT key = kpp->Key; + KMX_UINT shift = kpp->ShiftFlags; + + if (shift == 0) { + // Convert US key cap to a virtual key + if (!kmcmp::MapUSCharToVK(kpp->Key, &key, &shift)) { + return CERR_None; + } + } + + if (shift & (CAPITALFLAG | NOTCAPITALFLAG)) { + // Don't attempt expansion if either Caps Lock flag is specified in the key rule + return CERR_None; + } + + PKMX_WCHAR p = sp->dpString; + for (; *p; p = incxstr(p)) { + // We've already verified that the store contains only virtual keys in VerifyCasedKeys + if (*(p + 3) == key) { + break; + } + } + + if (!*p) { + // This key is not modified by Caps Lock + return CERR_None; + } + + // This key is modified by Caps Lock, so we need to duplicate this rule + PFILE_KEY k = new FILE_KEY[gp->cxKeyArray + 1]; + if (!k) return CERR_CannotAllocateMemory; + memcpy(k, gp->dpKeyArray, gp->cxKeyArray * sizeof(FILE_KEY)); + + kpp = &k[(int)(kpp - gp->dpKeyArray)]; + + delete gp->dpKeyArray; + gp->dpKeyArray = k; + gp->cxKeyArray++; + + k = &k[gp->cxKeyArray - 1]; + k->dpContext = new KMX_WCHAR[u16len(kpp->dpContext) + 1]; + k->dpOutput = new KMX_WCHAR[u16len(kpp->dpOutput) + 1]; + u16cpy(k->dpContext, kpp->dpContext ); // copy the context. + u16cpy(k->dpOutput, kpp->dpOutput ); // copy the output. + + k->Key = key; + k->Line = kpp->Line; + // Add the CAPITAL FLAG, invert shift flag for the rule + k->ShiftFlags = (shift ^ K_SHIFTFLAG) | CAPITALFLAG; + kpp->Key = key; + kpp->ShiftFlags = shift | NOTCAPITALFLAG; + + return CERR_None; +} diff --git a/developer/src/kmcmplib/src/CasedKeys.h b/developer/src/kmcmplib/src/CasedKeys.h new file mode 100644 index 0000000000..e97cc59389 --- /dev/null +++ b/developer/src/kmcmplib/src/CasedKeys.h @@ -0,0 +1,4 @@ +#pragma once + +KMX_DWORD VerifyCasedKeys(PFILE_STORE sp); +KMX_DWORD ExpandCapsRulesForGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp); diff --git a/developer/src/kmcmplib/src/CharToKeyConversion.cpp b/developer/src/kmcmplib/src/CharToKeyConversion.cpp new file mode 100644 index 0000000000..0c2b652d09 --- /dev/null +++ b/developer/src/kmcmplib/src/CharToKeyConversion.cpp @@ -0,0 +1,207 @@ + +#include "pch.h" +#include "CharToKeyConversion.h" + +/* Following VKeys come from Windows */ + +#define VK_COLON 0xBA +#define VK_EQUAL 0xBB +#define VK_COMMA 0xBC +#define VK_HYPHEN 0xBD +#define VK_PERIOD 0xBE +#define VK_SLASH 0xBF +#define VK_ACCENT 0xC0 +#define VK_LBRKT 0xDB +#define VK_BKSLASH 0xDC +#define VK_RBRKT 0xDD +#define VK_QUOTE 0xDE +#define VK_xDF 0xDF + +#define VK_NUMPAD0 0x60 +#define VK_NUMPAD9 0x69 +#define VK_SPACE 0x20 + + +/* Following code lifted from syskbd.cpp and tweaked for compiler use. Todo: consolidate */ + +KMX_WCHAR kmcmp::VKToChar(KMX_WORD keyCode, KMX_UINT shiftFlags) +{ + KMX_CHAR shiftedDigit[] = ")!@#$%^&*("; + int n, Shift; + + if (!(shiftFlags & ISVIRTUALKEY)) return keyCode; + + if (shiftFlags & (LCTRLFLAG | RCTRLFLAG | LALTFLAG | RALTFLAG)) return 0; + + if (keyCode >= '0' && keyCode <= '9') + { + n = keyCode - '0'; + return ((shiftFlags & K_SHIFTFLAG) ? shiftedDigit[n] : keyCode); + } + + if (keyCode >= 'A' && keyCode <= 'Z') + { + Shift = (shiftFlags & K_SHIFTFLAG); + if (shiftFlags & (CAPITALFLAG)) Shift = !Shift; + return (Shift ? keyCode : keyCode + 32); + } + + if (keyCode >= VK_NUMPAD0 && keyCode <= VK_NUMPAD9) + { + if (!(shiftFlags & NUMLOCKFLAG)) return 0; + return keyCode - (VK_NUMPAD0 - '0'); + } + + Shift = (shiftFlags & K_SHIFTFLAG); + + switch (keyCode) + { + case VK_ACCENT: + return Shift ? '~' : '`'; + case VK_HYPHEN: + return Shift ? '_' : '-'; + case VK_EQUAL: + return Shift ? '+' : '='; + case VK_BKSLASH: + return Shift ? '|' : 92; + case VK_LBRKT: + return Shift ? '{' : '['; + case VK_RBRKT: + return Shift ? '}' : ']'; + case VK_COLON: + return Shift ? ':' : ';'; + case VK_QUOTE: + return Shift ? '"' : 39; + case VK_COMMA: + return Shift ? '<' : ','; + case VK_PERIOD: + return Shift ? '>' : '.'; + case VK_SLASH: + return Shift ? '?' : '/'; + case VK_SPACE: + return ' '; + } + return 0; + //keyCode; +} + + +/* This array is lifted from preservedkeymap.cpp */ +// TODO: share this +const struct +{ + KMX_UINT key; + KMX_BOOL shift; +} USCharMap[] = { + { VK_SPACE, FALSE }, // 20 ' ' + { '1', TRUE }, // 21 '!' + { VK_QUOTE, TRUE }, // 22 '"' + { '3', TRUE }, // 23 '#' + { '4', TRUE }, // 24 '$' + { '5', TRUE }, // 25 '%' + { '7', TRUE }, // 26 '&' + { VK_QUOTE, FALSE }, // 27 ''' + { '9', TRUE }, // 28 '(' + { '0', TRUE }, // 29 ')' + { '8', TRUE }, // 2A '*' + { VK_EQUAL, TRUE }, // 2B '+' + { VK_COMMA, FALSE }, // 2C ',' + { VK_HYPHEN, FALSE }, // 2D '-' + { VK_PERIOD, FALSE }, // 2E '.' + { VK_SLASH, FALSE }, // 2F '/' + + { '0', FALSE }, // 30 '0' + { '1', FALSE }, // 31 '1' + { '2', FALSE }, // 32 '2' + { '3', FALSE }, // 33 '3' + { '4', FALSE }, // 34 '4' + { '5', FALSE }, // 35 '5' + { '6', FALSE }, // 36 '6' + { '7', FALSE }, // 37 '7' + { '8', FALSE }, // 38 '8' + { '9', FALSE }, // 39 '9' + { VK_COLON, TRUE }, // 3A ':' + { VK_COLON, FALSE }, // 3B ';' + { VK_COMMA, TRUE }, // 3C '<' + { VK_EQUAL, FALSE }, // 3D '=' + { VK_PERIOD, TRUE }, // 3E '>' + { VK_SLASH, TRUE }, // 3F '?' + + { '2', TRUE }, // 40 '@' + { 'A', TRUE }, // 41 'A' + { 'B', TRUE }, // 42 'B' + { 'C', TRUE }, // 43 'C' + { 'D', TRUE }, // 44 'D' + { 'E', TRUE }, // 45 'E' + { 'F', TRUE }, // 46 'F' + { 'G', TRUE }, // 47 'G' + { 'H', TRUE }, // 48 'H' + { 'I', TRUE }, // 49 'I' + { 'J', TRUE }, // 4A 'J' + { 'K', TRUE }, // 4B 'K' + { 'L', TRUE }, // 4C 'L' + { 'M', TRUE }, // 4D 'M' + { 'N', TRUE }, // 4E 'N' + { 'O', TRUE }, // 4F 'O' + + { 'P', TRUE }, // 50 'P' + { 'Q', TRUE }, // 51 'Q' + { 'R', TRUE }, // 52 'R' + { 'S', TRUE }, // 53 'S' + { 'T', TRUE }, // 54 'T' + { 'U', TRUE }, // 55 'U' + { 'V', TRUE }, // 56 'V' + { 'W', TRUE }, // 57 'W' + { 'X', TRUE }, // 58 'X' + { 'Y', TRUE }, // 59 'Y' + { 'Z', TRUE }, // 5A 'Z' + { VK_LBRKT, FALSE }, // 5B '[' + { VK_BKSLASH, FALSE }, // 5C '\' + { VK_RBRKT, FALSE }, // 5D ']' + { '6', TRUE }, // 5E '^' + { VK_HYPHEN, TRUE }, // 5F '_' + + { VK_ACCENT, FALSE }, // 60 '`' + { 'A', FALSE }, // 61 'a' + { 'B', FALSE }, // 62 'b' + { 'C', FALSE }, // 63 'c' + { 'D', FALSE }, // 64 'd' + { 'E', FALSE }, // 65 'e' + { 'F', FALSE }, // 66 'f' + { 'G', FALSE }, // 67 'g' + { 'H', FALSE }, // 68 'h' + { 'I', FALSE }, // 69 'i' + { 'J', FALSE }, // 6A 'j' + { 'K', FALSE }, // 6B 'k' + { 'L', FALSE }, // 6C 'l' + { 'M', FALSE }, // 6D 'm' + { 'N', FALSE }, // 6E 'n' + { 'O', FALSE }, // 6F 'o' + + { 'P', FALSE }, // 70 'p' + { 'Q', FALSE }, // 71 'q' + { 'R', FALSE }, // 72 'r' + { 'S', FALSE }, // 73 's' + { 'T', FALSE }, // 74 't' + { 'U', FALSE }, // 75 'u' + { 'V', FALSE }, // 76 'v' + { 'W', FALSE }, // 77 'w' + { 'X', FALSE }, // 78 'x' + { 'Y', FALSE }, // 79 'y' + { 'Z', FALSE }, // 7A 'z' + { VK_LBRKT, TRUE }, // 7B '{' + { VK_BKSLASH, TRUE }, // 7C '|' + { VK_RBRKT, TRUE }, // 7D '}' + { VK_ACCENT, TRUE } // 7E '~' +}; + +KMX_BOOL kmcmp::MapUSCharToVK(KMX_UINT ch, KMX_UINT *puKey, KMX_UINT *puShiftFlags) { + assert(puKey != NULL); + assert(puShiftFlags != NULL); + if (ch >= 0x20 && ch < 0x7F) { + *puKey = USCharMap[ch - 0x20].key; + *puShiftFlags = ISVIRTUALKEY | (USCharMap[ch - 0x20].shift ? K_SHIFTFLAG : 0); + return TRUE; + } + return FALSE; +} diff --git a/developer/src/kmcmplib/src/CharToKeyConversion.h b/developer/src/kmcmplib/src/CharToKeyConversion.h new file mode 100644 index 0000000000..dd71ccbc0b --- /dev/null +++ b/developer/src/kmcmplib/src/CharToKeyConversion.h @@ -0,0 +1,6 @@ +#pragma once + +namespace kmcmp { + KMX_BOOL MapUSCharToVK(KMX_UINT ch, KMX_UINT *puKey, KMX_UINT *puShiftFlags); + KMX_WCHAR VKToChar(KMX_WORD keyCode, KMX_UINT shiftFlags); +} \ No newline at end of file diff --git a/developer/src/kmcmplib/src/CheckFilenameConsistency.cpp b/developer/src/kmcmplib/src/CheckFilenameConsistency.cpp new file mode 100644 index 0000000000..4f5fd26ba2 --- /dev/null +++ b/developer/src/kmcmplib/src/CheckFilenameConsistency.cpp @@ -0,0 +1,145 @@ + +#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING 1 +#include "pch.h" +#include "compfile.h" +#include +#include "kmcmplib.h" +#include +#include "CheckFilenameConsistency.h" +#include "kmx_u16.h" +#include "filesystem.h" + +#ifdef _MSC_VER +#include +#endif + +namespace kmcmp { + extern KMX_CHAR CompileDir[260]; // TODO: this should not be a fixed buffer +} +bool IsRelativePath(KMX_CHAR const * p) { + // Relative path (returns TRUE): + // ..\...\BITMAP.BMP + // PATH\BITMAP.BMP + // BITMAP.BMP + + // Semi-absolute path (returns FALSE): + // \...\BITMAP.BMP + + // Absolute path (returns FALSE): + // C:\...\BITMAP.BMP + // \\SERVER\SHARE\...\BITMAP.BMP + + if ((*p == '\\') || (*p == '/')) return FALSE; + if (*p && *(p + 1) == ':') return FALSE; + + return TRUE; +} + +bool IsRelativePath(KMX_WCHAR const * p) { + // Relative path (returns TRUE): + // ..\...\BITMAP.BMP + // PATH\BITMAP.BMP + // BITMAP.BMP + + // Semi-absolute path (returns FALSE): + // \...\BITMAP.BMP + + // Absolute path (returns FALSE): + // C:\...\BITMAP.BMP + // \\SERVER\SHARE\...\BITMAP.BMP + + if ((*p == u'\\') || (*p == u'/'))return FALSE; + if (*p && *(p + 1) == u':') return FALSE; + + return TRUE; +} + +KMX_DWORD CheckFilenameConsistency( KMX_CHAR const * Filename, bool ReportMissingFile) { + PKMX_WCHAR WFilename = strtowstr(( KMX_CHAR *)Filename); + KMX_DWORD const result = CheckFilenameConsistency(WFilename, ReportMissingFile); + delete WFilename; + return result; +} + +KMX_DWORD CheckFilenameConsistency(KMX_WCHAR const * Filename, bool ReportMissingFile) { + // not ready yet: needs more attention-> common includes for non-Windows platforms + KMX_WCHAR Name[260]; // TODO: fixed buffer sizes bad + + + if (IsRelativePath(Filename)) { + PKMX_WCHAR WCompileDir = strtowstr(kmcmp::CompileDir); + u16ncpy(Name, WCompileDir, _countof(Name)); // I3481 + u16ncat(Name, Filename, _countof(Name)); // I3481 + delete[] WCompileDir; + } else { + u16ncpy(Name, Filename, _countof(Name)); // I3481 + } + +#ifndef _MSC_VER + // Filename consistency only needs to be checked on Windows, because other + // platforms are going to fail if the filename is inconsistent anyway! + if(!kmcmp_FileExists(Name)) { + if (ReportMissingFile) { + u16cpy(ErrExtraW, u"referenced file '"); + u16ncat(ErrExtraW, Filename, 256); + u16ncat(ErrExtraW, u"'", 256); + strcpy(ErrExtraLIB, string_from_u16string(ErrExtraW).c_str()); + AddWarning(CWARN_MissingFile); + } + return CERR_None; + } + return CERR_None; +#else + _wfinddata_t fi; + intptr_t n; + if ((n = _wfindfirst((const wchar_t*) Name, &fi)) == -1) { + if (ReportMissingFile) { + sprintf(ErrExtraLIB, "referenced file '%ls'", (wchar_t*) Filename); + AddWarning(CWARN_MissingFile); + } + return CERR_None; + } + + _findclose(n); + + KMX_WCHAR FName[_MAX_FNAME], Ext[_MAX_EXT]; + wchar_t WChName[_MAX_PATH]; + _wsplitpath_s((const wchar_t*)Filename, nullptr, 0, nullptr, 0, (wchar_t*) FName, _MAX_FNAME, (wchar_t*) Ext, _MAX_EXT); + _wmakepath_s(WChName, _MAX_PATH, nullptr, nullptr, (const wchar_t*) FName, (const wchar_t*) Ext); + if (wcscmp(WChName, fi.name) != 0) { + sprintf(ErrExtraLIB, "reference '%ls' does not match actual filename '%ls'", WChName, fi.name); + + AddWarning(CHINT_FilenameHasDifferingCase); + + } +#endif + + return CERR_None; +} + +KMX_DWORD CheckFilenameConsistencyForCalls(PFILE_KEYBOARD fk) { + // call() statements depend on a fairly ugly hack for js, + // where store(DllFunction) "my.dll:func" will look for a + // file called function.call_js. ( or should this be func.call_js ? ) + // This is ripe for rewrite! + // But let's check what we have anyway + + PFILE_STORE sp; + KMX_DWORD i, msg; + for (i = 0, sp = fk->dpStoreArray; i < fk->cxStoreArray; i++, sp++) { + if (!sp->fIsCall) continue; + + const std::u16string callsite(sp->dpString); + const auto colon = callsite.find(':'); + if (colon == std::u16string::npos) continue; + + auto func1 = callsite.substr(colon + 1); + std::u16string str_js(u".call_js"); + std::u16string func = func1+ str_js; + + if ((msg = CheckFilenameConsistency(func.c_str(), FALSE)) != CERR_None) { + return msg; + } + } + return CERR_None; +} diff --git a/developer/src/kmcmplib/src/CheckFilenameConsistency.h b/developer/src/kmcmplib/src/CheckFilenameConsistency.h new file mode 100644 index 0000000000..39f86db391 --- /dev/null +++ b/developer/src/kmcmplib/src/CheckFilenameConsistency.h @@ -0,0 +1,11 @@ +#pragma once + +#include "compfile.h" +#include "kmcmplib.h" + +KMX_DWORD CheckFilenameConsistencyForCalls(PFILE_KEYBOARD fk); +KMX_DWORD CheckFilenameConsistency(KMX_CHAR const * Filename, bool ReportMissingFile); +KMX_DWORD CheckFilenameConsistency(KMX_WCHAR const * Filename, bool ReportMissingFile); + +bool IsRelativePath(KMX_CHAR const * p); +bool IsRelativePath(KMX_WCHAR const * p); diff --git a/developer/src/kmcmplib/src/CheckForDuplicates.cpp b/developer/src/kmcmplib/src/CheckForDuplicates.cpp new file mode 100644 index 0000000000..11c995497f --- /dev/null +++ b/developer/src/kmcmplib/src/CheckForDuplicates.cpp @@ -0,0 +1,48 @@ + +#include "pch.h" + +#include "compfile.h" +#include +#include "kmcmplib.h" +#include +#include "kmx_u16.h" +#include + +#include "CheckForDuplicates.h" + +KMX_DWORD CheckForDuplicateGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) noexcept { + KMX_DWORD i; + PFILE_GROUP gp0 = fk->dpGroupArray; + for (i = 0; i < fk->cxGroupArray; i++, gp0++) { + if (gp0 == gp) { + continue; + } + if (u16icmp(gp0->szName, gp->szName) == 0) { + u16sprintf(ErrExtraW, 256, L" Group '%ls' declared on line %d", u16fmt(gp0->szName).c_str(), gp0->Line); + strcpy(ErrExtraLIB, string_from_u16string(ErrExtraW).c_str()); + return CERR_DuplicateGroup; + } + } + return CERR_None; +} + +KMX_DWORD CheckForDuplicateStore(PFILE_KEYBOARD fk, PFILE_STORE sp) noexcept { + if (!sp->szName[0]) { + // Stores with zero length names are reserved system stores. + // They cannot be defined in user code. This is not an issue. + return CERR_None; + } + KMX_DWORD i; + PFILE_STORE sp0 = fk->dpStoreArray; + for (i = 0; i < fk->cxStoreArray; i++, sp0++) { + if (sp0 == sp) { + continue; + } + if (u16icmp(sp0->szName, sp->szName) == 0) { + u16sprintf(ErrExtraW,256, L" Store '%ls' declared on line %d", u16fmt(sp0->szName).c_str(), sp0->line); + strcpy(ErrExtraLIB, string_from_u16string(ErrExtraW).c_str()); + return CERR_DuplicateStore; + } + } + return CERR_None; +} diff --git a/developer/src/kmcmplib/src/CheckForDuplicates.h b/developer/src/kmcmplib/src/CheckForDuplicates.h new file mode 100644 index 0000000000..20789dd5e2 --- /dev/null +++ b/developer/src/kmcmplib/src/CheckForDuplicates.h @@ -0,0 +1,4 @@ +#pragma once + +KMX_DWORD CheckForDuplicateGroup(PFILE_KEYBOARD fk, PFILE_GROUP gp) noexcept; +KMX_DWORD CheckForDuplicateStore(PFILE_KEYBOARD fk, PFILE_STORE sp) noexcept; diff --git a/developer/src/kmcmplib/src/CheckNCapsConsistency.cpp b/developer/src/kmcmplib/src/CheckNCapsConsistency.cpp new file mode 100644 index 0000000000..25e8c85b40 --- /dev/null +++ b/developer/src/kmcmplib/src/CheckNCapsConsistency.cpp @@ -0,0 +1,99 @@ + +#include "pch.h" + +#include +#include +#include +#include "CharToKeyConversion.h" + +/** + * If any rule uses CAPS or NCAPS for a given key, then every rule that + * uses that key must also use CAPS or NCAPS, as otherwise the results are + * inconsistent. For example, if Caps Lock is on, then [K_F] may still be + * matched: + * + * + [K_F] > 'foo' + * + [CAPS K_F] > 'bar' + * + * Because of the way that KeymanWeb compiles rules, this may even apply when + * we have a key rule that would otherwise be ignored due to context. In the + * following example, [Caps Lock] + [y] would result in no output (or default + * output) rather than 'bar', because the preceding rule would capture the + * Y key, ignoring Caps Lock, meaning that the subsequent rule would never + * even get tested. (Note that this was introduced in the KeymanWeb compiler + * fix for extremely long if/else ladders in Keyman 12 in #1561, and this is + * technically slightly inconsistent with Keyman Core, although in my analysis + * only in this already ambiguous situation. + * + * 'x' + [K_Y] > 'foo' + * [CAPS K_Y] > 'bar' + * + * Given all this, we'll warn any time we find a key that has inconsistent use + * of CAPS/NCAPS in its rules. + * + * @param fk Keyboard to check + */ +bool CheckNCapsConsistency(PFILE_KEYBOARD fk) { + struct CapsUsage { + int ncaps_line, caps_line, neither_line; + }; + + const int oldCurrentLine = kmcmp::currentLine; + + // 256 virtual key codes + sizeof the virtual key dictionary is max key code possible + const int nkeys = 256 + fk->cxVKDictionary; + auto caps_ncaps_usage = new CapsUsage [nkeys]; + + memset(caps_ncaps_usage, 0, nkeys * sizeof(CapsUsage)); + + PFILE_GROUP gp; + KMX_DWORD gn; + for (gn = 0, gp = fk->dpGroupArray; gn < fk->cxGroupArray; gn++, gp++) { + if (!gp->fUsingKeys) { + continue; + } + + PFILE_KEY kp; + KMX_DWORD kn; + for (kn = 0, kp = gp->dpKeyArray; kn < gp->cxKeyArray; kn++, kp++) { + KMX_UINT key; + KMX_UINT shift; + if (kp->ShiftFlags & ISVIRTUALKEY) { + if (kp->Key >= nkeys) { + assert(false); + continue; + } + key = kp->Key; + shift = kp->ShiftFlags; + } + else if (!kmcmp::MapUSCharToVK(kp->Key, &key, &shift)) { + // Not a valid key + continue; + } + + if (shift & NOTCAPITALFLAG) { + if (!caps_ncaps_usage[key].ncaps_line) caps_ncaps_usage[key].ncaps_line = (kp->Line == 0 ? 1 : kp->Line); + } + else if (shift & CAPITALFLAG) { + if (!caps_ncaps_usage[key].caps_line) caps_ncaps_usage[key].caps_line = (kp->Line == 0 ? 1 : kp->Line); + } + else { + if (!caps_ncaps_usage[key].neither_line) caps_ncaps_usage[key].neither_line = (kp->Line == 0 ? 1 : kp->Line); + } + } + } + + for (int i = 0; i < nkeys; i++) { + if (caps_ncaps_usage[i].neither_line && (caps_ncaps_usage[i].caps_line || caps_ncaps_usage[i].ncaps_line)) { + // We set the current line to one needing work: the developer should add the NCAPS flag + kmcmp::currentLine = caps_ncaps_usage[i].neither_line; + AddWarning(CWARN_KeyShouldIncludeNCaps); + } + } + + delete[] caps_ncaps_usage; + + kmcmp::currentLine = oldCurrentLine; + + return TRUE; +} diff --git a/developer/src/kmcmplib/src/CheckNCapsConsistency.h b/developer/src/kmcmplib/src/CheckNCapsConsistency.h new file mode 100644 index 0000000000..50fa744c4a --- /dev/null +++ b/developer/src/kmcmplib/src/CheckNCapsConsistency.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +bool CheckNCapsConsistency(PFILE_KEYBOARD fk); diff --git a/developer/src/kmcmplib/src/CompMsg.cpp b/developer/src/kmcmplib/src/CompMsg.cpp new file mode 100644 index 0000000000..2fa0d68322 --- /dev/null +++ b/developer/src/kmcmplib/src/CompMsg.cpp @@ -0,0 +1,158 @@ +#include + +struct CompilerError { + KMX_DWORD ErrorCode; + const KMX_CHAR* Text; + }; + +const struct CompilerError CompilerErrors[] = { + { CERR_InvalidLayoutLine , "Invalid 'layout' command"}, + { CERR_NoVersionLine , "No version line found for file"}, + { CERR_InvalidGroupLine , "Invalid 'group' command"}, + { CERR_InvalidStoreLine , "Invalid 'store' command"}, + { CERR_InvalidCodeInKeyPartOfRule , "Invalid command or code found in key part of rule"}, + { CERR_InvalidDeadkey , "Invalid 'deadkey' or 'dk' command"}, + { CERR_InvalidValue , "Invalid value in extended string"}, + { CERR_ZeroLengthString , "A string of zero characters was found"}, + { CERR_TooManyIndexToKeyRefs , "Too many index commands refering to key string"}, + { CERR_UnterminatedString , "Unterminated string in line"}, + { CERR_StringInVirtualKeySection , "extend string illegal in virtual key section"}, + { CERR_AnyInVirtualKeySection , "'any' command is illegal in virtual key section"}, + { CERR_InvalidAny , "Invalid 'any' command"}, + { CERR_StoreDoesNotExist , "Store referenced does not exist"}, + { CERR_BeepInVirtualKeySection , "'beep' command is illegal in virtual key section"}, + { CERR_IndexInVirtualKeySection , "'index' command is illegal in virtual key section"}, + { CERR_BadCallParams , "CompileKeyboardFile was called with bad parameters"}, + { CERR_InfileNotExist , "Cannot find the input file"}, + { CERR_CannotCreateOutfile , "Cannot open output file for writing"}, + { CERR_UnableToWriteFully , "Unable to write the file completely"}, + { CERR_CannotReadInfile , "Cannot read the input file"}, + { CERR_SomewhereIGotItWrong , "Internal error: contact Keyman"}, + { CERR_BufferOverflow , "The compiler memory buffer overflowed"}, + { CERR_Break , "Compiler interrupted by user"}, + { CERR_CannotAllocateMemory , "Out of memory"}, + { CERR_InvalidBitmapLine , "Invalid 'bitmaps' command"}, + { CERR_CannotReadBitmapFile , "Cannot open the bitmap or icon file for reading"}, + { CERR_IndexDoesNotPointToAny , "An index() in the output does not have a corresponding any() statement"}, + { CERR_ReservedCharacter , "A reserved character was found"}, + { CERR_InvalidCharacter , "A character was found that is outside the valid Unicode range (U+0000 - U+10FFFF)"}, + { CERR_InvalidCall , "The 'call' command is invalid"}, + { CERR_CallInVirtualKeySection , "'call' command is illegal in virtual key section"}, + { CERR_CodeInvalidInKeyStore , "The command is invalid inside a store that is used in a key part of the rule"}, + { CERR_CannotLoadIncludeFile , "Cannot load the included file: it is either invalid or does not exist"}, + { CERR_60FeatureOnly_EthnologueCode , "EthnologueCode system store requires VERSION 6.0 or higher"}, + { CERR_60FeatureOnly_MnemonicLayout , "MnemonicLayout functionality requires VERSION 6.0 or higher"}, + { CERR_60FeatureOnly_OldCharPosMatching , "OldCharPosMatching system store requires VERSION 6.0 or higher"}, + { CERR_60FeatureOnly_NamedCodes , "Named character constants requires VERSION 6.0 or higher"}, + { CERR_60FeatureOnly_Contextn , "Context(n) requires VERSION 6.0 or higher"}, + { CERR_501FeatureOnly_Call , "Call() requires VERSION 5.01 or higher"}, + { CERR_InvalidNamedCode , "Invalid named code constant"}, + { CERR_InvalidSystemStore , "Invalid system store name found"}, + { CERR_60FeatureOnly_VirtualCharKey , "Virtual character keys require VERSION 6.0 or higher"}, + { CERR_VersionAlreadyIncluded , "Only one VERSION or store(version) line allowed in a source file."}, + { CERR_70FeatureOnly , "This feature requires store(version) '7.0' or higher"}, + { CERR_80FeatureOnly , "This feature requires store(version) '8.0' or higher"}, + { CERR_InvalidInVirtualKeySection , "This statement is not valid in a virtual key section"}, + { CERR_InvalidIf , "The if() statement is not valid"}, + { CERR_InvalidReset , "The reset() statement is not valid"}, + { CERR_InvalidSet , "The set() statement is not valid"}, + { CERR_InvalidSave , "The save() statement is not valid"}, + { CERR_InvalidEthnologueCode , "Invalid ethnologuecode format"}, + { CERR_90FeatureOnly_IfSystemStores , "if(store) requires store(version) '9.0' or higher"}, + { CERR_IfSystemStore_NotFound , "System store in if() not found"}, + { CERR_90FeatureOnly_SetSystemStores , "set(store) requires store(version) '9.0' or higher"}, + { CERR_SetSystemStore_NotFound , "System store in set() not found"}, + { CERR_90FeatureOnlyVirtualKeyDictionary , "Custom virtual key names require store(version) '9.0'"}, + { CERR_InvalidIndex , "Invalid 'index' command"}, + { CERR_OutsInVirtualKeySection , "'outs' command is illegal in virtual key section"}, + { CERR_InvalidOuts , "Invalid 'outs' command"}, + { CERR_ContextInVirtualKeySection , "'context' command is illegal in virtual key section"}, + { CERR_InvalidUse , "Invalid 'use' command"}, + { CERR_GroupDoesNotExist , "Group does not exist"}, + { CERR_VirtualKeyNotAllowedHere , "Virtual key is not allowed here"}, + { CERR_InvalidSwitch , "Invalid 'switch' command"}, + { CERR_NoTokensFound , "No tokens found in line"}, + { CERR_InvalidLineContinuation , "Invalid line continuation"}, + { CERR_LineTooLong , "Line too long"}, + { CERR_InvalidCopyright , "Invalid 'copyright' command"}, + { CERR_CodeInvalidInThisSection , "This line is invalid in this section of the file"}, + { CERR_InvalidMessage , "Invalid 'message' command"}, + { CERR_InvalidLanguageName , "Invalid 'languagename' command"}, + { CERR_EndOfFile , "(no error - reserved code)"}, + { CERR_InvalidToken , "Invalid token found"}, + { CERR_InvalidBegin , "Invalid 'begin' command"}, + { CERR_InvalidName , "Invalid 'name' command"}, + { CERR_InvalidVersion , "Invalid 'version' command"}, + { CERR_InvalidLanguageLine , "Invalid 'language' command"}, + { CERR_LayoutButNoLanguage , "Layout command found but no language command"}, + { CERR_CannotCreateTempfile , "Cannot create temp file"}, + { CERR_90FeatureOnlyLayoutFile , "Touch layout file reference requires store(version) '9.0'or higher"}, + { CERR_90FeatureOnlyKeyboardVersion , "KeyboardVersion system store requires store(version) '9.0'or higher"}, + { CERR_KeyboardVersionFormatInvalid , "KeyboardVersion format is invalid, expecting dot-separated integers"}, + { CERR_ContextExHasInvalidOffset , "context() statement has offset out of range"}, + { CERR_90FeatureOnlyEmbedCSS , "Embedding CSS requires store(version) '9.0'or higher"}, + { CERR_90FeatureOnlyTargets , "TARGETS system store requires store(version) '9.0'or higher"}, + { CERR_ContextAndIndexInvalidInMatchNomatch , "context and index statements cannot be used in a match or nomatch statement"}, + { CERR_140FeatureOnlyContextAndNotAnyWeb , "For web and touch platforms, context() statement referring to notany() requires store(version) '14.0'or higher"}, + { CERR_ExpansionMustFollowCharacterOrVKey , "An expansion must follow a character or a virtual key"}, + { CERR_VKeyExpansionMustBeFollowedByVKey , "A virtual key expansion must be terminated by a virtual key"}, + { CERR_CharacterExpansionMustBeFollowedByCharacter , "A character expansion must be terminated by a character key"}, + { CERR_VKeyExpansionMustUseConsistentShift , "A virtual key expansion must use the same shift state for both terminators"}, + { CERR_ExpansionMustBePositive , "An expansion must have positive difference (i.e. A-Z, not Z-A)"}, + { CERR_CasedKeysMustContainOnlyVirtualKeys , "The &CasedKeys system store must contain only virtual keys or characters found on a US English keyboard"}, + { CERR_CasedKeysMustNotIncludeShiftStates , "The &CasedKeys system store must not include shift states"}, + { CERR_CasedKeysNotSupportedWithMnemonicLayout , "The &CasedKeys system store is not supported with mnemonic layouts"}, + { CERR_CannotUseReadWriteGroupFromReadonlyGroup , "Group used from a readonly group must also be readonly"}, + { CERR_StatementNotPermittedInReadonlyGroup , "Statement is not permitted in output of readonly group"}, + { CERR_OutputInReadonlyGroup , "Output is not permitted in a readonly group"}, + { CERR_NewContextGroupMustBeReadonly , "Group used in begin newContext must be readonly"}, + { CERR_PostKeystrokeGroupMustBeReadonly , "Group used in begin postKeystroke must be readonly"}, + { CERR_DuplicateGroup , "A group with this name has already been defined."}, + { CERR_DuplicateStore , "A store with this name has already been defined."}, + { CERR_RepeatedBegin , "Begin has already been set"}, + + { CHINT_FilenameHasDifferingCase , "Casing differences may fail on some platforms: "}, + { CHINT_UnreachableRule , "This rule will never be matched as another rule takes precedence"}, + + { CWARN_TooManyWarnings , "Too many warnings or errors"}, + { CWARN_OldVersion , "The keyboard file is an old version"}, + { CWARN_BitmapNotUsed , "The 'bitmaps' statement is obsolete and only the first bitmap referred to will be used, you should use 'bitmap'."}, + { CWARN_CustomLanguagesNotSupported , "Languages over 0x1FF, 0x1F are not supported correctly by Windows. You should use no LANGUAGE line instead."}, + { CWARN_KeyBadLength , "There are too many characters in the keystroke part of the rule."}, + { CWARN_IndexStoreShort , "The store referenced in index() is shorter than the store referenced in any()"}, + { CWARN_UnicodeInANSIGroup , "A Unicode character was found in an ANSI group"}, + { CWARN_ANSIInUnicodeGroup , "An ANSI character was found in a Unicode group"}, + { CWARN_UnicodeSurrogateUsed , "A Unicode surrogate character was found. You should use Unicode scalar values to represent values > U+FFFF"}, + { CWARN_ReservedCharacter , "A Unicode character was found that should not be used"}, + { CWARN_Info , "Information"}, + { CWARN_VirtualKeyWithMnemonicLayout , "Virtual key used instead of virtual character key with a mnemonic layout"}, + { CWARN_VirtualCharKeyWithPositionalLayout , "Virtual character key used with a positional layout instead of mnemonic layout"}, + { CWARN_StoreAlreadyUsedAsOptionOrCall , "Store already used as an option or in a call statement and should not be used as a normal store"}, + { CWARN_StoreAlreadyUsedAsStoreOrCall , "Store already used as a normal store or in a call statement and should not be used as an option"}, + { CWARN_StoreAlreadyUsedAsStoreOrOption , "Store already used as a normal store or as an option and should not be used in a call statement"}, + { CWARN_PunctuationInEthnologueCode , "Punctuation should not be used to separate Ethnologue codes; instead use spaces"}, + { CWARN_PlatformNotInTargets , "The specified platform is not a target platform"}, + { CWARN_HeaderStatementIsDeprecated , "Header statements are deprecated; use instead the equivalent system store"}, + { CWARN_UseNotLastStatementInRule , "A rule with use() statements in the output should not have other content following the use() statements"}, + { CWARN_KVKFileIsInSourceFormat , ".kvk file should be binary but is an XML file"}, + { CWARN_DontMixChiralAndNonChiralModifiers , "Don't mix the use of left/right modifiers with non-left/right modifiers in the same platform"}, + { CWARN_MixingLeftAndRightModifiers , "Left and right modifiers should not both be used in the same rule"}, + { CWARN_LanguageHeadersDeprecatedInKeyman10 , "This language header has been deprecated in Keyman 10. Instead, add language metadata in the package file"}, + { CWARN_HotkeyHasInvalidModifier , "Hotkey has modifiers that are not supported. Use only SHIFT, CTRL and ALT"}, + { CWARN_NulNotFirstStatementInContext , "nul must be the first statement in the context"}, + { CWARN_IfShouldBeAtStartOfContext , "if, platform and baselayout should be at start of context (after nul, if present)"}, + { CWARN_KeyShouldIncludeNCaps , "Other rules which reference this key include CAPS or NCAPS modifiers, so this rule must include NCAPS modifier to avoid inconsistent matches"}, + { CWARN_MissingFile , "The referenced file could not be found: "}, + + { 0, nullptr } + }; + +KMX_CHAR *GetCompilerErrorString(KMX_DWORD code) +{ + for(int i = 0; CompilerErrors[i].ErrorCode; i++) { + if(CompilerErrors[i].ErrorCode == code) { + return ( KMX_CHAR*) CompilerErrors[i].Text; + } + } + return nullptr; +} diff --git a/developer/src/kmcmplib/src/CompMsg.h b/developer/src/kmcmplib/src/CompMsg.h new file mode 100644 index 0000000000..38be6bd674 --- /dev/null +++ b/developer/src/kmcmplib/src/CompMsg.h @@ -0,0 +1,5 @@ + +#include "km_types.h" +#include + +KMX_CHAR *GetCompilerErrorString(KMX_DWORD code) ; diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp new file mode 100644 index 0000000000..e8be1590eb --- /dev/null +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -0,0 +1,3832 @@ +/* + Name: Compiler + Copyright: Copyright (C) SIL International. + Documentation: + Description: + Create Date: 20 Jun 2006 + + Modified Date: 25 Oct 2016 + Authors: mcdurdin + Related Files: + Dependencies: + + Bugs: + Todo: + Notes: + History: 20 Jun 2006 - mcdurdin - Initial version + 23 Aug 2006 - mcdurdin - Add VISUALKEYBOARD, KMW_RTL, KMW_HELPFILE, KMW_HELPTEXT, KMW_EMBEDJS system stores + 14 Sep 2006 - mcdurdin - Support icons in version 7 + 28 Sep 2006 - mcdurdin - Added product validation + 28 Sep 2006 - mcdurdin - Added test for version 7.0 icon support + 06 Oct 2006 - mcdurdin - Fix buffer overflow in UTF8 conversion + 04 Dec 2006 - mcdurdin - Fix readfile buffer bug + 04 Jan 2007 - mcdurdin - Add notany support + 22 Jan 2007 - mcdurdin - Add K_NPENTER reference + 25 Jan 2007 - mcdurdin - Resize buffers to 4095 + 30 May 2007 - mcdurdin - I786 - Compiler crash if zero length string in keystroke any + 23 Aug 2007 - mcdurdin - I1011 - Fix buffer clobbering for UTF8 conversion of large files + 27 Mar 2008 - mcdurdin - I1358 - Support for multiple languages for office config + 14 Jun 2008 - mcdurdin - Support documenting language id as a single WORD instead of by PRIMARY/SUB + 14 Jun 2008 - mcdurdin - Support Windows languages list + 28 Jul 2008 - mcdurdin - I1569 - line prefixes + 22 Mar 2010 - mcdurdin - Compiler fixup - x64 support + 25 May 2010 - mcdurdin - I1632 - Keyboard Options + 24 Jun 2010 - mcdurdin - I2432 - Use local buffers so GetXString can be re-entrant (used by if()) + 26 Jul 2010 - mcdurdin - I2467 - 8.0 renumber + 18 Mar 2011 - mcdurdin - I2646 - Compiler warning on invalid Ethnologue codes + 18 Mar 2011 - mcdurdin - I2525 - Unterminated string can crash compiler + 19 Jul 2011 - mcdurdin - I2993 - Named code constants cause a warning 0x208D to appear + 26 Jun 2012 - mcdurdin - I3377 - KM9 - Update code references from 8.0 to 9.0 + 17 Aug 2012 - mcdurdin - I3431 - V9.0 - Spaces in values in if comparisons break the compiler parser + 27 Aug 2012 - mcdurdin - I3439 - V9.0 - Refactor xstring support in C++ code + 27 Aug 2012 - mcdurdin - I3437 - V9.0 - Add support for set(&layer) and layer() + 27 Aug 2012 - mcdurdin - I3438 - V9.0 - Add support for custom virtual keys + 27 Aug 2012 - mcdurdin - I3430 - V9.0 - Add support for if(&platform) and if(&baselayout) to compilers + 27 Aug 2012 - mcdurdin - I3440 - V9.0 - Tidy up set statement delimiter recognition + 24 Oct 2012 - mcdurdin - I3483 - V9.0 - Add support for compiling in the layout file + 24 Oct 2012 - mcdurdin - I3481 - V9.0 - Eliminate unsafe calls in C++ + 24 Jan 2012 - mcdurdin - I3137 - If key part of VK rule is missing, compiler generates invalid file + 06 Feb 2012 - mcdurdin - I3228 - kmcmpdll sometimes tries to write temp files to Program Files + 03 Nov 2012 - mcdurdin - I3510 - V9.0 - Merge of I3228 - kmcmpdll sometimes tries to write temp files to Program Files + 03 Nov 2012 - mcdurdin - I3511 - V9.0 - Merge of I3137 - If key part of VK rule is missing, compiler generates invalid file + 13 Dec 2012 - mcdurdin - I3654 - V9.0 - Compiler appears to create unregistered keyboards even when registered + 13 Dec 2012 - mcdurdin - I3641 - V9.0 - compiler dll buffer overrun bugs + 13 Dec 2012 - mcdurdin - I3681 - V9.0 - KeymanWeb compiler should output formatted js when debug=1 + 13 Dec 2012 - mcdurdin - I3686 - V9.0 - AddStore attaches property flags to wrong store structure + 19 Mar 2014 - mcdurdin - I4140 - V9.0 - Add keyboard version information to keyboards + 04 Nov 2014 - mcdurdin - I4504 - V9.0 - Consolidate the compile action into single command + 02 Jul 2015 - mcdurdin - I4784 - Compiler does not recognise baselayout, layer or platform at the start of a line + 02 Jul 2015 - mcdurdin - I4785 - baselayout(), layer() and platform() produce incorrect compiled code + 24 Aug 2015 - mcdurdin - I4865 - Add treat hints and warnings as errors into project + 24 Aug 2015 - mcdurdin - I4866 - Add warn on deprecated features to project and compile + 24 Aug 2015 - mcdurdin - I4867 - Add test for code after use warning to compile + 06 Nov 2015 - mcdurdin - I4914 - kmcmpdll does not pick an index() statement that has an offset one past the key + 23 Feb 2016 - mcdurdin - I4982 - Defined character constants cannot be referenced correctly in other stores + 25 Oct 2016 - mcdurdin - I5135 - Remove product and licensing references from Developer projects +*/ +#include "pch.h" + +#include + +#include "compfile.h" +#include +#include "../../../../common/windows/cpp/include/vkeys.h" +#include +#include "versioning.h" +#include "kmcmplib.h" +#include "DeprecationChecks.h" + +#include "virtualcharkeys.h" + +// TODO: These three should be under common/cpp/include -- not windows specific +#include "../../../../common/windows/cpp/include/keymanversion.h" +#include "../../../../common/windows/cpp/include/crc32.h" +#include "../../../../common/windows/cpp/include/ConvertUTF.h" + +#include "debugstore.h" +#include "NamedCodeConstants.h" + +#include "xstring.h" + +#include "Edition.h" + +#include "CharToKeyConversion.h" +#include "CasedKeys.h" +#include +#include +#include "CheckNCapsConsistency.h" +#include "CheckFilenameConsistency.h" +#include "UnreachableRules.h" +#include "CheckForDuplicates.h" +#include "kmx_u16.h" +#include "filesystem.h" +#include + +/* These macros are adapted from winnt.h and legacy use only */ +#define MAKELANGID(p, s) ((((uint16_t)(s)) << 10) | (uint16_t)(p)) +#define PRIMARYLANGID(lgid) ((uint16_t)(lgid) & 0x3ff) +#define SUBLANGID(lgid) ((uint16_t)(lgid) >> 10) + + +using namespace kmcmp; + + char ErrExtraLIB[256]; + KMX_WCHAR ErrExtraW[256]; + KMX_BOOL AWarnDeprecatedCode_GLOBAL_LIB; + +namespace kmcmp{ + KMX_BOOL FShouldAddCompilerVersion = TRUE; + KMX_BOOL FSaveDebug, FCompilerWarningsAsErrors; // I4865 // I4866 + int ErrChr; + int nErrors = 0; + KMX_BOOL FMnemonicLayout = FALSE; + KMX_BOOL FOldCharPosMatching = FALSE; + int CompileTarget; + KMX_CHAR CompileDir[260]; // TODO: this should not be a fixed buffer + int BeginLine[4]; + + KMX_BOOL IsValidCallStore(PFILE_STORE fs); + void RecordDeadkeyNames(PFILE_KEYBOARD fk); + KMX_DWORD AddCompilerVersionStore(PFILE_KEYBOARD fk); + KMX_BOOL CheckStoreUsage(PFILE_KEYBOARD fk, int storeIndex, KMX_BOOL fIsStore, KMX_BOOL fIsOption, KMX_BOOL fIsCall); + int UTF32ToUTF16(int n, int *n1, int *n2); + int CheckUTF16(int n); + int cmpkeys(const void *key, const void *elem); +} + +int xatoi(PKMX_WCHAR *p); +int atoiW(PKMX_WCHAR p); +void safe_wcsncpy(PKMX_WCHAR out, PKMX_WCHAR in, int cbMax); +int GetDeadKey(PFILE_KEYBOARD fk, PKMX_WCHAR p); + +KMX_BOOL IsSameToken(PKMX_WCHAR *p, KMX_WCHAR const * token); +KMX_DWORD GetRHS(PFILE_KEYBOARD fk, PKMX_WCHAR p, PKMX_WCHAR buf, int bufsize, int offset, int IsUnicode); +PKMX_WCHAR GetDelimitedString(PKMX_WCHAR *p, KMX_WCHAR const * Delimiters, KMX_WORD Flags); +KMX_DWORD GetXString(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_WCHAR const * token, PKMX_WCHAR output, int max, int offset, PKMX_WCHAR *newp, int isVKey, int isUnicode); + +int GetGroupNum(PFILE_KEYBOARD fk, PKMX_WCHAR p); +int LineTokenType(PKMX_WCHAR *str); + +KMX_DWORD ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str); + +KMX_DWORD ProcessGroupFinish(PFILE_KEYBOARD fk); +KMX_DWORD ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p); +KMX_DWORD ProcessStoreLine(PFILE_KEYBOARD fk, PKMX_WCHAR p); +KMX_DWORD AddDebugStore(PFILE_KEYBOARD fk, KMX_WCHAR const * str); +KMX_DWORD ProcessKeyLine(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnicode); +KMX_DWORD ProcessEthnologueStore(PKMX_WCHAR p); // I2646 +KMX_DWORD ProcessHotKey(PKMX_WCHAR p, KMX_DWORD *hk); +KMX_DWORD ImportBitmapFile(PFILE_KEYBOARD fk, PKMX_WCHAR szName, PKMX_DWORD FileSize, PKMX_BYTE *Buf); + +KMX_DWORD ExpandKp(PFILE_KEYBOARD fk, PFILE_KEY kpp, KMX_DWORD storeIndex); + +KMX_DWORD ReadLine(FILE* fp_in , PKMX_WCHAR wstr, KMX_BOOL PreProcess); + +KMX_DWORD WriteCompiledKeyboard(PFILE_KEYBOARD fk, FILE* fp_out); +KMX_BOOL CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk); + +int GetVKCode(PFILE_KEYBOARD fk, PKMX_WCHAR p); // I3438 // TODO: Consolidate GetDeadKey and GetVKCode? +KMX_DWORD BuildVKDictionary(PFILE_KEYBOARD fk); // I3438 +KMX_DWORD AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, KMX_WCHAR const * str, KMX_DWORD *dwStoreID= NULL); +KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE sp); + +KMX_DWORD process_if(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx); +KMX_DWORD process_reset(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx); +KMX_DWORD process_set(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx); +KMX_DWORD process_save(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx); +KMX_DWORD process_platform(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx); // I3430 +KMX_DWORD process_baselayout(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx); // I3430 +KMX_DWORD process_set_synonym(KMX_DWORD dwSystemID, PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx); // I3437 +KMX_DWORD process_expansion(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx, int max); + +KMX_BOOL IsValidKeyboardVersion(KMX_WCHAR *dpString); + +FILE* UTF16TempFromUTF8(FILE* fp_in , KMX_BOOL hasPreamble); + +const KMX_WCHAR * LineTokens[] = { + u"SVNBHBGMNSCCLLCMLB", u"store", u"VERSION ", u"NAME ", + u"BITMAP ", u"HOTKEY ", u"begin", u"group", u"match", u"nomatch", + u"SHIFT FREES CAPS", u"CAPS ON ONLY", u"CAPS ALWAYS OFF", + u"LANGUAGE ", u"LAYOUT ", u"COPYRIGHT ", u"MESSAGE ", u"LANGUAGENAME ", + u"BITMAPS " }; + +#define SSN__PREFIX u"&" + +const KMX_WCHAR * StoreTokens[TSS__MAX + 2] = { + u"", + SSN__PREFIX u"BITMAP", + SSN__PREFIX u"COPYRIGHT", + SSN__PREFIX u"HOTKEY", + SSN__PREFIX u"LANGUAGE", + SSN__PREFIX u"LAYOUT", + SSN__PREFIX u"MESSAGE", + SSN__PREFIX u"NAME", + SSN__PREFIX u"VERSION", + SSN__PREFIX u"CAPSONONLY", + SSN__PREFIX u"CAPSALWAYSOFF", + SSN__PREFIX u"SHIFTFREESCAPS", + SSN__PREFIX u"LANGUAGENAME", + u"", + u"", + SSN__PREFIX u"ETHNOLOGUECODE", + u"", + SSN__PREFIX u"MNEMONICLAYOUT", + SSN__PREFIX u"INCLUDECODES", + SSN__PREFIX u"OLDCHARPOSMATCHING", + u"", + u"", + u"", + u"", + SSN__PREFIX u"VISUALKEYBOARD", + SSN__PREFIX u"KMW_RTL", + SSN__PREFIX u"KMW_HELPFILE", + SSN__PREFIX u"KMW_HELPTEXT", + SSN__PREFIX u"KMW_EMBEDJS", + SSN__PREFIX u"WINDOWSLANGUAGES", + u"", + SSN__PREFIX u"PLATFORM", // read only // I3430 + SSN__PREFIX u"BASELAYOUT", // read only // I3430 + SSN__PREFIX u"LAYER", // read-write via set? // I3430 + u"", // I3438 + SSN__PREFIX u"LAYOUTFILE", // I3483 + SSN__PREFIX u"KEYBOARDVERSION", // I4140 + SSN__PREFIX u"KMW_EMBEDCSS", + SSN__PREFIX u"TARGETS", // I4504 + SSN__PREFIX u"CASEDKEYS", // #2241 + SSN__PREFIX u"", // TSS_BEGIN_NEWCONTEXT + SSN__PREFIX u"", // TSS_BEGIN_POSTKEYSTROKE + SSN__PREFIX u"NEWLAYER", + SSN__PREFIX u"OLDLAYER", + NULL +}; + +static_assert(sizeof(StoreTokens) / sizeof(StoreTokens[0]) == TSS__MAX + 2, "StoreTokens should have exactly TSS__MAX+2 elements"); + +enum LinePrefixType { lptNone, lptKeymanAndKeymanWeb, lptKeymanWebOnly, lptKeymanOnly, lptOther }; + +/* Compile target */ + +kmcmp_CompilerMessageProc msgproc = NULL; +void* msgprocContext = NULL; + +int kmcmp::currentLine = 0; + +kmcmp::NamedCodeConstants *CodeConstants = NULL; + +/* Compile target */ + +#define CKF_KEYMAN 0 +#define CKF_KEYMANWEB 1 + +PKMX_WCHAR strtowstr(PKMX_STR in) +{ + PKMX_WCHAR result; + + auto c = u16string_from_string(in); + + result = new KMX_WCHAR[c.length() + 1]; + u16cpy(result, c.c_str()); + return result; +} + +PKMX_STR wstrtostr(PKMX_WCHAR in) +{ + PKMX_STR result; + + auto c = string_from_u16string(in); + + result = new KMX_CHAR[c.length() + 1]; + strcpy(result, c.c_str()); + return result; +} + +KMX_BOOL kmcmp::AddCompileWarning(PKMX_CHAR buf) +{ + (*msgproc)(kmcmp::currentLine + 1, CWARN_Info, buf, msgprocContext); + return FALSE; +} + +KMX_BOOL AddCompileError(KMX_DWORD msg) +{ + KMX_CHAR szText[SZMAX_ERRORTEXT + 1 + 280]; + KMX_CHAR* szTextp = NULL; + + if (msg & CERR_FATAL) + { + szTextp = GetCompilerErrorString(msg); + (*msgproc)(kmcmp::currentLine + 1, msg, szTextp, msgprocContext); + kmcmp::nErrors++; + return TRUE; + } + + if (msg & CERR_ERROR) + kmcmp::nErrors++; + szTextp = GetCompilerErrorString(msg); + + if (szTextp) { + strcpy(szText, szTextp); + } + else { + sprintf(szText, "Unknown error %x", msg); + } + + if (kmcmp::ErrChr > 0) + sprintf(strchr(szText, 0), " character offset: %d", kmcmp::ErrChr); + + if (*ErrExtraLIB) { + sprintf(strchr(szText, 0), "%s", ErrExtraLIB); + } + + ErrChr = 0; *ErrExtraLIB =0; + if (!(*msgproc)(kmcmp::currentLine, msg, szText, msgprocContext)) return TRUE; + return FALSE; +} + +extern "C" bool kmcmp_SetCompilerOptions(KMCMP_COMPILER_OPTIONS* options) { + //printf("°°-> changed to SetCompilerOptions() of kmcmplib \n"); + if(!options || options->dwSize < sizeof(KMCMP_COMPILER_OPTIONS)) { + return FALSE; + } + kmcmp::FShouldAddCompilerVersion = options->ShouldAddCompilerVersion; + return TRUE; +} + +extern "C" uint32_t kmcmp_CompileKeyboardFile(char* pszInfile, + char* pszOutfile, bool ASaveDebug, bool ACompilerWarningsAsErrors, + bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, void* AmsgprocContext +) { + FILE* fp_in = NULL; + FILE* fp_out = NULL; + KMX_BOOL err; + KMX_CHAR str[260]; + + //printf("°°-> changed to CompileKeyboardFile() of kmcmplib \n"); + + kmcmp::FSaveDebug = ASaveDebug; + kmcmp::FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865 + AWarnDeprecatedCode_GLOBAL_LIB = AWarnDeprecatedCode; + + kmcmp::CompileTarget = CKF_KEYMAN; + + if (!pMsgproc || !pszInfile || !pszOutfile) SetError(CERR_BadCallParams); + + PKMX_STR p; + + if ((p = strrchr_slash(pszInfile)) != nullptr) + { + strncpy(kmcmp::CompileDir, pszInfile, (int)(p - pszInfile + 1)); // I3481 + kmcmp::CompileDir[(int)(p - pszInfile + 1)] = 0; + } + else + kmcmp::CompileDir[0] = 0; + + msgproc = pMsgproc; + msgprocContext = AmsgprocContext; + kmcmp::currentLine = 0; + kmcmp::nErrors = 0; + + fp_in = Open_File(pszInfile, "rb"); + + if (fp_in == NULL) SetError(CERR_InfileNotExist); + + + // Transfer the file to a memory stream for processing UTF-8 or ANSI to UTF-16? + // What about really large files? Transfer to a temp file... + if (!fread(str, 1, 3, fp_in)) + { + fclose(fp_in); + return CERR_CannotReadInfile; + } + + fseek(fp_in, 0, SEEK_SET); + if (str[0] == UTF8Sig[0] && str[1] == UTF8Sig[1] && str[2] == UTF8Sig[2]) + fp_in = UTF16TempFromUTF8(fp_in, TRUE); + else if (str[0] == UTF16Sig[0] && str[1] == UTF16Sig[1]) + fseek(fp_in, 2, SEEK_SET); + else + fp_in = UTF16TempFromUTF8(fp_in, FALSE); + if (fp_in == NULL) + { + return CERR_CannotCreateTempfile; + } + + fp_out = Open_File(pszOutfile, "wb"); + + if (fp_out == NULL) SetError(CERR_CannotCreateOutfile); + + + KMX_DWORD msg; + FILE_KEYBOARD fk; + CodeConstants = new kmcmp::NamedCodeConstants; + err = CompileKeyboardHandle(fp_in, &fk); + if (err) + { + if ((msg = WriteCompiledKeyboard(&fk, fp_out)) != CERR_None) + AddCompileError(msg); + } + else + AddCompileError(CERR_InvalidValue); + + fclose(fp_in); + fclose(fp_out); + + delete CodeConstants; + + if (kmcmp::nErrors > 0) + { + remove(pszOutfile); + return FALSE; + } + + return err; +} + + + +extern "C" uint32_t kmcmp_CompileKeyboardFileToBuffer(char* pszInfile, void* pfkBuffer, bool ACompilerWarningsAsErrors, bool AWarnDeprecatedCode, + kmcmp_CompilerMessageProc pMsgproc, void* AmsgprocContext, int Target) // I4865 // I4866 +{ + //printf("°°-> changed to CompileKeyboardFileToBuffer() of kmcmplib \n"); + FILE* fp_in = NULL; + KMX_BOOL err; + KMX_CHAR str[260]; + + kmcmp::FSaveDebug = TRUE; // I3681 + kmcmp::FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865 + AWarnDeprecatedCode_GLOBAL_LIB = AWarnDeprecatedCode; + kmcmp::CompileTarget = Target; + + if (!pMsgproc || !pszInfile || !pfkBuffer) SetError(CERR_BadCallParams); + + PKMX_STR p; + + if ((p = strrchr_slash(pszInfile)) != nullptr) + { + strncpy(kmcmp::CompileDir, pszInfile, (int)(p - pszInfile + 1)); // I3481 + kmcmp::CompileDir[(int)(p - pszInfile + 1)] = 0; + } + else + kmcmp::CompileDir[0] = 0; + + msgproc = pMsgproc; + msgprocContext = AmsgprocContext; + kmcmp::currentLine = 0; + kmcmp::nErrors = 0; + + fp_in = Open_File(pszInfile,"rb"); + + if (fp_in == NULL) SetError(CERR_InfileNotExist); + + // Transfer the file to a memory stream for processing UTF-8 or ANSI to UTF-16? + // What about really large files? Transfer to a temp file... + + if( !fread(str,1,3,fp_in)) + { + fclose(fp_in); + return CERR_CannotReadInfile; + } + + fseek( fp_in,0,SEEK_SET); + if (str[0] == UTF8Sig[0] && str[1] == UTF8Sig[1] && str[2] == UTF8Sig[2]) + fp_in = UTF16TempFromUTF8(fp_in, TRUE); + else if (str[0] == UTF16Sig[0] && str[1] == UTF16Sig[1]) + fseek( fp_in,2,SEEK_SET); + else + fp_in = UTF16TempFromUTF8(fp_in, FALSE); + + CodeConstants = new kmcmp::NamedCodeConstants; + + err = CompileKeyboardHandle(fp_in, static_cast(pfkBuffer)); + delete CodeConstants; + fclose(fp_in); + + if (kmcmp::nErrors > 0) + return FALSE; + return err; +} + +KMX_BOOL CompileKeyboardHandle(FILE* fp_in, PFILE_KEYBOARD fk) +{ + PKMX_WCHAR str, p; + + KMX_DWORD msg; + + kmcmp::FMnemonicLayout = FALSE; + + if (!fk) { + SetError(CERR_SomewhereIGotItWrong); + } + + str = new KMX_WCHAR[LINESIZE]; + if (!str) { + SetError(CERR_CannotAllocateMemory); + } + + fk->KeyboardID = 0; + fk->version = 0; + fk->dpStoreArray = NULL; + fk->dpGroupArray = NULL; + fk->cxStoreArray = 0; + fk->cxGroupArray = 0; + fk->StartGroup[0] = fk->StartGroup[1] = -1; + fk->szName[0] = 0; + fk->szCopyright[0] = 0; + fk->dwFlags = KF_AUTOMATICVERSION; + fk->currentGroup = 0xFFFFFFFF; + fk->currentStore = 0; + fk->cxDeadKeyArray = 0; + fk->dpDeadKeyArray = NULL; + fk->cxVKDictionary = 0; // I3438 + fk->dpVKDictionary = NULL; // I3438 + +/* fk->szMessage[0] = 0; + fk->szLanguageName[0] = 0;*/ + fk->dwBitmapSize = 0; + fk->dwHotKey = 0; + + kmcmp::BeginLine[BEGIN_ANSI] = -1; + kmcmp::BeginLine[BEGIN_UNICODE] = -1; + kmcmp::BeginLine[BEGIN_NEWCONTEXT] = -1; + kmcmp::BeginLine[BEGIN_POSTKEYSTROKE] = -1; + + + /* Add a store for the Keyman 6.0 copyright information string */ + + if(kmcmp::FShouldAddCompilerVersion) { + u16sprintf(str,LINESIZE, L"Created with Keyman Developer version %d.%d.%d.%d", KEYMAN_VersionMajor, KEYMAN_VersionMinor, KEYMAN_VersionPatch, 0); + AddStore(fk, TSS_KEYMANCOPYRIGHT, str); + } + + /* Add a system store for the Keyman edition number */ + u16sprintf(str, LINESIZE, L"%d", 0); // I3481 + AddStore(fk, TSS_CUSTOMKEYMANEDITION, str); + + PKMX_WCHAR tbuf = strtowstr((KMX_CHAR*) "Keyman"); + AddStore(fk, TSS_CUSTOMKEYMANEDITIONNAME, tbuf); + delete tbuf; + + // must preprocess for group and store names -> this isn't really necessary, but never mind! + while ((msg = ReadLine(fp_in, str, TRUE)) == CERR_None) + { + p = str; + switch (LineTokenType(&p)) + { + case T_VERSION: + *(p + 4) = 0; + if ((msg = AddStore(fk, TSS_VERSION, p)) != CERR_None) SetError(msg); + break; + + case T_GROUP: + if ((msg = ProcessGroupLine(fk, p)) != CERR_None) SetError(msg); + break; + + case T_STORE: + if ((msg = ProcessStoreLine(fk, p)) != CERR_None) SetError(msg); + break; + + default: + break; + } + } + + if (msg != CERR_EndOfFile) SetError(msg); + + fseek( fp_in,2,SEEK_SET); + kmcmp::currentLine = 0; + + /* Reindex the list of codeconstants after stores added */ + + CodeConstants->reindex(); + + /* ReadLine will automatically skip over $Keyman lines, and parse wrapped lines */ + while ((msg = ReadLine(fp_in, str, FALSE)) == CERR_None) + { + msg = ParseLine(fk, str); + if (msg != CERR_None) SetError(msg); + } + + if (msg != CERR_EndOfFile) SetError(msg); + + ProcessGroupFinish(fk); + + if (kmcmp::FSaveDebug) kmcmp::RecordDeadkeyNames(fk); + + /* Add the compiler version as a system store */ + if ((msg = kmcmp::AddCompilerVersionStore(fk)) != CERR_None) SetError(msg); + + if ((msg = BuildVKDictionary(fk)) != CERR_None) SetError(msg); // I3438 + + if ((msg = CheckFilenameConsistencyForCalls(fk)) != CERR_None) SetError(msg); + + delete str; + + if (!kmcmp::CheckKeyboardFinalVersion(fk)) { + return FALSE; + } + + /* Warn on inconsistent use of NCAPS */ + if (!kmcmp::FMnemonicLayout) { + CheckNCapsConsistency(fk); + } + + /* Flag presence of deprecated features */ + kmcmp::CheckForDeprecatedFeatures(fk); + + return TRUE; +} + +KMX_DWORD ProcessBeginLine(PFILE_KEYBOARD fk, PKMX_WCHAR p) +{ + KMX_WCHAR tstr[128]; + PKMX_WCHAR q, pp; + int BeginMode; + KMX_DWORD msg; + + pp = p; + + q = ( PKMX_WCHAR) u16chr(p, '>'); + if (!q) return CERR_NoTokensFound; + + while (iswspace(*p)) p++; + if (u16nicmp(p, u"unicode", 7) == 0) BeginMode = BEGIN_UNICODE; + else if (u16nicmp(p, u"ansi", 4) == 0) BeginMode = BEGIN_ANSI; + else if (u16nicmp(p, u"newContext", 10) == 0) BeginMode = BEGIN_NEWCONTEXT; + else if (u16nicmp(p, u"postKeystroke", 13) == 0) BeginMode = BEGIN_POSTKEYSTROKE; + else if (*p != '>') return CERR_InvalidToken; + else BeginMode = BEGIN_ANSI; + + if(kmcmp::BeginLine[BeginMode] != -1) { + return CERR_RepeatedBegin; + } + + kmcmp::BeginLine[BeginMode] = kmcmp::currentLine; + + if ((msg = GetRHS(fk, p, tstr, 80, (int)(p - pp), FALSE)) != CERR_None) return msg; + + if (tstr[0] != UC_SENTINEL || tstr[1] != CODE_USE) { + return CERR_InvalidBegin; + } + if (tstr[3] != 0) { + return CERR_InvalidToken; + } + + if (BeginMode == BEGIN_ANSI || BeginMode == BEGIN_UNICODE) { + fk->StartGroup[BeginMode] = tstr[2] - 1; + //mcd-03-01-2000: removed the secondary group idea; this was undocumented and + //is not supported under Keyman 5.0: ugly!! + //if(tstr[3] == UC_SENTINEL && tstr[4] == CODE_USE) fk->StartGroup[1] = tstr[5] - 1; + + if (kmcmp::FSaveDebug) { + /* Record a system store for the line number of the begin statement */ + AddDebugStore(fk, BeginMode == BEGIN_UNICODE ? DEBUGSTORE_BEGIN u"Unicode" : DEBUGSTORE_BEGIN u"ANSI"); + } + } + else { + PFILE_GROUP gp = &fk->dpGroupArray[tstr[2] - 1]; + if (!gp->fReadOnly) { + return BeginMode == BEGIN_NEWCONTEXT ? + CERR_NewContextGroupMustBeReadonly : + CERR_PostKeystrokeGroupMustBeReadonly; + } + return AddStore(fk, BeginMode == BEGIN_NEWCONTEXT ? TSS_BEGIN_NEWCONTEXT : TSS_BEGIN_POSTKEYSTROKE, tstr, NULL); + } + + + + return CERR_None; +} + +KMX_DWORD ValidateMatchNomatchOutput(PKMX_WCHAR p) { + while (p && *p) { + if (*p == UC_SENTINEL) { + switch (*(p + 1)) { + case CODE_CONTEXT: + case CODE_CONTEXTEX: + case CODE_INDEX: + return CERR_ContextAndIndexInvalidInMatchNomatch; + } + } + p = incxstr(p); + } + return CERR_None; +} + +KMX_DWORD ParseLine(PFILE_KEYBOARD fk, PKMX_WCHAR str) +{ + PKMX_WCHAR p, q, pp; + PFILE_GROUP gp; + KMX_DWORD msg; + int IsUnicode = TRUE; // For NOW! + + KMX_WCHAR sep[2] = u"\n"; + PKMX_WCHAR p_sep =sep; + p = str; + pp = str; + + switch (LineTokenType(&p)) + { + case T_BLANK: + case T_COMMENT: + break; // Ignore the line + case T_VERSION: + case T_STORE: + break; // The line has already been processed + + case T_BEGIN: + // after a begin can be "Unicode" or "ANSI" or nothing (=ANSI) + if ((msg = ProcessBeginLine(fk, p)) != CERR_None) return msg; + break; + + case T_GROUP: + if (fk->currentGroup == 0xFFFFFFFF) fk->currentGroup = 0; + else + { + if ((msg = ProcessGroupFinish(fk)) != CERR_None) return msg; // finish off previous group first? + fk->currentGroup++; + } + // if( (err = ProcessGroupLine( fk, p )) != CERR_None ) return err; + break; + + case T_NAME: + kmcmp::WarnDeprecatedHeader(); // I4866 + q = GetDelimitedString(&p, u"\"\"", 0); + if (!q) return CERR_InvalidName; + + if ((msg = AddStore(fk, TSS_NAME, q)) != CERR_None) return msg; + break; + + case T_COPYRIGHT: + kmcmp::WarnDeprecatedHeader(); // I4866 + q = GetDelimitedString(&p, u"\"\"", 0); + if (!q) return CERR_InvalidCopyright; + + if ((msg = AddStore(fk, TSS_COPYRIGHT, q)) != CERR_None) return msg; + break; + + case T_MESSAGE: + kmcmp::WarnDeprecatedHeader(); // I4866 + q = GetDelimitedString(&p, u"\"\"", 0); + if (!q) return CERR_InvalidMessage; + + if ((msg = AddStore(fk, TSS_MESSAGE, q)) != CERR_None) return msg; + break; + + case T_LANGUAGENAME: + kmcmp::WarnDeprecatedHeader(); // I4866 + q = GetDelimitedString(&p, u"\"\"", 0); + if (!q) return CERR_InvalidLanguageName; + + if ((msg = AddStore(fk, TSS_LANGUAGENAME, q)) != CERR_None) return msg; + break; + + case T_LANGUAGE: + { + kmcmp::WarnDeprecatedHeader(); // I4866 + KMX_WCHAR *tokcontext = NULL; + q = u16tok(p, p_sep, &tokcontext); // I3481 + + if ((msg = AddStore(fk, TSS_LANGUAGE, q)) != CERR_None) return msg; + break; + } + case T_LAYOUT: + { + kmcmp::WarnDeprecatedHeader(); // I4866 + KMX_WCHAR *tokcontext = NULL; + q = u16tok(p, p_sep, &tokcontext); // I3481 + if ((msg = AddStore(fk, TSS_LAYOUT, q)) != CERR_None) return msg; + break; + } + case T_CAPSOFF: + kmcmp::WarnDeprecatedHeader(); // I4866 + if ((msg = AddStore(fk, TSS_CAPSALWAYSOFF, u"1")) != CERR_None) return msg; + break; + + case T_CAPSON: + kmcmp::WarnDeprecatedHeader(); // I4866 + if ((msg = AddStore(fk, TSS_CAPSONONLY, u"1")) != CERR_None) return msg; + break; + + case T_SHIFT: + kmcmp::WarnDeprecatedHeader(); // I4866 + if ((msg = AddStore(fk, TSS_SHIFTFREESCAPS, u"1")) != CERR_None) return msg; + break; + + case T_HOTKEY: + { + kmcmp::WarnDeprecatedHeader(); // I4866 + KMX_WCHAR *tokcontext = NULL; + if ((q = u16tok(p, p_sep, &tokcontext)) == NULL) return CERR_CodeInvalidInThisSection; // I3481 + if ((msg = AddStore(fk, TSS_HOTKEY, q)) != CERR_None) return msg; + break; + } + case T_BITMAP: + { + kmcmp::WarnDeprecatedHeader(); // I4866 + KMX_WCHAR *tokcontext = NULL; + if ((q = u16tok(p, p_sep, &tokcontext)) == NULL) return CERR_InvalidBitmapLine; // I3481 + + while (iswspace(*q)) q++; + if (*q == '"') { + p = q; + q = GetDelimitedString(&p, u"\"\"", 0); + if (!q) return CERR_InvalidBitmapLine; + } + + if ((msg = AddStore(fk, TSS_BITMAP, q)) != CERR_None) return msg; + break; + } + case T_BITMAPS: + { + kmcmp::WarnDeprecatedHeader(); // I4866 + KMX_WCHAR *tokcontext = NULL; + AddWarning(CWARN_BitmapNotUsed); + + if ((q = u16tok(p, p_sep, &tokcontext)) == NULL) return CERR_InvalidBitmapLine; // I3481 + + if ((PKMX_WCHAR) u16chr(q, ',')) *(PKMX_WCHAR) u16chr(q, ',') = 0; + if ((msg = AddStore(fk, TSS_BITMAP, q)) != CERR_None) return msg; + + break; + } + case T_KEYTOKEY: // A rule + if (fk->currentGroup == 0xFFFFFFFF) return CERR_CodeInvalidInThisSection; + if ((msg = ProcessKeyLine(fk, p, IsUnicode)) != CERR_None) return msg; + break; + + case T_MATCH: + if (fk->currentGroup == 0xFFFFFFFF) return CERR_CodeInvalidInThisSection; + { + PKMX_WCHAR buf = new KMX_WCHAR[GLOBAL_BUFSIZE]; + if ((msg = GetRHS(fk, p, buf, GLOBAL_BUFSIZE - 1, (int)(p - pp), IsUnicode)) != CERR_None) + { + delete[] buf; + return msg; + } + + if ((msg = ValidateMatchNomatchOutput(buf)) != CERR_None) { + delete[] buf; + return msg; + } + + gp = &fk->dpGroupArray[fk->currentGroup]; + + gp->dpMatch = new KMX_WCHAR[u16len(buf) + 1]; + u16ncpy(gp->dpMatch, buf, u16len(buf) + 1); // I3481 + + delete[] buf; + + if (kmcmp::FSaveDebug) + { + KMX_WCHAR tstr[128]; + //swprintf(tstr, "%d", fk->currentGroup); + /* Record a system store for the line number of the begin statement */ + //wcscpy(tstr, DEBUGSTORE_MATCH); + u16sprintf(tstr, _countof(tstr), L"%ls%d ", u16fmt(DEBUGSTORE_MATCH).c_str(), (int) fk->currentGroup); + u16ncat(tstr, gp->szName, _countof(tstr)); + + AddDebugStore(fk, tstr); + } + } + break; + + case T_NOMATCH: + if (fk->currentGroup == 0xFFFFFFFF) return CERR_CodeInvalidInThisSection; + { + PKMX_WCHAR buf = new KMX_WCHAR[GLOBAL_BUFSIZE]; + if ((msg = GetRHS(fk, p, buf, GLOBAL_BUFSIZE, (int)(p - pp), IsUnicode)) != CERR_None) + { + delete[] buf; + return msg; + } + + if ((msg = ValidateMatchNomatchOutput(buf)) != CERR_None) { + delete[] buf; + return msg; + } + + gp = &fk->dpGroupArray[fk->currentGroup]; + + gp->dpNoMatch = new KMX_WCHAR[u16len(buf) + 1]; + u16ncpy(gp->dpNoMatch, buf, u16len(buf) + 1); // I3481 + + delete[] buf; + + if (kmcmp::FSaveDebug) + { + KMX_WCHAR tstr[128]; + /* Record a system store for the line number of the begin statement */ + u16sprintf(tstr, _countof(tstr), L"%ls%d ", u16fmt(DEBUGSTORE_NOMATCH).c_str(), (int) fk->currentGroup); + u16ncat(tstr, gp->szName, _countof(tstr)); + AddDebugStore(fk, tstr); + } + } + break; + + default: + return CERR_InvalidToken; + } + + return CERR_None; +} + +//********************************************************************************************************************** + +KMX_DWORD ProcessGroupLine(PFILE_KEYBOARD fk, PKMX_WCHAR p) +{ + PFILE_GROUP gp; + PKMX_WCHAR q; + + gp = new FILE_GROUP[fk->cxGroupArray + 1]; + if (!gp) return CERR_CannotAllocateMemory; + + if (fk->dpGroupArray) + { + memcpy(gp, fk->dpGroupArray, sizeof(FILE_GROUP) * fk->cxGroupArray); + delete fk->dpGroupArray; + } + + fk->dpGroupArray = gp; + gp = &fk->dpGroupArray[fk->cxGroupArray]; + fk->cxGroupArray++; + + gp->dpKeyArray = NULL; + gp->dpMatch = NULL; + gp->dpNoMatch = NULL; + gp->cxKeyArray = 0; + + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q) return CERR_InvalidGroupLine; + + gp->fUsingKeys = FALSE; + gp->fReadOnly = IsSameToken(&p, u"readonly"); + if (!gp->fReadOnly) { + if (IsSameToken(&p, u"using") && IsSameToken(&p, u"keys")) + gp->fUsingKeys = TRUE; + } + + safe_wcsncpy(gp->szName, q, SZMAX_GROUPNAME); + + gp->Line = kmcmp::currentLine; + + if (kmcmp::FSaveDebug) + { + KMX_WCHAR tstr[128]; + /* Record a system store for the line number of the begin statement */ + u16sprintf(tstr, _countof(tstr), L"%ls%d ", u16fmt(DEBUGSTORE_GROUP).c_str(), fk->cxGroupArray - 1); + u16ncat(tstr, gp->szName, _countof(tstr)); + AddDebugStore(fk, tstr); + } + + return CheckForDuplicateGroup(fk, gp); +} + +int kmcmp::cmpkeys(const void *key, const void *elem) +{ + PFILE_KEY akey; + PFILE_KEY aelem; + int l1, l2; + KMX_WCHAR char_key, char_elem; + akey = (PFILE_KEY)key; + aelem = (PFILE_KEY)elem; + char_key = kmcmp::VKToChar(akey->Key, akey->ShiftFlags); + char_elem = kmcmp::VKToChar(aelem->Key, aelem->ShiftFlags); + if (char_key == char_elem) //akey->Key == aelem->Key) + { + l1 = xstrlen(akey->dpContext); l2 = xstrlen(aelem->dpContext); + if (l1 == l2) + { + if (akey->Line < aelem->Line) return -1; + if (akey->Line > aelem->Line) return 1; + if(akey->Key == aelem->Key) { + if(akey->ShiftFlags == aelem->ShiftFlags) { + return akey->LineStoreIndex - aelem->LineStoreIndex; + } + return akey->ShiftFlags - aelem->ShiftFlags; + } + return akey->Key - aelem->Key; + } + if (l1 < l2) return 1; + if (l1 > l2) return -1; + if(akey->Key == aelem->Key) { + if(akey->ShiftFlags == aelem->ShiftFlags) { + return akey->LineStoreIndex - aelem->LineStoreIndex; + } + return akey->ShiftFlags - aelem->ShiftFlags; + } + return akey->Key - aelem->Key; + } + return(char_key - char_elem); // akey->Key - aelem->Key); +} + +KMX_DWORD ProcessGroupFinish(PFILE_KEYBOARD fk) +{ + PFILE_GROUP gp; + KMX_DWORD msg; + + if (fk->currentGroup == 0xFFFFFFFF) return CERR_None; + // Just got to first group - so nothing to finish yet + + gp = &fk->dpGroupArray[fk->currentGroup]; + + // Finish off the previous group stuff! + if ((msg = ExpandCapsRulesForGroup(fk, gp)) != CERR_None) return msg; + qsort(gp->dpKeyArray, gp->cxKeyArray, sizeof(FILE_KEY), kmcmp::cmpkeys); + + return VerifyUnreachableRules(gp); +} + +/*************************************** +* Store management +*/ + +KMX_DWORD ProcessStoreLine(PFILE_KEYBOARD fk, PKMX_WCHAR p) +{ + PKMX_WCHAR q, pp; + PFILE_STORE sp; + //WCHAR temp[GLOBAL_BUFSIZE]; + KMX_DWORD msg; + int i = 0; + + pp = p; + + if ((q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL)) == NULL) return CERR_InvalidStoreLine; + + if (*q == *SSN__PREFIX) + { + for (i = 0; StoreTokens[i]; i++) + if (!u16icmp(q, StoreTokens[i])) // I3481 + break; + if (!StoreTokens[i]) return CERR_InvalidSystemStore; + } + + sp = new FILE_STORE[fk->cxStoreArray + 1]; + if (!sp) return CERR_CannotAllocateMemory; + + if (fk->dpStoreArray) + { + memcpy(sp, fk->dpStoreArray, sizeof(FILE_STORE) * fk->cxStoreArray); + delete fk->dpStoreArray; + } + + fk->dpStoreArray = sp; + sp = &fk->dpStoreArray[fk->cxStoreArray]; + + sp->line = kmcmp::currentLine; + sp->fIsOption = FALSE; + sp->fIsReserved = FALSE; + sp->fIsStore = FALSE; + sp->fIsDebug = FALSE; + sp->fIsCall = FALSE; + + safe_wcsncpy(sp->szName, q, SZMAX_STORENAME); + { + PKMX_WCHAR temp = new KMX_WCHAR[GLOBAL_BUFSIZE]; + + if ((msg = GetXString(fk, p, u"c\n", temp, GLOBAL_BUFSIZE - 1, (int)(p - pp), &p, FALSE, TRUE)) != CERR_None) + { + delete[] temp; + return msg; + } + + sp->dwSystemID = i; + sp->dpString = new KMX_WCHAR[u16len(temp) + 1]; + u16ncpy(sp->dpString, temp, u16len(temp) + 1); // I3481 + + delete[] temp; + } + + if (xstrlen(sp->dpString) == 1 && *sp->dpString != UC_SENTINEL && + sp->dwSystemID == 0 && (fk->version >= VERSION_60 || fk->version == 0)) + { + // In this case, we want to change behaviour for older versioned keyboards so that + // we don't mix up named character codes which weren't supported in 5.x + VERIFY_KEYBOARD_VERSION(fk, VERSION_60, CERR_60FeatureOnly_NamedCodes); + // Add a single char store as a defined character constant + if (Uni_IsSurrogate1(*sp->dpString)) + CodeConstants->AddCode(Uni_SurrogateToUTF32(sp->dpString[0], sp->dpString[1]), sp->szName, fk->cxStoreArray); + else + CodeConstants->AddCode(sp->dpString[0], sp->szName, fk->cxStoreArray); + CodeConstants->reindex(); // has to be done after every character add due to possible use in another store. // I4982 + } + + fk->cxStoreArray++; // increment now, because GetXString refers to stores + + if (i > 0) + if ((msg = ProcessSystemStore(fk, i, sp)) != CERR_None) return msg; + + return CheckForDuplicateStore(fk, sp); +} + +KMX_DWORD AddStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, KMX_WCHAR const * str, KMX_DWORD *dwStoreID) +{ + PFILE_STORE sp; + sp = new FILE_STORE[fk->cxStoreArray + 1]; + if (!sp) return CERR_CannotAllocateMemory; + + if (fk->dpStoreArray) + { + memcpy(sp, fk->dpStoreArray, sizeof(FILE_STORE) * fk->cxStoreArray); + delete fk->dpStoreArray; + } + + fk->dpStoreArray = sp; + sp = &fk->dpStoreArray[fk->cxStoreArray]; + + sp->line = kmcmp::currentLine; + sp->fIsOption = FALSE; // I3686 + sp->fIsReserved = (SystemID != TSS_NONE); + sp->fIsStore = FALSE; + sp->fIsDebug = FALSE; + sp->fIsCall = FALSE; + + safe_wcsncpy(sp->szName, (PKMX_WCHAR) StoreTokens[SystemID], SZMAX_STORENAME); + + sp->dpString = new KMX_WCHAR[u16len(str) + 1]; + u16ncpy(sp->dpString, str, u16len(str) + 1); // I3481 + + sp->dwSystemID = SystemID; + + if (dwStoreID) *dwStoreID = fk->cxStoreArray; + + fk->cxStoreArray++; + + return ProcessSystemStore( fk, SystemID, sp); +} + +KMX_DWORD AddDebugStore(PFILE_KEYBOARD fk, KMX_WCHAR const * str) +{ + PFILE_STORE sp; + KMX_WCHAR tstr[16]; + u16sprintf(tstr, _countof(tstr), L"%d", kmcmp::currentLine); // I3481 + + sp = new FILE_STORE[fk->cxStoreArray + 1]; + if (!sp) return CERR_CannotAllocateMemory; + + if (fk->dpStoreArray) + { + memcpy(sp, fk->dpStoreArray, sizeof(FILE_STORE) * fk->cxStoreArray); + delete[] fk->dpStoreArray; + } + + fk->dpStoreArray = sp; + sp = &fk->dpStoreArray[fk->cxStoreArray]; + + safe_wcsncpy(sp->szName, (PKMX_WCHAR) str, SZMAX_STORENAME); + + sp->dpString = new KMX_WCHAR[u16len(tstr) + 1]; + u16ncpy(sp->dpString, tstr, u16len(tstr) + 1); // I3481 + sp->line = 0; + sp->fIsOption = FALSE; + sp->fIsReserved = TRUE; + sp->fIsStore = FALSE; + sp->fIsDebug = TRUE; + sp->fIsCall = FALSE; + sp->dwSystemID = TSS_DEBUG_LINE; + fk->cxStoreArray++; + + return CERR_None; +} + +PKMX_WCHAR pssBuf = NULL; + +KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE sp) +{ + //WCHAR buf[GLOBAL_BUFSIZE]; + int i, j; + KMX_DWORD msg; + PKMX_WCHAR p, q; + KMX_CHAR *pp; + + if (!pssBuf) pssBuf = new KMX_WCHAR[GLOBAL_BUFSIZE]; + PKMX_WCHAR buf = pssBuf; + + switch (SystemID) + { + case TSS_BITMAP: + if ((msg = ImportBitmapFile(fk, sp->dpString, &fk->dwBitmapSize, &fk->lpBitmap)) != CERR_None) + return msg; + break; + + case TSS_CALLDEFINITION: + break; + + case TSS_CALLDEFINITION_LOADFAILED: + break; + + case TSS_CAPSALWAYSOFF: + if (*sp->dpString == u'1') fk->dwFlags |= KF_CAPSALWAYSOFF; + break; + + case TSS_CAPSONONLY: + if (*sp->dpString == u'1') fk->dwFlags |= KF_CAPSONONLY; + break; + + case TSS_COMPILEDVERSION: + break; + + case TSS_COPYRIGHT: + break; + + case TSS_DEBUG_LINE: + break; + + case TSS_ETHNOLOGUECODE: + VERIFY_KEYBOARD_VERSION(fk, VERSION_60, CERR_60FeatureOnly_EthnologueCode); + if ((msg = ProcessEthnologueStore(sp->dpString)) != CERR_None) return msg; // I2646 + break; + + case TSS_HOTKEY: + if ((msg = ProcessHotKey(sp->dpString, &fk->dwHotKey)) != CERR_None) return msg; + u16sprintf(buf, GLOBAL_BUFSIZE, L"%d", (int)fk->dwHotKey); // I3481 + delete[] sp->dpString; + sp->dpString = new KMX_WCHAR[u16len(buf) + 1]; + u16ncpy(sp->dpString, buf, u16len(buf) + 1); // I3481 + break; + + case TSS_INCLUDECODES: + VERIFY_KEYBOARD_VERSION(fk, VERSION_60, CERR_60FeatureOnly_NamedCodes); + pp = wstrtostr(sp->dpString); + if (!CodeConstants->LoadFile(pp)) + { + delete[] pp; + return CERR_CannotLoadIncludeFile; + } + delete[] pp; + CodeConstants->reindex(); // I4982 + break; + + case TSS_LANGUAGE: + { + KMX_WCHAR *context = NULL; + KMX_WCHAR sep_c[3] = u", "; + PKMX_WCHAR p_sep_c = sep_c; + q = u16tok(sp->dpString, p_sep_c, &context); // I3481 + if (!q) return CERR_InvalidLanguageLine; + + i = xatoi(&q); + KMX_WCHAR sep_n[4] = u" c\n"; + PKMX_WCHAR p_sep_n = sep_n; + q = u16tok(NULL, p_sep_n, &context); // I3481 + if (!q) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_70, CERR_InvalidLanguageLine); + j = SUBLANGID(i); + i = PRIMARYLANGID(i); + } + else + j = xatoi(&q); + + if (i < 1 || j < 1 || i > 0x3FF || j > 0x3F) return CERR_InvalidLanguageLine; + if (i >= 0x200 || j >= 0x20) AddWarning(CWARN_CustomLanguagesNotSupported); + + fk->KeyboardID = (KMX_DWORD)MAKELANGID(i, j); + + u16sprintf(buf, GLOBAL_BUFSIZE, L"%x %x", i, j); // I3481 + delete[] sp->dpString; + sp->dpString = new KMX_WCHAR[u16len(buf) + 1]; + u16ncpy(sp->dpString, buf, u16len(buf) + 1); // I3481 + + break; + } + case TSS_LANGUAGENAME: + break; + + case TSS_LAYOUT: + if (fk->KeyboardID == 0) return CERR_LayoutButNoLanguage; + + q = sp->dpString; + + fk->KeyboardID |= (xatoi(&q) << 16L); + break; + + case TSS_MESSAGE: + break; + + case TSS_MNEMONIC: + VERIFY_KEYBOARD_VERSION(fk, VERSION_60, CERR_60FeatureOnly_MnemonicLayout); + kmcmp::FMnemonicLayout = atoiW(sp->dpString) == 1; + if (kmcmp::FMnemonicLayout && FindSystemStore(fk, TSS_CASEDKEYS) != NULL) { + // The &CasedKeys system store is not supported for + // mnemonic layouts + return CERR_CasedKeysNotSupportedWithMnemonicLayout; + } + break; + + case TSS_NAME: + break; + + case TSS_OLDCHARPOSMATCHING: + VERIFY_KEYBOARD_VERSION(fk, VERSION_60, CERR_60FeatureOnly_OldCharPosMatching); + kmcmp::FOldCharPosMatching = atoiW(sp->dpString); + break; + + case TSS_SHIFTFREESCAPS: + if (*sp->dpString == u'1') fk->dwFlags |= KF_SHIFTFREESCAPS; + break; + + case TSS_VERSION: + if ((fk->dwFlags & KF_AUTOMATICVERSION) == 0) return CERR_VersionAlreadyIncluded; + p = sp->dpString; + if (u16tof (p) < 5.0) { + AddWarning(CWARN_OldVersion); + } + + if (u16ncmp(p, u"3.0", 3) == 0) fk->version = VERSION_50; //0x0a0b000n= a.bn + else if (u16ncmp(p, u"3.1", 3) == 0) fk->version = VERSION_50; //all versions < 5.0 + else if (u16ncmp(p, u"3.2", 3) == 0) fk->version = VERSION_50; //we compile as if + else if (u16ncmp(p, u"4.0", 3) == 0) fk->version = VERSION_50; //they are 5.0.100.0 + else if (u16ncmp(p, u"5.01", 4) == 0) fk->version = VERSION_501; + else if (u16ncmp(p, u"5.0", 3) == 0) fk->version = VERSION_50; + else if (u16ncmp(p, u"6.0", 3) == 0) fk->version = VERSION_60; + else if (u16ncmp(p, u"7.0", 3) == 0) fk->version = VERSION_70; + else if (u16ncmp(p, u"8.0", 3) == 0) fk->version = VERSION_80; + else if (u16ncmp(p, u"9.0", 3) == 0) fk->version = VERSION_90; + else if (u16ncmp(p, u"10.0", 4) == 0) fk->version = VERSION_100; + else if (u16ncmp(p, u"14.0", 4) == 0) fk->version = VERSION_140; // Adds support for #917 -- context() with notany() for KeymanWeb + else if (u16ncmp(p, u"15.0", 4) == 0) fk->version = VERSION_150; // Adds support for U_xxxx_yyyy #2858 + + else return CERR_InvalidVersion; + + if (fk->version < VERSION_60) kmcmp::FOldCharPosMatching = TRUE; + + fk->dwFlags &= ~KF_AUTOMATICVERSION; + + break; + + case TSS_VISUALKEYBOARD: + VERIFY_KEYBOARD_VERSION(fk, VERSION_70, CERR_70FeatureOnly); + { + // Strip path from the store, leaving bare filename only + p = sp->dpString; + + KMX_WCHAR *pp = (KMX_WCHAR*) u16rchr_slash((const PKMX_WCHAR) p); + + if (!pp) { + pp = p; + } else { + pp++; + } + q = new KMX_WCHAR[u16len(pp) + 1]; + u16ncpy(q, pp, u16len(pp) + 1); + + // Change compiled reference file extension to .kvk + pp = ( km_kbp_cp *) u16chr(q, 0) - 5; + if (pp > q && u16icmp(pp, u".kvks") == 0) { + pp[4] = 0; + } + + delete[] sp->dpString; + sp->dpString = q; + + if ((msg = CheckFilenameConsistency( (sp->dpString), FALSE)) != CERR_None) { + return msg; + } + } + break; + case TSS_KMW_RTL: + case TSS_KMW_HELPTEXT: + VERIFY_KEYBOARD_VERSION(fk, VERSION_70, CERR_70FeatureOnly); + break; + + case TSS_KMW_HELPFILE: + case TSS_KMW_EMBEDJS: + VERIFY_KEYBOARD_VERSION(fk, VERSION_70, CERR_70FeatureOnly); + if ((msg = CheckFilenameConsistency(sp->dpString, FALSE)) != CERR_None) { + return msg; + } + break; + + case TSS_KMW_EMBEDCSS: + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_90FeatureOnlyEmbedCSS); + if ((msg = CheckFilenameConsistency(sp->dpString, FALSE)) != CERR_None) { + return msg; + } + break; + + case TSS_TARGETS: // I4504 + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_90FeatureOnlyTargets); + break; + + case TSS_WINDOWSLANGUAGES: + { + KMX_WCHAR *context = NULL; + VERIFY_KEYBOARD_VERSION(fk, VERSION_70, CERR_70FeatureOnly); + size_t szQ = u16len(sp->dpString) * 6 + 1; // I3481 + q = new KMX_WCHAR[szQ]; // guaranteed to be enough space for recoding + *q = 0; KMX_WCHAR *r = q; + KMX_WCHAR sep_s[4] = u" "; + PKMX_WCHAR p_sep_s = sep_s; + p = u16tok(sp->dpString, p_sep_s, &context); // I3481 + while (p) + { + int n = xatoi(&p); + + j = SUBLANGID(n); + i = PRIMARYLANGID(n); + + if (i < 1 || j < 1 || i > 0x3FF || j > 0x3F) { + delete[] q; + return CERR_InvalidLanguageLine; + } + + u16sprintf(r, szQ - (size_t)(r - q), L"x%04.4x ", n); // I3481 + p = u16tok(NULL, sep_s, &context); // I3481 + r = (KMX_WCHAR*) u16chr(q, 0); // I3481 + } + delete[] sp->dpString; + if (*q) { + *((KMX_WCHAR*) u16chr(q, 0) - 1) = 0; // delete final space - safe because we control the formatting - ugly? scared? + } + sp->dpString = q; + break; + } + case TSS_COMPARISON: + VERIFY_KEYBOARD_VERSION(fk, VERSION_80, CERR_80FeatureOnly); + break; + + case TSS_VKDICTIONARY: // I3438 + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_90FeatureOnlyVirtualKeyDictionary); + break; + + case TSS_LAYOUTFILE: // I3483 + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_90FeatureOnlyLayoutFile); // I4140 + if ((msg = CheckFilenameConsistency(sp->dpString, FALSE)) != CERR_None) { + return msg; + } + // Used by KMW compiler + break; + + case TSS_KEYBOARDVERSION: // I4140 + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_90FeatureOnlyKeyboardVersion); + if (!IsValidKeyboardVersion(sp->dpString)) { + return CERR_KeyboardVersionFormatInvalid; + } + break; + + case TSS_CASEDKEYS: + if ((msg = VerifyCasedKeys(sp)) != CERR_None) { + return msg; + } + break; + + case TSS_BEGIN_NEWCONTEXT: + case TSS_BEGIN_POSTKEYSTROKE: + break; + + case TSS_NEWLAYER: + case TSS_OLDLAYER: + break; + + default: + return CERR_InvalidSystemStore; + } + return CERR_None; +} + +KMX_BOOL IsValidKeyboardVersion(KMX_WCHAR *dpString) { // I4140 + /* version format \d+(\.\d+)* e.g. 9.0.3, 1.0, 1.2.3.4, 6.2.1.4.6.4, blank is not allowed */ + + do { + if (!iswdigit(*dpString)) { + return FALSE; + } + while (iswdigit(*dpString)) { + dpString++; + } + if (*dpString == '.') { + dpString++; + if (!iswdigit(*dpString)) { + return FALSE; + } + } + } while (*dpString != 0); + + return TRUE; +} + + +KMX_DWORD kmcmp::AddCompilerVersionStore(PFILE_KEYBOARD fk) +{ + KMX_DWORD msg; + + if(!kmcmp::FShouldAddCompilerVersion) { + return CERR_None; + } + + if ((msg = AddStore(fk, TSS_COMPILEDVERSION, KEYMAN_VersionWin_W16)) != CERR_None) return msg; + + return CERR_None; +} + +/**************************** +* Rule lines +*/ + +KMX_DWORD CheckStatementOffsets(PFILE_KEYBOARD fk, PFILE_GROUP gp, PKMX_WCHAR context, PKMX_WCHAR output, PKMX_WCHAR key) { + PKMX_WCHAR p, q; + int i; + for (p = output; *p; p = incxstr(p)) { + if (*p == UC_SENTINEL) { + if (*(p + 1) == CODE_INDEX) { + int indexStore = *(p + 2) - 1; + int contextOffset = *(p + 3); + for (q = context, i = 1; *q && i < contextOffset; q = incxstr(q), i++); + + if (*q == 0) { + if (!gp->fUsingKeys) + // no key in the rule, so offset is past end of context + return CERR_IndexDoesNotPointToAny; + if (i < contextOffset) // I4914 + // offset is beyond the key + return CERR_IndexDoesNotPointToAny; + q = key; + } + + // find the any + if (*q != UC_SENTINEL || *(q + 1) != CODE_ANY) + return CERR_IndexDoesNotPointToAny; + + int anyStore = *(q + 2) - 1; + + if (xstrlen(fk->dpStoreArray[indexStore].dpString) < xstrlen(fk->dpStoreArray[anyStore].dpString)) { + AddWarning(CWARN_IndexStoreShort); //TODO: if this fails, then we return FALSE instead of an error + } + } else if (*(p + 1) == CODE_CONTEXTEX) { + int contextOffset = *(p + 2); + if (contextOffset > xstrlen(context)) + return CERR_ContextExHasInvalidOffset; + + // Due to a limitation in earlier versions of KeymanWeb, the minimum version + // for context() referring to notany() is 14.0. See #917 for details. + if (kmcmp::CompileTarget == CKF_KEYMANWEB) { + for (q = context, i = 1; *q && i < contextOffset; q = incxstr(q), i++); + if (*q == UC_SENTINEL && *(q + 1) == CODE_NOTANY) { + VERIFY_KEYBOARD_VERSION(fk, VERSION_140, CERR_140FeatureOnlyContextAndNotAnyWeb); + } + } + } + } + } + return CERR_None; +} + +/** + *Checks that the order of statements in the context matches the specification + * Rule structure: [context] ['+' key] '>' output + * Context structure: [nul] [if()|baselayout()|platform()]+ [char|any|context()|deadkey()|dk()|index()|notany()|outs()] + * Test that nul is first, then if(), baselayout(), platform() statements are before any other content + */ +KMX_BOOL CheckContextStatementPositions(PKMX_WCHAR context) { + KMX_BOOL hadContextChar = FALSE; + for (PKMX_WCHAR p = context; *p; p = incxstr(p)) { + if (*p == UC_SENTINEL) { + switch (*(p + 1)) { + case CODE_NUL: + if (p > context) { + AddWarning(CWARN_NulNotFirstStatementInContext); + } + break; + case CODE_IFOPT: + case CODE_IFSYSTEMSTORE: + if (hadContextChar) { + AddWarning(CWARN_IfShouldBeAtStartOfContext); + } + break; + default: + hadContextChar = TRUE; + } + } + else { + hadContextChar = TRUE; + } + } + + return TRUE; +} +/** + * Checks if a use() statement is followed by other content in the output of a rule + */ +KMX_DWORD CheckUseStatementsInOutput(const PFILE_GROUP gp,PKMX_WCHAR output) { + KMX_BOOL hasUse = FALSE; + PKMX_WCHAR p; + for (p = output; *p; p = incxstr(p)) { + if (*p == UC_SENTINEL && *(p + 1) == CODE_USE) { + hasUse = TRUE; + } else if (hasUse) { + AddWarning(CWARN_UseNotLastStatementInRule); + break; + } + } + return CERR_None; +} + +/** + * Adds implicit `context` to start of output of rules for readonly groups + */ +KMX_DWORD InjectContextToReadonlyOutput(PKMX_WCHAR pklOut) { + if (pklOut[0] != UC_SENTINEL || pklOut[1] != CODE_CONTEXT) { + if (u16len(pklOut) > GLOBAL_BUFSIZE - 3) { + return CERR_CannotAllocateMemory; + } + memmove(pklOut + 2, pklOut, (u16len(pklOut) + 1) * 2); + pklOut[0] = UC_SENTINEL; + pklOut[1] = CODE_CONTEXT; + } + return CERR_None; +} + +/** + * Verifies that a keyboard does not attempt to emit characters or + * other changes to text store when processing a readonly group + */ +KMX_DWORD CheckOutputIsReadonly(const PFILE_KEYBOARD fk, const PKMX_WCHAR output) { // I4867 + PKMX_WCHAR p; + for (p = output; *p; p = incxstr(p)) { + if (*p != UC_SENTINEL) { + return CERR_OutputInReadonlyGroup; + } + switch (*(p + 1)) { + case CODE_CALL: + // We cannot be sure that the callee is going to be readonly + // but we have to operate on a trust basis for call() in any + // case, so we'll allow it. + continue; + case CODE_USE: + // We only allow use() of other readonly groups + { + PFILE_GROUP targetGroup = &fk->dpGroupArray[*(p + 2) - 1]; + if (!targetGroup->fReadOnly) { + return CERR_CannotUseReadWriteGroupFromReadonlyGroup; + } + } + continue; + case CODE_SETOPT: + case CODE_RESETOPT: + case CODE_SAVEOPT: + // it is okay to set, reset or save keyboard options + // although it's hard to see good use cases for this + continue; + case CODE_SETSYSTEMSTORE: + // it is okay to set system stores; Engine or Core will + // ignore set(&) that are not permissible in the given context + continue; + case CODE_CONTEXT: + // We allow `context` but only as the very first statement in output + if (p == output) { + continue; + } + return CERR_OutputInReadonlyGroup; + default: + // Note: conceptually, CODE_NUL could be transformed to CODE_CONTEXT + // if the context was also empty, but it is probably safest to avoid this, + // given CODE_CONTEXT does what we need anyway + return CERR_StatementNotPermittedInReadonlyGroup; + } + } + return CERR_None; +} + +KMX_DWORD ProcessKeyLineImpl(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnicode, PKMX_WCHAR pklIn, PKMX_WCHAR pklKey, PKMX_WCHAR pklOut); + +KMX_DWORD ProcessKeyLine(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnicode) +{ + PKMX_WCHAR pklIn, pklKey, pklOut; + + pklIn = new KMX_WCHAR[GLOBAL_BUFSIZE]; // I2432 - Allocate buffers each line -- slightly slower but safer than keeping a single buffer + pklKey = new KMX_WCHAR[GLOBAL_BUFSIZE]; + pklOut = new KMX_WCHAR[GLOBAL_BUFSIZE]; + if (!pklIn || !pklKey || !pklOut) + return CERR_CannotAllocateMemory; // forget about the little leak if pklKey or pklOut fail... + + KMX_DWORD result = ProcessKeyLineImpl(fk, str, IsUnicode, pklIn, pklKey, pklOut); + + delete[] pklIn; // I2432 - Allocate buffers each line -- slightly slower but safer than keeping a single buffer + delete[] pklKey; + delete[] pklOut; + + return result; +} + +KMX_DWORD ProcessKeyLineImpl(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnicode, PKMX_WCHAR pklIn, PKMX_WCHAR pklKey, PKMX_WCHAR pklOut) { + PKMX_WCHAR p, pp; + KMX_DWORD msg; + PFILE_GROUP gp; + PFILE_KEY kp; + + gp = &fk->dpGroupArray[fk->currentGroup]; + + pp = str; + + if (gp->fUsingKeys) { + if ((msg = GetXString(fk, str, u"+", pklIn, GLOBAL_BUFSIZE - 1, (int)(str - pp), &p, TRUE, IsUnicode)) != CERR_None) return msg; + + str = p + 1; + if ((msg = GetXString(fk, str, u">", pklKey, GLOBAL_BUFSIZE - 1, (int)(str - pp), &p, TRUE, IsUnicode)) != CERR_None) return msg; + if (pklKey[0] == 0) return CERR_ZeroLengthString; + if (xstrlen(pklKey) > 1) AddWarning(CWARN_KeyBadLength); + } else { + if ((msg = GetXString(fk, str, u">", pklIn, GLOBAL_BUFSIZE - 1, (int)(str - pp), &p, TRUE, IsUnicode)) != CERR_None) return msg; + if (pklIn[0] == 0) return CERR_ZeroLengthString; + } + + str = p + 1; + if ((msg = GetXString(fk, str, u"c\n", pklOut, GLOBAL_BUFSIZE - 1, (int)(str - pp), &p, TRUE, IsUnicode)) != CERR_None) return msg; + + if (pklOut[0] == 0) return CERR_ZeroLengthString; + + CheckContextStatementPositions(pklIn); + + // Test index and context offsets in context + if ((msg = CheckStatementOffsets(fk, gp, pklIn, pklOut, pklKey)) != CERR_None) return msg; + + // Test that use() statements are not followed by other content + if ((msg = CheckUseStatementsInOutput(gp, pklOut)) != CERR_None) { + return msg; // I4867 + } + + if (gp->fReadOnly) { + // Ensure no output is made from the rule, and that + // use() statements meet required readonly semantics + if ((msg = CheckOutputIsReadonly(fk, pklOut)) != CERR_None) { + return msg; + } + + // Inject `context` to start of output if group is readonly + // to keep the output internally consistent + if ((msg = InjectContextToReadonlyOutput(pklOut)) != CERR_None) { + return msg; + } + } + + kp = new FILE_KEY[gp->cxKeyArray + 1]; + if (!kp) return CERR_CannotAllocateMemory; + if (gp->dpKeyArray) + { + memcpy(kp, gp->dpKeyArray, gp->cxKeyArray * sizeof(FILE_KEY)); + delete gp->dpKeyArray; + } + + gp->dpKeyArray = kp; + kp = &gp->dpKeyArray[gp->cxKeyArray]; + + gp->cxKeyArray++; + + kp->dpOutput = new KMX_WCHAR[u16len(pklOut) + 1]; + u16ncpy(kp->dpOutput, pklOut, u16len(pklOut) + 1); // I3481 + + kp->dpContext = new KMX_WCHAR[u16len(pklIn) + 1]; + u16ncpy(kp->dpContext, pklIn, u16len(pklIn) + 1); // I3481 + + kp->Line = kmcmp::currentLine; + kp->LineStoreIndex = 0; + + // Finished if we are not using keys + + if (!gp->fUsingKeys) + { + kp->Key = 0; + kp->ShiftFlags = 0; + return CERR_None; + } + + // Expand each rule out into multiple rules - much faster processing at the key hit time + + if (*pklKey == 0) return CERR_ZeroLengthString; + + if (*pklKey == UC_SENTINEL) + switch (*(pklKey + 1)) + { + case CODE_ANY: + kp->ShiftFlags = 0; + if ((msg = ExpandKp(fk, kp, *(pklKey + 2) - 1)) != CERR_None) return msg; + break; + + case CODE_EXTENDED: + kp->Key = *(pklKey + 3); + kp->ShiftFlags = *(pklKey + 2); + break; + + default: + return CERR_InvalidCodeInKeyPartOfRule; + } + else + { + kp->ShiftFlags = 0; + kp->Key = *pklKey; + } + + return CERR_None; +} + + + +KMX_DWORD ExpandKp_ReplaceIndex(PFILE_KEYBOARD fk, PFILE_KEY k, KMX_DWORD keyIndex, int nAnyIndex) +{ + /* Replace each index(xx,keyIndex) in k->dpOutput with appropriate char as based on nAnyIndex */ + PFILE_STORE s; + int i; + PKMX_WCHAR pIndex, pStore; + + for (pIndex = k->dpOutput; *pIndex; pIndex = incxstr(pIndex)) + { + if (*pIndex == UC_SENTINEL && *(pIndex + 1) == CODE_INDEX && *(pIndex + 3) == keyIndex) + { + s = &fk->dpStoreArray[*(pIndex + 2) - 1]; + for (i = 0, pStore = s->dpString; i < nAnyIndex; i++, pStore = incxstr(pStore)); + PKMX_WCHAR qStore = incxstr(pStore); + + int w = (int)(qStore - pStore); + if (w > 4) + { + *pIndex = UC_SENTINEL; + *(pIndex + 1) = CODE_BEEP; + memmove(pIndex + 2, pIndex + 4, u16len(pIndex + 3) * 2); + } + else + { + memcpy(pIndex, pStore, w * 2); + if (w < 4) memmove(pIndex + w, pIndex + 4, u16len(pIndex + 3) * 2); + } + } + } + + return CERR_None; +} + + +KMX_DWORD ExpandKp(PFILE_KEYBOARD fk, PFILE_KEY kpp, KMX_DWORD storeIndex) +{ + PFILE_KEY k; + PKMX_WCHAR pn; + KMX_DWORD nchrs, n; + int keyIndex; + + PFILE_STORE sp = &fk->dpStoreArray[storeIndex]; + PFILE_GROUP gp = &fk->dpGroupArray[fk->currentGroup]; + + PKMX_WCHAR dpContext = kpp->dpContext; + PKMX_WCHAR dpOutput = kpp->dpOutput; + + nchrs = xstrlen(sp->dpString); + pn = sp->dpString; + keyIndex = xstrlen(dpContext) + 1; + + /* + Now we change them to plain characters in the output in multiple rules, + and set the keystroke to the appropriate character in the store. + */ + + k = new FILE_KEY[gp->cxKeyArray + nchrs - 1]; + if (!k) return CERR_CannotAllocateMemory; + memcpy(k, gp->dpKeyArray, gp->cxKeyArray * sizeof(FILE_KEY)); + + kpp = &k[(int)(kpp - gp->dpKeyArray)]; + + delete gp->dpKeyArray; + gp->dpKeyArray = k; + gp->cxKeyArray += nchrs - 1; + + for (k = kpp, n = 0, pn = sp->dpString; *pn; pn = incxstr(pn), k++, n++) + { + k->dpContext = new KMX_WCHAR[u16len(dpContext) + 1]; + k->dpOutput = new KMX_WCHAR[u16len(dpOutput) + 1]; + + u16ncpy(k->dpContext, dpContext, u16len(dpContext) + 1); // copy the context. // I3481 + u16ncpy(k->dpOutput, dpOutput, u16len(dpOutput) + 1); // copy the output. + + if (*pn == UC_SENTINEL) + { + switch (*(pn + 1)) + { + case CODE_EXTENDED: + k->Key = *(pn + 3); // set the key to store offset. + k->ShiftFlags = *(pn + 2); + break; + default: + return CERR_CodeInvalidInKeyStore; + } + } + else + { + k->Key = *pn; // set the key to store offset. + k->ShiftFlags = 0; + } + k->Line = kpp->Line; + k->LineStoreIndex = n; + ExpandKp_ReplaceIndex(fk, k, keyIndex, n); + } + + delete dpContext; + delete dpOutput; + + return CERR_None; +} + + +PKMX_WCHAR GetDelimitedString(PKMX_WCHAR *p, KMX_WCHAR const * Delimiters, KMX_WORD Flags) +{ + PKMX_WCHAR q, r; + KMX_WCHAR dOpen, dClose; + + dOpen = *Delimiters; dClose = *(Delimiters + 1); + + q = *p; + while (iswspace(*q)) q++; //***QUERY + + if (*q != dOpen) return NULL; + + q++; + + r = xstrchr(q, &dClose); // Find closing delimiter + if (!r) return NULL; + + if (Flags & GDS_CUTLEAD) + while (iswspace(*q)) q++; // cut off leading spaces + + if (Flags & GDS_CUTFOLL) + if (!iswspace(*(r - 1))) *r = 0; + else + { + r--; // Cut off following spaces + while (iswspace(*r) && r > q) r--; + r++; + *r = 0; r = xstrchr((r + 1), &dClose); + } + else *r = 0; + + r++; while (iswspace(*r)) r++; // Ignore spaces after the close + if (*r == 0) r--; // Safety for terminating strings. + + *p = r; // Update pointer position + + return q; // Return delimited string +} + +#ifndef __iswcsym +#define __iswcsym(_c) (iswalnum(_c) || ((_c)=='_')) +#endif + +LinePrefixType GetLinePrefixType(PKMX_WCHAR *p) +{ + PKMX_WCHAR s = *p; + + while (iswspace(*s)) s++; + + PKMX_WCHAR q = s; + + if (*s != '$') return lptNone; + + /* I1569 - fix named constants at the start of the line */ + s++; + while (__iswcsym(*s)) s++; + if (*s != ':') return lptNone; + + if (u16nicmp(q, u"$keyman:", 8) == 0) + { + *p += 8; + return lptKeymanAndKeymanWeb; + } + if (u16nicmp(q, u"$keymanweb:", 11) == 0) + { + *p += 11; + return lptKeymanWebOnly; + } + if (u16nicmp(q, u"$keymanonly:", 12) == 0) + { + *p += 12; + return lptKeymanOnly; + } + + return lptOther; +} + +int LineTokenType(PKMX_WCHAR *str) +{ + int i; + size_t l; + PKMX_WCHAR p = *str; + + LinePrefixType lpt = GetLinePrefixType(&p); + if (lpt == lptOther) return T_BLANK; + + /* Test KeymanWeb, Keyman and KeymanOnly prefixes */ + if (kmcmp::CompileTarget == CKF_KEYMAN && lpt == lptKeymanWebOnly) return T_BLANK; + if (kmcmp::CompileTarget == CKF_KEYMANWEB && lpt == lptKeymanOnly) return T_BLANK; + + while (iswspace(*p)) p++; + + if (u16chr(LineTokens[0], towupper(*p))) + for (i = 0; i <= T_W_END - T_W_START; i++) + { + l = u16len(LineTokens[i + 1]); + if (u16nicmp(p, LineTokens[i + 1], l) == 0) + { + p += l; while (iswspace(*p)) p++; *str = p; + return i + T_W_START; + } + } + + switch (towupper(*p)) + { + case 'C': + if (iswspace(*(p + 1))) return T_COMMENT; + break; + case 0: + return T_BLANK; + default: + if (u16chr(u"\"aAbBlLpPnN[OoxXdD0123456789\'+UuiI$", *p)) // I4784 + { + *str = p; + return T_KEYTOKEY; + } + } + return T_UNKNOWN; +} + +KMX_WCHAR const * DeadKeyChars = +u"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"; + +KMX_BOOL StrValidChrs(PKMX_WCHAR q, KMX_WCHAR const * chrs) +{ + for (; *q; q++) + if (!u16chr(chrs, *q)) return FALSE; + return TRUE; +} + +KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_WCHAR const * token, + PKMX_WCHAR output, int max, int offset, PKMX_WCHAR *newp, int isVKey, int isUnicode +); + +KMX_DWORD GetXString(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_WCHAR const * token, + PKMX_WCHAR output, int max, int offset, PKMX_WCHAR *newp, int isVKey, int isUnicode +) { + PKMX_WCHAR tstr = new KMX_WCHAR[max]; // I2432 - Allocate buffers each line -- slightly slower but safer than keeping a single buffer - GetXString is re-entrant with if() + KMX_DWORD err = GetXStringImpl(tstr, fk, str, token, output, max, offset, newp, isVKey, isUnicode); + delete[] tstr; + return err; +} + +KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_WCHAR const * token, + PKMX_WCHAR output, int max, int offset, PKMX_WCHAR *newp, int isVKey, int isUnicode +) { + KMX_DWORD err; + PKMX_WCHAR p = str, q, r; + int type, mx = 0, n, n1, n2, tokenFound = FALSE, z, sFlag = 0, j; + KMX_DWORD i; + KMX_BOOL finished = FALSE; + KMX_WCHAR c; + + *tstr = 0; + + *output = 0; + + p = str; + do + { + tokenFound = FALSE; + while (iswspace(*p) && !u16chr(token, *p)) p++; + if (!*p) break; + + ErrChr = (int)(p - str) + offset + 1; + + /* + char *tokenTypes[] = { + "clearcontext", "deadkey", "context", "return", "switch", + "index", "outs", "beep", "nul", "use", "any", "fix", "dk", "k_", "x", "d", "c", + "[", "]" }; + */ + + switch (towupper(*p)) + { + case 'X': + case 'D': type = 0; break; // xFF, d130: chars, deadkey(n) + case '\"': type = 1; break; // "xxxx": chars + case '\'': type = 2; break; // 'xxxx': chars + case 'A': type = 3; break; // any(s) + case 'B': type = 4; break; // beep, baselayout (synonym for if(&baselayout)) // I3430 + case 'I': type = 5; break; // index(s,n), if + case 'O': type = 6; break; // outs(s) + case 'C': type = 7; break; // context, comments, clearcontext, call(s) + case 'N': type = 8; break; // nul, notany + case 'U': type = 9; break; // use(g) + case 'R': type = 10; break; // return, reset + case '[': type = 11; break; // start of vkey section + //case ']': type = 12; break; // end of vkey section + //case 'K': type = 13; break; // virtual key name or "key" + case 'S': type = 14; break; // switch, set, save + case 'F': type = 15; break; // fix (synonym for clearcontext) + case '$': type = 16; break; // named code constants + case 'P': type = 17; break; // platform (synonym for if(&platform)) // I3430 + case 'L': type = 18; break; // layer (synonym for set(&layer)) // I3437 + case '.': type = 19; break; // .. allows us to specify ranges -- either vkeys or characters + default: + if (iswdigit(*p)) type = 0; // octal number + else type = 99; // error! + } + if (u16chr(token, *p)) tokenFound = TRUE; + + switch (type) + { + case 99: + if (tokenFound) break; + { + sprintf(ErrExtraLIB,"token: %c",(int)*p); + } + return CERR_InvalidToken; + case 0: + if (u16nicmp(p, u"deadkey", z = 7) == 0 || + u16nicmp(p, u"dk", z = 2) == 0) + { + p += z; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidDeadkey; + + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_DEADKEY; + if (!StrValidChrs(q, DeadKeyChars)) return CERR_InvalidDeadkey; + tstr[mx++] = GetDeadKey(fk, q); //atoiW(q); 7-5-01: named deadkeys + tstr[mx] = 0; + } + else + { + n = xatoi(&p); + if (*p != '\0' && !iswspace(*p)) return CERR_InvalidValue; + if ((err = kmcmp::UTF32ToUTF16(n, &n1, &n2)) != CERR_None) return err; + tstr[mx++] = n1; + if (n2 >= 0) tstr[mx++] = n2; + tstr[mx] = 0; + } + continue; + + case 1: + q = (PKMX_WCHAR) u16chr(p + 1, '\"'); + if (!q) return CERR_UnterminatedString; + if ((int)(q - p) - 1 + mx > max) return CERR_UnterminatedString; + if (sFlag) return CERR_StringInVirtualKeySection; + u16ncat(tstr, p + 1, (int)(q - p) - 1); // I3481 + mx += (int)(q - p) - 1; + tstr[mx] = 0; + p = q + 1; + continue; + case 2: + q = (PKMX_WCHAR) u16chr(p + 1, '\''); + if (!q) return CERR_UnterminatedString; + if ((int)(q - p) - 1 + mx > max) return CERR_UnterminatedString; + if (sFlag) return CERR_StringInVirtualKeySection; + u16ncat(tstr, p + 1, (int)(q - p) - 1); // I3481 + mx += (int)(q - p) - 1; + tstr[mx] = 0; + p = q + 1; + continue; + case 3: + if (u16nicmp(p, u"any", 3) != 0) return CERR_InvalidToken; + if (sFlag) return CERR_AnyInVirtualKeySection; + p += 3; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidAny; + + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(q, fk->dpStoreArray[i].szName) == 0) break; + } + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + + if (!*fk->dpStoreArray[i].dpString) return CERR_ZeroLengthString; + kmcmp::CheckStoreUsage(fk, i, TRUE, FALSE, FALSE); + + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_ANY; + tstr[mx++] = (KMX_WCHAR)i + 1; // store to index + 1, avoids End-of-string + tstr[mx] = 0; + continue; + case 4: + if (u16nicmp(p, u"beep", 4) == 0) + { + if (sFlag) return CERR_BeepInVirtualKeySection; + p += 4; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_BEEP; + tstr[mx] = 0; + } + else if (u16nicmp(p, u"baselayout", 10) == 0) // I3430 + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_90FeatureOnly_IfSystemStores); + if (sFlag) return CERR_InvalidInVirtualKeySection; + p += 10; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidToken; + err = process_baselayout(fk, q, tstr, &mx); + if (err != CERR_None) return err; + } + else + return CERR_InvalidToken; + + continue; + case 5: + if (u16nicmp(p, u"if", 2) == 0) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_80, CERR_80FeatureOnly); + if (sFlag) return CERR_InvalidInVirtualKeySection; + p += 2; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidIf; + + err = process_if(fk, q, tstr, &mx); + if (err != CERR_None) return err; + } + else + { + if (u16nicmp(p, u"index", 5) != 0) return CERR_InvalidToken; + if (sFlag) return CERR_IndexInVirtualKeySection; + p += 5; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + + if (!q || !*q) return CERR_InvalidIndex; + + { + KMX_WCHAR *context = NULL; + KMX_WCHAR sep_com[3] = u" ,"; + PKMX_WCHAR p_sep_com = sep_com; + r = u16tok(q, p_sep_com, &context); // I3481 + if (!r) return CERR_InvalidIndex; + + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(r, fk->dpStoreArray[i].szName) == 0) break; + } + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + + kmcmp::CheckStoreUsage(fk, i, TRUE, FALSE, FALSE); + + r = u16tok(NULL, p_sep_com, &context); // I3481 + if (!r) return CERR_InvalidIndex; + } + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_INDEX; + tstr[mx++] = (KMX_WCHAR)i + 1; // avoid EOS for stores + tstr[mx++] = atoiW(r); // character offset of original any. + + tstr[mx] = 0; + } + continue; + case 6: + if (u16nicmp(p, u"outs", 4) != 0) return CERR_InvalidToken; + if (sFlag) return CERR_OutsInVirtualKeySection; + p += 4; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidOuts; + + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(q, fk->dpStoreArray[i].szName) == 0) break; + } + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + + kmcmp::CheckStoreUsage(fk, i, TRUE, FALSE, FALSE); + + for (q = fk->dpStoreArray[i].dpString; *q; q++) + { + tstr[mx++] = *q; + if (mx >= max - 1) return CERR_BufferOverflow; + } + tstr[mx] = 0; + continue; + case 7: + if (iswspace(*(p + 1))) break; // is a comment -- pre-stripped - so why this test? + if (u16nicmp(p, u"context", 7) == 0) + { + if (sFlag) return CERR_ContextInVirtualKeySection; + p += 7; + + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (q && *q) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_60, CERR_60FeatureOnly_Contextn); + int n1; + n1 = atoiW(q); + if (n1 < 1 || n1 >= 0xF000) return CERR_InvalidToken; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_CONTEXTEX; + tstr[mx++] = n1; + tstr[mx] = 0; + } + else + { + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_CONTEXT; + tstr[mx] = 0; + } + } + else if (u16nicmp(p, u"clearcontext", 12) == 0) + { + p += 12; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_CLEARCONTEXT; + tstr[mx] = 0; + } + else if (u16nicmp(p, u"call", 4) == 0) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_501, CERR_501FeatureOnly_Call); + if (sFlag) return CERR_CallInVirtualKeySection; + p += 4; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidCall; + + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(q, fk->dpStoreArray[i].szName) == 0) break; + } + + if (!kmcmp::IsValidCallStore(&fk->dpStoreArray[i])) return CERR_InvalidCall; + kmcmp::CheckStoreUsage(fk, i, FALSE, FALSE, TRUE); + + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_CALL; + tstr[mx++] = (KMX_WCHAR)i + 1; + tstr[mx] = 0; + + fk->dpStoreArray[i].dwSystemID = TSS_CALLDEFINITION; + } + else + return CERR_InvalidToken; + continue; + case 8: + if (u16nicmp(p, u"notany", 6) == 0) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_70, CERR_70FeatureOnly) + if (sFlag) return CERR_AnyInVirtualKeySection; + p += 6; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidAny; + + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(q, fk->dpStoreArray[i].szName) == 0) break; + } + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + kmcmp::CheckStoreUsage(fk, i, TRUE, FALSE, FALSE); + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_NOTANY; + tstr[mx++] = (KMX_WCHAR)i + 1; // store to index + 1, avoids End-of-string + tstr[mx] = 0; + continue; + } + if (u16nicmp(p, u"nul", 3) != 0) return CERR_InvalidToken; + + p += 3; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_NUL; + tstr[mx] = 0; + continue; + case 9: + if (u16nicmp(p, u"use", 3) != 0) + { + if (*(p + 1) == '+') + { + n = xatoi(&p); + if (*p != '\0' && !iswspace(*p)) return CERR_InvalidValue; + if ((err = kmcmp::UTF32ToUTF16(n, &n1, &n2)) != CERR_None) return err; + tstr[mx++] = n1; + if (n2 >= 0) tstr[mx++] = n2; + tstr[mx] = 0; + if (!isUnicode) AddWarning(CWARN_UnicodeInANSIGroup); + continue; + } + return CERR_InvalidToken; + } + p += 3; + + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidUse; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_USE; + tstr[mx] = GetGroupNum(fk, q); + if (tstr[mx] == 0) return CERR_GroupDoesNotExist; + tstr[++mx] = 0; + continue; + case 10: + if (u16nicmp(p, u"reset", 5) == 0) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_80, CERR_80FeatureOnly); + if (sFlag) return CERR_InvalidInVirtualKeySection; + p += 5; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidReset; + + err = process_reset(fk, q, tstr, &mx); + if (err != CERR_None) return err; + } + else + { + if (u16nicmp(p, u"return", 6) != 0) return CERR_InvalidToken; + + p += 6; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_RETURN; + tstr[mx] = 0; + u16ncpy(output, tstr, max); // I3481 + output[max - 1] = 0; + return 0; + } + continue; + case 11: + p++; sFlag = ISVIRTUALKEY /* 0 */; finished = FALSE; + + //printf("--EXTENDEDSTRING--\n"); + + do + { + while (iswspace(*p)) p++; + + switch (towupper(*p)) + { + case 'N': + if (u16nicmp(p, u"NCAPS", 5) == 0) + sFlag |= NOTCAPITALFLAG, p += 5; + else finished = TRUE; + break; + case 'L': + if (u16nicmp(p, u"LALT", 4) == 0) + sFlag |= LALTFLAG, p += 4; + else if (u16nicmp(p, u"LCTRL", 5) == 0) + sFlag |= LCTRLFLAG, p += 5; + else finished = TRUE; + break; + case 'R': + if (u16nicmp(p, u"RALT", 4) == 0) + sFlag |= RALTFLAG, p += 4; + else if (u16nicmp(p, u"RCTRL", 5) == 0) + sFlag |= RCTRLFLAG, p += 5; + else finished = TRUE; + break; + case 'A': + if (u16nicmp(p, u"ALT", 3) == 0) + sFlag |= K_ALTFLAG, p += 3; + else finished = TRUE; + break; + case 'C': + if (u16nicmp(p, u"CTRL", 4) == 0) + sFlag |= K_CTRLFLAG, p += 4; + else if (u16nicmp(p, u"CAPS", 4) == 0) + sFlag |= CAPITALFLAG, p += 4; + else finished = TRUE; + break; + case 'S': + if (u16nicmp(p, u"SHIFT", 5) == 0) + sFlag |= K_SHIFTFLAG, p += 5; + else finished = TRUE; + break; + default: + finished = TRUE; + break; + } + } while (!finished); + + if ((sFlag & (LCTRLFLAG | LALTFLAG)) && (sFlag & (RCTRLFLAG | RALTFLAG))) { + AddWarning(CWARN_MixingLeftAndRightModifiers); + } + + // If we use chiral modifiers, or we use state keys, and we target web in the keyboard, and we don't manually specify a keyboard version, bump the minimum + // version to 10.0. This makes an assumption that if we are using these features in a keyboard and it has no version specified, that we want to use the features + // in the web target platform, even if there are platform() rules excluding this possibility. In that (rare) situation, the keyboard developer should simply specify + // the &version to be 9.0 or whatever to avoid this behaviour. + if (sFlag & (LCTRLFLAG | LALTFLAG | RCTRLFLAG | RALTFLAG | CAPITALFLAG | NOTCAPITALFLAG | NUMLOCKFLAG | NOTNUMLOCKFLAG | SCROLLFLAG | NOTSCROLLFLAG) && + kmcmp::CompileTarget == CKF_KEYMANWEB && + fk->dwFlags & KF_AUTOMATICVERSION) { + VERIFY_KEYBOARD_VERSION(fk, VERSION_100, 0); + } + //printf("sFlag: %x\n", sFlag); + + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_EXTENDED; + tstr[mx++] = sFlag; + + while (iswspace(*p)) p++; + + q = p; + + if (*q == ']') + { + return CERR_InvalidToken; // I3137 - key portion of VK is missing e.g. "[CTRL ALT]", this generates invalid kmx file that can crash Keyman or compiler later on // I3511 + } + + while (*q != ']') + { + if (*q == '\'' || *q == '"') + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_60, CERR_60FeatureOnly_VirtualCharKey); + if (!kmcmp::FMnemonicLayout) AddWarning(CWARN_VirtualCharKeyWithPositionalLayout); + KMX_WCHAR chQuote = *q; + q++; if (*q == chQuote || *q == '\n' || *q == 0) return CERR_InvalidToken; + tstr[mx - 1] |= VIRTUALCHARKEY; + tstr[mx++] = *q; + q++; if (*q != chQuote) return CERR_InvalidToken; + q++; + while (iswspace(*q)) q++; + if (*q != ']') return CERR_InvalidToken; + break; /* out of while loop */ + } + + for (j = 0; !iswspace(*q) && *q != ']' && *q != 0; q++, j++); + + if (*q == 0) return CERR_InvalidToken; + + KMX_WCHAR vkname[SZMAX_VKDICTIONARYNAME]; // I3438 + + if (j >= SZMAX_VKDICTIONARYNAME) return CERR_InvalidToken; + + u16ncpy(vkname, p, j); // I3481 + vkname[j] = 0; + + if (u16icmp(vkname, u"K_NPENTER") == 0) + i = 5; // I649 - K_NPENTER hack + else + { + for (i = 0; i <= VK__MAX; i++) + { + if (u16icmp(vkname, VKeyNames[i]) == 0 || u16icmp(vkname, VKeyISO9995Names[i]) == 0) + break; + } + } + + if (i == VK__MAX + 1) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_InvalidToken); + + i = GetVKCode(fk, vkname); // I3438 + if (i == 0) + return CERR_InvalidToken; + } + + p = q; + + tstr[mx++] = (int)i; + + if (kmcmp::FMnemonicLayout && (i <= VK__MAX) && VKeyMayBeVCKey[i]) AddWarning(CWARN_VirtualKeyWithMnemonicLayout); // I3438 + + while (iswspace(*q)) q++; + } + tstr[mx++] = UC_SENTINEL_EXTENDEDEND; + tstr[mx] = 0; + //printf("--EXTENDEDEND--\n"); + + p = q + 1; + + sFlag = 0; + + continue; + case 14: + if (u16nicmp(p, u"set", 3) == 0) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_80, CERR_80FeatureOnly); + p += 3; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidSet; + + err = process_set(fk, q, tstr, &mx); + if (err != CERR_None) return err; + } + else if (u16nicmp(p, u"save", 4) == 0) + { + VERIFY_KEYBOARD_VERSION(fk, VERSION_80, CERR_80FeatureOnly); + p += 4; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidSave; + + err = process_save(fk, q, tstr, &mx); + if (err != CERR_None) return err; + } + else + { + if (u16nicmp(p, u"switch", 6) != 0) return CERR_InvalidToken; + p += 6; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidSwitch; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_SWITCH; + tstr[mx++] = atoiW(q); + tstr[mx] = 0; + } + continue; + case 15: + if (u16nicmp(p, u"fix", 3) == 0) + { + p += 3; + tstr[mx++] = UC_SENTINEL; + tstr[mx++] = CODE_CLEARCONTEXT; + tstr[mx] = 0; + } + else + return CERR_InvalidToken; + continue; + case 16: + VERIFY_KEYBOARD_VERSION(fk, VERSION_60, CERR_60FeatureOnly_NamedCodes); + q = p + 1; + while (*q && !iswspace(*q)) q++; + c = *q; *q = 0; + n = CodeConstants->GetCode(p + 1, &i); + *q = c; + if (n == 0) return CERR_InvalidNamedCode; + if (i < 0xFFFFFFFFL) kmcmp::CheckStoreUsage(fk, i, TRUE, FALSE, FALSE); // I2993 + if (n > 0xFFFF) + { + tstr[mx++] = Uni_UTF32ToSurrogate1(n); + tstr[mx++] = Uni_UTF32ToSurrogate2(n); + } + else + tstr[mx++] = n; + tstr[mx] = 0; + p = q; + continue; + case 17: + if (u16nicmp(p, u"platform", 8) != 0) return CERR_InvalidToken; // I3430 + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_90FeatureOnly_IfSystemStores); + if (sFlag) return CERR_InvalidInVirtualKeySection; + p += 8; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidToken; + err = process_platform(fk, q, tstr, &mx); + if (err != CERR_None) return err; + continue; + case 18: // I3437 + if (u16nicmp(p, u"layer", 5) != 0) return CERR_InvalidToken; + VERIFY_KEYBOARD_VERSION(fk, VERSION_90, CERR_90FeatureOnly_SetSystemStores); + if (sFlag) return CERR_InvalidInVirtualKeySection; + p += 5; + q = GetDelimitedString(&p, u"()", GDS_CUTLEAD | GDS_CUTFOLL); + if (!q || !*q) return CERR_InvalidToken; + err = process_set_synonym(TSS_LAYER, fk, q, tstr, &mx); + if (err != CERR_None) return err; + continue; + case 19: // #2241 + if (*(p + 1) != '.') return CERR_InvalidToken; + if (sFlag) return CERR_InvalidInVirtualKeySection; + p += 2; + err = process_expansion(fk, p, tstr, &mx, max); + if (err != CERR_None) return err; + continue; + default: + return CERR_InvalidToken; + } + if (tokenFound) + { + *newp = p; + u16ncpy(output, tstr, max); // I3481 + output[max - 1] = 0; + ErrChr = 0; + return CERR_None; + } + if (mx >= max) return CERR_BufferOverflow; + } while (*p); + + if (!*token) + { + *newp = p; + u16ncpy(output, tstr, max); // I3481 + output[max - 1] = 0; + ErrChr = 0; + return CERR_None; + } + + return CERR_NoTokensFound; +} + +KMX_DWORD process_if_synonym(KMX_DWORD dwSystemID, PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx); // I3430 + +KMX_DWORD process_baselayout(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) // I3430 +{ + /* baselayout() */ + return process_if_synonym(TSS_BASELAYOUT, fk, q, tstr, mx); +} + +KMX_DWORD process_platform(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) // I3430 +{ + /* platform() */ + return process_if_synonym(TSS_PLATFORM, fk, q, tstr, mx); +} + +KMX_DWORD process_if_synonym(KMX_DWORD dwSystemID, PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) // I3430 +{ + PKMX_WCHAR temp = new KMX_WCHAR[GLOBAL_BUFSIZE]; + + KMX_DWORD msg; + + PKMX_WCHAR r; + + if ((msg = GetXString(fk, q, u"", temp, GLOBAL_BUFSIZE - 1, 0, &r, FALSE, TRUE)) != CERR_None) + { + delete[] temp; + return msg; + } + + KMX_DWORD dwStoreID; + + if ((msg = AddStore(fk, TSS_COMPARISON, temp, &dwStoreID)) != CERR_None) + { + delete[] temp; + return msg; + } + + tstr[(*mx)++] = UC_SENTINEL; + tstr[(*mx)++] = (KMX_WCHAR)CODE_IFSYSTEMSTORE; + tstr[(*mx)++] = (KMX_WCHAR)(dwSystemID + 1); // I4785 + tstr[(*mx)++] = 2; + tstr[(*mx)++] = (KMX_WCHAR)(dwStoreID + 1); + tstr[(*mx)] = 0; + + delete[] temp; + + return CERR_None; +} + +KMX_DWORD process_if(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) // I3431 +{ + /* if( <'='|'!='> ) */ + KMX_DWORD i, code; + KMX_DWORD nnot = FALSE; + PKMX_WCHAR r = q, s = q; + while (*s && *s != u' ' && *s != u'!' && *s !=u'=') s++; + r = s; + while (*s == u' ') s++; + if (*s == u'!') + { + s++; + nnot = TRUE; + } + + if (*s != '=') return CERR_InvalidIf; + s++; + while (*s == ' ') s++; + *r = 0; + r = q; + + if (r[0] == '&') + { + VERIFY_KEYBOARD_VERSION( fk, VERSION_90, CERR_90FeatureOnly_IfSystemStores); + for (i = 0; StoreTokens[i]; i++) + { + if (u16icmp(r, StoreTokens[i]) == 0) break; + } + if (!StoreTokens[i]) return CERR_IfSystemStore_NotFound; + code = CODE_IFSYSTEMSTORE; + } + else + { + code = CODE_IFOPT; + + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(r, fk->dpStoreArray[i].szName) == 0) break; + } + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + kmcmp::CheckStoreUsage(fk, i, FALSE, TRUE, FALSE); + } + + PKMX_WCHAR temp = new KMX_WCHAR[GLOBAL_BUFSIZE]; + + KMX_DWORD msg; + + if ((msg = GetXString(fk, s, u"", temp, GLOBAL_BUFSIZE - 1, 0, &r, FALSE, TRUE)) != CERR_None) + { + delete[] temp; + return msg; + } + + KMX_DWORD dwStoreID; + + if ((msg = AddStore(fk, TSS_COMPARISON, temp, &dwStoreID)) != CERR_None) + { + delete[] temp; + return msg; + } + + tstr[(*mx)++] = UC_SENTINEL; + tstr[(*mx)++] = (KMX_WCHAR)code; + tstr[(*mx)++] = (KMX_WCHAR)(i + 1); + tstr[(*mx)++] = nnot ? 1 : 2; + tstr[(*mx)++] = (KMX_WCHAR)(dwStoreID + 1); + tstr[(*mx)] = 0; + + return CERR_None; +} + +KMX_DWORD process_reset(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) +{ + /* reset() */ + KMX_DWORD i; + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(q, fk->dpStoreArray[i].szName) == 0) break; + } + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + kmcmp::CheckStoreUsage(fk, i, FALSE, TRUE, FALSE); + + tstr[(*mx)++] = UC_SENTINEL; + tstr[(*mx)++] = CODE_RESETOPT; + tstr[(*mx)++] = (KMX_WCHAR)(i + 1); + tstr[(*mx)] = 0; + + return CERR_None; +} + +KMX_DWORD process_expansion(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx, int max) { + KMX_BOOL isVKey = FALSE; + + KMX_WORD BaseKey=0, BaseShiftFlags=0; + KMX_DWORD BaseChar=0; + + if (*mx == 0) { + return CERR_ExpansionMustFollowCharacterOrVKey; + } + PKMX_WCHAR p = &tstr[*mx]; + p = decxstr(p, tstr); + if (*p == UC_SENTINEL) { + if (*(p + 1) != CODE_EXTENDED) { + return CERR_ExpansionMustFollowCharacterOrVKey; + } + isVKey = TRUE; + BaseKey = *(p + 3); + BaseShiftFlags = *(p + 2); + } + else { + BaseChar = Uni_UTF16ToUTF32(p); + } + + // Look ahead at next element + KMX_WCHAR temp[GLOBAL_BUFSIZE]; + PKMX_WCHAR r = NULL; + + KMX_DWORD msg; + + if ((msg = GetXString(fk, q, u"", temp, _countof(temp) - 1, 0, &r, FALSE, TRUE)) != CERR_None) + { + return msg; + } + + KMX_WORD HighKey, HighShiftFlags; + KMX_DWORD HighChar; + + switch(temp[0]) { + case 0: + return isVKey ? CERR_VKeyExpansionMustBeFollowedByVKey : CERR_CharacterExpansionMustBeFollowedByCharacter; + case UC_SENTINEL: + // Verify that range is valid virtual key range + if(!isVKey) { + return CERR_CharacterExpansionMustBeFollowedByCharacter; + } + if (temp[1] != CODE_EXTENDED) { + return CERR_VKeyExpansionMustBeFollowedByVKey; + } + HighKey = temp[3], HighShiftFlags = temp[2]; + if (HighShiftFlags != BaseShiftFlags) { + return CERR_VKeyExpansionMustUseConsistentShift; + } + if (HighKey <= BaseKey) { + return CERR_ExpansionMustBePositive; + } + // Verify space in buffer + if (*mx + (HighKey - BaseKey) * 5 + 1 >= max) return CERR_BufferOverflow; + // Inject an expansion. + for (BaseKey++; BaseKey < HighKey; BaseKey++) { + // < HighKey because caller will add HighKey to output + tstr[(*mx)++] = UC_SENTINEL; + tstr[(*mx)++] = CODE_EXTENDED; + tstr[(*mx)++] = BaseShiftFlags; + tstr[(*mx)++] = BaseKey; + tstr[(*mx)++] = UC_SENTINEL_EXTENDEDEND; + } + tstr[*mx] = 0; + break; + default: + // Verify that range is a valid character range + if (isVKey) { + return CERR_VKeyExpansionMustBeFollowedByVKey; + } + + HighChar = Uni_UTF16ToUTF32(temp); + if (HighChar <= BaseChar) { + return CERR_ExpansionMustBePositive; + } + // Inject an expansion. + for (BaseChar++; BaseChar < HighChar; BaseChar++) { + // < HighChar because caller will add HighChar to output + if (Uni_IsSMP(BaseChar)) { + // We'll test on each char to avoid complex calculations crossing SMP boundary + if (*mx + 3 >= max) return CERR_BufferOverflow; + tstr[(*mx)++] = (KMX_WCHAR) Uni_UTF32ToSurrogate1(BaseChar); + tstr[(*mx)++] = (KMX_WCHAR) Uni_UTF32ToSurrogate2(BaseChar); + } + else { + if (*mx + 2 >= max) return CERR_BufferOverflow; + tstr[(*mx)++] = (KMX_WCHAR) BaseChar; + } + } + tstr[*mx] = 0; + } + + return CERR_None; +} + +KMX_DWORD process_set_synonym(KMX_DWORD dwSystemID, PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) // I3437 +{ + /* set( <'='> ), layer */ + PKMX_WCHAR temp = new KMX_WCHAR[GLOBAL_BUFSIZE], r; + KMX_DWORD msg; + + if ((msg = GetXString(fk, q, u"", temp, GLOBAL_BUFSIZE - 1, 0, &r, FALSE, TRUE)) != CERR_None) + { + delete[] temp; + return msg; + } + + KMX_DWORD dwStoreID; + + msg = AddStore(fk, TSS_COMPARISON, temp, &dwStoreID); + delete[] temp; + if (msg != CERR_None) return msg; + + tstr[(*mx)++] = UC_SENTINEL; + tstr[(*mx)++] = (KMX_WCHAR)CODE_SETSYSTEMSTORE; + tstr[(*mx)++] = (KMX_WCHAR)(dwSystemID + 1); + tstr[(*mx)++] = (KMX_WCHAR)(dwStoreID + 1); + tstr[(*mx)] = 0; + return CERR_None; +} + +KMX_DWORD process_set(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) +{ + /* set( <'='> */ + PKMX_WCHAR r = q, s = q; // I3440 + while (*s && *s != u' ' && *s != u'=') s++; + r = s; + while (*s == u' ') s++; + if (*s != '=') return CERR_InvalidSet; + s++; + while (*s == ' ') s++; + *r = 0; + r = q; + + KMX_DWORD i, code; + + if (r[0] == '&') + { + VERIFY_KEYBOARD_VERSION((PFILE_KEYBOARD) fk, VERSION_90, CERR_90FeatureOnly_SetSystemStores); // I3437 + for (i = 0; StoreTokens[i]; i++) + { + if (u16icmp(r, StoreTokens[i]) == 0) break; + } + if (!StoreTokens[i]) return CERR_SetSystemStore_NotFound; + code = CODE_SETSYSTEMSTORE; + } + else + { + KMX_WCHAR *context = NULL; + KMX_WCHAR sep_eq[3] = u" ="; + PKMX_WCHAR r = u16tok(q, sep_eq, &context); // I3481 + + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(r, fk->dpStoreArray[i].szName) == 0) break; + } + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + kmcmp::CheckStoreUsage(fk, i, FALSE, TRUE, FALSE); + code = CODE_SETOPT; + } + + PKMX_WCHAR temp = new KMX_WCHAR[GLOBAL_BUFSIZE]; + + KMX_DWORD msg; + + //r = wcstok(NULL, L" ="); + + if ((msg = GetXString(fk, s, u"", temp, GLOBAL_BUFSIZE - 1, 0, &r, FALSE, TRUE)) != CERR_None) + { + delete[] temp; + return msg; + } + + KMX_DWORD dwStoreID; + + msg = AddStore(fk, TSS_COMPARISON, temp, &dwStoreID); + delete[] temp; + if (msg != CERR_None) return msg; + + tstr[(*mx)++] = UC_SENTINEL; + tstr[(*mx)++] = (KMX_WCHAR)code; + tstr[(*mx)++] = (KMX_WCHAR)(i + 1); + tstr[(*mx)++] = (KMX_WCHAR)(dwStoreID + 1); + tstr[(*mx)] = 0; + return CERR_None; +} + +KMX_DWORD process_save(PFILE_KEYBOARD fk, PKMX_WCHAR q, PKMX_WCHAR tstr, int *mx) +{ + /* save() */ + KMX_DWORD i; + for (i = 0; i < fk->cxStoreArray; i++) + { + if (u16icmp(q, fk->dpStoreArray[i].szName) == 0) break; + } + if (i == fk->cxStoreArray) return CERR_StoreDoesNotExist; + kmcmp::CheckStoreUsage(fk, i, FALSE, TRUE, FALSE); + + tstr[(*mx)++] = UC_SENTINEL; + tstr[(*mx)++] = CODE_SAVEOPT; + tstr[(*mx)++] = (KMX_WCHAR)(i + 1); + tstr[(*mx)] = 0; + return CERR_None; +} + +int xatoi(PKMX_WCHAR *p) +{ + PKMX_WCHAR endptr; + int n; + + switch (towupper(**p)) + { + case 'U': + (*p)++; + if (**p != '+') return 0; + (*p)++; + n = (int)u16tol(*p, &endptr, 16); + *p = endptr; + break; + case 'X': + (*p)++; + n = (int)u16tol(*p, &endptr, 16); + *p = endptr; + break; + case 'D': + (*p)++; + n = (int)u16tol(*p, &endptr, 10); + *p = endptr; + break; + default: + n = (int)u16tol(*p, &endptr, 8); + *p = endptr; + break; + } + return n; +} + +int GetGroupNum(PFILE_KEYBOARD fk, PKMX_WCHAR p) +{ + PFILE_GROUP gp; + KMX_DWORD i; + + for (i = 0, gp = fk->dpGroupArray; i < fk->cxGroupArray; gp++, i++) + { + if (u16icmp(gp->szName, p) == 0) return i + 1; + } + return 0; +} + + +KMX_DWORD ProcessEthnologueStore(PKMX_WCHAR p) // I2646 +{ + KMX_DWORD res = CERR_None; + PKMX_WCHAR q = NULL; + while (*p) + { + while (u16chr(u" ,;", *p)) + { + if (*p != ' ') res = CWARN_PunctuationInEthnologueCode; + p++; + } + if (q == p) return CERR_InvalidEthnologueCode; + if (*p) + { + for (int i = 0; i < 3; i++) + { + if (!iswalpha(*p)) return CERR_InvalidEthnologueCode; + p++; + } + } + q = p; + } + return res; +} + +#define K_HOTKEYSHIFTFLAGS (K_SHIFTFLAG | K_CTRLFLAG | K_ALTFLAG | ISVIRTUALKEY) + +KMX_DWORD ProcessHotKey(PKMX_WCHAR p, KMX_DWORD *hk) +{ + PKMX_WCHAR q, r; + KMX_DWORD sFlag; + int j, i; + + *hk = 0; + + if (*p == UC_SENTINEL && *(p + 1) == CODE_EXTENDED) { + KMX_WORD Key = *(p + 3); + KMX_WORD ShiftFlags = *(p + 2); + + // Convert virtual key to hotkey (different bitflags) + + if (ShiftFlags & ~K_HOTKEYSHIFTFLAGS) { + AddWarning(CWARN_HotkeyHasInvalidModifier); + } + + if (ShiftFlags & K_SHIFTFLAG) *hk |= HK_SHIFT; + if (ShiftFlags & K_CTRLFLAG) *hk |= HK_CTRL; + if (ShiftFlags & K_ALTFLAG) *hk |= HK_ALT; + + *hk |= Key; + + return CERR_None; + } + + q = (PKMX_WCHAR) u16chr(p, '['); + if (q) + { + q++; + sFlag = 0; + + do + { + while (iswspace(*q)) q++; + + if (u16nicmp(q, u"ALT", 3) == 0) sFlag |= HK_ALT, q += 3; + else if (u16nicmp(q, u"CTRL", 4) == 0) sFlag |= HK_CTRL, q += 4; + else if (u16nicmp(q, u"SHIFT", 5) == 0) sFlag |= HK_SHIFT, q += 5; + else if (towupper(*q) != 'K') return CERR_InvalidToken; + } while (towupper(*q) != 'K'); + + r = (PKMX_WCHAR) u16chr(q, ']'); + if (r) + { + r--; + while (iswspace(*r) && r > q) r--; + r++; + } + else return CERR_NoTokensFound; + + j = (int)(r - q); + + for (i = 0; i <= VK__MAX; i++) // I3438 + if (j == (int) u16len(VKeyNames[i]) && u16nicmp(q, VKeyNames[i], j) == 0) break; + + if (i == VK__MAX + 1) return CERR_InvalidToken; // I3438 + + *hk = i | sFlag; + + return CERR_None; + } + + q = GetDelimitedString(&p, u"\"\"", GDS_CUTLEAD | GDS_CUTFOLL); + if (q) + { + if (u16chr(q, '^')) *hk |= HK_CTRL; + if (u16chr(q, '+')) *hk |= HK_SHIFT; + if (u16chr(q, '%')) *hk |= HK_ALT; + q = (PKMX_WCHAR) u16chr(q, 0) - 1; + *hk |= *q; + return CERR_None; + } + + return CERR_CodeInvalidInThisSection; +} + + +void SetChecksum(PKMX_BYTE buf, PKMX_DWORD CheckSum, KMX_DWORD sz) +{ + BuildCRCTable(); + *CheckSum = CalculateBufferCRC(buf, sz); +} + + +KMX_BOOL kmcmp::CheckStoreUsage(PFILE_KEYBOARD fk, int storeIndex, KMX_BOOL fIsStore, KMX_BOOL fIsOption, KMX_BOOL fIsCall) +{ + PFILE_STORE sp = &fk->dpStoreArray[storeIndex]; + if (fIsStore && !sp->fIsStore) + { + if (sp->fIsDebug || sp->fIsOption || sp->fIsReserved || sp->fIsCall) + AddWarning(CWARN_StoreAlreadyUsedAsOptionOrCall); + sp->fIsStore = TRUE; + } + else if (fIsOption && !sp->fIsOption) + { + if (sp->fIsDebug || sp->fIsStore || sp->fIsReserved || sp->fIsCall) + AddWarning(CWARN_StoreAlreadyUsedAsStoreOrCall); + sp->fIsOption = TRUE; + } + else if (fIsCall && !sp->fIsCall) + { + if (sp->fIsDebug || sp->fIsStore || sp->fIsReserved || sp->fIsOption) + AddWarning(CWARN_StoreAlreadyUsedAsStoreOrOption); + sp->fIsCall = TRUE; + } + + return TRUE; +} + +KMX_DWORD WriteCompiledKeyboard(PFILE_KEYBOARD fk, FILE* fp_out) +{ + PFILE_GROUP fgp; + PFILE_STORE fsp; + PFILE_KEY fkp; + + PCOMP_KEYBOARD ck; + PCOMP_GROUP gp; + PCOMP_STORE sp; + PCOMP_KEY kp; + PKMX_BYTE buf; + size_t offset; + size_t size; + KMX_DWORD i, j; + + // Calculate how much memory to allocate + + size = sizeof(COMP_KEYBOARD) + + fk->cxGroupArray * sizeof(COMP_GROUP) + + fk->cxStoreArray * sizeof(COMP_STORE) + + /*wcslen(fk->szName)*2 + 2 + + wcslen(fk->szCopyright)*2 + 2 + + wcslen(fk->szLanguageName)*2 + 2 + + wcslen(fk->szMessage)*2 + 2 +*/ + fk->dwBitmapSize; + + for (i = 0, fgp = fk->dpGroupArray; i < fk->cxGroupArray; i++, fgp++) + { + if (kmcmp::FSaveDebug) size += u16len(fgp->szName) * 2 + 2; + size += fgp->cxKeyArray * sizeof(COMP_KEY); + for (j = 0, fkp = fgp->dpKeyArray; j < fgp->cxKeyArray; j++, fkp++) + { + size += u16len(fkp->dpOutput) * 2 + 2; + size += u16len(fkp->dpContext) * 2 + 2; + } + + if (fgp->dpMatch) size += u16len(fgp->dpMatch) * 2 + 2; + if (fgp->dpNoMatch) size += u16len(fgp->dpNoMatch) * 2 + 2; + } + + for (i = 0; i < fk->cxStoreArray; i++) + { + size += u16len(fk->dpStoreArray[i].dpString) * 2 + 2; + if (kmcmp::FSaveDebug || fk->dpStoreArray[i].fIsOption) size += u16len(fk->dpStoreArray[i].szName) * 2 + 2; + } + + buf = new KMX_BYTE[size]; + if (!buf) return CERR_CannotAllocateMemory; + memset(buf, 0, size); + + ck = (PCOMP_KEYBOARD)buf; + + ck->dwIdentifier = FILEID_COMPILED; + ck->dwFileVersion = fk->version; + ck->dwCheckSum = 0; // do checksum afterwards. + ck->KeyboardID = fk->KeyboardID; + ck->IsRegistered = TRUE; // I5135 + ck->cxStoreArray = fk->cxStoreArray; + ck->cxGroupArray = fk->cxGroupArray; + ck->StartGroup[0] = fk->StartGroup[0]; + ck->StartGroup[1] = fk->StartGroup[1]; + ck->dwHotKey = fk->dwHotKey; + + ck->dwFlags = fk->dwFlags; + + offset = sizeof(COMP_KEYBOARD); + + /*ck->dpLanguageName = offset; + wcscpy((PWSTR)(buf + offset), fk->szLanguageName); + offset += wcslen(fk->szLanguageName)*2 + 2; + + ck->dpName = offset; + wcscpy((PWSTR)(buf + offset), fk->szName); + offset += wcslen(fk->szName)*2 + 2; + + ck->dpCopyright = offset; + wcscpy((PWSTR)(buf + offset), fk->szCopyright); + offset += wcslen(fk->szCopyright)*2 + 2; + + ck->dpMessage = offset; + wcscpy((PWSTR)(buf + offset), fk->szMessage); + offset += wcslen(fk->szMessage)*2 + 2;*/ + + ck->dpStoreArray = (KMX_DWORD)offset; + sp = (PCOMP_STORE)(buf + offset); + fsp = fk->dpStoreArray; + offset += sizeof(COMP_STORE) * ck->cxStoreArray; + for (i = 0; i < ck->cxStoreArray; i++, sp++, fsp++) + { + sp->dwSystemID = fsp->dwSystemID; + sp->dpString = (KMX_DWORD)offset; + u16ncpy((PKMX_WCHAR)(buf + offset), fsp->dpString, (size - offset) / sizeof(KMX_WCHAR)); // I3481 // I3641 + offset += u16len(fsp->dpString) * 2 + 2; + + if (kmcmp::FSaveDebug || fsp->fIsOption) + { + sp->dpName = (KMX_DWORD)offset; + u16ncpy((PKMX_WCHAR)(buf + offset), fsp->szName, (size - offset) / sizeof(KMX_WCHAR)); // I3481 // I3641 + offset += u16len(fsp->szName) * 2 + 2; + } + else sp->dpName = 0; + } + + ck->dpGroupArray = (KMX_DWORD)offset; + gp = (PCOMP_GROUP)(buf + offset); + fgp = fk->dpGroupArray; + + offset += sizeof(COMP_GROUP) * ck->cxGroupArray; + + for (i = 0; i < ck->cxGroupArray; i++, gp++, fgp++) + { + gp->cxKeyArray = fgp->cxKeyArray; + gp->fUsingKeys = fgp->fUsingKeys; + + gp->dpMatch = gp->dpNoMatch = 0; + + if (fgp->dpMatch) + { + gp->dpMatch = (KMX_DWORD)offset; + u16ncpy((PKMX_WCHAR)(buf + offset), fgp->dpMatch, (size - offset) / sizeof(KMX_WCHAR)); // I3481 // I3641 + offset += u16len(fgp->dpMatch) * 2 + 2; + } + if (fgp->dpNoMatch) + { + gp->dpNoMatch = (KMX_DWORD)offset; + u16ncpy((PKMX_WCHAR)(buf + offset), fgp->dpNoMatch, (size - offset) / sizeof(KMX_WCHAR)); // I3481 // I3641 + offset += u16len(fgp->dpNoMatch) * 2 + 2; + } + + if (kmcmp::FSaveDebug) + { + gp->dpName = (KMX_DWORD)offset; + u16ncpy((PKMX_WCHAR)(buf + offset), fgp->szName, (size - offset) / sizeof(KMX_WCHAR)); // I3481 // I3641 + offset += u16len(fgp->szName) * 2 + 2; + } + else gp->dpName = 0; + + gp->dpKeyArray = (KMX_DWORD)offset; + kp = (PCOMP_KEY )(buf + offset); + fkp = fgp->dpKeyArray; + offset += gp->cxKeyArray * sizeof(COMP_KEY); + for (j = 0; j < gp->cxKeyArray; j++, kp++, fkp++) + { + kp->_reserved = 0; + kp->Key = fkp->Key; + if (kmcmp::FSaveDebug) kp->Line = fkp->Line; else kp->Line = 0; + kp->ShiftFlags = fkp->ShiftFlags; + kp->dpOutput = (KMX_DWORD)offset; + u16ncpy((PKMX_WCHAR)(buf + offset), fkp->dpOutput, (size - offset) / sizeof(KMX_WCHAR)); // I3481 // I3641 + offset += u16len(fkp->dpOutput) * 2 + 2; + kp->dpContext = (KMX_DWORD)offset; + u16ncpy((PKMX_WCHAR)(buf + offset), fkp->dpContext, (size - offset) / sizeof(KMX_WCHAR)); // I3481 // I3641 + offset += u16len(fkp->dpContext) * 2 + 2; + } + } + + ck->dwBitmapSize = fk->dwBitmapSize; + ck->dpBitmapOffset = (KMX_DWORD)offset; + memcpy(buf + offset, fk->lpBitmap, fk->dwBitmapSize); + offset += fk->dwBitmapSize; + + if (offset != size) { + delete[] buf; + return CERR_SomewhereIGotItWrong; + } + + SetChecksum(buf, &ck->dwCheckSum, (KMX_DWORD)size); + + KMX_DWORD dwBytesWritten = 0; + dwBytesWritten = fwrite(buf,1, (KMX_DWORD)size , fp_out); + + if (dwBytesWritten != size) { + delete[] buf; + return CERR_UnableToWriteFully; + } + + delete[] buf; + + return CERR_None; +} + +KMX_DWORD ReadLine(FILE* fp_in , PKMX_WCHAR wstr, KMX_BOOL PreProcess) +{ + KMX_DWORD len; + PKMX_WCHAR p; + KMX_BOOL LineCarry = FALSE, InComment = FALSE; + KMX_DWORD n; + KMX_WCHAR currentQuotes = 0; + KMX_WCHAR str[LINESIZE + 3]; + len = fread( str , 1 ,LINESIZE * 2,fp_in); + if (ferror(fp_in) ) return CERR_CannotReadInfile; + len /= 2; + str[len] = 0; auto cur = ftell(fp_in); + fseek(fp_in, 0, SEEK_END); + auto fsize = ftell(fp_in); + fseek(fp_in, cur, SEEK_SET); + + if (cur == fsize) + + // \r\n is still added here even though Linux doesn`t use \r. + // This is to ensure to still have a working windows-only-version + u16ncat(str, u"\r\n", _countof(str)); // I3481 // Always a "\r\n" to the EOF, avoids funny bugs + + if (len == 0) return CERR_EndOfFile; + + // neccessary to add this block for using on non-windows platforms (removes all \r for platforms that use \n instead of \r\n) + for (p = str, n = 0; n < len; n++, p++) { + if (*p == L'\r') + *p = L' '; + } + + // \r is still left in this block even though Linux doesn`t use \r. + // This is to ensure to still have a working windows-only-version + for (p = str, n = 0; n < len; n++, p++) + { + if (currentQuotes != 0) + { + if (*p == L'\n') + { + *p = 0; // I2525 + u16ncpy(wstr, str, LINESIZE); // I3481 + return (PreProcess ? CERR_None : CERR_UnterminatedString); + } + if (*p == currentQuotes) currentQuotes = 0; + continue; + } + if (InComment) { + if (*p == L'\n') break; + *p = L' '; + continue; + } + if(*p == L'\\') { + LineCarry = TRUE; + *p = L' '; + continue; + } + if (LineCarry) + { + switch (*p) + { + case L' ': + case L'\t': + case L'\r': + *p = L' '; + continue; + case L'\n': + kmcmp::currentLine++; + LineCarry = FALSE; + *p = L' '; + continue; + } + *p = 0; // I2525 + u16ncpy(wstr, str, LINESIZE); // I3481 + return (PreProcess ? CERR_None : CERR_InvalidLineContinuation); + } + + if (*p == L'\n') break; + switch (*p) + { + case L'c': + case L'C': + if ((p == str || iswspace(*(p - 1))) && iswspace(*(p + 1))) { + InComment = TRUE; + *p = L' '; + } + continue; + case L'\r': + case L'\t': + *p = L' '; + continue; + case L'\'': + case L'\"': + currentQuotes = *p; + continue; + } + } + + if (n == len) + { + str[LINESIZE - 1] = 0; // I2525 + u16ncpy(wstr, str, LINESIZE); // I3481 + if (len == LINESIZE) + return (PreProcess ? CERR_None : CERR_LineTooLong); + } + + if (*p == L'\n') kmcmp::currentLine++; + + fseek(fp_in, -(int)(len * 2 - (int)(p - str) * 2 - 2), SEEK_CUR); + + p--; + while (p >= str && iswspace(*p)) p--; + p++; + *p++ = L'\n'; + *p = 0; + // trim spaces now, why not? + u16ncpy(wstr, str, LINESIZE); // I3481 + + return CERR_None; +} + +KMX_DWORD GetRHS(PFILE_KEYBOARD fk, PKMX_WCHAR p, PKMX_WCHAR buf, int bufsize, int offset, int IsUnicode) +{ + PKMX_WCHAR q; + p = (const PKMX_WCHAR) u16chr(p, '>'); + + if (!p) return CERR_NoTokensFound; + + p++; + + return GetXString(fk, p, u"c\n", buf, bufsize, offset, &q, TRUE, IsUnicode); +} + +void safe_wcsncpy(PKMX_WCHAR out, PKMX_WCHAR in, int cbMax) +{ + u16ncpy(out, in, cbMax - 1); // I3481 + out[cbMax - 1] = 0; +} + +KMX_BOOL IsSameToken(PKMX_WCHAR *p, KMX_WCHAR const * token) +{ + PKMX_WCHAR q; + q = *p; + while (iswspace(*q)) q++; + if (u16nicmp(q, token, u16len(token)) == 0) + { + q += u16len(token); + while (iswspace(*q)) q++; + *p = q; + return TRUE; + } + return FALSE; +} + +KMX_DWORD ImportBitmapFile(PFILE_KEYBOARD fk, PKMX_WCHAR szName, PKMX_DWORD FileSize, PKMX_BYTE *Buf) +{ + FILE *fp; + KMX_WCHAR szNewName[260]; + + if (IsRelativePath(szName)) + { + PKMX_WCHAR WCompileDir = strtowstr(kmcmp::CompileDir); + u16ncpy(szNewName, WCompileDir, _countof(szNewName)); // I3481 + u16ncat(szNewName,szName, _countof(szNewName )); // I3481 + } + else + u16ncpy(szNewName, szName, _countof(szNewName)); // I3481 + + fp=Open_File(szNewName, u"rb"); + + if ( fp == NULL) + { + // else if filename.bmp is not in the folder -> attempt to open filename.bmp.bmp ! + if ( u16cmp(szNewName+u16len(szNewName)-4, u".bmp") ) + u16ncat(szNewName, u".bmp", _countof(szNewName)); // I3481 + + fp= Open_File(szNewName, u"rb"); + + if ( fp == NULL) + return CERR_CannotReadBitmapFile; + } + + KMX_DWORD msg; + if ((msg = CheckFilenameConsistency(szNewName, FALSE)) != CERR_None) { + return msg; + } + + fseek(fp, 0, SEEK_END); + *FileSize = ftell(fp); + fseek(fp ,0,SEEK_SET); + if (*FileSize < 0) { + fclose(fp); + return CERR_CannotReadBitmapFile; + } + + if (*FileSize < 2) return CERR_CannotReadBitmapFile; + *Buf = new KMX_BYTE[*FileSize]; + + if (fread(*Buf, 1, *FileSize, fp) < (size_t) *FileSize) { + delete[] * Buf; + *Buf = NULL; + return CERR_CannotReadBitmapFile; + } + + fclose(fp); + + /* Test for version 7.0 icon support */ + if (*((PKMX_CHAR)*Buf) != 'B' && *(((PKMX_CHAR)*Buf) + 1) != 'M') { + VERIFY_KEYBOARD_VERSION(fk, VERSION_70, CERR_70FeatureOnly); + } + + return CERR_None; +} + +int atoiW(PKMX_WCHAR p) +{ + PKMX_STR q = wstrtostr(p); + int i = atoi(q); + delete[] q; + return i; +} + +int kmcmp::CheckUTF16(int n) +{ + const int res[] = { + 0xFDD0, 0xFDD1, 0xFDD2, 0xFDD3, 0xFDD4, 0xFDD5, 0xFDD6, 0xFDD7, + 0xFDD8, 0xFDD9, 0xFDDA, 0xFDDB, 0xFDDC, 0xFDDD, 0xFDDE, 0xFDDF, + 0xFDE0, 0xFDE1, 0xFDE2, 0xFDE3, 0xFDE4, 0xFDE5, 0xFDE6, 0xFDE7, + 0xFDE8, 0xFDE9, 0xFDEA, 0xFDEB, 0xFDEC, 0xFDED, 0xFDEE, 0xFDEF, + 0xFFFF, 0xFFFE, 0 }; + + if (n == 0) return CERR_ReservedCharacter; + for (int i = 0; res[i] > 0; i++) + if (n == res[i]) + { + AddWarning(CWARN_ReservedCharacter); + break; + } + return CERR_None; +} + +int kmcmp::UTF32ToUTF16(int n, int *n1, int *n2) +{ + *n2 = -1; + if (n <= 0xFFFF) + { + *n1 = n; + if (n >= 0xD800 && n <= 0xDFFF) AddWarning(CWARN_UnicodeSurrogateUsed); + return kmcmp::CheckUTF16(*n1); + } + + if ((n & 0xFFFF) == 0xFFFF || (n & 0xFFFF) == 0xFFFE) AddWarning(CWARN_ReservedCharacter); + if (n < 0 || n > 0x10FFFF) return CERR_InvalidCharacter; + n = n - 0x10000; + *n1 = (n / 0x400) + 0xD800; + *n2 = (n % 0x400) + 0xDC00; + if ((n = kmcmp::CheckUTF16(*n1)) != CERR_None) return n; + return kmcmp::CheckUTF16(*n2); +} + +KMX_DWORD BuildVKDictionary(PFILE_KEYBOARD fk) +{ + KMX_DWORD i; + size_t len = 0; + if (fk->cxVKDictionary == 0) return CERR_None; + for (i = 0; i < fk->cxVKDictionary; i++) + { + len += u16len(fk->dpVKDictionary[i].szName) + 1; + } + PKMX_WCHAR storeval = new KMX_WCHAR[len], p = storeval; + for (i = 0; i < fk->cxVKDictionary; i++) + { + u16ncpy(p, fk->dpVKDictionary[i].szName, len - (size_t)(p - storeval)); // I3481 + p = (PKMX_WCHAR) u16chr(p, 0); + *p = ' '; + p++; + } + + p--; + *p = 0; + + KMX_DWORD dwStoreID; + KMX_DWORD msg = AddStore(fk, TSS_VKDICTIONARY, storeval, &dwStoreID); + delete[] storeval; + return msg; +} + +int GetVKCode(PFILE_KEYBOARD fk, PKMX_WCHAR p) +{ + KMX_DWORD i; + + for (i = 0; i < fk->cxVKDictionary; i++) + if (u16icmp(fk->dpVKDictionary[i].szName, p) == 0) + return i + VK__MAX + 1; // 256 + + if (fk->cxVKDictionary % 10 == 0) + { + PFILE_VKDICTIONARY pvk = new FILE_VKDICTIONARY[fk->cxVKDictionary + 10]; + memcpy(pvk, fk->dpVKDictionary, fk->cxVKDictionary * sizeof(FILE_VKDICTIONARY)); + delete fk->dpVKDictionary; + fk->dpVKDictionary = pvk; + } + u16ncpy(fk->dpVKDictionary[fk->cxVKDictionary].szName, p, _countof(fk->dpVKDictionary[fk->cxVKDictionary].szName) ); // I3481 + fk->dpVKDictionary[fk->cxVKDictionary].szName[SZMAX_VKDICTIONARYNAME - 1] = 0; + + fk->cxVKDictionary++; + return fk->cxVKDictionary + VK__MAX; // 256-1 +} + +int GetDeadKey(PFILE_KEYBOARD fk, PKMX_WCHAR p) +{ + KMX_DWORD i; + + for (i = 0; i < fk->cxDeadKeyArray; i++) + if (u16icmp(fk->dpDeadKeyArray[i].szName, p) == 0) + return i + 1; + + if (fk->cxDeadKeyArray % 10 == 0) + { + PFILE_DEADKEY dk = new FILE_DEADKEY[fk->cxDeadKeyArray + 10]; + memcpy(dk, fk->dpDeadKeyArray, fk->cxDeadKeyArray * sizeof(FILE_DEADKEY)); + delete[] fk->dpDeadKeyArray; + fk->dpDeadKeyArray = dk; + } + u16ncpy(fk->dpDeadKeyArray[fk->cxDeadKeyArray].szName,p, _countof(fk->dpDeadKeyArray[fk->cxDeadKeyArray].szName)); // I3481 + fk->dpDeadKeyArray[fk->cxDeadKeyArray].szName[SZMAX_DEADKEYNAME - 1] = 0; + + fk->cxDeadKeyArray++; + return fk->cxDeadKeyArray; +} + +void kmcmp::RecordDeadkeyNames(PFILE_KEYBOARD fk) +{ + KMX_WCHAR buf[SZMAX_DEADKEYNAME + 16]; + KMX_DWORD i; + for (i = 0; i < fk->cxDeadKeyArray; i++) + { + u16sprintf(buf, _countof(buf), L"%ls%d ", u16fmt(DEBUGSTORE_DEADKEY).c_str(), (int)i); + u16ncat(buf, fk->dpDeadKeyArray[i].szName, _countof(buf)); + + AddDebugStore(fk, buf); + } +} + +KMX_BOOL kmcmp::IsValidCallStore(PFILE_STORE fs) +{ + int i; + PKMX_WCHAR p; + for (i = 0, p = fs->dpString; *p; p++) + if (*p == ':') i++; + else if (!((*p >= 'a' && *p <= 'z') || + (*p >= 'A' && *p <= 'Z') || + (*p >= '0' && *p <= '9') || + *p == '.' || + *p == '_')) + return FALSE; + + return i == 1; +} + +FILE* CreateTempFile() +{ + return tmpfile(); +} + +/////////////////// + +FILE* UTF16TempFromUTF8(FILE* fp_in , KMX_BOOL hasPreamble) +{ + FILE *fp_out = CreateTempFile(); + if(fp_out == NULL) // I3228 // I3510 + { + fclose(fp_in); + return NULL; //return INVALID_HANDLE_VALUE; _S2 can I exchange that? + } + + PKMX_BYTE buf, p; + PKMX_WCHAR outbuf, poutbuf; + KMX_DWORD len; + KMX_DWORD len2; + KMX_WCHAR prolog = 0xFEFF; + fwrite(&prolog,2, 1, fp_out); + + fseek(fp_in, 0, SEEK_END); + len = ftell(fp_in); + fseek(fp_in, 0, SEEK_SET); + if (hasPreamble) { + fseek( fp_in,3,SEEK_SET); // Cut off UTF-8 marker + len -= 3; + } + + buf = new KMX_BYTE[len + 1]; // null terminated + outbuf = new KMX_WCHAR[len + 1]; + + len2= fread(buf,1,len,fp_in); + if (len2) { + buf[len2] = 0; + p = buf; + poutbuf = outbuf; + if (hasPreamble) { + // We have a preamble, so we attempt to read as UTF-8 and allow conversion errors to be filtered. This is not great for a + // compiler but matches existing behaviour -- in future versions we may not do lenient conversion. + ConvertUTF8toUTF16(&p, &buf[len2], (UTF16 **)&poutbuf, (const UTF16 *)&outbuf[len], lenientConversion); + fwrite(outbuf, (KMX_DWORD)(poutbuf - outbuf) * 2 , 1, fp_out); + } + else { + // No preamble, so we attempt to read as strict UTF-8 and fall back to ANSI if that fails + ConversionResult cr = ConvertUTF8toUTF16(&p, &buf[len2], (UTF16 **)&poutbuf, (const UTF16 *)&outbuf[len], strictConversion); + if (cr == sourceIllegal) { + // Not a valid UTF-8 file, so fall back to ANSI + // AddCompileError(CHINT_NonUnicodeFile); + // note, while this message is defined, for now we will not emit it + // because we don't support HINT/INFO messages yet and we don't want + // this to cause a blocking compile at this stage + // do strtowstr only when no invalid characters are found + if( p==0){ + poutbuf = strtowstr((PKMX_STR)buf); + fwrite(poutbuf, (KMX_DWORD)u16len(poutbuf) * 2 , 1, fp_out); + delete[] poutbuf; + } + else + AddCompileError(CERR_InvalidCharacter); + } + + else { + fwrite(outbuf, (KMX_DWORD)(poutbuf - outbuf) * 2 , 1, fp_out); + } + } + } + + fclose( fp_in); + delete[] buf; + delete[] outbuf; + fseek( fp_out,2,SEEK_SET); + return fp_out; +} + +PFILE_STORE FindSystemStore(PFILE_KEYBOARD fk, KMX_DWORD dwSystemID) +{ + assert(fk != NULL); + assert(dwSystemID != 0); + + PFILE_STORE sp = fk->dpStoreArray; + for (KMX_DWORD i = 0; i < fk->cxStoreArray; i++, sp++) { + if (sp->dwSystemID == dwSystemID) { + return sp; + } + } + return NULL; +} diff --git a/developer/src/kmcmplib/src/DeprecationChecks.cpp b/developer/src/kmcmplib/src/DeprecationChecks.cpp new file mode 100644 index 0000000000..7153a6f723 --- /dev/null +++ b/developer/src/kmcmplib/src/DeprecationChecks.cpp @@ -0,0 +1,53 @@ + +#include "pch.h" + +#include "compfile.h" +#include +#include "kmcmplib.h" +#include "DeprecationChecks.h" + +KMX_BOOL kmcmp::WarnDeprecatedHeader() { // I4866 +if( AWarnDeprecatedCode_GLOBAL_LIB){ + AddWarning(CWARN_HeaderStatementIsDeprecated); + } + return TRUE; +} + +/* Flag presence of deprecated features */ +KMX_BOOL kmcmp::CheckForDeprecatedFeatures(PFILE_KEYBOARD fk) { + /* + For Keyman 10, we deprecated: + // < Keyman 7 + #define TSS_LANGUAGE 4 + #define TSS_LAYOUT 5 + #define TSS_LANGUAGENAME 12 + #define TSS_ETHNOLOGUECODE 15 + + // Keyman 7 + #define TSS_WINDOWSLANGUAGES 29 + */ + int oldCurrentLine = kmcmp::currentLine; + KMX_DWORD i; + PFILE_STORE sp; + + if (!AWarnDeprecatedCode_GLOBAL_LIB) { + return TRUE; + } + + if (fk->version >= VERSION_100) { + for (i = 0, sp = fk->dpStoreArray; i < fk->cxStoreArray; i++, sp++) { + if (sp->dwSystemID == TSS_LANGUAGE || + sp->dwSystemID == TSS_LAYOUT || + sp->dwSystemID == TSS_LANGUAGENAME || + sp->dwSystemID == TSS_ETHNOLOGUECODE || + sp->dwSystemID == TSS_WINDOWSLANGUAGES) { + kmcmp::currentLine = sp->line; + AddWarning(CWARN_LanguageHeadersDeprecatedInKeyman10); + } + } + } + + kmcmp::currentLine = oldCurrentLine; + + return TRUE; +} diff --git a/developer/src/kmcmplib/src/DeprecationChecks.h b/developer/src/kmcmplib/src/DeprecationChecks.h new file mode 100644 index 0000000000..941b87f1a4 --- /dev/null +++ b/developer/src/kmcmplib/src/DeprecationChecks.h @@ -0,0 +1,9 @@ +#pragma once + +#include "compfile.h" +#include "kmcmplib.h" + +namespace kmcmp{ +KMX_BOOL WarnDeprecatedHeader(); +KMX_BOOL CheckForDeprecatedFeatures(PFILE_KEYBOARD fk); +} diff --git a/developer/src/kmcmplib/src/Edition.cpp b/developer/src/kmcmplib/src/Edition.cpp new file mode 100644 index 0000000000..cdf82ee2f8 --- /dev/null +++ b/developer/src/kmcmplib/src/Edition.cpp @@ -0,0 +1,8 @@ + +#include "pch.h" +#include "Edition.h" + +int GetEdition() +{ + return ED_STANDARD; +} diff --git a/developer/src/kmcmplib/src/Edition.h b/developer/src/kmcmplib/src/Edition.h new file mode 100644 index 0000000000..26eb44c616 --- /dev/null +++ b/developer/src/kmcmplib/src/Edition.h @@ -0,0 +1,12 @@ + +#ifndef _EDITION_H +#define _EDITION_H + +int GetEdition(); + +#define ED_DEMO 0 +#define ED_STANDARD 1 +#define ED_PRO 2 +#define ED_OEM 3 + +#endif diff --git a/developer/src/kmcmplib/src/NamedCodeConstants.cpp b/developer/src/kmcmplib/src/NamedCodeConstants.cpp new file mode 100644 index 0000000000..d6c52df3ed --- /dev/null +++ b/developer/src/kmcmplib/src/NamedCodeConstants.cpp @@ -0,0 +1,346 @@ +/*2012 + Name: NamedCodeConstants + Copyright: Copyright (C) 2003-2017 SIL International. + Documentation: + Description: + Create Date: 19 Jul 2011 + + Modified Date: 13 Dec 2012 + Authors: mcdurdin + Related Files: + Dependencies: + + Bugs: + Todo: + Notes: + History: 19 Jul 2011 - mcdurdin - I2993 - Named code constants cause a warning 0x208D to appear + 24 Oct 2012 - mcdurdin - I3481 - V9.0 - Eliminate unsafe calls in C++ + 06 Feb 2012 - mcdurdin - I3056 - If file was not found in first search folder, named code constants failed to compile + 06 Feb 2012 - mcdurdin - I3056 - UTF-8 support for named code constants file + 03 Nov 2012 - mcdurdin - I3512 - V9.0 - Merge of I3056 - If file was not found in first search folder, named code constants failed to compile + 13 Dec 2012 - mcdurdin - I3641 - V9.0 - compiler dll buffer overrun bugs +*/ + +#include "pch.h" +#include +#include "NamedCodeConstants.h" +#include "CheckFilenameConsistency.h" +#include +#include "kmcompx.h" +#include "filesystem.h" + +using namespace kmcmp; + +int IsHangulSyllable(const KMX_WCHAR *codename, int *code); + +namespace kmcmp { + extern KMX_CHAR CompileDir[]; + + int __cdecl sort_entries(const void *elem1, const void *elem2) + { + return u16icmp( + ((NCCENTRY *)elem1)->name, + ((NCCENTRY *)elem2)->name); + } +} + +NamedCodeConstants::NamedCodeConstants() +{ + nEntries = 0; + entries = NULL; + nEntries_file = 0; + entries_file = NULL; + reindex(); +} + +NamedCodeConstants::~NamedCodeConstants() +{ + if(entries) delete entries; + if(entries_file) delete entries_file; +} + +void NamedCodeConstants::AddCode(int n, const KMX_WCHAR *p, KMX_DWORD storeIndex) +{ + if((nEntries_file % ALLOC_SIZE) == 0) + { + NCCENTRY *bn = new NCCENTRY[nEntries_file + ALLOC_SIZE]; + if(nEntries_file > 0) + { + memcpy(bn, entries_file, sizeof(NCCENTRY) * nEntries_file); + delete entries_file; + } + entries_file = bn; + } + + entries_file[nEntries_file].code = n; + u16ncpy(entries_file[nEntries_file].name, p, _countof(entries_file[nEntries_file].name)); // I3481 + entries_file[nEntries_file].name[MAX_ENAME] = 0; + + for (KMX_WCHAR *r = entries_file[nEntries_file].name; *r; r++) + if (iswblank(*r) && *r != '-') *r = '_'; + + entries_file[nEntries_file].storeIndex = storeIndex; + nEntries_file++; +} + +void NamedCodeConstants::AddCode_IncludedCodes(int n, const KMX_WCHAR *p) +{ + if((nEntries % ALLOC_SIZE) == 0) + { + NCCENTRY *bn = new NCCENTRY[nEntries + ALLOC_SIZE]; + if(nEntries > 0) + { + memcpy(bn, entries, sizeof(NCCENTRY) * nEntries); + delete entries; + } + entries = bn; + } + + entries[nEntries].code = n; + u16ncpy(entries[nEntries].name, p, MAX_ENAME); // I3481 + entries[nEntries].name[MAX_ENAME] = 0; + for (KMX_WCHAR *r = entries[nEntries].name; *r; r++) + if (iswblank(*r)) *r = '_'; + + entries[nEntries].storeIndex = 0xFFFFFFFFL; + nEntries++; +} + +// int __cdecl sort_entries(const void *elem1, const void *elem2) moved into namespace further up + +KMX_BOOL NamedCodeConstants::IntLoadFile(const KMX_CHAR *filename) +{ + const int str_size = 256; + FILE *fp = NULL; + + if (CheckFilenameConsistency(filename, FALSE) != NULL) { + return FALSE; + } + + fp = Open_File(filename, "rt"); + if(fp == NULL) { + return FALSE; // I3481 + } + + KMX_CHAR str[str_size], *p, *q, *context = NULL; + KMX_BOOL isEol , first = TRUE; + + while(fgets(str, str_size, fp)) + { + isEol = *(strchr(str, 0) - 1) == '\n'; + p = strtok_r(str, ";", &context); // I3481 + q = strtok_r(NULL, ";\n", &context); + if(p && q) + { + if(first && *p == (KMX_CHAR)0xEF && *(p+1) == (KMX_CHAR)0xBB && *(p+2) == (KMX_CHAR)0xBF) p += 3; // I3056 UTF-8 // I3512 + first = FALSE; + strupr(q); // I3481 // I3641 + int n = strtol(p, NULL, 16); + if (*q != '<') { + PKMX_WCHAR q0 = strtowstr(q); + AddCode_IncludedCodes(n, q0); + delete[] q0; + } + } + if(!isEol ) + { + while(fgets(str, str_size, fp)) if(*(strchr(str, 0)-1) == '\n') break; + } + } + + fclose(fp); + + return TRUE; +} + +KMX_BOOL NamedCodeConstants::LoadFile(const KMX_CHAR *filename) +{ + const int buf_size = 260; + KMX_CHAR buf[buf_size]; + // Look in current directory first -- REMOVED AS DANGEROUS + /* strncpy(buf, filename, (buf_size-1)); buf[buf_size-1] = 0; // I3481 + if(kmcmp_FileExists(buf)) + return IntLoadFile(buf); + */ + // Then look in keyboard file directory (CompileDir) + strncpy(buf, CompileDir, (buf_size-1)); buf[buf_size-1] = 0; // I3481 + strncat(buf, filename, (buf_size-1)-strlen(CompileDir)); buf[buf_size-1] = 0; + if(kmcmp_FileExists(buf)) + return IntLoadFile(buf); + + //TODO: sort out how to find common includes in non-Windows platforms: + #ifdef _WINDOWS_ + // Finally look in kmcmpdll.dll directory + GetModuleFileName(0, buf, buf_size); + + KMX_CHAR *p = strrchr_slash(buf); + if(p) + p++; + else + p = buf; + *p = 0; + strncat_s(buf, _countof(buf), filename, (buf_size-1)-strlen(buf)); buf[buf_size-1] = 0; // I3481 // I3641 + if(kmcmp_FileExists(buf)) + return IntLoadFile(buf); + #endif + + reindex(); + + return FALSE; +} + +void NamedCodeConstants::reindex() +{ + if (entries != NULL) { + qsort(entries, nEntries, sizeof(NCCENTRY), sort_entries); + } + + KMX_WCHAR c = u'.', d; + int i; + + for(i = 0; i < 128; i++) chrindexes[i] = -1; + + if (entries != NULL) { + for (i = 0; i < nEntries; i++) + { + d = towupper(entries[i].name[0]); + if (d != c && d >= 32 && d <= 127) + chrindexes[c = d] = i; + } + } +} + +int NamedCodeConstants::GetCode(const KMX_WCHAR *codename, KMX_DWORD *storeIndex) +{ + *storeIndex = 0xFFFFFFFFL; // I2993 + int code = GetCode_IncludedCodes(codename); + if(code) return code; + for(int i = 0; i < nEntries_file; i++) { + if(!u16icmp(entries_file[i].name, codename)) { + *storeIndex = entries_file[i].storeIndex; + return entries_file[i].code; + } + } + return 0; +} + +int NamedCodeConstants::GetCode_IncludedCodes(const KMX_WCHAR *codename) +{ + KMX_WCHAR c = towupper(*codename); + int code; + + if(IsHangulSyllable(codename, &code)) return code; + + if(c < 32 || c > 127 || chrindexes[c] < 0) return 0; + for(int n = chrindexes[c]; n < nEntries && towupper(entries[n].name[0]) == c; n++) + { + int cmp = u16icmp(codename, entries[n].name); + if(cmp == 0) return entries[n].code; + if(cmp < 0) break; + } + return 0; +} + +/* + + Hangul Syllables + +*/ + +const int + HangulSBase = 0xAC00, + //HangulLBase = 0x1100, + //HangulVBase = 0x1161, + //HangulTBase = 0x11A7, + HangulLCount = 19, + HangulVCount = 21, + HangulTCount = 28; + //HangulNCount = HangulVCount * HangulTCount; // 588 + //HangulSCount = HangulLCount * HangulNCount; // 11172 + +const KMX_WCHAR * + Hangul_JAMO_L_TABLE[] = { + u"G", u"GG", u"N", u"D", u"DD", u"R", u"M", u"B", u"BB", + u"S", u"SS", u"", u"J", u"JJ", u"C", u"K", u"T", u"P", u"H" }; + +const KMX_WCHAR * + Hangul_JAMO_V_TABLE[] = { + u"A", u"AE", u"YA", u"YAE", u"EO", u"E", u"YEO", u"YE", u"O", + u"WA", u"WAE", u"OE", u"YO", u"U", u"WEO", u"WE", u"WI", + u"YU", u"EU", u"YI", u"I" }; + + +const KMX_WCHAR * + Hangul_JAMO_T_TABLE[] = { + u"", u"G", u"GG", u"GS", u"N", u"NJ", u"NH", u"D", u"u", u"LG", u"LM", + u"LB", u"LS", u"LT", u"LP", u"LH", u"M", u"B", u"BS", + u"S", u"SS", u"NG", u"J", u"C", u"K", u"T", u"P", u"H" }; + + +int IsHangulSyllable(const KMX_WCHAR *codename, int *code) +{ + if(u16nicmp(codename, u"HANGUL_SYLLABLE_", 16)) return 0; + codename += 16; + if(!*codename) return 0; + + int i, LIndex, VIndex, TIndex; + + /* Find initial */ + + int ch = towupper(*codename); + if(strchr("GNDRMBSJCKTPH", ch)) + { + /* Has an initial syllable */ + int isDoubled = towupper(*(codename+1)) == ch; + + LIndex = -1; + for(i = 0; i < HangulLCount; i++) { + if(Hangul_JAMO_L_TABLE[i][0] == ch && (!isDoubled || (Hangul_JAMO_L_TABLE[i][1] == ch && isDoubled))) { + LIndex = i; + break; + } + } + if(LIndex == -1) return 0; + codename++; + if(isDoubled) codename++; + } + else LIndex = 11; /* no initial */ + + /* Find vowel */ + + KMX_WCHAR V[4] = u""; + V[0] = *codename; + if(V[0] && strchr("AEIOUWY", towupper(*(codename+1)))) V[1] = *(codename+1); + if(V[1] && strchr("AEIOUWY", towupper(*(codename+2)))) V[2] = *(codename+2); + + VIndex = -1; + for(i = 0; i < HangulVCount; i++) { + if(!u16icmp(Hangul_JAMO_V_TABLE[i], V)) { + VIndex = i; + break; + } + } + + if(VIndex == -1) return 0; + + codename += u16len(V); + + /* Find final */ + + TIndex = -1; + + for(i = 0; i < HangulTCount; i++) { + if(!u16icmp(Hangul_JAMO_T_TABLE[i], codename)) { + TIndex = i; + break; + } + } + + if(TIndex == -1) return 0; + + /* Composition */ + + *code = (HangulSBase + (LIndex * HangulVCount + VIndex) * HangulTCount) + TIndex; + + return 1; +} diff --git a/developer/src/kmcmplib/src/NamedCodeConstants.h b/developer/src/kmcmplib/src/NamedCodeConstants.h new file mode 100644 index 0000000000..83d707d092 --- /dev/null +++ b/developer/src/kmcmplib/src/NamedCodeConstants.h @@ -0,0 +1,37 @@ + +#ifndef NAMEDCODECONSTANTS_H +#define NAMEDCODECONSTANTS_H + +#define MAX_ENAME 128 +#define ALLOC_SIZE 256 + +struct NCCENTRY +{ + KMX_WCHAR name[MAX_ENAME+1]; + int code; + KMX_DWORD storeIndex; +}; + +namespace kmcmp{ + class NamedCodeConstants + { + private: + NCCENTRY *entries; // entries from &includecodes + NCCENTRY *entries_file; // entries from store(myconst) x + int nEntries, nEntries_file; + int chrindexes[128]; // A-Z, 0-9, -, _; simple index + + int GetCode_IncludedCodes(const KMX_WCHAR *codename); + void AddCode_IncludedCodes(int n, const KMX_WCHAR *p); + KMX_BOOL IntLoadFile(const KMX_CHAR *filename); + public: + NamedCodeConstants(); + ~NamedCodeConstants(); + + void reindex(); + void AddCode(int n, const KMX_WCHAR *p, KMX_DWORD storeIndex); + KMX_BOOL LoadFile(const KMX_CHAR *filename); + int GetCode(const KMX_WCHAR *codename, KMX_DWORD *storeIndex); + }; +} +#endif //NAMEDCODECONSTANTS_H diff --git a/developer/src/kmcmplib/src/UnreachableRules.cpp b/developer/src/kmcmplib/src/UnreachableRules.cpp new file mode 100644 index 0000000000..f7a9b4a5fe --- /dev/null +++ b/developer/src/kmcmplib/src/UnreachableRules.cpp @@ -0,0 +1,57 @@ + +#include "pch.h" + +#include "compfile.h" +#include +#include "../../../../common/windows/cpp/include/vkeys.h" +#include "kmcmplib.h" + +#include +#include +#include +#include + +#include "UnreachableRules.h" + +namespace kmcmp { + std::wstring MakeHashKeyFromFileKey(PFILE_KEY kp) { + std::wstringstream key; + key << kp->Key << "," << kp->ShiftFlags << ","; + if (kp->dpContext) { + std::wstring Context_ws = u16fmt((const PKMX_WCHAR) kp->dpContext); + key << Context_ws; + } + return key.str(); + } + +} +KMX_DWORD VerifyUnreachableRules(PFILE_GROUP gp) { + PFILE_KEY kp = gp->dpKeyArray; + KMX_DWORD i; + + int oldCurrentLine = kmcmp::currentLine; + + std::unordered_map map; + std::unordered_set reportedLines; + + for (i = 0; i < gp->cxKeyArray; i++, kp++) { + std::wstring key = kmcmp::MakeHashKeyFromFileKey(kp); + if (map.count(key) > 0) { + FILE_KEY const & k1 = map.at(key); + if (kp->Line != k1.Line && reportedLines.count(kp->Line) == 0) { + reportedLines.insert(kp->Line); + kmcmp::currentLine = kp->Line; + u16sprintf(ErrExtraW, 256, L" Overridden by rule on line %d", k1.Line); + strcpy(ErrExtraLIB, string_from_u16string(ErrExtraW).c_str()); + AddWarning(CHINT_UnreachableRule); + } + } + else { + map.insert({ key, *kp }); + } + } + + kmcmp::currentLine = oldCurrentLine; + + return CERR_None; +} diff --git a/developer/src/kmcmplib/src/UnreachableRules.h b/developer/src/kmcmplib/src/UnreachableRules.h new file mode 100644 index 0000000000..d9eac65ce3 --- /dev/null +++ b/developer/src/kmcmplib/src/UnreachableRules.h @@ -0,0 +1,3 @@ +#pragma once + +KMX_DWORD VerifyUnreachableRules(PFILE_GROUP gp); diff --git a/developer/src/kmcmplib/src/comperr.h b/developer/src/kmcmplib/src/comperr.h new file mode 100644 index 0000000000..3d1658af0e --- /dev/null +++ b/developer/src/kmcmplib/src/comperr.h @@ -0,0 +1,233 @@ +/* + Name: Comperr + Copyright: Copyright (C) SIL International. + Documentation: + Description: + Create Date: 23 Aug 2006 + + Modified Date: 6 Mar 2014 + Authors: mcdurdin + Related Files: + Dependencies: + + Bugs: + Todo: + Notes: + History: 23 Aug 2006 - mcdurdin - Add Keyman 7.0 feature error + 25 May 2010 - mcdurdin - I1632 - Keyboard Options + 21 Feb 2014 - mcdurdin - I4061 - V9.0 - KeymanWeb compiler needs defined codes for some errors + 06 Mar 2014 - mcdurdin - I4118 - V9.0 - KMW compiler should warn when extended shift flags are used + 22 Jul 2020 - eddieantonio - Add lexical model range https://github.com/keymanapp/keyman/pull/3385 +*/ + // I4061 +#ifndef _COMPERR_H +#define _COMPERR_H + +// Note: these are not be a bitmask +#define CERR_FATAL 0x00008000 +#define CERR_ERROR 0x00004000 +#define CERR_WARNING 0x00002000 +#define CERR_HINT 0x00001000 + +// Any messages from the lexical model compiler occupy this range: +#define CERR_LEXICAL_MODEL_MIN 0x00000800 +#define CERR_LEXICAL_MODEL_MAX 0x000008FF + +#define CERR_None 0x00000000 +#define CERR_EndOfFile 0x00000001 + +#define CERR_BadCallParams 0x00008002 +#define CERR_CannotAllocateMemory 0x00008004 +#define CERR_InfileNotExist 0x00008005 +#define CERR_CannotCreateOutfile 0x00008006 +#define CERR_UnableToWriteFully 0x00008007 +#define CERR_CannotReadInfile 0x00008008 +#define CERR_SomewhereIGotItWrong 0x00008009 + +#define CERR_InvalidToken 0x0000400A +#define CERR_InvalidBegin 0x0000400B +#define CERR_InvalidName 0x0000400C +#define CERR_InvalidVersion 0x0000400D +#define CERR_InvalidLanguageLine 0x0000400E +#define CERR_LayoutButNoLanguage 0x0000400F +#define CERR_InvalidLayoutLine 0x00004010 +#define CERR_NoVersionLine 0x00004011 +#define CERR_InvalidGroupLine 0x00004012 +#define CERR_InvalidStoreLine 0x00004013 +#define CERR_InvalidCodeInKeyPartOfRule 0x00004014 +#define CERR_InvalidDeadkey 0x00004015 +#define CERR_InvalidValue 0x00004016 +#define CERR_ZeroLengthString 0x00004017 +#define CERR_TooManyIndexToKeyRefs 0x00004018 +#define CERR_UnterminatedString 0x00004019 +#define CERR_StringInVirtualKeySection 0x0000401A +#define CERR_AnyInVirtualKeySection 0x0000401B +#define CERR_InvalidAny 0x0000401C +#define CERR_StoreDoesNotExist 0x0000401D +#define CERR_BeepInVirtualKeySection 0x0000401E +#define CERR_IndexInVirtualKeySection 0x0000401F +#define CERR_InvalidIndex 0x00004020 +#define CERR_OutsInVirtualKeySection 0x00004021 +#define CERR_InvalidOuts 0x00004022 +#define CERR_ContextInVirtualKeySection 0x00004024 +#define CERR_InvalidUse 0x00004025 +#define CERR_GroupDoesNotExist 0x00004026 +#define CERR_VirtualKeyNotAllowedHere 0x00004027 +#define CERR_InvalidSwitch 0x00004028 +#define CERR_NoTokensFound 0x00004029 +#define CERR_InvalidLineContinuation 0x0000402A +#define CERR_LineTooLong 0x0000402B +#define CERR_InvalidCopyright 0x0000402C +#define CERR_CodeInvalidInThisSection 0x0000402D +#define CERR_InvalidMessage 0x0000402E +#define CERR_InvalidLanguageName 0x0000402F +#define CERR_InvalidBitmapLine 0x00004030 +#define CERR_CannotReadBitmapFile 0x00004031 +#define CERR_IndexDoesNotPointToAny 0x00004032 +#define CERR_ReservedCharacter 0x00004033 +#define CERR_InvalidCharacter 0x00004034 +#define CERR_InvalidCall 0x00004035 +#define CERR_CallInVirtualKeySection 0x00004036 +#define CERR_CodeInvalidInKeyStore 0x00004037 +#define CERR_CannotLoadIncludeFile 0x00004038 + +#define CERR_60FeatureOnly_EthnologueCode 0x00004039 +#define CERR_60FeatureOnly_MnemonicLayout 0x0000403A +#define CERR_60FeatureOnly_OldCharPosMatching 0x0000403B +#define CERR_60FeatureOnly_NamedCodes 0x0000403C +#define CERR_60FeatureOnly_Contextn 0x0000403D +#define CERR_501FeatureOnly_Call 0x0000403E + +#define CERR_InvalidNamedCode 0x0000403F +#define CERR_InvalidSystemStore 0x00004040 + +#define CERR_60FeatureOnly_VirtualCharKey 0x00004044 + +#define CERR_VersionAlreadyIncluded 0x00004045 + +#define CERR_70FeatureOnly 0x00004046 + +#define CERR_80FeatureOnly 0x00004047 +#define CERR_InvalidInVirtualKeySection 0x00004048 +#define CERR_InvalidIf 0x00004049 +#define CERR_InvalidReset 0x0000404A +#define CERR_InvalidSet 0x0000404B +#define CERR_InvalidSave 0x0000404C + +#define CERR_InvalidEthnologueCode 0x0000404D + +#define CERR_CannotCreateTempfile 0x0000804E + +#define CERR_90FeatureOnly_IfSystemStores 0x0000404F +#define CERR_IfSystemStore_NotFound 0x00004050 +#define CERR_90FeatureOnly_SetSystemStores 0x00004051 +#define CERR_SetSystemStore_NotFound 0x00004052 +#define CERR_90FeatureOnlyVirtualKeyDictionary 0x00004053 + +#define CERR_NotSupportedInKeymanWebContext 0x00004054 +#define CERR_NotSupportedInKeymanWebOutput 0x00004055 +#define CERR_NotSupportedInKeymanWebStore 0x00004056 +#define CERR_VirtualCharacterKeysNotSupportedInKeymanWeb 0x00004057 +#define CERR_VirtualKeysNotValidForMnemonicLayouts 0x00004058 +#define CERR_InvalidTouchLayoutFile 0x00004059 +#define CERR_TouchLayoutInvalidIdentifier 0x0000405A +#define CERR_InvalidKeyCode 0x0000405B +#define CERR_90FeatureOnlyLayoutFile 0x0000405C +#define CERR_90FeatureOnlyKeyboardVersion 0x0000405D +#define CERR_KeyboardVersionFormatInvalid 0x0000405E +#define CERR_ContextExHasInvalidOffset 0x0000405F +#define CERR_90FeatureOnlyEmbedCSS 0x00004060 +#define CERR_90FeatureOnlyTargets 0x00004061 +#define CERR_ContextAndIndexInvalidInMatchNomatch 0x00004062 +#define CERR_140FeatureOnlyContextAndNotAnyWeb 0x00004063 + +#define CERR_ExpansionMustFollowCharacterOrVKey 0x00004064 +#define CERR_VKeyExpansionMustBeFollowedByVKey 0x00004065 +#define CERR_CharacterExpansionMustBeFollowedByCharacter 0x00004066 +#define CERR_VKeyExpansionMustUseConsistentShift 0x00004067 +#define CERR_ExpansionMustBePositive 0x00004068 + +#define CERR_CasedKeysMustContainOnlyVirtualKeys 0x00004069 +#define CERR_CasedKeysMustNotIncludeShiftStates 0x0000406A +#define CERR_CasedKeysNotSupportedWithMnemonicLayout 0x0000406B + +#define CERR_CannotUseReadWriteGroupFromReadonlyGroup 0x0000406C +#define CERR_StatementNotPermittedInReadonlyGroup 0x0000406D +#define CERR_OutputInReadonlyGroup 0x0000406E +#define CERR_NewContextGroupMustBeReadonly 0x0000406F +#define CERR_PostKeystrokeGroupMustBeReadonly 0x00004070 + +#define CERR_DuplicateGroup 0x00004071 +#define CERR_DuplicateStore 0x00004072 + +#define CERR_RepeatedBegin 0x00004073 + +#define CWARN_TooManyWarnings 0x00002080 +#define CWARN_OldVersion 0x00002081 +#define CWARN_BitmapNotUsed 0x00002082 +#define CWARN_CustomLanguagesNotSupported 0x00002083 +#define CWARN_KeyBadLength 0x00002084 +#define CWARN_IndexStoreShort 0x00002085 +#define CWARN_UnicodeInANSIGroup 0x00002086 +#define CWARN_ANSIInUnicodeGroup 0x00002087 +#define CWARN_UnicodeSurrogateUsed 0x00002088 +#define CWARN_ReservedCharacter 0x00002089 +#define CWARN_Info 0x0000208A +#define CWARN_VirtualKeyWithMnemonicLayout 0x0000208B +#define CWARN_VirtualCharKeyWithPositionalLayout 0x0000208C +#define CWARN_StoreAlreadyUsedAsOptionOrCall 0x0000208D +#define CWARN_StoreAlreadyUsedAsStoreOrCall 0x0000208E +#define CWARN_StoreAlreadyUsedAsStoreOrOption 0x0000208F + +#define CWARN_PunctuationInEthnologueCode 0x00002090 + +#define CWARN_TouchLayoutMissingLayer 0x00002091 +#define CWARN_TouchLayoutCustomKeyNotDefined 0x00002092 +#define CWARN_TouchLayoutMissingRequiredKeys 0x00002093 +#define CWARN_HelpFileMissing 0x00002094 +#define CWARN_EmbedJsFileMissing 0x00002095 +#define CWARN_TouchLayoutFileMissing 0x00002096 +#define CWARN_VisualKeyboardFileMissing 0x00002097 +#define CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb 0x00002098 // I4118 +#define CWARN_TouchLayoutUnidentifiedKey 0x00002099 +#define CHINT_UnreachableKeyCode 0x0000109A + +#define CWARN_CouldNotCopyJsonFile 0x0000209B +#define CWARN_PlatformNotInTargets 0x0000209C + +#define CWARN_HeaderStatementIsDeprecated 0x0000209D +#define CWARN_UseNotLastStatementInRule 0x0000209E + +#define CWARN_TouchLayoutFontShouldBeSameForAllPlatforms 0x0000209F +#define CWARN_InvalidJSONMetadataFile 0x000020A0 +#define CWARN_JSONMetadataOSKFontShouldMatchTouchFont 0x000020A1 +#define CWARN_KVKFileIsInSourceFormat 0x000020A2 + +#define CWARN_DontMixChiralAndNonChiralModifiers 0x000020A3 +#define CWARN_MixingLeftAndRightModifiers 0x000020A4 + +#define CWARN_LanguageHeadersDeprecatedInKeyman10 0x000020A5 + +#define CHINT_NonUnicodeFile 0x000010A6 + +#define CWARN_TooManyErrorsOrWarnings 0x000020A7 + +#define CWARN_HotkeyHasInvalidModifier 0x000020A8 + +#define CWARN_TouchLayoutSpecialLabelOnNormalKey 0x000020A9 + +#define CWARN_OptionStoreNameInvalid 0x000020AA + +#define CWARN_NulNotFirstStatementInContext 0x000020AB +#define CWARN_IfShouldBeAtStartOfContext 0x000020AC + +#define CWARN_KeyShouldIncludeNCaps 0x000020AD + +#define CHINT_UnreachableRule 0x000010AE +#define CHINT_FilenameHasDifferingCase 0x000010AF +#define CWARN_MissingFile 0x000020B0 + +#define CERR_BufferOverflow 0x000080C0 +#define CERR_Break 0x000080C1 + +#endif // _COMPERR_H diff --git a/developer/src/kmcmplib/src/compfile.h b/developer/src/kmcmplib/src/compfile.h new file mode 100644 index 0000000000..48be5f2048 --- /dev/null +++ b/developer/src/kmcmplib/src/compfile.h @@ -0,0 +1,220 @@ +/* + Name: Compfile + Copyright: Copyright (C) SIL International. + Documentation: + Description: + Create Date: 25 Jan 2007 + + Modified Date: 25 May 2010 + Authors: mcdurdin + Related Files: + Dependencies: + + Bugs: + Todo: + Notes: + History: 25 Jan 2007 - mcdurdin - Add GLOBAL_BUFSIZE, enlarge LINESIZE + 25 May 2010 - mcdurdin - I1632 - Keyboard Options +*/ + +#ifndef _COMPFILE_H +#define _COMPFILE_H + +#include "kmcompx.h" +#include + +#define LINESIZE 8192 +#define GLOBAL_BUFSIZE 4096 + +#define SZMAX_STORENAME 80 +#define SZMAX_GROUPNAME 80 +#define SZMAX_DEADKEYNAME 80 +#define SZMAX_ERRORTEXT 512 +#define SZMAX_VKDICTIONARYNAME 80 + +#define MAX_WARNINGS 100 + +#define T_COMMENT 1 // A comment line +#define T_KEYTOKEY 2 // A rule line +#define T_BLANK 3 // A blank line + +#define T_W_START 4 // Start of easily matched line types +#define T_STORE 4 // A store line +#define T_VERSION 5 // A 'VERSION 3.2/3.1/3.0' line +#define T_NAME 6 // A 'NAME "xxxx"' line +#define T_BITMAP 7 // A 'BITMAP bmpfile' line +#define T_HOTKEY 8 // A 'HOTKEY "^%+C"' line +#define T_BEGIN 9 // A 'begin > use(xxxx)' line +#define T_GROUP 10 // A 'group(xxxx)' line +#define T_MATCH 11 // A 'match > "XXXX"' line +#define T_NOMATCH 12 // A 'nomatch > "XXXX"' line +#define T_SHIFT 13 // A 'SHIFT FREES CAPS' line +#define T_CAPSON 14 // A 'CAPS ON ONLY' line +#define T_CAPSOFF 15 // A 'CAPS ALWAYS OFF' line +#define T_LANGUAGE 16 // A 'LANGUAGE xxxh, xxh' line +#define T_LAYOUT 17 // A 'LAYOUT xxxxh' line +#define T_COPYRIGHT 18 // A 'COPYRIGHT "so and so"' line +#define T_MESSAGE 19 // A 'MESSAGE "so and so"' line +#define T_LANGUAGENAME 20 // A 'LANGUAGENAME "xxxx"' line +#define T_BITMAPS 21 // An unused 'BITMAPS' line (version 3.x) +#define T_W_END 21 // End of easily matched rule types + +#define T_UNKNOWN 99 // Unrecognized line type (illegal line) + +#define GDS_CUTLEAD 0x01 // GetDelimitedString: cut leading spaces +#define GDS_CUTFOLL 0x02 // GetDelimitedString: cut following spaces + +#define GXS_LINE 0x00 // GetExtendedString error: in a "line" +#define GXS_RULE 0x01 // GetExtendedString error: in a "rule" +#define GXS_STORE 0x02 // GetExtendedString error: in a "store" + +enum FileStoreType { FST_STORE, FST_OPTION, FST_RESERVED }; + +struct FILE_STORE { + KMX_DWORD dwSystemID; + KMX_WCHAR szName[SZMAX_STORENAME]; // the name of the store + PKMX_WCHAR dpString; // from start of store structure + //FileStoreType fstType; + KMX_BOOL fIsStore; + KMX_BOOL fIsReserved; + KMX_BOOL fIsOption; + KMX_BOOL fIsDebug; + KMX_BOOL fIsCall; + int line; + }; + +typedef FILE_STORE * PFILE_STORE; + + +struct FILE_KEY { + KMX_WCHAR Key; // WCHAR for consistency; only a byte used however + KMX_WORD LineStoreIndex; + KMX_DWORD Line; + KMX_DWORD ShiftFlags; + PKMX_WCHAR dpOutput; // from start of key structure + PKMX_WCHAR dpContext; // from start of key structure + }; +typedef FILE_KEY *PFILE_KEY; + + +struct FILE_GROUP { + KMX_WCHAR szName[SZMAX_GROUPNAME]; + PFILE_KEY dpKeyArray; // address of first item in key array, from start of group structure + PKMX_WCHAR dpMatch; // from start of group structure + PKMX_WCHAR dpNoMatch; // from start of group structure + KMX_DWORD cxKeyArray; // in array items + KMX_BOOL fUsingKeys; // group(xx) [using keys] <-- specified or not + KMX_BOOL fReadOnly; // group(xx) [readonly] <-- specified or not + KMX_DWORD Line; + }; +typedef FILE_GROUP *PFILE_GROUP; + +struct FILE_DEADKEY +{ + KMX_WCHAR szName[SZMAX_DEADKEYNAME]; +}; +typedef FILE_DEADKEY *PFILE_DEADKEY; + +struct FILE_VKDICTIONARY +{ + KMX_WCHAR szName[SZMAX_VKDICTIONARYNAME]; +}; +typedef FILE_VKDICTIONARY *PFILE_VKDICTIONARY; + +struct FILE_KEYBOARD { + KMX_DWORD KeyboardID; // as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts + + KMX_DWORD version; // keyboard file version with VERSION keyword + + PFILE_STORE dpStoreArray; // address of first item in store array, from start of store structure + PFILE_GROUP dpGroupArray; // address of first item in group array, from start of group structure + + KMX_DWORD cxStoreArray; // in number of items + KMX_DWORD cxGroupArray; // in number of items + KMX_DWORD StartGroup[2]; // index of starting groups [ANSI=0, Unicode=1] + + KMX_DWORD dwHotKey; // standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) + + KMX_WCHAR szName[SZMAX_KEYBOARDNAME]; // Keyboard layout name + KMX_WCHAR szLanguageName[SZMAX_LANGUAGENAME]; // Language name + KMX_WCHAR szCopyright[SZMAX_COPYRIGHT]; // Copyright information + KMX_WCHAR szMessage[SZMAX_MESSAGE]; // General information about the keyboard + PKMX_BYTE lpBitmap; + KMX_DWORD dwBitmapSize; + KMX_DWORD dwFlags; // Flags for the keyboard file + + KMX_DWORD currentGroup; // temp - current processing group + KMX_DWORD currentStore; // temp - current processing store + KMX_DWORD cxDeadKeyArray; + PFILE_DEADKEY dpDeadKeyArray; // temp - dead key array + KMX_DWORD cxVKDictionary; + PFILE_VKDICTIONARY dpVKDictionary; // temp - virtual key dictionary + }; + +typedef FILE_KEYBOARD *PFILE_KEYBOARD; + +/* +These size values are used in unit tests to ensure +that the structure sizes correspond precisely across +compilers (pas and c++). +*/ + +const KMX_DWORD sz_FILE_STORE = sizeof(FILE_STORE); +const KMX_DWORD sz_FILE_KEY = sizeof(FILE_KEY); +const KMX_DWORD sz_FILE_GROUP = sizeof(FILE_GROUP); +const KMX_DWORD sz_FILE_DEADKEY = sizeof(FILE_DEADKEY); +const KMX_DWORD sz_FILE_VKDICTIONARY = sizeof(FILE_VKDICTIONARY); +const KMX_DWORD sz_FILE_KEYBOARD = sizeof(FILE_KEYBOARD); + +struct COMPMSG { + KMX_CHAR szText[SZMAX_ERRORTEXT]; + KMX_DWORD Line; + KMX_DWORD dwMsgCode; + }; + +typedef COMPMSG *PCOMPMSG; + +struct COMPILEMESSAGES { + int nMessages; + int nErrors; + + PCOMPMSG cm; + + KMX_DWORD fatalCode; + KMX_CHAR szFatalText[SZMAX_ERRORTEXT]; + + KMX_DWORD currentLine; + }; + +typedef COMPILEMESSAGES *PCOMPILEMESSAGES; + +/* +struct TVersion +{ + //int MinVersion; // 0x0500 usually + //int CompilerVersion[4]; + //int MinCompilerVersion[4]; + int KeyboardVersion; // 0x0500 usually +}; + +extern TVersion FVersionInfo; +*/ + +/* +#define bstrcpy(c,d) (LPBYTE)strcpy((LPSTR)(c),(LPSTR)(d)) +#define bstrlen(c) strlen((LPSTR)(c)) +#define bstrcmp(c,d) strcmp((LPSTR)(c),(LPSTR)(d)) +#define bstrncmp(c,d,n) strncmp((LPSTR)(c),(LPSTR)(d),(n)) +#define bstrnicmp(c,d,n) strnicmp((LPSTR)(c),(LPSTR)(d),(n)) +#define bstricmp(c,d) stricmp((LPSTR)(c),(LPSTR)(d)) +#define bstrchr(c,ch) (LPBYTE)strchr((LPSTR)(c),(char)ch) +#define bstrncpy(c,d,n) (LPBYTE)strncpy((LPSTR)(c),(LPSTR)(d),(n)) +#define bstrtok(c,d) (LPBYTE)strtok((LPSTR)(c),(LPSTR)(d)) +#define bstrcat(c,d) (LPBYTE)strcat((LPSTR)(c),(LPSTR)(d)) +#define bstrncat(c,d,n) (LPBYTE)strncat((LPSTR)(c),(LPSTR)(d),(n)) +#define bstrrev(c) (LPBYTE)strrev((LPSTR)(c)) +#define batoi(c) atoi((LPSTR)(c)) +#define bstrtol(c,d,n) strtol((LPSTR)(c),(LPSTR *)(d),(n)) +*/ + +#endif // _COMPFILE_H diff --git a/developer/src/kmcmplib/src/debugstore.h b/developer/src/kmcmplib/src/debugstore.h new file mode 100644 index 0000000000..c54e3b45c3 --- /dev/null +++ b/developer/src/kmcmplib/src/debugstore.h @@ -0,0 +1,20 @@ + +#ifndef DEBUGSTORE_H +#define DEBUGSTORE_H + +#define DEBUGSTORE_BEGIN u"B" +#define DEBUGSTORE_BEGIN_C u'B' + +#define DEBUGSTORE_MATCH u"M" +#define DEBUGSTORE_MATCH_C u'M' + +#define DEBUGSTORE_NOMATCH u"N" +#define DEBUGSTORE_NOMATCH_C u'N' + +#define DEBUGSTORE_GROUP u"G" +#define DEBUGSTORE_GROUP_C u'G' + +#define DEBUGSTORE_DEADKEY u"D" +#define DEBUGSTORE_DEADKEY_C u'D' + +#endif /* DEBUGSTORE_H */ diff --git a/developer/src/kmcmplib/src/filesystem.cpp b/developer/src/kmcmplib/src/filesystem.cpp new file mode 100644 index 0000000000..aa1980cfdf --- /dev/null +++ b/developer/src/kmcmplib/src/filesystem.cpp @@ -0,0 +1,182 @@ + +#include +#include +#include "filesystem.h" + +#ifdef _MSC_VER +#include +#else +#include +#endif + +//#define _DEBUG_FOPEN 1 + +#ifdef __EMSCRIPTEN__ + +const std::string get_wasm_file_path(const std::string& filename) { + // Verify that we are passing a fully-qualified path + // TODO: we need to support relative paths based on CWD +#if _DEBUG_FOPEN + std::cout << "get_wasm_file_path ENTER (" << filename << ")" << std::endl; +#endif + + assert( + (filename.length() > 0 && filename.at(0) == '/') || + (filename.length() > 1 && filename.at(1) == ':') + ); + +#if _DEBUG_FOPEN + std::cout << "get_wasm_file_path assert passed " << std::endl; +#endif + + EM_ASM_({ + //console.log('EM_ASM enter'); + let path = Module.UTF8ToString($0); + const isWin32Path = path.match(/^[a-zA-Z]:/); + + //console.log('EM_ASM path = '+path); + let root = '/nodefs-mount'; + if(!FS.analyzePath(root).exists) { + //console.log('EM_ASM mkdir '+root); + FS.mkdir(root); + if(!isWin32Path) { + //console.log('EM_ASM mount '+root); + FS.mount(NODEFS, {root : '/'}, root); + } + } + + if(isWin32Path) { + // Win32 path, one mount per drive + root += "/" + path.charAt(0); + if(!FS.analyzePath(root).exists) { + //console.log('EM_ASM mkdir '+root); + FS.mkdir(root); + //console.log('EM_ASM mount '+root); + FS.mount(NODEFS, {root : path.substr(0,3) }, root); + } + } + }, filename.c_str()); + +#if _DEBUG_FOPEN + std::cout << "get_wasm_file_path EM_ASM_ passed " << std::endl; +#endif + + std::string f = std::string("/nodefs-mount"); + + if(filename.length() > 2 && filename.at(1) == ':') { + f += std::string("/") + filename.at(0) + filename.substr(2); + } else { + f += filename; + } + +#if _DEBUG_FOPEN + std::cout << "get_wasm_file_path opening virtual path: " << f << std::endl; +#endif + + return f; +} + +FILE* fopen_wasm(const std::string& filename, const std::string& mode) { + std::string f = get_wasm_file_path(filename); + FILE* fp = fopen(f.c_str(), mode.c_str()); + +#if _DEBUG_FOPEN + std::cout << "get_wasm_file_path fopen called, returned " << fp << std::endl; +#endif + + return fp; +} + +#endif + +#ifndef _MSC_VER +#ifdef __EMSCRIPTEN__ +#define fopen_wrapper fopen_wasm +#else +#define fopen_wrapper fopen +#endif +#endif + +FILE* Open_File(const KMX_CHAR* Filename, const KMX_CHAR* mode) { +#ifdef _MSC_VER + std::string cpath = Filename; //, cmode = mode; + std::replace(cpath.begin(), cpath.end(), '/', '\\'); + return fopen(cpath.c_str(), (const KMX_CHAR*) mode); +#else + return fopen_wrapper(Filename, mode); + std::string cpath, cmode; + cpath = (const KMX_CHAR*) Filename; + cmode = (const KMX_CHAR*) mode; + return fopen_wrapper(cpath.c_str(), cmode.c_str()); +#endif +}; + +FILE* Open_File(const KMX_WCHART* Filename, const KMX_WCHART* mode) { +#ifdef _MSC_VER + std::wstring cpath = Filename; //, cmode = mode; + std::replace(cpath.begin(), cpath.end(), '/', '\\'); + return _wfsopen(cpath.c_str(), mode, _SH_DENYWR); +#else + std::string cpath, cmode; + cpath = string_from_wstring(Filename); + cmode = string_from_wstring(mode); + return fopen_wrapper(cpath.c_str(), cmode.c_str()); +#endif +}; + +FILE* Open_File(const KMX_WCHAR* Filename, const KMX_WCHAR* mode) { +#ifdef _MSC_VER + std::wstring cpath = convert_pchar16T_To_wstr((KMX_WCHAR*) Filename); + std::wstring cmode = convert_pchar16T_To_wstr((KMX_WCHAR*) mode); + std::replace(cpath.begin(), cpath.end(), '/', '\\'); + return _wfsopen(cpath.c_str(), cmode.c_str(), _SH_DENYWR); +#else + std::string cpath, cmode; + cpath = string_from_u16string(Filename); + cmode = string_from_u16string(mode); + return fopen_wrapper(cpath.c_str(), cmode.c_str()); +#endif +}; + +KMX_BOOL kmcmp_FileExists(const KMX_CHAR *filename) { + +#ifdef _MSC_VER + intptr_t n; + _finddata_t fi; + if((n = _findfirst(filename, &fi)) != -1) { + _findclose(n); + return TRUE; + } +#else //!_MSC_VER + +#ifdef __EMSCRIPTEN__ + std::string f = get_wasm_file_path(filename); +#else //!__EMSCRIPTEN__ + std::string f = filename; +#endif // !__EMSCRIPTEN__ + + if(access(f.c_str(), F_OK) != -1) { + return TRUE; + } + +#endif // !_MSC_VER + + return FALSE; +} + +KMX_BOOL kmcmp_FileExists(const KMX_WCHAR* filename) { +#ifdef _MSC_VER + intptr_t n; + _wfinddata_t fi; + if((n = _wfindfirst((wchar_t*) filename, &fi)) != -1) { + _findclose(n); + return TRUE; + } +#else + std::string cpath; + cpath = string_from_u16string(filename); + return kmcmp_FileExists(cpath.c_str()); +#endif + + return FALSE; +}; diff --git a/developer/src/kmcmplib/src/filesystem.h b/developer/src/kmcmplib/src/filesystem.h new file mode 100644 index 0000000000..4fa134972c --- /dev/null +++ b/developer/src/kmcmplib/src/filesystem.h @@ -0,0 +1,20 @@ +#pragma once + +#ifdef __EMSCRIPTEN__ +#include +#include +#endif + +#include +#include +#include + +#include "kmx_u16.h" + +// Opens files on windows and non-windows platforms. Datatypes for Filename and mode must be the same. +// returns FILE* if file could be opened; FILE needs to be closed in calling function +FILE* Open_File(const KMX_CHAR* Filename, const KMX_CHAR* mode); +FILE* Open_File(const KMX_WCHART* Filename, const KMX_WCHART* mode); +FILE* Open_File(const KMX_WCHAR* Filename, const KMX_WCHAR* mode); +KMX_BOOL kmcmp_FileExists(const KMX_CHAR *filename); +KMX_BOOL kmcmp_FileExists(const KMX_WCHAR *filename); diff --git a/developer/src/kmcmplib/src/json-validation.cpp b/developer/src/kmcmplib/src/json-validation.cpp new file mode 100644 index 0000000000..b561e0b42f --- /dev/null +++ b/developer/src/kmcmplib/src/json-validation.cpp @@ -0,0 +1,68 @@ + +#include +#include + +#include +#include "kmcompx.h" + +using nlohmann::json; +using nlohmann::json_uri; +using nlohmann::json_schema_draft4::json_validator; + +static void loader(const json_uri &uri, json &schema) +{ + std::fstream lf("." + uri.path()); + if (!lf.good()) + throw std::invalid_argument("could not open " + uri.url() + " tried with " + uri.path()); + + lf >> schema; +} + +extern "C" bool kmcmp_ValidateJsonFile(std::fstream& f, std::fstream& fd, kmcmp_ValidateJsonMessageProc MessageProc, void* context) { + if (!f.good()) { + MessageProc(-1, "Schema file could not be loaded.", context); + return FALSE; + } + + // 1) Read the schema for the document you want to validate + json schema; + try { + f >> schema; + } + catch (std::exception &e) { + MessageProc(f.tellp(), e.what(), context); + return FALSE; + } + + // 2) create the validator and + json_validator validator(loader, [](const std::string &, const std::string &) {}); + + try { + // insert this schema as the root to the validator + // this resolves remote-schemas, sub-schemas and references via the given loader-function + validator.set_root_schema(schema); + } + catch (std::exception &e) { + MessageProc(-2, e.what(), context); + return FALSE; + } + + // 3) do the actual validation of the document + json document; + + if (!fd.good()) { + MessageProc(-3, "Json file could not be loaded.", context); + return FALSE; + } + + try { + fd >> document; + validator.validate(document); + } + catch (std::exception &e) { + MessageProc(fd.tellp(), e.what(), context); + return FALSE; + } + + return TRUE; +} \ No newline at end of file diff --git a/developer/src/kmcmplib/src/kmcmplib.h b/developer/src/kmcmplib/src/kmcmplib.h new file mode 100644 index 0000000000..896ed8e10a --- /dev/null +++ b/developer/src/kmcmplib/src/kmcmplib.h @@ -0,0 +1,21 @@ +#pragma once + +#include "compfile.h" + +namespace kmcmp { + KMX_BOOL AddCompileWarning(char* buf); + extern int currentLine; +} + +extern KMX_BOOL AWarnDeprecatedCode_GLOBAL_LIB; +extern char ErrExtraLIB[256]; +extern KMX_WCHAR ErrExtraW[256]; +KMX_BOOL AddCompileError(KMX_DWORD msg); + +// TODO: These macros can return FALSE in functions that expect a DWORD CERR_x +// return value type. This is just plain wrong! +#define SetError(err) { if(AddCompileError(err) || (err & CERR_FATAL)) return FALSE; } +#define AddWarning(warn) { if(AddCompileError(warn)) return FALSE; } + +PKMX_WCHAR strtowstr(PKMX_STR in); +PFILE_STORE FindSystemStore(PFILE_KEYBOARD fk, KMX_DWORD dwSystemID); diff --git a/developer/src/kmcmplib/src/kmx_u16.cpp b/developer/src/kmcmplib/src/kmx_u16.cpp new file mode 100644 index 0000000000..6162f532af --- /dev/null +++ b/developer/src/kmcmplib/src/kmx_u16.cpp @@ -0,0 +1,296 @@ + +//#include "../../kmcompx/include/kmcompx.h" +#include +#include "kmx_u16.h" + +#include +#include +#include +#include +#include +#include + +//String <- wstring +std::string string_from_wstring(std::wstring const str) { + std::wstring_convert, wchar_t> converter; + return converter.to_bytes(str); +} +//wstring <- string +std::wstring wstring_from_string(std::string const str) { + std::wstring_convert, wchar_t> converter; + return converter.from_bytes(str); +} + +//u16String <- string +std::u16string u16string_from_string(std::string const str) { + std::wstring_convert, char16_t> converter; + return converter.from_bytes(str); +} + +//string <- u16string +std::string string_from_u16string(std::u16string const str) { + std::wstring_convert, char16_t> converter; + return converter.to_bytes(str); +} + +// often used with c_str() e.g. u16fmt( DEBUGSTORE_MATCH).c_str() +// UTF16 (= const char16_t*) -> UTF8 (= std::string) -> UTF16 ( = std::wstring 16 bit) +std::wstring u16fmt(const KMX_WCHAR * str) { + std::wstring_convert, wchar_t> convert_wstring; + std::wstring_convert, char16_t> convert; + + // UTF16 (= const char16_t*) -> UTF8 (= std::string) -> UTF16 ( = std::wstring 16 bit) + std::string utf8str = convert.to_bytes(str); // UTF16 (= const char16_t*) -> UTF8 (= std::string) + std::wstring wstr = convert_wstring.from_bytes(utf8str); // UTF8 (= std::string) -> UTF16 ( = std::wstring 16 bit) + return wstr; +} + +void u16sprintf(KMX_WCHAR * dst, const size_t sz, const wchar_t* fmt, ...) { + // UTF16 (=const wchar_t*) -> -> std::string -> std::u16string -> UTF16 ( = char16_t*) + wchar_t* wbuf = new wchar_t[sz]; + va_list args; + va_start(args, fmt); + vswprintf(wbuf, sz, fmt, args); + va_end(args); + + std::wstring_convert, wchar_t> convert_wstring; + std::wstring_convert, char16_t> convert; + + // UTF16 (=const wchar_t*) -> -> std::string -> std::u16string -> UTF16 ( = char16_t*) + std::string utf8str = convert_wstring.to_bytes(wbuf); // UTF16 ( = const wchar_t*) -> std::string + std::u16string u16str = convert.from_bytes(utf8str); // std::string -> std::u16string + u16ncpy(dst, u16str.c_str(), sz); // std::u16string.c_str() -> char16_t* + delete[] wbuf; +} + + std::wstring convert_pchar16T_To_wstr(KMX_WCHAR *Name){ + // convert char16_t* -> std::u16string -> std::string -> std::wstring + // char16_t* -> std::u16string + std::u16string u16str(Name); + // std::u16string -> std::string + std::string stri = string_from_u16string(u16str); + // std::string -> std::wstring + std::wstring wstr = wstring_from_string(stri); + return wstr; + } + +long int u16tol(const KMX_WCHAR* str, KMX_WCHAR** endptr, int base) +{ + auto s = string_from_u16string(str); + char* t; + long int result = strtol(s.c_str(), &t, base); + if (endptr != nullptr) *endptr = (KMX_WCHAR*)str + (t - s.c_str()); + return result; +} + +std::string toHex(int num1) { + if (num1 == 0) + return "0"; + int num = num1; + std::string s = ""; + while (num) { + int temp = num % 16; + if (temp <= 9) + s += (48 + temp); + else + s += (87 + temp); + num = num / 16; + } + reverse(s.begin(), s.end()); + return s; +} + +const KMX_WCHAR * u16ncat(KMX_WCHAR *dst, const KMX_WCHAR *src, size_t max) { + KMX_WCHAR* o = dst; + dst = (KMX_WCHAR*) u16chr(dst, 0); + //max -= (dst-o); + while (*src && max > 0) { + *dst++ = *src++; + max--; + } + if(max > 0) + *dst = 0; + return o; +} + +const KMX_WCHAR* u16rchr_slash(KMX_WCHAR const* Name) +{ + const KMX_WCHAR* cp = NULL; + cp = u16rchr(Name, '\\'); + if (cp == NULL) + cp = u16rchr(Name, '/'); + return cp; +} + +KMX_CHAR* strrchr_slash(KMX_CHAR* Name) +{ + KMX_CHAR* cp = NULL; + cp = strrchr(Name, '\\'); + if (cp == NULL) + cp = strrchr(Name, '/'); + return cp; +} + +// u16rchr returns last occurence of ch in p; It returns NULL if ch = '\0' and NULL if ch is not found +const KMX_WCHAR* u16rchr(const KMX_WCHAR* p, KMX_WCHAR ch) { + const KMX_WCHAR* p_end = p + u16len(p) - 1; + + if (ch == '\0') return p_end + 1; + while (p_end >= p) { + if (*p_end == ch) return p_end; + p_end--; + } + return NULL; +} + +const KMX_WCHAR * u16chr(const KMX_WCHAR *p, KMX_WCHAR ch) { + while (*p) { + if (*p == ch) return p; + p++; + } + return ch == 0 ? p : NULL; +} + +const KMX_WCHAR * u16cpy(KMX_WCHAR *dst, const KMX_WCHAR *src) { + KMX_WCHAR *o = dst; + while (*src) { + *dst++ = *src++; + } + *dst = 0; + return o; +} + +const KMX_WCHAR * u16ncpy(KMX_WCHAR *dst, const KMX_WCHAR *src, size_t max) { + KMX_WCHAR *o = dst; + while (*src && max > 0) { + *dst++ = *src++; + max--; + } + while(max > 0) { + *dst++ = 0; + max--; + } + return o; +} + +size_t u16len(const KMX_WCHAR *p) { + int i = 0; + while (*p) { + p++; + i++; + } + return i; +} + +int u16cmp(const KMX_WCHAR *p, const KMX_WCHAR *q) { + while (*p && *q) { + if (*p != *q) return *p - *q; + p++; + q++; + } + return *p - *q; +} + +int u16nicmp(const KMX_WCHAR *p, const KMX_WCHAR *q, size_t count) { + while (*p && *q && count) { + if (toupper(*p) != toupper(*q)) return *p - *q; + p++; + q++; + count--; + } + if (count) + return *p - *q; + return 0; +} + +int u16icmp(const KMX_WCHAR *p, const KMX_WCHAR *q) { + while (*p && *q) { + if (toupper(*p) != toupper(*q)) return *p - *q; + p++; + q++; + } + return *p - *q; +} + +int u16ncmp(const KMX_WCHAR *p, const KMX_WCHAR *q, size_t count) { + while (*p && *q && count) { + if (*p != *q) return *p - *q; + p++; + q++; + count--; + } + if (count) + return *p - *q; + return 0; +} + +KMX_WCHAR * u16tok(KMX_WCHAR *p, KMX_WCHAR ch, KMX_WCHAR **ctx) { + if (!p) { + p = *ctx; + if (!p) return NULL; + } + + KMX_WCHAR *q = p; + while (*q && *q != ch) { + q++; + } + if (*q) { + *q = 0; + q++; + while (*q == ch) q++; + *ctx = q; + } + else { + *ctx = NULL; + } + return p; +} + +KMX_WCHAR * u16tok(KMX_WCHAR* p, KMX_WCHAR* delim, KMX_WCHAR** ctx) { + if (!p) { + p = *ctx; + if (!p) return NULL; + } + + KMX_WCHAR * q = p; + while (*q && !u16chr(delim, *q)) { + q++; + } + if (*q) { + *q = 0; + q++; + while (u16chr(delim, *q)) q++; + *ctx = q; + } + else { + *ctx = NULL; + } + return p; +} + +double u16tof( KMX_WCHAR* str) +{ + double val = 0; + int offsetdot=0; + char digit; + + PKMX_WCHAR q = (PKMX_WCHAR)u16chr(str, '.'); + int pos_dot = q-str ; + + if (pos_dot < 0) + pos_dot = u16len(str); + + for (int i = 0; i < u16len(str); i++) + { + digit = static_cast(towupper(*str)); + + if (i > pos_dot - 1) + offsetdot = 1; + + if (digit != '.') + val =val+ ((int(digit)) - 48) * pow(10, (pos_dot - 1- i + offsetdot)); + + str++; + } + return val; +} diff --git a/developer/src/kmcmplib/src/kmx_u16.h b/developer/src/kmcmplib/src/kmx_u16.h new file mode 100644 index 0000000000..99ad2006bb --- /dev/null +++ b/developer/src/kmcmplib/src/kmx_u16.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include +#include "kmcompx.h" + +std::string string_from_wstring(std::wstring const str); +std::wstring wstring_from_string(std::string const str); +std::u16string u16string_from_string(std::string const str); +std::string string_from_u16string(std::u16string const str); + +std::wstring u16fmt(const KMX_WCHAR * str); +void u16sprintf(KMX_WCHAR * dst, const size_t sz, const wchar_t* fmt, ...) ; + +std::wstring convert_pchar16T_To_wstr(KMX_WCHAR *Name); + +size_t u16len(const KMX_WCHAR *p); +int u16cmp(const KMX_WCHAR *p, const KMX_WCHAR *q); +int u16icmp(const KMX_WCHAR *p, const KMX_WCHAR *q); +int u16ncmp(const KMX_WCHAR *p, const KMX_WCHAR *q, size_t count); +int u16nicmp(const KMX_WCHAR *p, const KMX_WCHAR *q, size_t count) ; +const KMX_WCHAR * u16ncpy(KMX_WCHAR *dst, const KMX_WCHAR *src, size_t max); +const KMX_WCHAR * u16cpy(KMX_WCHAR *dst, const KMX_WCHAR *src); +const KMX_WCHAR * u16rchr(const KMX_WCHAR *p, KMX_WCHAR ch) ; +const KMX_WCHAR * u16chr(const KMX_WCHAR *p, KMX_WCHAR ch) ; +const KMX_WCHAR * u16ncat(KMX_WCHAR *dst, const KMX_WCHAR *src, size_t max); +KMX_WCHAR * u16tok(KMX_WCHAR *p, KMX_WCHAR ch, KMX_WCHAR **ctx) ; +KMX_WCHAR * u16tok(KMX_WCHAR* p, KMX_WCHAR* ch, KMX_WCHAR** ctx) ; +long int u16tol(const KMX_WCHAR* str, KMX_WCHAR** endptr, int base) ; +double u16tof( KMX_WCHAR* str); + +KMX_CHAR* strrchr_slash(KMX_CHAR* Name); +const KMX_WCHAR* u16rchr_slash(KMX_WCHAR const* Name); + +std::string toHex(int num1); diff --git a/developer/src/kmcmplib/src/meson.build b/developer/src/kmcmplib/src/meson.build new file mode 100644 index 0000000000..66504785e0 --- /dev/null +++ b/developer/src/kmcmplib/src/meson.build @@ -0,0 +1,71 @@ +# +# Keyman is copyright (C) SIL International. MIT License. +# +# Cross platform build script to compile kmcompx +# + +# TODO: is this required? It should be Keyman Core only +defns += ['-DKMN_KBP_EXPORTING'] +version_res = [] + +if cpp_compiler.get_id() == 'gcc' or cpp_compiler.get_id() == 'clang' + warns += [ + '-Wall', + '-Wextra' + ] +endif + +if cpp_compiler.get_id() == 'msvc' + # /n = append null + # /c65001 = utf-8 file format + version_res += import('windows').compile_resources('version.rc', args:['/n','/c65001']) +endif + +if cpp_compiler.get_id() == 'emscripten' + links += ['-lnodefs.js', '-sEXPORTED_RUNTIME_METHODS=[\'UTF8ToString\']'] +endif + + +lib = library('kmcmplib', + 'CasedKeys.cpp', + 'CharToKeyConversion.cpp', + 'Compiler.cpp', + 'DeprecationChecks.cpp', + 'Edition.cpp', + 'filesystem.cpp', + 'json-validation.cpp', + 'NamedCodeConstants.cpp', + 'versioning.cpp', + 'virtualcharkeys.cpp', + 'xstring.cpp', + 'CharToKeyConversion.cpp', + 'CheckFilenameConsistency.cpp', + 'CheckForDuplicates.cpp', + 'CheckNCapsConsistency.cpp', + 'UnreachableRules.cpp', + 'kmx_u16.cpp', + 'CompMsg.cpp', + + '../../../../common/windows/cpp/src/ConvertUTF.c', + '../../../../common/windows/cpp/src/crc32.cpp', + '../../../../common/windows/cpp/src/vkeys.cpp', + 'xstring.cpp', + + '../../ext/json-schema-validator/json-schema-draft4.json.cpp', + '../../ext/json-schema-validator/json-uri.cpp', + '../../ext/json-schema-validator/json-validator.cpp', + version_res, + cpp_args: defns + warns + flags, + link_args: links, + version: meson.project_version(), + include_directories: inc, + install: true) + +kmcmplib = declare_dependency(link_with: lib, include_directories: inc) + +pkg = import('pkgconfig') +pkg.generate( + name: 'keyman_kmn_compiler', + version: meson.project_version(), + description: 'Keyman compiler for KMN keyboards.', + libraries: lib) diff --git a/developer/src/kmcmplib/src/pch.cpp b/developer/src/kmcmplib/src/pch.cpp new file mode 100644 index 0000000000..17305716aa --- /dev/null +++ b/developer/src/kmcmplib/src/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" \ No newline at end of file diff --git a/developer/src/kmcmplib/src/pch.h b/developer/src/kmcmplib/src/pch.h new file mode 100644 index 0000000000..f878ad11be --- /dev/null +++ b/developer/src/kmcmplib/src/pch.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#define USE_CHAR16_T +#include +#include "kmx_u16.h" +#include + +#include "../../../../common/windows/cpp/include/crc32.h" + +#include +#include + +#include diff --git a/developer/src/kmcmplib/src/version.rc b/developer/src/kmcmplib/src/version.rc new file mode 100644 index 0000000000..685b3ff8e4 --- /dev/null +++ b/developer/src/kmcmplib/src/version.rc @@ -0,0 +1,32 @@ +#include "../../../../common/windows/cpp/include/keymanversion.h" + +1 VERSIONINFO + FILEVERSION KV_FILEVERSION + PRODUCTVERSION KV_PRODUCTVERSION + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "0C0904E4" + BEGIN + VALUE "CompanyName", KV_COMPANY_NAME + VALUE "FileDescription", "Keyman compiler library\0" + VALUE "FileVersion", KV_VERSION_STRING + VALUE "InternalName", "KMCOMP\0" + VALUE "LegalCopyright", KV_LEGAL_COPYRIGHT + VALUE "LegalTrademarks", KV_LEGAL_TRADEMARKS + VALUE "OriginalFilename", "KMCOMP.DLL\0" + VALUE "ProductName", "Keyman Developer\0" + VALUE "ProductVersion", KV_VERSION_STRING + VALUE "Comments", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0xc09, 1252 + END + END diff --git a/developer/src/kmcmplib/src/versioning.cpp b/developer/src/kmcmplib/src/versioning.cpp new file mode 100644 index 0000000000..df85aafd5a --- /dev/null +++ b/developer/src/kmcmplib/src/versioning.cpp @@ -0,0 +1,34 @@ +#include "pch.h" +#include "compfile.h" +#include +#include "kmcmplib.h" +#include "versioning.h" + +KMX_BOOL kmcmp::CheckKeyboardFinalVersion(PFILE_KEYBOARD fk) { + KMX_CHAR buf[128]; + + if (fk->dwFlags & KF_AUTOMATICVERSION) { + if (fk->version <= 0) { + fk->version = VERSION_60; // minimum version that we can be safe with + } + + sprintf(buf, "The compiler has assigned a minimum engine version of %d.%d based on features used in this keyboard", (int)((fk->version & 0xFF00) >> 8), (int)(fk->version & 0xFF)); + AddCompileWarning(buf); + } + + return TRUE; +} + +// Note: max is not a standard c api function or macro +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +KMX_BOOL VerifyKeyboardVersion(PFILE_KEYBOARD fk, KMX_DWORD ver) { + if (fk->dwFlags & KF_AUTOMATICVERSION) { + fk->version = max(fk->version, ver); + return TRUE; + } + + return fk->version >= ver; +} diff --git a/developer/src/kmcmplib/src/versioning.h b/developer/src/kmcmplib/src/versioning.h new file mode 100644 index 0000000000..a3a1c597bf --- /dev/null +++ b/developer/src/kmcmplib/src/versioning.h @@ -0,0 +1,15 @@ +#pragma once + +#include "compfile.h" +#include "../../../../common/include/km_types.h" + +#define VERIFY_KEYBOARD_VERSION(fk, ver, err) { \ + if(!VerifyKeyboardVersion((fk), (ver))) \ + return (err); \ +} + +namespace kmcmp { + KMX_BOOL CheckKeyboardFinalVersion(PFILE_KEYBOARD fk); +} + +KMX_BOOL VerifyKeyboardVersion(PFILE_KEYBOARD fk, KMX_DWORD ver); diff --git a/developer/src/kmcmplib/src/virtualcharkeys.cpp b/developer/src/kmcmplib/src/virtualcharkeys.cpp new file mode 100644 index 0000000000..eaef45aac4 --- /dev/null +++ b/developer/src/kmcmplib/src/virtualcharkeys.cpp @@ -0,0 +1,274 @@ +#include "pch.h" +#include "virtualcharkeys.h" + +KMX_BOOL VKeyMayBeVCKey[256] = { + FALSE, // L"K_?00", // &H0 + FALSE, // L"K_LBUTTON", // &H1 + FALSE, // L"K_RBUTTON", // &H2 + FALSE, // L"K_CANCEL", // &H3 + FALSE, // L"K_MBUTTON", // &H4 + FALSE, // L"K_?05", // &H5 + FALSE, // L"K_?06", // &H6 + FALSE, // L"K_?07", // &H7 + FALSE, // L"K_BKSP", // &H8 + FALSE, // L"K_TAB", // &H9 + FALSE, // L"K_?0A", // &HA + FALSE, // L"K_?0B", // &HB + FALSE, // L"K_KP5", // &HC + FALSE, // L"K_ENTER", // &HD + FALSE, // L"K_?0E", // &HE + FALSE, // L"K_?0F", // &HF + FALSE, // L"K_SHIFT", // &H10 + FALSE, // L"K_CONTROL", // &H11 + FALSE, // L"K_ALT", // &H12 + FALSE, // L"K_PAUSE", // &H13 + FALSE, // L"K_CAPS", // &H14 + FALSE, // L"K_KANJI?15", // &H15 + FALSE, // L"K_KANJI?16", // &H16 + FALSE, // L"K_KANJI?17", // &H17 + FALSE, // L"K_KANJI?18", // &H18 + FALSE, // L"K_KANJI?19", // &H19 + FALSE, // L"K_?1A", // &H1A + FALSE, // L"K_ESC", // &H1B + FALSE, // L"K_KANJI?1C", // &H1C + FALSE, // L"K_KANJI?1D", // &H1D + FALSE, // L"K_KANJI?1E", // &H1E + FALSE, // L"K_KANJI?1F", // &H1F + TRUE, // L"K_SPACE", // &H20 + FALSE, // L"K_PGUP", // &H21 + FALSE, // L"K_PGDN", // &H22 + FALSE, // L"K_END", // &H23 + FALSE, // L"K_HOME", // &H24 + FALSE, // L"K_LEFT", // &H25 + FALSE, // L"K_UP", // &H26 + FALSE, // L"K_RIGHT", // &H27 + FALSE, // L"K_DOWN", // &H28 + FALSE, // L"K_SEL", // &H29 + FALSE, // L"K_PRINT", // &H2A + FALSE, // L"K_EXEC", // &H2B + FALSE, // L"K_PRTSCN", // &H2C + FALSE, // L"K_INS", // &H2D + FALSE, // L"K_DEL", // &H2E + FALSE, // L"K_HELP", // &H2F + TRUE, // L"K_0", // &H30 + TRUE, // L"K_1", // &H31 + TRUE, // L"K_2", // &H32 + TRUE, // L"K_3", // &H33 + TRUE, // L"K_4", // &H34 + TRUE, // L"K_5", // &H35 + TRUE, // L"K_6", // &H36 + TRUE, // L"K_7", // &H37 + TRUE, // L"K_8", // &H38 + TRUE, // L"K_9", // &H39 + FALSE, // L"K_?3A", // &H3A + FALSE, // L"K_?3B", // &H3B + FALSE, // L"K_?3C", // &H3C + FALSE, // L"K_?3D", // &H3D + FALSE, // L"K_?3E", // &H3E + FALSE, // L"K_?3F", // &H3F + FALSE, // L"K_?40", // &H40 + + TRUE, // L"K_A", // &H41 + TRUE, // L"K_B", // &H42 + TRUE, // L"K_C", // &H43 + TRUE, // L"K_D", // &H44 + TRUE, // L"K_E", // &H45 + TRUE, // L"K_F", // &H46 + TRUE, // L"K_G", // &H47 + TRUE, // L"K_H", // &H48 + TRUE, // L"K_I", // &H49 + TRUE, // L"K_J", // &H4A + TRUE, // L"K_K", // &H4B + TRUE, // L"K_L", // &H4C + TRUE, // L"K_M", // &H4D + TRUE, // L"K_N", // &H4E + TRUE, // L"K_O", // &H4F + TRUE, // L"K_P", // &H50 + TRUE, // L"K_Q", // &H51 + TRUE, // L"K_R", // &H52 + TRUE, // L"K_S", // &H53 + TRUE, // L"K_T", // &H54 + TRUE, // L"K_U", // &H55 + TRUE, // L"K_V", // &H56 + TRUE, // L"K_W", // &H57 + TRUE, // L"K_X", // &H58 + TRUE, // L"K_Y", // &H59 + TRUE, // L"K_Z", // &H5A + FALSE, // L"K_?5B", // &H5B + FALSE, // L"K_?5C", // &H5C + FALSE, // L"K_?5D", // &H5D + FALSE, // L"K_?5E", // &H5E + FALSE, // L"K_?5F", // &H5F + FALSE, // L"K_NP0", // &H60 + FALSE, // L"K_NP1", // &H61 + FALSE, // L"K_NP2", // &H62 + FALSE, // L"K_NP3", // &H63 + FALSE, // L"K_NP4", // &H64 + FALSE, // L"K_NP5", // &H65 + FALSE, // L"K_NP6", // &H66 + FALSE, // L"K_NP7", // &H67 + FALSE, // L"K_NP8", // &H68 + FALSE, // L"K_NP9", // &H69 + FALSE, // L"K_NPSTAR", // &H6A + FALSE, // L"K_NPPLUS", // &H6B + FALSE, // L"K_SEPARATOR", // &H6C + FALSE, // L"K_NPMINUS", // &H6D + FALSE, // L"K_NPDOT", // &H6E + FALSE, // L"K_NPSLASH", // &H6F + FALSE, // L"K_F1", // &H70 + FALSE, // L"K_F2", // &H71 + FALSE, // L"K_F3", // &H72 + FALSE, // L"K_F4", // &H73 + FALSE, // L"K_F5", // &H74 + FALSE, // L"K_F6", // &H75 + FALSE, // L"K_F7", // &H76 + FALSE, // L"K_F8", // &H77 + FALSE, // L"K_F9", // &H78 + FALSE, // L"K_F10", // &H79 + FALSE, // L"K_F11", // &H7A + FALSE, // L"K_F12", // &H7B + FALSE, // L"K_F13", // &H7C + FALSE, // L"K_F14", // &H7D + FALSE, // L"K_F15", // &H7E + FALSE, // L"K_F16", // &H7F + FALSE, // L"K_F17", // &H80 + FALSE, // L"K_F18", // &H81 + FALSE, // L"K_F19", // &H82 + FALSE, // L"K_F20", // &H83 + FALSE, // L"K_F21", // &H84 + FALSE, // L"K_F22", // &H85 + FALSE, // L"K_F23", // &H86 + FALSE, // L"K_F24", // &H87 + + FALSE, // L"K_?88", // &H88 + FALSE, // L"K_?89", // &H89 + FALSE, // L"K_?8A", // &H8A + FALSE, // L"K_?8B", // &H8B + FALSE, // L"K_?8C", // &H8C + FALSE, // L"K_?8D", // &H8D + FALSE, // L"K_?8E", // &H8E + FALSE, // L"K_?8F", // &H8F + + FALSE, // L"K_NUMLOCK", // &H90 + FALSE, // L"K_SCROLL", // &H91 + + FALSE, // L"K_?92", // &H92 + FALSE, // L"K_?93", // &H93 + FALSE, // L"K_?94", // &H94 + FALSE, // L"K_?95", // &H95 + FALSE, // L"K_?96", // &H96 + FALSE, // L"K_?97", // &H97 + FALSE, // L"K_?98", // &H98 + FALSE, // L"K_?99", // &H99 + FALSE, // L"K_?9A", // &H9A + FALSE, // L"K_?9B", // &H9B + FALSE, // L"K_?9C", // &H9C + FALSE, // L"K_?9D", // &H9D + FALSE, // L"K_?9E", // &H9E + FALSE, // L"K_?9F", // &H9F + FALSE, // L"K_?A0", // &HA0 + FALSE, // L"K_?A1", // &HA1 + FALSE, // L"K_?A2", // &HA2 + FALSE, // L"K_?A3", // &HA3 + FALSE, // L"K_?A4", // &HA4 + FALSE, // L"K_?A5", // &HA5 + FALSE, // L"K_?A6", // &HA6 + FALSE, // L"K_?A7", // &HA7 + FALSE, // L"K_?A8", // &HA8 + FALSE, // L"K_?A9", // &HA9 + FALSE, // L"K_?AA", // &HAA + FALSE, // L"K_?AB", // &HAB + FALSE, // L"K_?AC", // &HAC + FALSE, // L"K_?AD", // &HAD + FALSE, // L"K_?AE", // &HAE + FALSE, // L"K_?AF", // &HAF + FALSE, // L"K_?B0", // &HB0 + FALSE, // L"K_?B1", // &HB1 + FALSE, // L"K_?B2", // &HB2 + FALSE, // L"K_?B3", // &HB3 + FALSE, // L"K_?B4", // &HB4 + FALSE, // L"K_?B5", // &HB5 + FALSE, // L"K_?B6", // &HB6 + FALSE, // L"K_?B7", // &HB7 + FALSE, // L"K_?B8", // &HB8 + FALSE, // L"K_?B9", // &HB9 + + TRUE, // L"K_COLON", // &HBA + TRUE, // L"K_EQUAL", // &HBB + TRUE, // L"K_COMMA", // &HBC + TRUE, // L"K_HYPHEN", // &HBD + TRUE, // L"K_PERIOD", // &HBE + TRUE, // L"K_SLASH", // &HBF + TRUE, // L"K_BKQUOTE", // &HC0 + + TRUE, // L"K_?C1", // &HC1 -- 103rd key on Brazilian - /? + FALSE, // L"K_?C2", // &HC2 -- 104th key on Brazilian - numpad . + FALSE, // L"K_?C3", // &HC3 + FALSE, // L"K_?C4", // &HC4 + FALSE, // L"K_?C5", // &HC5 + FALSE, // L"K_?C6", // &HC6 + FALSE, // L"K_?C7", // &HC7 + FALSE, // L"K_?C8", // &HC8 + FALSE, // L"K_?C9", // &HC9 + FALSE, // L"K_?CA", // &HCA + FALSE, // L"K_?CB", // &HCB + FALSE, // L"K_?CC", // &HCC + FALSE, // L"K_?CD", // &HCD + FALSE, // L"K_?CE", // &HCE + FALSE, // L"K_?CF", // &HCF + FALSE, // L"K_?D0", // &HD0 + FALSE, // L"K_?D1", // &HD1 + FALSE, // L"K_?D2", // &HD2 + FALSE, // L"K_?D3", // &HD3 + FALSE, // L"K_?D4", // &HD4 + FALSE, // L"K_?D5", // &HD5 + FALSE, // L"K_?D6", // &HD6 + FALSE, // L"K_?D7", // &HD7 + FALSE, // L"K_?D8", // &HD8 + FALSE, // L"K_?D9", // &HD9 + FALSE, // L"K_?DA", // &HDA + + TRUE, // L"K_LBRKT", // &HDB + TRUE, // L"K_BKSLASH", // &HDC + TRUE, // L"K_RBRKT", // &HDD + TRUE, // L"K_QUOTE", // &HDE + TRUE, // L"K_oDF", // &HDF + TRUE, // L"K_oE0", // &HE0 + TRUE, // L"K_oE1", // &HE1 + TRUE, // L"K_oE2", // &HE2 + TRUE, // L"K_oE3", // &HE3 + TRUE, // L"K_oE4", // &HE4 + + FALSE, // L"K_?E5", // &HE5 + + TRUE, // L"K_oE6", // &HE6 + + FALSE, // L"K_?E7", // &HE7 + FALSE, // L"K_?E8", // &HE8 + + TRUE, // L"K_oE9", // &HE9 + TRUE, // L"K_oEA", // &HEA + TRUE, // L"K_oEB", // &HEB + TRUE, // L"K_oEC", // &HEC + TRUE, // L"K_oED", // &HED + TRUE, // L"K_oEE", // &HEE + TRUE, // L"K_oEF", // &HEF + TRUE, // L"K_oF0", // &HF0 + TRUE, // L"K_oF1", // &HF1 + TRUE, // L"K_oF2", // &HF2 + TRUE, // L"K_oF3", // &HF3 + TRUE, // L"K_oF4", // &HF4 + TRUE, // L"K_oF5", // &HF5 + + FALSE, // L"K_?F6", // &HF6 + FALSE, // L"K_?F7", // &HF7 + FALSE, // L"K_?F8", // &HF8 + FALSE, // L"K_?F9", // &HF9 + FALSE, // L"K_?FA", // &HFA + FALSE, // L"K_?FB", // &HFB + FALSE, // L"K_?FC", // &HFC + FALSE, // L"K_?FD", // &HFD + FALSE, // L"K_?FE", // &HFE + FALSE, // L"K_?FF" // &HFF + }; + diff --git a/developer/src/kmcmplib/src/virtualcharkeys.h b/developer/src/kmcmplib/src/virtualcharkeys.h new file mode 100644 index 0000000000..539c5c5d40 --- /dev/null +++ b/developer/src/kmcmplib/src/virtualcharkeys.h @@ -0,0 +1,7 @@ +#ifndef _VIRTUALCHARKEYS_H +#define _VIRTUALCHARKEYS_H + +extern KMX_BOOL VKeyMayBeVCKey[256]; + +#endif + diff --git a/developer/src/kmcmplib/src/xstring.cpp b/developer/src/kmcmplib/src/xstring.cpp new file mode 100644 index 0000000000..870e991656 --- /dev/null +++ b/developer/src/kmcmplib/src/xstring.cpp @@ -0,0 +1,152 @@ + +#include "pch.h" +#include "xstring.h" +// used to be windows/src/global/vc/xstring.cpp +/* +* int xstrlen( PKMX_BYTE p ); +* +* Parameters: p Pointer to string to get length of +* +* Returns: length of string +* +* Called by: various functions +* +* xstrlen calculates the length of a string, ignoring some special chars. +*/ +PKMX_WCHAR incxstr(PKMX_WCHAR p) { + + if (*p == 0) + return p; + if (*p != UC_SENTINEL) { + if (*p >= 0xD800 && *p <= 0xDBFF && *(p + 1) >= 0xDC00 && *(p + 1) <= 0xDFFF) + return p + 2; + return p + 1; + } + // UC_SENTINEL(FFFF) with UC_SENTINEL_EXTENDEDEND(0x10) == variable length + if (*(p + 1) == CODE_EXTENDED) { + p += 2; + while (*p && *p != UC_SENTINEL_EXTENDEDEND) + p++; + + if (*p == 0) return p; + return p + 1; + } + + if (*(p + 1) > CODE_LASTCODE || CODE__SIZE[*(p + 1)] == -1) { + return p + 1; + } + + int deltaptr = 2 + CODE__SIZE[*(p + 1)]; + + // check for \0 between UC_SENTINEL(FFFF) and next printable character + for (int i = 0; i < deltaptr; i++) { + if (*p == 0) + return p; + p++; + } + return p; +} + +PKMX_WCHAR decxstr(PKMX_WCHAR p, PKMX_WCHAR pStart) +{ + PKMX_WCHAR q; + + if(p <= pStart) { + return NULL; + } + + p--; + if(*p == UC_SENTINEL_EXTENDEDEND) { + int n = 0; + while (p > pStart && *p != UC_SENTINEL && n < 10) { + p--; + n++; + } + + return p; + } + + if (p == pStart) { + // Don't allow test before pStart + return p; + } + + if(*p >= 0xDC00 && *p <= 0xDFFF && *(p-1) >= 0xD800 && *(p-1) <= 0xDBFF) { + return p-1; + } + + // Look for a UC_SENTINEL to jump to + // note: If we are pointing to the middle of a UC_SENTINEL CODE_x, then we won't treat it as valid, + // and will just go back a single wchar + q = p; + for (int i = 0; i < CODE__SIZE_MAX && q >= pStart; i++, q--) { + // *q == UC_SENTINEL && *(q + 1) is within CODE__SIZE && next CODE_ right of UC_SENTINEL ( looked up in CODE__SIZE+1) has value i + if (*q == UC_SENTINEL && *(q + 1) <= CODE_LASTCODE && CODE__SIZE[*(q + 1)] + 1 == i) + return q; + } + + return p; +} + +int xstrlen_ignoreifopt(PKMX_WCHAR p) +{ + int i; + for(i = 0; *p; i++, p=incxstr(p)) + { + if(*p == UC_SENTINEL && (*(p+1) == CODE_IFOPT || *(p+1) == CODE_IFSYSTEMSTORE)) i--; // I3432 + } + return i; +} + +int xstrlen(PKMX_WCHAR p) +{ + int i; + for(i = 0; *p; i++, p=incxstr(p)); + return i; +} + +int xstrpos(PKMX_WCHAR p1, PKMX_WCHAR p) +{ + int i; + for(i = 0; p < p1; p = incxstr(p), i++); + return i; +} + +PKMX_WCHAR xstrchr(PKMX_WCHAR buf, PKMX_WCHAR chr) +{ + for(PKMX_WCHAR q = incxstr(buf); *buf; buf = q, q = incxstr(buf)) + if(!u16ncmp(buf, chr, (intptr_t)(q-buf))) + return buf; + return NULL; +} + +const int CODE__SIZE[] = { + -1, // undefined 0x00 + 1, // CODE_ANY 0x01 + 2, // CODE_INDEX 0x02 + 0, // CODE_CONTEXT 0x03 + 0, // CODE_NUL 0x04 + 1, // CODE_USE 0x05 + 0, // CODE_RETURN 0x06 + 0, // CODE_BEEP 0x07 + 1, // CODE_DEADKEY 0x08 + -1, // unused 0x09 + 2, // CODE_EXTENDED 0x0A + -1, // CODE_EXTENDEDEND 0x0B (unused) + 1, // CODE_SWITCH 0x0C + -1, // CODE_KEY 0x0D (never used) + 0, // CODE_CLEARCONTEXT 0x0E + 1, // CODE_CALL 0x0F + -1, // UC_SENTINEL_EXTENDEDEND 0x10 (not valid with UC_SENTINEL) + 1, // CODE_CONTEXTEX 0x11 + 1, // CODE_NOTANY 0x12 + 2, // CODE_SETOPT 0x13 + 3, // CODE_IFOPT 0x14 + 1, // CODE_SAVEOPT 0x15 + 1, // CODE_RESETOPT 0x16 + 3, // CODE_IFSYSTEMSTORE 0x17 + 2 // CODE_SETSYSTEMSTORE 0x18 +}; + +// Ensure that all CODE_### sizes are defined +static_assert(sizeof(CODE__SIZE) / sizeof(CODE__SIZE[0]) == (CODE_LASTCODE + 1), "Size of array CODE__SIZE not correct"); diff --git a/developer/src/kmcmplib/src/xstring.h b/developer/src/kmcmplib/src/xstring.h new file mode 100644 index 0000000000..ae08cfe64a --- /dev/null +++ b/developer/src/kmcmplib/src/xstring.h @@ -0,0 +1,15 @@ +// TODO: merge with xstring.h from common +#pragma once +#ifndef XSTRING_H +#define SXTRING_H +#include + +KMX_UCHAR* incxstr(KMX_UCHAR* p); +KMX_UCHAR* decxstr(KMX_UCHAR* p, KMX_UCHAR* pStart); +int xstrlen(KMX_UCHAR* p); +int xstrlen_ignoreifopt(KMX_UCHAR* p); +int xstrpos(KMX_UCHAR* p1, KMX_UCHAR* p); +KMX_UCHAR* xstrchr(KMX_UCHAR* buf, KMX_UCHAR* chr); +int xchrcmp(KMX_UCHAR* ch1, KMX_UCHAR* ch2); + +#endif // XSTRING_H diff --git a/developer/src/kmcmplib/tests/README.md b/developer/src/kmcmplib/tests/README.md new file mode 100644 index 0000000000..367c1f9685 --- /dev/null +++ b/developer/src/kmcmplib/tests/README.md @@ -0,0 +1,30 @@ +# Unit tests for kmcmplib + +kmcmplib tests include building all keyboards in the keyboards repository and +comparing against a 'known good' legacy compiler set. This is trickier than it +sounds because the legacy compiler only runs under Windows/WINE and we don't +want to introduce a dependency on that for running the tests. + +Instead we've gone the route of adding a pre-compiled set of .kmx fixtures, +alongside a commit ref in keyboards_commit_ref.txt. The test script will +checkout that specific ref in its own private clone of the keyboards repository +(including a shallow clone of the keyboards repo if it isn't already present), +and compiling the sources from that specific commit. + +For performance reasons, it is useful to setup KEYBOARDS_ROOT env var to point +to your local clone of the keyboards repository. The build will make a private +clone of this repo rather than the remote clone if it is available, which is +typically much faster. + +# Preparing fixtures + +prep.sh allows us to regenerate the fixtures with the legacy compiler for +testing. It depends on the regression test scripts in keyboards.sh, and specific +changes introduced into those scripts in +https://github.com/keymanapp/keyboards/pull/2169. + +It is essential that the keyboards repository is clean and checked out to the +commit that you want to be using (usually this will be HEAD of master). All of +Keyman Developer must be built locally and binaries should be in developer/bin/. + +prep.sh has only been tested on Windows, because it relies on kmcomp.exe. diff --git a/developer/src/kmcmplib/tests/fixtures/adiga_danef.kmx b/developer/src/kmcmplib/tests/fixtures/adiga_danef.kmx new file mode 100644 index 0000000000..022254f30c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/adiga_danef.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/ahom_star.kmx b/developer/src/kmcmplib/tests/fixtures/ahom_star.kmx new file mode 100644 index 0000000000..bb4a25dc3e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/ahom_star.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/aksarabali_panlex.kmx b/developer/src/kmcmplib/tests/fixtures/aksarabali_panlex.kmx new file mode 100644 index 0000000000..8ef0107686 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/aksarabali_panlex.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/alephwithbeth.kmx b/developer/src/kmcmplib/tests/fixtures/alephwithbeth.kmx new file mode 100644 index 0000000000..2e2140a47d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/alephwithbeth.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/anii.kmx b/developer/src/kmcmplib/tests/fixtures/anii.kmx new file mode 100644 index 0000000000..b7364fc649 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/anii.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/arabic_izza.kmx b/developer/src/kmcmplib/tests/fixtures/arabic_izza.kmx new file mode 100644 index 0000000000..c573fecd20 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/arabic_izza.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/aramaic_hebrew.kmx b/developer/src/kmcmplib/tests/fixtures/aramaic_hebrew.kmx new file mode 100644 index 0000000000..583078c418 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/aramaic_hebrew.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/armenian_mnemonic.kmx b/developer/src/kmcmplib/tests/fixtures/armenian_mnemonic.kmx new file mode 100644 index 0000000000..8010790e3d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/armenian_mnemonic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/armenian_mnemonic_r.kmx b/developer/src/kmcmplib/tests/fixtures/armenian_mnemonic_r.kmx new file mode 100644 index 0000000000..d54f85abee Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/armenian_mnemonic_r.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/athinkra_vai.kmx b/developer/src/kmcmplib/tests/fixtures/athinkra_vai.kmx new file mode 100644 index 0000000000..127914ffe5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/athinkra_vai.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/athinkra_vai_typewriter.kmx b/developer/src/kmcmplib/tests/fixtures/athinkra_vai_typewriter.kmx new file mode 100644 index 0000000000..cab129cf0b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/athinkra_vai_typewriter.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/ausephon.kmx b/developer/src/kmcmplib/tests/fixtures/ausephon.kmx new file mode 100644 index 0000000000..5e1d993451 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/ausephon.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/balochi_inpage.kmx b/developer/src/kmcmplib/tests/fixtures/balochi_inpage.kmx new file mode 100644 index 0000000000..2d7e060688 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/balochi_inpage.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/balochi_latin.kmx b/developer/src/kmcmplib/tests/fixtures/balochi_latin.kmx new file mode 100644 index 0000000000..5718c9ed54 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/balochi_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/balochi_persian.kmx b/developer/src/kmcmplib/tests/fixtures/balochi_persian.kmx new file mode 100644 index 0000000000..0aa472e7d7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/balochi_persian.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/balochi_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/balochi_phonetic.kmx new file mode 100644 index 0000000000..38714eb788 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/balochi_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/balochi_scientific.kmx b/developer/src/kmcmplib/tests/fixtures/balochi_scientific.kmx new file mode 100644 index 0000000000..20ca365b71 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/balochi_scientific.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/balochi_urdu.kmx b/developer/src/kmcmplib/tests/fixtures/balochi_urdu.kmx new file mode 100644 index 0000000000..43112d0ad4 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/balochi_urdu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bangla_joy.kmx b/developer/src/kmcmplib/tests/fixtures/bangla_joy.kmx new file mode 100644 index 0000000000..6228742eca Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bangla_joy.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bangla_munir.kmx b/developer/src/kmcmplib/tests/fixtures/bangla_munir.kmx new file mode 100644 index 0000000000..ba449452e6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bangla_munir.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bangla_probhat.kmx b/developer/src/kmcmplib/tests/fixtures/bangla_probhat.kmx new file mode 100644 index 0000000000..582b517ef5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bangla_probhat.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbda1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbda1.kmx new file mode 100644 index 0000000000..a4e8a01c01 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbda1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbda2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbda2.kmx new file mode 100644 index 0000000000..87712cb69c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbda2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbda3.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbda3.kmx new file mode 100644 index 0000000000..dacb36e258 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbda3.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdadlm.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdadlm.kmx new file mode 100644 index 0000000000..81159040ee Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdadlm.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdal.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdal.kmx new file mode 100644 index 0000000000..797300726e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdal.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdarme.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdarme.kmx new file mode 100644 index 0000000000..9210a7fa3a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdarme.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdarmph.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdarmph.kmx new file mode 100644 index 0000000000..e77ad47a93 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdarmph.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdarmty.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdarmty.kmx new file mode 100644 index 0000000000..a02cdd54ba Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdarmty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdarmw.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdarmw.kmx new file mode 100644 index 0000000000..073ce6d16f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdarmw.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdaze.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdaze.kmx new file mode 100644 index 0000000000..490aaac05f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdaze.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdazel.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdazel.kmx new file mode 100644 index 0000000000..d12f8d6f92 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdazel.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdazst.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdazst.kmx new file mode 100644 index 0000000000..3c56347f51 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdazst.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbash.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbash.kmx new file mode 100644 index 0000000000..b5c2783d68 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbash.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbe.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbe.kmx new file mode 100644 index 0000000000..9000c86436 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbe.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbene.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbene.kmx new file mode 100644 index 0000000000..b0d15fa23a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbene.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbgph.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbgph.kmx new file mode 100644 index 0000000000..ddd9bded81 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbgph.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbgph1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbgph1.kmx new file mode 100644 index 0000000000..284a8878a1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbgph1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbhc.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbhc.kmx new file mode 100644 index 0000000000..937f755ea9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbhc.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdblr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdblr.kmx new file mode 100644 index 0000000000..2a36c25044 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdblr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbr.kmx new file mode 100644 index 0000000000..f3d117172c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbu.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbu.kmx new file mode 100644 index 0000000000..8e27a0dbc6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbug.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbug.kmx new file mode 100644 index 0000000000..c1021e5c7f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbug.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdbulg.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdbulg.kmx new file mode 100644 index 0000000000..88c242a58f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdbulg.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdca.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdca.kmx new file mode 100644 index 0000000000..ebb3bae6ce Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdca.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdcan.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdcan.kmx new file mode 100644 index 0000000000..65e70a2c70 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdcan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdcher.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdcher.kmx new file mode 100644 index 0000000000..792054a890 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdcher.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdcherp.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdcherp.kmx new file mode 100644 index 0000000000..91c769d249 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdcherp.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdcr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdcr.kmx new file mode 100644 index 0000000000..fe0e9c7048 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdcr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdcz.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdcz.kmx new file mode 100644 index 0000000000..e293b056cd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdcz.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdcz1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdcz1.kmx new file mode 100644 index 0000000000..5a7243bd93 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdcz1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdcz2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdcz2.kmx new file mode 100644 index 0000000000..8cf0d820b9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdcz2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdda.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdda.kmx new file mode 100644 index 0000000000..aa282296e3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdda.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbddiv1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbddiv1.kmx new file mode 100644 index 0000000000..eea1945059 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbddiv1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbddiv2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbddiv2.kmx new file mode 100644 index 0000000000..a2bf45f00c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbddiv2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbddv.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbddv.kmx new file mode 100644 index 0000000000..f4731412f0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbddv.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbddzo.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbddzo.kmx new file mode 100644 index 0000000000..1b2b258451 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbddzo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdes.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdes.kmx new file mode 100644 index 0000000000..97cd31535d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdes.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdest.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdest.kmx new file mode 100644 index 0000000000..d66c6984b5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdest.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdfa.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdfa.kmx new file mode 100644 index 0000000000..5c4f44b6ad Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdfa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdfar.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdfar.kmx new file mode 100644 index 0000000000..59bcae67d1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdfar.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdfi.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdfi.kmx new file mode 100644 index 0000000000..cc53ecc0c6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdfi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdfi1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdfi1.kmx new file mode 100644 index 0000000000..fa9d6c4c73 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdfi1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdfo.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdfo.kmx new file mode 100644 index 0000000000..8aa400b50b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdfo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdfr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdfr.kmx new file mode 100644 index 0000000000..a243166c2d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdfr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdfthrk.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdfthrk.kmx new file mode 100644 index 0000000000..bc26f81605 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdfthrk.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgae.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgae.kmx new file mode 100644 index 0000000000..31a621f17b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgae.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgeo.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeo.kmx new file mode 100644 index 0000000000..458e4ec060 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgeoer.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeoer.kmx new file mode 100644 index 0000000000..107967ba6f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeoer.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgeome.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeome.kmx new file mode 100644 index 0000000000..1ac4c9083d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeome.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgeooa.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeooa.kmx new file mode 100644 index 0000000000..c356eecd7b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeooa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgeoqw.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeoqw.kmx new file mode 100644 index 0000000000..7e251ebc11 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgeoqw.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgkl.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgkl.kmx new file mode 100644 index 0000000000..d264860a10 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgkl.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgn.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgn.kmx new file mode 100644 index 0000000000..cfd3cf5c31 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgn.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgr.kmx new file mode 100644 index 0000000000..116ee9be91 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgr1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgr1.kmx new file mode 100644 index 0000000000..8672a9c7c1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgr1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgrlnd.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgrlnd.kmx new file mode 100644 index 0000000000..dfbc61f0ee Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgrlnd.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdgthc.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdgthc.kmx new file mode 100644 index 0000000000..c8ffe27cf7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdgthc.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhau.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhau.kmx new file mode 100644 index 0000000000..8486d0af50 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhau.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhaw.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhaw.kmx new file mode 100644 index 0000000000..9cf3c48b9a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhaw.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhe.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhe.kmx new file mode 100644 index 0000000000..2268775a7d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhe.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhe220.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhe220.kmx new file mode 100644 index 0000000000..bdfc400f75 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhe220.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhe319.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhe319.kmx new file mode 100644 index 0000000000..100fe70446 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhe319.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdheb.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdheb.kmx new file mode 100644 index 0000000000..72fb99e682 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdheb.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhebl3.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhebl3.kmx new file mode 100644 index 0000000000..b28ab2f42b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhebl3.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhela2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhela2.kmx new file mode 100644 index 0000000000..e52d1e2122 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhela2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhela3.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhela3.kmx new file mode 100644 index 0000000000..044cc06f26 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhela3.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhept.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhept.kmx new file mode 100644 index 0000000000..e629ffda18 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhept.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhu.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhu.kmx new file mode 100644 index 0000000000..92205a9bd9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdhu1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdhu1.kmx new file mode 100644 index 0000000000..5d9ff3d278 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdhu1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdibo.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdibo.kmx new file mode 100644 index 0000000000..081025252b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdibo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdic.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdic.kmx new file mode 100644 index 0000000000..6d9df2e7a0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinasa.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinasa.kmx new file mode 100644 index 0000000000..cac2443783 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinasa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinbe2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinbe2.kmx new file mode 100644 index 0000000000..78a5acd301 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinbe2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinben.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinben.kmx new file mode 100644 index 0000000000..a660d951b8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinben.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdindev.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdindev.kmx new file mode 100644 index 0000000000..32d454daaa Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdindev.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinen.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinen.kmx new file mode 100644 index 0000000000..0ce474be7c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinen.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinguj.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinguj.kmx new file mode 100644 index 0000000000..3529d62f77 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinguj.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinhin.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinhin.kmx new file mode 100644 index 0000000000..754d7fc8c8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinhin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinkan.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinkan.kmx new file mode 100644 index 0000000000..33a2802a73 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinkan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinmal.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinmal.kmx new file mode 100644 index 0000000000..00f6e8c4e8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinmal.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinmar.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinmar.kmx new file mode 100644 index 0000000000..6d7289da4a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinmar.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinori.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinori.kmx new file mode 100644 index 0000000000..dfd8244e33 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinori.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinpun.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinpun.kmx new file mode 100644 index 0000000000..5ccb95ae1c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinpun.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdintam.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdintam.kmx new file mode 100644 index 0000000000..61fd2637db Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdintam.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdintel.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdintel.kmx new file mode 100644 index 0000000000..217f05338f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdintel.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdinuk2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdinuk2.kmx new file mode 100644 index 0000000000..00b4e83b70 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdinuk2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdir.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdir.kmx new file mode 100644 index 0000000000..2df897edd9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdir.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdit.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdit.kmx new file mode 100644 index 0000000000..97488aaf63 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdit.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdit142.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdit142.kmx new file mode 100644 index 0000000000..d8b9d5f487 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdit142.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdiulat.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdiulat.kmx new file mode 100644 index 0000000000..29b9e8cd62 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdiulat.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdjav.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdjav.kmx new file mode 100644 index 0000000000..2d903c534f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdjav.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdkaz.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdkaz.kmx new file mode 100644 index 0000000000..aec72e3a96 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdkaz.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdkhmr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdkhmr.kmx new file mode 100644 index 0000000000..e1ad6cff7e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdkhmr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdkni.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdkni.kmx new file mode 100644 index 0000000000..06a5b460b0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdkni.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdkurd.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdkurd.kmx new file mode 100644 index 0000000000..86e3cf2680 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdkurd.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdkyr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdkyr.kmx new file mode 100644 index 0000000000..a6a3465254 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdkyr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdla.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdla.kmx new file mode 100644 index 0000000000..8bdf865cf2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdla.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlao.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlao.kmx new file mode 100644 index 0000000000..3d9a155282 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlao.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlisub.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlisub.kmx new file mode 100644 index 0000000000..584fe2cdab Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlisub.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlisus.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlisus.kmx new file mode 100644 index 0000000000..4fc843fb72 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlisus.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlt.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlt.kmx new file mode 100644 index 0000000000..fc3d74e8e2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlt.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlt1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlt1.kmx new file mode 100644 index 0000000000..0d4a108b46 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlt1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlt2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlt2.kmx new file mode 100644 index 0000000000..c250d4afbf Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlt2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlv.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlv.kmx new file mode 100644 index 0000000000..417a7f5a7c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlv.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlv1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlv1.kmx new file mode 100644 index 0000000000..9b599d3f0f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlv1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdlvst.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdlvst.kmx new file mode 100644 index 0000000000..a1f6d165d3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdlvst.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmac.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmac.kmx new file mode 100644 index 0000000000..031d3308d3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmac.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmacst.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmacst.kmx new file mode 100644 index 0000000000..300b2b4bfc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmacst.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmaori.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmaori.kmx new file mode 100644 index 0000000000..b4a23b82c6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmaori.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmlt47.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmlt47.kmx new file mode 100644 index 0000000000..16a9866e00 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmlt47.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmlt48.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmlt48.kmx new file mode 100644 index 0000000000..8168c69548 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmlt48.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmon.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmon.kmx new file mode 100644 index 0000000000..7e5e01839e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmon.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmonmo.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmonmo.kmx new file mode 100644 index 0000000000..0eb2da7dfc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmonmo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmonst.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmonst.kmx new file mode 100644 index 0000000000..92e3394b6b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmonst.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdmyan.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdmyan.kmx new file mode 100644 index 0000000000..0b9e74cd88 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdmyan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdne.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdne.kmx new file mode 100644 index 0000000000..bf71710dbf Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdne.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdnepr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdnepr.kmx new file mode 100644 index 0000000000..6d828eb350 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdnepr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdnko.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdnko.kmx new file mode 100644 index 0000000000..099947ed55 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdnko.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdno.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdno.kmx new file mode 100644 index 0000000000..ed63bae4f8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdno.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdno1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdno1.kmx new file mode 100644 index 0000000000..6daa96d542 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdno1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdnso.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdnso.kmx new file mode 100644 index 0000000000..342556e10d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdnso.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdntl.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdntl.kmx new file mode 100644 index 0000000000..e090efd2e6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdntl.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdogham.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdogham.kmx new file mode 100644 index 0000000000..b92652758f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdogham.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdolch.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdolch.kmx new file mode 100644 index 0000000000..3b2c0e1f95 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdolch.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdoldit.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdoldit.kmx new file mode 100644 index 0000000000..d4d21fc9bb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdoldit.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdosa.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdosa.kmx new file mode 100644 index 0000000000..49e2f06fce Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdosa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdosm.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdosm.kmx new file mode 100644 index 0000000000..ef355a0eed Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdosm.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdpash.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdpash.kmx new file mode 100644 index 0000000000..56461e8050 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdpash.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdphags.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdphags.kmx new file mode 100644 index 0000000000..f76a7c010e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdphags.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdpl.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdpl.kmx new file mode 100644 index 0000000000..28ebf385cf Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdpl.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdpl1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdpl1.kmx new file mode 100644 index 0000000000..5034a1f819 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdpl1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdpo.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdpo.kmx new file mode 100644 index 0000000000..dbb01e1391 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdpo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdropr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdropr.kmx new file mode 100644 index 0000000000..b5697f6ce5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdropr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdrost.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdrost.kmx new file mode 100644 index 0000000000..8da352fb79 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdrost.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdru.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdru.kmx new file mode 100644 index 0000000000..39963e29cd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdru.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdru1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdru1.kmx new file mode 100644 index 0000000000..3dd977a73b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdru1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdrum.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdrum.kmx new file mode 100644 index 0000000000..d32a78212f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdrum.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsf.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsf.kmx new file mode 100644 index 0000000000..e990000b16 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsf.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsg.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsg.kmx new file mode 100644 index 0000000000..8e48bbca74 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsg.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsl.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsl.kmx new file mode 100644 index 0000000000..c744b17657 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsl.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsl1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsl1.kmx new file mode 100644 index 0000000000..8b7e53848a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsl1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsmsfi.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsmsfi.kmx new file mode 100644 index 0000000000..d7156aeeb1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsmsfi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsmsno.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsmsno.kmx new file mode 100644 index 0000000000..43b8227761 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsmsno.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsn1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsn1.kmx new file mode 100644 index 0000000000..ac06d938dd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsn1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsora.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsora.kmx new file mode 100644 index 0000000000..5780bffad6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsora.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsorex.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsorex.kmx new file mode 100644 index 0000000000..8ee12d5340 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsorex.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsors1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsors1.kmx new file mode 100644 index 0000000000..4ffb2ac210 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsors1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsp.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsp.kmx new file mode 100644 index 0000000000..ddfb512ac0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsp.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsw.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsw.kmx new file mode 100644 index 0000000000..79ad8b9191 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsw.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsw09.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsw09.kmx new file mode 100644 index 0000000000..10a92aa9fd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsw09.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsyr1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsyr1.kmx new file mode 100644 index 0000000000..03faa96bde Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsyr1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdsyr2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdsyr2.kmx new file mode 100644 index 0000000000..0bb6cd7737 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdsyr2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtaile.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtaile.kmx new file mode 100644 index 0000000000..f6965e49f3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtaile.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtajik.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtajik.kmx new file mode 100644 index 0000000000..34fa144e1d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtajik.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtam99.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtam99.kmx new file mode 100644 index 0000000000..10581a0360 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtam99.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdth0.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdth0.kmx new file mode 100644 index 0000000000..4111fffc03 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdth0.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdth1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdth1.kmx new file mode 100644 index 0000000000..25ebec813b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdth1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdth2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdth2.kmx new file mode 100644 index 0000000000..50e9501d62 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdth2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdth3.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdth3.kmx new file mode 100644 index 0000000000..388a30f355 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdth3.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtifi.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtifi.kmx new file mode 100644 index 0000000000..ea957fb340 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtifi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtifi2.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtifi2.kmx new file mode 100644 index 0000000000..62538f2a1a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtifi2.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtiprd.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtiprd.kmx new file mode 100644 index 0000000000..3fdba0e590 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtiprd.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtt102.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtt102.kmx new file mode 100644 index 0000000000..6140e900a4 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtt102.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtuf.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtuf.kmx new file mode 100644 index 0000000000..3b377481f5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtuf.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtuq.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtuq.kmx new file mode 100644 index 0000000000..cbd7edec80 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtuq.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdturme.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdturme.kmx new file mode 100644 index 0000000000..e90d4804e6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdturme.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdtzm.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdtzm.kmx new file mode 100644 index 0000000000..6fa483fdd1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdtzm.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdughr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdughr.kmx new file mode 100644 index 0000000000..b2cd49ec36 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdughr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdughr1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdughr1.kmx new file mode 100644 index 0000000000..c15af76e8f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdughr1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbduk.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbduk.kmx new file mode 100644 index 0000000000..4422e72bd3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbduk.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdukx.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdukx.kmx new file mode 100644 index 0000000000..aa6a5df2dd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdukx.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdur.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdur.kmx new file mode 100644 index 0000000000..79a262c7d6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdur.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdur1.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdur1.kmx new file mode 100644 index 0000000000..0f18312658 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdur1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdurdu.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdurdu.kmx new file mode 100644 index 0000000000..9627028597 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdurdu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdus.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdus.kmx new file mode 100644 index 0000000000..ddf9eb6bec Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdus.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdusa.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdusa.kmx new file mode 100644 index 0000000000..77b0662814 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdusa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdusl.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdusl.kmx new file mode 100644 index 0000000000..1866a0da59 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdusl.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdusr.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdusr.kmx new file mode 100644 index 0000000000..f03ab91487 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdusr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdusx.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdusx.kmx new file mode 100644 index 0000000000..4f1639ebf3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdusx.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbduzb.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbduzb.kmx new file mode 100644 index 0000000000..26270dcfb3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbduzb.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdvntc.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdvntc.kmx new file mode 100644 index 0000000000..cf3c5f2bdd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdvntc.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdwol.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdwol.kmx new file mode 100644 index 0000000000..616dd09565 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdwol.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdyak.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdyak.kmx new file mode 100644 index 0000000000..32f30e18ba Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdyak.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdyba.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdyba.kmx new file mode 100644 index 0000000000..a30ea443ab Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdyba.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdycc.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdycc.kmx new file mode 100644 index 0000000000..38cdb5844b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdycc.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/basic_kbdycl.kmx b/developer/src/kmcmplib/tests/fixtures/basic_kbdycl.kmx new file mode 100644 index 0000000000..b6a0c27592 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/basic_kbdycl.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/batak.kmx b/developer/src/kmcmplib/tests/fixtures/batak.kmx new file mode 100644 index 0000000000..953244d282 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/batak.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/baybayin.kmx b/developer/src/kmcmplib/tests/fixtures/baybayin.kmx new file mode 100644 index 0000000000..a98eb66f7f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/baybayin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bhaiksuki_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/bhaiksuki_inscript.kmx new file mode 100644 index 0000000000..59dbfdf7b6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bhaiksuki_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_cree_east.kmx b/developer/src/kmcmplib/tests/fixtures/bj_cree_east.kmx new file mode 100644 index 0000000000..db3ae95284 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_cree_east.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_cree_east_james_bay.kmx b/developer/src/kmcmplib/tests/fixtures/bj_cree_east_james_bay.kmx new file mode 100644 index 0000000000..c4ffe3262f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_cree_east_james_bay.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_cree_east_latn.kmx b/developer/src/kmcmplib/tests/fixtures/bj_cree_east_latn.kmx new file mode 100644 index 0000000000..f8a7734542 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_cree_east_latn.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_cree_west_latn.kmx b/developer/src/kmcmplib/tests/fixtures/bj_cree_west_latn.kmx new file mode 100644 index 0000000000..da25ab5de8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_cree_west_latn.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_cree_woods.kmx b/developer/src/kmcmplib/tests/fixtures/bj_cree_woods.kmx new file mode 100644 index 0000000000..a4da2173b7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_cree_woods.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_innu.kmx b/developer/src/kmcmplib/tests/fixtures/bj_innu.kmx new file mode 100644 index 0000000000..3071a9c18d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_innu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_innu_phonemic.kmx b/developer/src/kmcmplib/tests/fixtures/bj_innu_phonemic.kmx new file mode 100644 index 0000000000..fef5055f99 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_innu_phonemic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_mista_wasaha_cree.kmx b/developer/src/kmcmplib/tests/fixtures/bj_mista_wasaha_cree.kmx new file mode 100644 index 0000000000..bc297ffb33 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_mista_wasaha_cree.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_naskapi_classic.kmx b/developer/src/kmcmplib/tests/fixtures/bj_naskapi_classic.kmx new file mode 100644 index 0000000000..3308462a43 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_naskapi_classic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_naskapi_common.kmx b/developer/src/kmcmplib/tests/fixtures/bj_naskapi_common.kmx new file mode 100644 index 0000000000..c7e3cba869 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_naskapi_common.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bj_oji_cree.kmx b/developer/src/kmcmplib/tests/fixtures/bj_oji_cree.kmx new file mode 100644 index 0000000000..d81548c7cb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bj_oji_cree.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/brahmi_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/brahmi_inscript.kmx new file mode 100644 index 0000000000..c2a6a0210e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/brahmi_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/btl_kenya.kmx b/developer/src/kmcmplib/tests/fixtures/btl_kenya.kmx new file mode 100644 index 0000000000..ce701d6055 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/btl_kenya.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/bu_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/bu_phonetic.kmx new file mode 100644 index 0000000000..bf5f8b54a2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/bu_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/buhid.kmx b/developer/src/kmcmplib/tests/fixtures/buhid.kmx new file mode 100644 index 0000000000..b379b84bb7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/buhid.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/burushaski_girminas.kmx b/developer/src/kmcmplib/tests/fixtures/burushaski_girminas.kmx new file mode 100644 index 0000000000..e472e1e658 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/burushaski_girminas.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/cabecar.kmx b/developer/src/kmcmplib/tests/fixtures/cabecar.kmx new file mode 100644 index 0000000000..3122d53320 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/cabecar.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/carian.kmx b/developer/src/kmcmplib/tests/fixtures/carian.kmx new file mode 100644 index 0000000000..28788cf090 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/carian.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/chalchiteko.kmx b/developer/src/kmcmplib/tests/fixtures/chalchiteko.kmx new file mode 100644 index 0000000000..d8a7799b3b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/chalchiteko.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/chechen_latin.kmx b/developer/src/kmcmplib/tests/fixtures/chechen_latin.kmx new file mode 100644 index 0000000000..619a3b42ca Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/chechen_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/chinuk_wawa.kmx b/developer/src/kmcmplib/tests/fixtures/chinuk_wawa.kmx new file mode 100644 index 0000000000..e902d3fda7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/chinuk_wawa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/choctaw_modern.kmx b/developer/src/kmcmplib/tests/fixtures/choctaw_modern.kmx new file mode 100644 index 0000000000..b995728e16 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/choctaw_modern.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/cim.kmx b/developer/src/kmcmplib/tests/fixtures/cim.kmx new file mode 100644 index 0000000000..25096b14a3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/cim.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/clavbur9.kmx b/developer/src/kmcmplib/tests/fixtures/clavbur9.kmx new file mode 100644 index 0000000000..3a7c6594a3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/clavbur9.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/colchis_latin.kmx b/developer/src/kmcmplib/tests/fixtures/colchis_latin.kmx new file mode 100644 index 0000000000..ab7f85d3d7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/colchis_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/colchis_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/colchis_phonetic.kmx new file mode 100644 index 0000000000..6eadc71757 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/colchis_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/common_devanagari.kmx b/developer/src/kmcmplib/tests/fixtures/common_devanagari.kmx new file mode 100644 index 0000000000..ec1329475e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/common_devanagari.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/coptic_greek.kmx b/developer/src/kmcmplib/tests/fixtures/coptic_greek.kmx new file mode 100644 index 0000000000..e380cea953 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/coptic_greek.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/coptic_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/coptic_qwerty.kmx new file mode 100644 index 0000000000..b65388efb1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/coptic_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/dagbani.kmx b/developer/src/kmcmplib/tests/fixtures/dagbani.kmx new file mode 100644 index 0000000000..31cfe39981 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/dagbani.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/dega.kmx b/developer/src/kmcmplib/tests/fixtures/dega.kmx new file mode 100644 index 0000000000..31e3373f76 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/dega.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/dene.kmx b/developer/src/kmcmplib/tests/fixtures/dene.kmx new file mode 100644 index 0000000000..835bbf1a63 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/dene.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/deseret.kmx b/developer/src/kmcmplib/tests/fixtures/deseret.kmx new file mode 100644 index 0000000000..a9f2646572 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/deseret.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/dogra_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/dogra_inscript.kmx new file mode 100644 index 0000000000..bae4778243 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/dogra_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/easy_chakma.kmx b/developer/src/kmcmplib/tests/fixtures/easy_chakma.kmx new file mode 100644 index 0000000000..df87cec7e7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/easy_chakma.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/ekwtamil99uni.kmx b/developer/src/kmcmplib/tests/fixtures/ekwtamil99uni.kmx new file mode 100644 index 0000000000..5b2bf899f9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/ekwtamil99uni.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/el_dinka.kmx b/developer/src/kmcmplib/tests/fixtures/el_dinka.kmx new file mode 100644 index 0000000000..5d0983836d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/el_dinka.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/el_harari_latin.kmx b/developer/src/kmcmplib/tests/fixtures/el_harari_latin.kmx new file mode 100644 index 0000000000..1dd0c497b2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/el_harari_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/el_naija.kmx b/developer/src/kmcmplib/tests/fixtures/el_naija.kmx new file mode 100644 index 0000000000..9a5456e214 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/el_naija.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/el_nuer.kmx b/developer/src/kmcmplib/tests/fixtures/el_nuer.kmx new file mode 100644 index 0000000000..1b418368fb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/el_nuer.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/el_pasifika.kmx b/developer/src/kmcmplib/tests/fixtures/el_pasifika.kmx new file mode 100644 index 0000000000..08a6cc250e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/el_pasifika.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/el_yolngu.kmx b/developer/src/kmcmplib/tests/fixtures/el_yolngu.kmx new file mode 100644 index 0000000000..0233d5c10f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/el_yolngu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/embera_north.kmx b/developer/src/kmcmplib/tests/fixtures/embera_north.kmx new file mode 100644 index 0000000000..601a25116c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/embera_north.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/enga.kmx b/developer/src/kmcmplib/tests/fixtures/enga.kmx new file mode 100644 index 0000000000..9543f557b9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/enga.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/enggano.kmx b/developer/src/kmcmplib/tests/fixtures/enggano.kmx new file mode 100644 index 0000000000..4e8ddd14db Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/enggano.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/english_shavian_igc.kmx b/developer/src/kmcmplib/tests/fixtures/english_shavian_igc.kmx new file mode 100644 index 0000000000..628d747947 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/english_shavian_igc.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/english_shavian_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/english_shavian_qwerty.kmx new file mode 100644 index 0000000000..92ac37c693 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/english_shavian_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/engram.kmx b/developer/src/kmcmplib/tests/fixtures/engram.kmx new file mode 100644 index 0000000000..83f5d167f1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/engram.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/esperuni.kmx b/developer/src/kmcmplib/tests/fixtures/esperuni.kmx new file mode 100644 index 0000000000..093a94a107 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/esperuni.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/farsiman.kmx b/developer/src/kmcmplib/tests/fixtures/farsiman.kmx new file mode 100644 index 0000000000..f5ac429891 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/farsiman.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/finongan.kmx b/developer/src/kmcmplib/tests/fixtures/finongan.kmx new file mode 100644 index 0000000000..122cd34d45 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/finongan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fulfulde_ajami_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/fulfulde_ajami_qwerty.kmx new file mode 100644 index 0000000000..9bf05cacc8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fulfulde_ajami_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fulfulde_latin_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/fulfulde_latin_qwerty.kmx new file mode 100644 index 0000000000..9df1ae0728 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fulfulde_latin_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_dakelh.kmx b/developer/src/kmcmplib/tests/fixtures/fv_dakelh.kmx new file mode 100644 index 0000000000..1ab7508254 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_dakelh.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_dane_zaa_zaage.kmx b/developer/src/kmcmplib/tests/fixtures/fv_dane_zaa_zaage.kmx new file mode 100644 index 0000000000..4f5f5c2343 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_dane_zaa_zaage.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_denesuline_epsilon.kmx b/developer/src/kmcmplib/tests/fixtures/fv_denesuline_epsilon.kmx new file mode 100644 index 0000000000..a55a6f0e73 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_denesuline_epsilon.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_diitiidatx.kmx b/developer/src/kmcmplib/tests/fixtures/fv_diitiidatx.kmx new file mode 100644 index 0000000000..dfae3c8f99 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_diitiidatx.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_gitsenimx.kmx b/developer/src/kmcmplib/tests/fixtures/fv_gitsenimx.kmx new file mode 100644 index 0000000000..3cf3b42f11 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_gitsenimx.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_gwichin.kmx b/developer/src/kmcmplib/tests/fixtures/fv_gwichin.kmx new file mode 100644 index 0000000000..f99115394a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_gwichin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_hailzaqvla.kmx b/developer/src/kmcmplib/tests/fixtures/fv_hailzaqvla.kmx new file mode 100644 index 0000000000..d39dde6a48 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_hailzaqvla.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_haisla.kmx b/developer/src/kmcmplib/tests/fixtures/fv_haisla.kmx new file mode 100644 index 0000000000..90b43453b2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_haisla.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_halqemeylem.kmx b/developer/src/kmcmplib/tests/fixtures/fv_halqemeylem.kmx new file mode 100644 index 0000000000..0572a5f9fc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_halqemeylem.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_han.kmx b/developer/src/kmcmplib/tests/fixtures/fv_han.kmx new file mode 100644 index 0000000000..0de6f7d922 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_han.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_henqeminem.kmx b/developer/src/kmcmplib/tests/fixtures/fv_henqeminem.kmx new file mode 100644 index 0000000000..e2d4968e53 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_henqeminem.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_hlgaagilda_xaayda_kil.kmx b/developer/src/kmcmplib/tests/fixtures/fv_hlgaagilda_xaayda_kil.kmx new file mode 100644 index 0000000000..127e612a29 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_hlgaagilda_xaayda_kil.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_kanienkeha_e.kmx b/developer/src/kmcmplib/tests/fixtures/fv_kanienkeha_e.kmx new file mode 100644 index 0000000000..cfaf38533b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_kanienkeha_e.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_ktunaxa.kmx b/developer/src/kmcmplib/tests/fixtures/fv_ktunaxa.kmx new file mode 100644 index 0000000000..e893954de8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_ktunaxa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_kwakwala.kmx b/developer/src/kmcmplib/tests/fixtures/fv_kwakwala.kmx new file mode 100644 index 0000000000..d4f0f395b4 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_kwakwala.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_kwakwala_liqwala.kmx b/developer/src/kmcmplib/tests/fixtures/fv_kwakwala_liqwala.kmx new file mode 100644 index 0000000000..13444e38f3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_kwakwala_liqwala.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_migmaq.kmx b/developer/src/kmcmplib/tests/fixtures/fv_migmaq.kmx new file mode 100644 index 0000000000..05cab8441f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_migmaq.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_natwits.kmx b/developer/src/kmcmplib/tests/fixtures/fv_natwits.kmx new file mode 100644 index 0000000000..55f1f49e2b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_natwits.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_nisgaa.kmx b/developer/src/kmcmplib/tests/fixtures/fv_nisgaa.kmx new file mode 100644 index 0000000000..4e020950bc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_nisgaa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_nlekepmxcin.kmx b/developer/src/kmcmplib/tests/fixtures/fv_nlekepmxcin.kmx new file mode 100644 index 0000000000..c99549d94f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_nlekepmxcin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_northern_tutchone.kmx b/developer/src/kmcmplib/tests/fixtures/fv_northern_tutchone.kmx new file mode 100644 index 0000000000..27e05e8115 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_northern_tutchone.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_nsilxcen.kmx b/developer/src/kmcmplib/tests/fixtures/fv_nsilxcen.kmx new file mode 100644 index 0000000000..1732ce5c37 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_nsilxcen.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_nuucaanul.kmx b/developer/src/kmcmplib/tests/fixtures/fv_nuucaanul.kmx new file mode 100644 index 0000000000..0fa9e4ca53 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_nuucaanul.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_secwepemctsin.kmx b/developer/src/kmcmplib/tests/fixtures/fv_secwepemctsin.kmx new file mode 100644 index 0000000000..c87c548e0a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_secwepemctsin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_sencoten.kmx b/developer/src/kmcmplib/tests/fixtures/fv_sencoten.kmx new file mode 100644 index 0000000000..049ac70085 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_sencoten.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_shashishalhem.kmx b/developer/src/kmcmplib/tests/fixtures/fv_shashishalhem.kmx new file mode 100644 index 0000000000..200d72f3a3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_shashishalhem.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_smalgyax.kmx b/developer/src/kmcmplib/tests/fixtures/fv_smalgyax.kmx new file mode 100644 index 0000000000..cdc7b6b3be Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_smalgyax.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_southern_tutchone.kmx b/developer/src/kmcmplib/tests/fixtures/fv_southern_tutchone.kmx new file mode 100644 index 0000000000..d500f6ea9d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_southern_tutchone.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_statimcets.kmx b/developer/src/kmcmplib/tests/fixtures/fv_statimcets.kmx new file mode 100644 index 0000000000..012755488a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_statimcets.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_stlatlimxec.kmx b/developer/src/kmcmplib/tests/fixtures/fv_stlatlimxec.kmx new file mode 100644 index 0000000000..01b8ba7bdb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_stlatlimxec.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_tagizi_dene.kmx b/developer/src/kmcmplib/tests/fixtures/fv_tagizi_dene.kmx new file mode 100644 index 0000000000..838054ba56 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_tagizi_dene.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_taltan.kmx b/developer/src/kmcmplib/tests/fixtures/fv_taltan.kmx new file mode 100644 index 0000000000..5d7f52ce64 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_taltan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_tlingit.kmx b/developer/src/kmcmplib/tests/fixtures/fv_tlingit.kmx new file mode 100644 index 0000000000..80f13d6898 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_tlingit.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_tsekehne.kmx b/developer/src/kmcmplib/tests/fixtures/fv_tsekehne.kmx new file mode 100644 index 0000000000..277d17c7e3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_tsekehne.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_tsilhqotin.kmx b/developer/src/kmcmplib/tests/fixtures/fv_tsilhqotin.kmx new file mode 100644 index 0000000000..3462213857 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_tsilhqotin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_uwikala.kmx b/developer/src/kmcmplib/tests/fixtures/fv_uwikala.kmx new file mode 100644 index 0000000000..129819a755 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_uwikala.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/fv_xaislakala.kmx b/developer/src/kmcmplib/tests/fixtures/fv_xaislakala.kmx new file mode 100644 index 0000000000..5a98769f3b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/fv_xaislakala.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/galaxie_greek_mnemonic.kmx b/developer/src/kmcmplib/tests/fixtures/galaxie_greek_mnemonic.kmx new file mode 100644 index 0000000000..111e206752 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/galaxie_greek_mnemonic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/galaxie_greek_positional.kmx b/developer/src/kmcmplib/tests/fixtures/galaxie_greek_positional.kmx new file mode 100644 index 0000000000..dbdcfc4e41 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/galaxie_greek_positional.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/galaxie_hebrew_mnemonic.kmx b/developer/src/kmcmplib/tests/fixtures/galaxie_hebrew_mnemonic.kmx new file mode 100644 index 0000000000..1773d43a20 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/galaxie_hebrew_mnemonic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/galaxie_hebrew_positional.kmx b/developer/src/kmcmplib/tests/fixtures/galaxie_hebrew_positional.kmx new file mode 100644 index 0000000000..ca089a8727 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/galaxie_hebrew_positional.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gandhari.kmx b/developer/src/kmcmplib/tests/fixtures/gandhari.kmx new file mode 100644 index 0000000000..880b46b6ed Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gandhari.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/geezbrhan.kmx b/developer/src/kmcmplib/tests/fixtures/geezbrhan.kmx new file mode 100644 index 0000000000..57d4f37e93 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/geezbrhan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_amh_7.kmx b/developer/src/kmcmplib/tests/fixtures/gff_amh_7.kmx new file mode 100644 index 0000000000..e265cc988d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_amh_7.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_amharic.kmx b/developer/src/kmcmplib/tests/fixtures/gff_amharic.kmx new file mode 100644 index 0000000000..ba94ba13cc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_amharic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_blin.kmx b/developer/src/kmcmplib/tests/fixtures/gff_blin.kmx new file mode 100644 index 0000000000..5c69d20dfc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_blin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_ethiopic_7.kmx b/developer/src/kmcmplib/tests/fixtures/gff_ethiopic_7.kmx new file mode 100644 index 0000000000..6dbb905de6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_ethiopic_7.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_geez.kmx b/developer/src/kmcmplib/tests/fixtures/gff_geez.kmx new file mode 100644 index 0000000000..08cd45f84c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_geez.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_gurage.kmx b/developer/src/kmcmplib/tests/fixtures/gff_gurage.kmx new file mode 100644 index 0000000000..eb108c5d52 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_gurage.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_gurage_legacy.kmx b/developer/src/kmcmplib/tests/fixtures/gff_gurage_legacy.kmx new file mode 100644 index 0000000000..35456108f2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_gurage_legacy.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_musnad.kmx b/developer/src/kmcmplib/tests/fixtures/gff_musnad.kmx new file mode 100644 index 0000000000..be00b433cd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_musnad.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_tigrinya_eritrea.kmx b/developer/src/kmcmplib/tests/fixtures/gff_tigrinya_eritrea.kmx new file mode 100644 index 0000000000..32e7202e58 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_tigrinya_eritrea.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gff_tigrinya_ethiopia.kmx b/developer/src/kmcmplib/tests/fixtures/gff_tigrinya_ethiopia.kmx new file mode 100644 index 0000000000..e2aab80909 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gff_tigrinya_ethiopia.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/ghana.kmx b/developer/src/kmcmplib/tests/fixtures/ghana.kmx new file mode 100644 index 0000000000..5ef98ec4d8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/ghana.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gilaki.kmx b/developer/src/kmcmplib/tests/fixtures/gilaki.kmx new file mode 100644 index 0000000000..6e73cdb300 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gilaki.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gilaki_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/gilaki_phonetic.kmx new file mode 100644 index 0000000000..b6d7c24ae2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gilaki_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gondi_dev.kmx b/developer/src/kmcmplib/tests/fixtures/gondi_dev.kmx new file mode 100644 index 0000000000..a11e9dbc65 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gondi_dev.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gondi_gunjala.kmx b/developer/src/kmcmplib/tests/fixtures/gondi_gunjala.kmx new file mode 100644 index 0000000000..40635fdec1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gondi_gunjala.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/gondi_tel.kmx b/developer/src/kmcmplib/tests/fixtures/gondi_tel.kmx new file mode 100644 index 0000000000..f53e419795 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/gondi_tel.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/greekclassical.kmx b/developer/src/kmcmplib/tests/fixtures/greekclassical.kmx new file mode 100644 index 0000000000..b52d644663 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/greekclassical.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/hanunoo.kmx b/developer/src/kmcmplib/tests/fixtures/hanunoo.kmx new file mode 100644 index 0000000000..e27248f01e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/hanunoo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/haroi.kmx b/developer/src/kmcmplib/tests/fixtures/haroi.kmx new file mode 100644 index 0000000000..ab97cbb1b9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/haroi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/hatran_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/hatran_inscript.kmx new file mode 100644 index 0000000000..a9c7206c16 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/hatran_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/hausa_ajami_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/hausa_ajami_qwerty.kmx new file mode 100644 index 0000000000..3893c37d12 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/hausa_ajami_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/hausa_kano.kmx b/developer/src/kmcmplib/tests/fixtures/hausa_kano.kmx new file mode 100644 index 0000000000..8b670fa110 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/hausa_kano.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/hcesar.kmx b/developer/src/kmcmplib/tests/fixtures/hcesar.kmx new file mode 100644 index 0000000000..bd2ac004d6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/hcesar.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/hieroglyphic.kmx b/developer/src/kmcmplib/tests/fixtures/hieroglyphic.kmx new file mode 100644 index 0000000000..20e616e0e0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/hieroglyphic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/himyarit_musnad.kmx b/developer/src/kmcmplib/tests/fixtures/himyarit_musnad.kmx new file mode 100644 index 0000000000..8d6dd77e25 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/himyarit_musnad.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/hindi_modular.kmx b/developer/src/kmcmplib/tests/fixtures/hindi_modular.kmx new file mode 100644 index 0000000000..ff755dabe0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/hindi_modular.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/indigenous_nt.kmx b/developer/src/kmcmplib/tests/fixtures/indigenous_nt.kmx new file mode 100644 index 0000000000..d5c20049c1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/indigenous_nt.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/indonesia.kmx b/developer/src/kmcmplib/tests/fixtures/indonesia.kmx new file mode 100644 index 0000000000..4141cd4278 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/indonesia.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/indonesian_suku.kmx b/developer/src/kmcmplib/tests/fixtures/indonesian_suku.kmx new file mode 100644 index 0000000000..c7c77ad062 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/indonesian_suku.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/inuktitut_naqittaut.kmx b/developer/src/kmcmplib/tests/fixtures/inuktitut_naqittaut.kmx new file mode 100644 index 0000000000..6cd4ba4462 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/inuktitut_naqittaut.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/ishkashimi_cyrillic.kmx b/developer/src/kmcmplib/tests/fixtures/ishkashimi_cyrillic.kmx new file mode 100644 index 0000000000..512a576c4a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/ishkashimi_cyrillic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/itrans_bengali.kmx b/developer/src/kmcmplib/tests/fixtures/itrans_bengali.kmx new file mode 100644 index 0000000000..49103e231a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/itrans_bengali.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/itrans_devanagari_hindi.kmx b/developer/src/kmcmplib/tests/fixtures/itrans_devanagari_hindi.kmx new file mode 100644 index 0000000000..69a3bed266 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/itrans_devanagari_hindi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/itrans_devanagari_sanskrit_vedic.kmx b/developer/src/kmcmplib/tests/fixtures/itrans_devanagari_sanskrit_vedic.kmx new file mode 100644 index 0000000000..06adc62f38 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/itrans_devanagari_sanskrit_vedic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/itrans_gujarati.kmx b/developer/src/kmcmplib/tests/fixtures/itrans_gujarati.kmx new file mode 100644 index 0000000000..d46598d8d2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/itrans_gujarati.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/itrans_gurmukhi.kmx b/developer/src/kmcmplib/tests/fixtures/itrans_gurmukhi.kmx new file mode 100644 index 0000000000..c56a17b39c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/itrans_gurmukhi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/itrans_odia.kmx b/developer/src/kmcmplib/tests/fixtures/itrans_odia.kmx new file mode 100644 index 0000000000..7cc9c171e1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/itrans_odia.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/itrans_roman.kmx b/developer/src/kmcmplib/tests/fixtures/itrans_roman.kmx new file mode 100644 index 0000000000..a019db3923 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/itrans_roman.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/jawa.kmx b/developer/src/kmcmplib/tests/fixtures/jawa.kmx new file mode 100644 index 0000000000..709021f21c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/jawa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/jorai.kmx b/developer/src/kmcmplib/tests/fixtures/jorai.kmx new file mode 100644 index 0000000000..519a4d2fab Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/jorai.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/karakalpak_cyrillic.kmx b/developer/src/kmcmplib/tests/fixtures/karakalpak_cyrillic.kmx new file mode 100644 index 0000000000..a6dc30f7d1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/karakalpak_cyrillic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/karakalpak_latin.kmx b/developer/src/kmcmplib/tests/fixtures/karakalpak_latin.kmx new file mode 100644 index 0000000000..919e2ca185 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/karakalpak_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/kayan.kmx b/developer/src/kmcmplib/tests/fixtures/kayan.kmx new file mode 100644 index 0000000000..7aec141c66 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/kayan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/kbdsn1.kmx b/developer/src/kmcmplib/tests/fixtures/kbdsn1.kmx new file mode 100644 index 0000000000..b580f1905d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/kbdsn1.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/kharoshthi_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/kharoshthi_inscript.kmx new file mode 100644 index 0000000000..a47fe866cd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/kharoshthi_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/khmer_advanced.kmx b/developer/src/kmcmplib/tests/fixtures/khmer_advanced.kmx new file mode 100644 index 0000000000..cc95b2cca7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/khmer_advanced.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/khmer_angkor.kmx b/developer/src/kmcmplib/tests/fixtures/khmer_angkor.kmx new file mode 100644 index 0000000000..d8495d187c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/khmer_angkor.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/khojki_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/khojki_inscript.kmx new file mode 100644 index 0000000000..3ace43836b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/khojki_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/kmhmu_2008.kmx b/developer/src/kmcmplib/tests/fixtures/kmhmu_2008.kmx new file mode 100644 index 0000000000..e0b8576fa6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/kmhmu_2008.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/koalibrere.kmx b/developer/src/kmcmplib/tests/fixtures/koalibrere.kmx new file mode 100644 index 0000000000..abd7ba9210 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/koalibrere.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/korean_rr.kmx b/developer/src/kmcmplib/tests/fixtures/korean_rr.kmx new file mode 100644 index 0000000000..74057b8d43 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/korean_rr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/koreguaje.kmx b/developer/src/kmcmplib/tests/fixtures/koreguaje.kmx new file mode 100644 index 0000000000..f99ac0c0a7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/koreguaje.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/krung.kmx b/developer/src/kmcmplib/tests/fixtures/krung.kmx new file mode 100644 index 0000000000..596ed3f502 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/krung.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/lahu.kmx b/developer/src/kmcmplib/tests/fixtures/lahu.kmx new file mode 100644 index 0000000000..8d7ecec5ec Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/lahu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/lamkaang.kmx b/developer/src/kmcmplib/tests/fixtures/lamkaang.kmx new file mode 100644 index 0000000000..eeb73b13ae Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/lamkaang.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/landuma.kmx b/developer/src/kmcmplib/tests/fixtures/landuma.kmx new file mode 100644 index 0000000000..2a106877d3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/landuma.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/lao_2008_basic.kmx b/developer/src/kmcmplib/tests/fixtures/lao_2008_basic.kmx new file mode 100644 index 0000000000..f6a3cf5240 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/lao_2008_basic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/lao_2008_rapid.kmx b/developer/src/kmcmplib/tests/fixtures/lao_2008_rapid.kmx new file mode 100644 index 0000000000..7c19d841b5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/lao_2008_rapid.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/lao_pali.kmx b/developer/src/kmcmplib/tests/fixtures/lao_pali.kmx new file mode 100644 index 0000000000..f2579f0f21 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/lao_pali.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/lao_pali_us.kmx b/developer/src/kmcmplib/tests/fixtures/lao_pali_us.kmx new file mode 100644 index 0000000000..90023f2e74 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/lao_pali_us.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/lao_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/lao_phonetic.kmx new file mode 100644 index 0000000000..9e7abb7f82 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/lao_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/lazuri.kmx b/developer/src/kmcmplib/tests/fixtures/lazuri.kmx new file mode 100644 index 0000000000..19c9dec735 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/lazuri.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/libtralo.kmx b/developer/src/kmcmplib/tests/fixtures/libtralo.kmx new file mode 100644 index 0000000000..df52a88479 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/libtralo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/makasar_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/makasar_inscript.kmx new file mode 100644 index 0000000000..b630f2a899 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/makasar_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/malar_braille.kmx b/developer/src/kmcmplib/tests/fixtures/malar_braille.kmx new file mode 100644 index 0000000000..069ed73292 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/malar_braille.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/malar_malayalam.kmx b/developer/src/kmcmplib/tests/fixtures/malar_malayalam.kmx new file mode 100644 index 0000000000..b34931675b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/malar_malayalam.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/malar_malayalam_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/malar_malayalam_inscript.kmx new file mode 100644 index 0000000000..06984b9a68 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/malar_malayalam_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/malar_tirhuta.kmx b/developer/src/kmcmplib/tests/fixtures/malar_tirhuta.kmx new file mode 100644 index 0000000000..de13a1a8c3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/malar_tirhuta.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/maltese.kmx b/developer/src/kmcmplib/tests/fixtures/maltese.kmx new file mode 100644 index 0000000000..8d083c4015 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/maltese.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/mandaic_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/mandaic_phonetic.kmx new file mode 100644 index 0000000000..0fd9217afb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/mandaic_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/masaram_gondi.kmx b/developer/src/kmcmplib/tests/fixtures/masaram_gondi.kmx new file mode 100644 index 0000000000..ecf782860c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/masaram_gondi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/me_en.kmx b/developer/src/kmcmplib/tests/fixtures/me_en.kmx new file mode 100644 index 0000000000..d9770fb8bb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/me_en.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/meitei_legacy.kmx b/developer/src/kmcmplib/tests/fixtures/meitei_legacy.kmx new file mode 100644 index 0000000000..fd43336cc6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/meitei_legacy.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/miluk_hanis_siuslaw.kmx b/developer/src/kmcmplib/tests/fixtures/miluk_hanis_siuslaw.kmx new file mode 100644 index 0000000000..42057fdfb8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/miluk_hanis_siuslaw.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/modi_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/modi_inscript.kmx new file mode 100644 index 0000000000..caf54dfe1c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/modi_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/mon_anonta.kmx b/developer/src/kmcmplib/tests/fixtures/mon_anonta.kmx new file mode 100644 index 0000000000..95edf95455 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/mon_anonta.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/mon_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/mon_phonetic.kmx new file mode 100644 index 0000000000..1f8e5504d0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/mon_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/mongolian_cyrillic_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/mongolian_cyrillic_qwerty.kmx new file mode 100644 index 0000000000..e20fee204f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/mongolian_cyrillic_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/mozhi_malayalam.kmx b/developer/src/kmcmplib/tests/fixtures/mozhi_malayalam.kmx new file mode 100644 index 0000000000..1c0137b88c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/mozhi_malayalam.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/mro_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/mro_phonetic.kmx new file mode 100644 index 0000000000..0c24868d1e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/mro_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/multani_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/multani_inscript.kmx new file mode 100644 index 0000000000..db5c54f6aa Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/multani_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/multi_pak_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/multi_pak_phonetic.kmx new file mode 100644 index 0000000000..0f3ebfe1c9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/multi_pak_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/munji.kmx b/developer/src/kmcmplib/tests/fixtures/munji.kmx new file mode 100644 index 0000000000..bfc51c4c86 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/munji.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/myancode_san.kmx b/developer/src/kmcmplib/tests/fixtures/myancode_san.kmx new file mode 100644 index 0000000000..95987ef8fa Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/myancode_san.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nabataean_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/nabataean_inscript.kmx new file mode 100644 index 0000000000..f8e708fff9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nabataean_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/naijatype.kmx b/developer/src/kmcmplib/tests/fixtures/naijatype.kmx new file mode 100644 index 0000000000..d2345dfda7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/naijatype.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nailangs.kmx b/developer/src/kmcmplib/tests/fixtures/nailangs.kmx new file mode 100644 index 0000000000..8dd07c6a08 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nailangs.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nasa_yuwe.kmx b/developer/src/kmcmplib/tests/fixtures/nasa_yuwe.kmx new file mode 100644 index 0000000000..de011fdf95 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nasa_yuwe.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nepali_traditional.kmx b/developer/src/kmcmplib/tests/fixtures/nepali_traditional.kmx new file mode 100644 index 0000000000..206a4ac6d0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nepali_traditional.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/newa_romanized.kmx b/developer/src/kmcmplib/tests/fixtures/newa_romanized.kmx new file mode 100644 index 0000000000..1b2282ae0c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/newa_romanized.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/newa_traditional.kmx b/developer/src/kmcmplib/tests/fixtures/newa_traditional.kmx new file mode 100644 index 0000000000..9d1bdce86d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/newa_traditional.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nias.kmx b/developer/src/kmcmplib/tests/fixtures/nias.kmx new file mode 100644 index 0000000000..d7079a039c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nias.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nisenan.kmx b/developer/src/kmcmplib/tests/fixtures/nisenan.kmx new file mode 100644 index 0000000000..a102ebd4b1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nisenan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nko.kmx b/developer/src/kmcmplib/tests/fixtures/nko.kmx new file mode 100644 index 0000000000..69705f32b7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nko.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nkonya.kmx b/developer/src/kmcmplib/tests/fixtures/nkonya.kmx new file mode 100644 index 0000000000..62812dab27 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nkonya.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_bengali_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_bengali_winscript.kmx new file mode 100644 index 0000000000..a99f0a6d1b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_bengali_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_devanagari_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_devanagari_winscript.kmx new file mode 100644 index 0000000000..894ae528cf Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_devanagari_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_gujarati_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_gujarati_winscript.kmx new file mode 100644 index 0000000000..171939f8f0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_gujarati_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_gurmukhi_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_gurmukhi_winscript.kmx new file mode 100644 index 0000000000..cf966d1f79 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_gurmukhi_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_ipa.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_ipa.kmx new file mode 100644 index 0000000000..f7b1bb493e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_ipa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_kannada_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_kannada_winscript.kmx new file mode 100644 index 0000000000..3a96d7f934 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_kannada_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_malayalam_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_malayalam_winscript.kmx new file mode 100644 index 0000000000..0035303ca4 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_malayalam_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_oriya_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_oriya_winscript.kmx new file mode 100644 index 0000000000..e3496b0640 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_oriya_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_tamil_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_tamil_winscript.kmx new file mode 100644 index 0000000000..a9d22bfded Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_tamil_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nlci_telugu_winscript.kmx b/developer/src/kmcmplib/tests/fixtures/nlci_telugu_winscript.kmx new file mode 100644 index 0000000000..176ce86e78 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nlci_telugu_winscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nrc_makah.kmx b/developer/src/kmcmplib/tests/fixtures/nrc_makah.kmx new file mode 100644 index 0000000000..4c5dcebbd9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nrc_makah.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/ntl_onekey.kmx b/developer/src/kmcmplib/tests/fixtures/ntl_onekey.kmx new file mode 100644 index 0000000000..e39ae5d918 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/ntl_onekey.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/numanggang.kmx b/developer/src/kmcmplib/tests/fixtures/numanggang.kmx new file mode 100644 index 0000000000..6064a1e7d9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/numanggang.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/nw_iranian_latin.kmx b/developer/src/kmcmplib/tests/fixtures/nw_iranian_latin.kmx new file mode 100644 index 0000000000..2d2b49f683 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/nw_iranian_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/o_tissi.kmx b/developer/src/kmcmplib/tests/fixtures/o_tissi.kmx new file mode 100644 index 0000000000..58515ef239 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/o_tissi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/obolo_chwerty.kmx b/developer/src/kmcmplib/tests/fixtures/obolo_chwerty.kmx new file mode 100644 index 0000000000..873f70b33b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/obolo_chwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/obolo_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/obolo_qwerty.kmx new file mode 100644 index 0000000000..7ef2dcdadb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/obolo_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/old_hungarian.kmx b/developer/src/kmcmplib/tests/fixtures/old_hungarian.kmx new file mode 100644 index 0000000000..ccb6ca06a4 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/old_hungarian.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/old_turkic_udw21_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/old_turkic_udw21_qwerty.kmx new file mode 100644 index 0000000000..3be7e17688 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/old_turkic_udw21_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/orma.kmx b/developer/src/kmcmplib/tests/fixtures/orma.kmx new file mode 100644 index 0000000000..63fb4e8cc0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/orma.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/osage_nation.kmx b/developer/src/kmcmplib/tests/fixtures/osage_nation.kmx new file mode 100644 index 0000000000..69333f2e45 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/osage_nation.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/osage_nation_new.kmx b/developer/src/kmcmplib/tests/fixtures/osage_nation_new.kmx new file mode 100644 index 0000000000..ead429bb10 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/osage_nation_new.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/otoe_missouria.kmx b/developer/src/kmcmplib/tests/fixtures/otoe_missouria.kmx new file mode 100644 index 0000000000..3722c24dbf Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/otoe_missouria.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/persian_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/persian_phonetic.kmx new file mode 100644 index 0000000000..89620cddcd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/persian_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/pid_piaroa.kmx b/developer/src/kmcmplib/tests/fixtures/pid_piaroa.kmx new file mode 100644 index 0000000000..4e8529646c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/pid_piaroa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/pingelap.kmx b/developer/src/kmcmplib/tests/fixtures/pingelap.kmx new file mode 100644 index 0000000000..a54eab2acc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/pingelap.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/postmodern_english_uk_dualstroke.kmx b/developer/src/kmcmplib/tests/fixtures/postmodern_english_uk_dualstroke.kmx new file mode 100644 index 0000000000..48859e2af0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/postmodern_english_uk_dualstroke.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/postmodern_english_uk_natural.kmx b/developer/src/kmcmplib/tests/fixtures/postmodern_english_uk_natural.kmx new file mode 100644 index 0000000000..e8db651d31 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/postmodern_english_uk_natural.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/postmodern_english_us_dualstroke.kmx b/developer/src/kmcmplib/tests/fixtures/postmodern_english_us_dualstroke.kmx new file mode 100644 index 0000000000..322b9fec3b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/postmodern_english_us_dualstroke.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/postmodern_english_us_natural.kmx b/developer/src/kmcmplib/tests/fixtures/postmodern_english_us_natural.kmx new file mode 100644 index 0000000000..8b96e384e0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/postmodern_english_us_natural.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/pukapuka.kmx b/developer/src/kmcmplib/tests/fixtures/pukapuka.kmx new file mode 100644 index 0000000000..8c892107a4 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/pukapuka.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/qom.kmx b/developer/src/kmcmplib/tests/fixtures/qom.kmx new file mode 100644 index 0000000000..ca6f9fb41d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/qom.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/quinault.kmx b/developer/src/kmcmplib/tests/fixtures/quinault.kmx new file mode 100644 index 0000000000..82f88cf241 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/quinault.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/qwerty_farang.kmx b/developer/src/kmcmplib/tests/fixtures/qwerty_farang.kmx new file mode 100644 index 0000000000..8f27dd42d2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/qwerty_farang.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_aer.kmx b/developer/src/kmcmplib/tests/fixtures/rac_aer.kmx new file mode 100644 index 0000000000..f32daed259 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_aer.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_arabic.kmx b/developer/src/kmcmplib/tests/fixtures/rac_arabic.kmx new file mode 100644 index 0000000000..ba7ffbaa40 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_arabic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_balti.kmx b/developer/src/kmcmplib/tests/fixtures/rac_balti.kmx new file mode 100644 index 0000000000..942b98e893 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_balti.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_brahui.kmx b/developer/src/kmcmplib/tests/fixtures/rac_brahui.kmx new file mode 100644 index 0000000000..6a0fd1cafa Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_brahui.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_brahui_latin.kmx b/developer/src/kmcmplib/tests/fixtures/rac_brahui_latin.kmx new file mode 100644 index 0000000000..6e63256900 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_brahui_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_burushaski.kmx b/developer/src/kmcmplib/tests/fixtures/rac_burushaski.kmx new file mode 100644 index 0000000000..3864031e74 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_burushaski.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_dameli.kmx b/developer/src/kmcmplib/tests/fixtures/rac_dameli.kmx new file mode 100644 index 0000000000..8eb9c3359d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_dameli.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_dhatki.kmx b/developer/src/kmcmplib/tests/fixtures/rac_dhatki.kmx new file mode 100644 index 0000000000..3e4abc594a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_dhatki.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_dogri.kmx b/developer/src/kmcmplib/tests/fixtures/rac_dogri.kmx new file mode 100644 index 0000000000..77345ca8a0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_dogri.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_gawar_bati.kmx b/developer/src/kmcmplib/tests/fixtures/rac_gawar_bati.kmx new file mode 100644 index 0000000000..dba08659fb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_gawar_bati.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_gawri.kmx b/developer/src/kmcmplib/tests/fixtures/rac_gawri.kmx new file mode 100644 index 0000000000..3ae6573be7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_gawri.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_hazaragi.kmx b/developer/src/kmcmplib/tests/fixtures/rac_hazaragi.kmx new file mode 100644 index 0000000000..d24481e117 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_hazaragi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_hindko.kmx b/developer/src/kmcmplib/tests/fixtures/rac_hindko.kmx new file mode 100644 index 0000000000..99453a79c5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_hindko.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_indus_kohistani.kmx b/developer/src/kmcmplib/tests/fixtures/rac_indus_kohistani.kmx new file mode 100644 index 0000000000..7966cfda01 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_indus_kohistani.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_kalasha.kmx b/developer/src/kmcmplib/tests/fixtures/rac_kalasha.kmx new file mode 100644 index 0000000000..de56a3d6a8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_kalasha.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_kashmir_shina.kmx b/developer/src/kmcmplib/tests/fixtures/rac_kashmir_shina.kmx new file mode 100644 index 0000000000..075f85bf48 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_kashmir_shina.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_kashmiri.kmx b/developer/src/kmcmplib/tests/fixtures/rac_kashmiri.kmx new file mode 100644 index 0000000000..f2c5ee0545 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_kashmiri.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_khowar.kmx b/developer/src/kmcmplib/tests/fixtures/rac_khowar.kmx new file mode 100644 index 0000000000..122edb343c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_khowar.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_marwari.kmx b/developer/src/kmcmplib/tests/fixtures/rac_marwari.kmx new file mode 100644 index 0000000000..6144b12ccc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_marwari.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_munji.kmx b/developer/src/kmcmplib/tests/fixtures/rac_munji.kmx new file mode 100644 index 0000000000..3714489c5b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_munji.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_oadki.kmx b/developer/src/kmcmplib/tests/fixtures/rac_oadki.kmx new file mode 100644 index 0000000000..7a94331ecb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_oadki.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_ormuri.kmx b/developer/src/kmcmplib/tests/fixtures/rac_ormuri.kmx new file mode 100644 index 0000000000..fe4dda40f0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_ormuri.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_pahari.kmx b/developer/src/kmcmplib/tests/fixtures/rac_pahari.kmx new file mode 100644 index 0000000000..64d842679a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_pahari.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_palula.kmx b/developer/src/kmcmplib/tests/fixtures/rac_palula.kmx new file mode 100644 index 0000000000..d6a28b1843 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_palula.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_parkari_koli.kmx b/developer/src/kmcmplib/tests/fixtures/rac_parkari_koli.kmx new file mode 100644 index 0000000000..3dd6be1d5c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_parkari_koli.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_pashai.kmx b/developer/src/kmcmplib/tests/fixtures/rac_pashai.kmx new file mode 100644 index 0000000000..965feaf6bd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_pashai.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_pashto.kmx b/developer/src/kmcmplib/tests/fixtures/rac_pashto.kmx new file mode 100644 index 0000000000..3d5bb2970f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_pashto.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_saraiki.kmx b/developer/src/kmcmplib/tests/fixtures/rac_saraiki.kmx new file mode 100644 index 0000000000..1cc25371ed Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_saraiki.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_shina.kmx b/developer/src/kmcmplib/tests/fixtures/rac_shina.kmx new file mode 100644 index 0000000000..818c4bb9e0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_shina.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_sindhi.kmx b/developer/src/kmcmplib/tests/fixtures/rac_sindhi.kmx new file mode 100644 index 0000000000..7cf18e2146 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_sindhi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_torwali.kmx b/developer/src/kmcmplib/tests/fixtures/rac_torwali.kmx new file mode 100644 index 0000000000..b9917e064b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_torwali.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_urdu.kmx b/developer/src/kmcmplib/tests/fixtures/rac_urdu.kmx new file mode 100644 index 0000000000..c46a0af0e0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_urdu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_ushojo.kmx b/developer/src/kmcmplib/tests/fixtures/rac_ushojo.kmx new file mode 100644 index 0000000000..e518f79d00 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_ushojo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_uyghur.kmx b/developer/src/kmcmplib/tests/fixtures/rac_uyghur.kmx new file mode 100644 index 0000000000..3bf55f9393 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_uyghur.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_wadiyara.kmx b/developer/src/kmcmplib/tests/fixtures/rac_wadiyara.kmx new file mode 100644 index 0000000000..8b1dcc69bf Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_wadiyara.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_wakhi.kmx b/developer/src/kmcmplib/tests/fixtures/rac_wakhi.kmx new file mode 100644 index 0000000000..c3acae747f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_wakhi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_western_punjabi.kmx b/developer/src/kmcmplib/tests/fixtures/rac_western_punjabi.kmx new file mode 100644 index 0000000000..eac2a21ec0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_western_punjabi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rac_yidgha.kmx b/developer/src/kmcmplib/tests/fixtures/rac_yidgha.kmx new file mode 100644 index 0000000000..5d777ce16c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rac_yidgha.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rawang.kmx b/developer/src/kmcmplib/tests/fixtures/rawang.kmx new file mode 100644 index 0000000000..5ef43d22be Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rawang.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rejang.kmx b/developer/src/kmcmplib/tests/fixtures/rejang.kmx new file mode 100644 index 0000000000..c04ff065e2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rejang.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/remington_gail.kmx b/developer/src/kmcmplib/tests/fixtures/remington_gail.kmx new file mode 100644 index 0000000000..16412933b6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/remington_gail.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rohingya_arab.kmx b/developer/src/kmcmplib/tests/fixtures/rohingya_arab.kmx new file mode 100644 index 0000000000..07e61629b5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rohingya_arab.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/rossel.kmx b/developer/src/kmcmplib/tests/fixtures/rossel.kmx new file mode 100644 index 0000000000..98bca0b946 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/rossel.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/runeboard.kmx b/developer/src/kmcmplib/tests/fixtures/runeboard.kmx new file mode 100644 index 0000000000..d41acc4124 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/runeboard.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/russian_mnemonic_r.kmx b/developer/src/kmcmplib/tests/fixtures/russian_mnemonic_r.kmx new file mode 100644 index 0000000000..e9a99d02db Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/russian_mnemonic_r.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sabdalipi_assamese.kmx b/developer/src/kmcmplib/tests/fixtures/sabdalipi_assamese.kmx new file mode 100644 index 0000000000..1b7f80b8b1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sabdalipi_assamese.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sahaptin_umatilla.kmx b/developer/src/kmcmplib/tests/fixtures/sahaptin_umatilla.kmx new file mode 100644 index 0000000000..bfac93d7e6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sahaptin_umatilla.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sahaptin_yakima.kmx b/developer/src/kmcmplib/tests/fixtures/sahaptin_yakima.kmx new file mode 100644 index 0000000000..53d610e7e7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sahaptin_yakima.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sanjha_punjabi.kmx b/developer/src/kmcmplib/tests/fixtures/sanjha_punjabi.kmx new file mode 100644 index 0000000000..739d018693 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sanjha_punjabi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/santali_latin.kmx b/developer/src/kmcmplib/tests/fixtures/santali_latin.kmx new file mode 100644 index 0000000000..5a0756301c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/santali_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/saraiki.kmx b/developer/src/kmcmplib/tests/fixtures/saraiki.kmx new file mode 100644 index 0000000000..260e96f5ca Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/saraiki.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/satere.kmx b/developer/src/kmcmplib/tests/fixtures/satere.kmx new file mode 100644 index 0000000000..e9af319388 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/satere.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/shahmukhi_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/shahmukhi_phonetic.kmx new file mode 100644 index 0000000000..0d8cdb54f7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/shahmukhi_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/shan.kmx b/developer/src/kmcmplib/tests/fixtures/shan.kmx new file mode 100644 index 0000000000..d84a72e3ee Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/shan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/shaw_2layer.kmx b/developer/src/kmcmplib/tests/fixtures/shaw_2layer.kmx new file mode 100644 index 0000000000..87cd30ad34 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/shaw_2layer.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/siddham_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/siddham_inscript.kmx new file mode 100644 index 0000000000..0f13960294 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/siddham_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_akha_act.kmx b/developer/src/kmcmplib/tests/fixtures/sil_akha_act.kmx new file mode 100644 index 0000000000..6a81a33d8b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_akha_act.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_arabic_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_arabic_phonetic.kmx new file mode 100644 index 0000000000..4caa43ac64 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_arabic_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_areare.kmx b/developer/src/kmcmplib/tests/fixtures/sil_areare.kmx new file mode 100644 index 0000000000..8ffe02d000 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_areare.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_bari.kmx b/developer/src/kmcmplib/tests/fixtures/sil_bari.kmx new file mode 100644 index 0000000000..639e50e028 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_bari.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_bengali_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_bengali_phonetic.kmx new file mode 100644 index 0000000000..dae551bdbd Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_bengali_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_bolivia.kmx b/developer/src/kmcmplib/tests/fixtures/sil_bolivia.kmx new file mode 100644 index 0000000000..75cf86a81d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_bolivia.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_boonkit.kmx b/developer/src/kmcmplib/tests/fixtures/sil_boonkit.kmx new file mode 100644 index 0000000000..dfd184f1ab Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_boonkit.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_brao.kmx b/developer/src/kmcmplib/tests/fixtures/sil_brao.kmx new file mode 100644 index 0000000000..80d140b65a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_brao.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_bru.kmx b/developer/src/kmcmplib/tests/fixtures/sil_bru.kmx new file mode 100644 index 0000000000..0bb31ea045 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_bru.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_buang.kmx b/developer/src/kmcmplib/tests/fixtures/sil_buang.kmx new file mode 100644 index 0000000000..288f2fb7fb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_buang.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_bunong.kmx b/developer/src/kmcmplib/tests/fixtures/sil_bunong.kmx new file mode 100644 index 0000000000..7eeaf731e1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_bunong.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_busa.kmx b/developer/src/kmcmplib/tests/fixtures/sil_busa.kmx new file mode 100644 index 0000000000..4e907fa2f2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_busa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_bwe_karen.kmx b/developer/src/kmcmplib/tests/fixtures/sil_bwe_karen.kmx new file mode 100644 index 0000000000..8fb25d32a6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_bwe_karen.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_cameroon_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_cameroon_azerty.kmx new file mode 100644 index 0000000000..da7f23d2d0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_cameroon_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_cameroon_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_cameroon_qwerty.kmx new file mode 100644 index 0000000000..0e3bf67607 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_cameroon_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_cherokee_nation.kmx b/developer/src/kmcmplib/tests/fixtures/sil_cherokee_nation.kmx new file mode 100644 index 0000000000..c568a85e05 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_cherokee_nation.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_cheyenne.kmx b/developer/src/kmcmplib/tests/fixtures/sil_cheyenne.kmx new file mode 100644 index 0000000000..0fef098219 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_cheyenne.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_cipher_music.kmx b/developer/src/kmcmplib/tests/fixtures/sil_cipher_music.kmx new file mode 100644 index 0000000000..f1eda8ec03 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_cipher_music.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_devanagari_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_devanagari_phonetic.kmx new file mode 100644 index 0000000000..f4a4a85f62 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_devanagari_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_devanagari_romanized.kmx b/developer/src/kmcmplib/tests/fixtures/sil_devanagari_romanized.kmx new file mode 100644 index 0000000000..dbb114e0c9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_devanagari_romanized.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_devanagari_typewriter.kmx b/developer/src/kmcmplib/tests/fixtures/sil_devanagari_typewriter.kmx new file mode 100644 index 0000000000..38dbb80085 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_devanagari_typewriter.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_dzongkha.kmx b/developer/src/kmcmplib/tests/fixtures/sil_dzongkha.kmx new file mode 100644 index 0000000000..d0a824cec8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_dzongkha.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_eastern_congo.kmx b/developer/src/kmcmplib/tests/fixtures/sil_eastern_congo.kmx new file mode 100644 index 0000000000..7d604831fb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_eastern_congo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_el_ethiopian_latin.kmx b/developer/src/kmcmplib/tests/fixtures/sil_el_ethiopian_latin.kmx new file mode 100644 index 0000000000..67834cb25c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_el_ethiopian_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_ethiopic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_ethiopic.kmx new file mode 100644 index 0000000000..3433f5c103 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_ethiopic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_ethiopic_power_g.kmx b/developer/src/kmcmplib/tests/fixtures/sil_ethiopic_power_g.kmx new file mode 100644 index 0000000000..ce697e4e16 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_ethiopic_power_g.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_euro_latin.kmx b/developer/src/kmcmplib/tests/fixtures/sil_euro_latin.kmx new file mode 100644 index 0000000000..60973192d7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_euro_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_extended_urdu_np.kmx b/developer/src/kmcmplib/tests/fixtures/sil_extended_urdu_np.kmx new file mode 100644 index 0000000000..3dd06bd052 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_extended_urdu_np.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_greek_polytonic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_greek_polytonic.kmx new file mode 100644 index 0000000000..904fdeea2b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_greek_polytonic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_hawaiian.kmx b/developer/src/kmcmplib/tests/fixtures/sil_hawaiian.kmx new file mode 100644 index 0000000000..74b83ca88a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_hawaiian.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_hebr_grek_trans.kmx b/developer/src/kmcmplib/tests/fixtures/sil_hebr_grek_trans.kmx new file mode 100644 index 0000000000..77128fbd01 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_hebr_grek_trans.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_hebrew.kmx b/developer/src/kmcmplib/tests/fixtures/sil_hebrew.kmx new file mode 100644 index 0000000000..18163f9a14 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_hebrew.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_hebrew_legacy.kmx b/developer/src/kmcmplib/tests/fixtures/sil_hebrew_legacy.kmx new file mode 100644 index 0000000000..0a8646d8ec Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_hebrew_legacy.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_hmd_plrd.kmx b/developer/src/kmcmplib/tests/fixtures/sil_hmd_plrd.kmx new file mode 100644 index 0000000000..b39614c213 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_hmd_plrd.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_indic_roman.kmx b/developer/src/kmcmplib/tests/fixtures/sil_indic_roman.kmx new file mode 100644 index 0000000000..f41b2cc8b3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_indic_roman.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_ipa.kmx b/developer/src/kmcmplib/tests/fixtures/sil_ipa.kmx new file mode 100644 index 0000000000..8d4d9d97e0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_ipa.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_jarai.kmx b/developer/src/kmcmplib/tests/fixtures/sil_jarai.kmx new file mode 100644 index 0000000000..90cc3a418d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_jarai.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_kayah_kali.kmx b/developer/src/kmcmplib/tests/fixtures/sil_kayah_kali.kmx new file mode 100644 index 0000000000..a4214e1dfc Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_kayah_kali.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_kayah_latn.kmx b/developer/src/kmcmplib/tests/fixtures/sil_kayah_latn.kmx new file mode 100644 index 0000000000..5ab026b835 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_kayah_latn.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_kayah_mymr.kmx b/developer/src/kmcmplib/tests/fixtures/sil_kayah_mymr.kmx new file mode 100644 index 0000000000..e918e45b0c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_kayah_mymr.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_khamti.kmx b/developer/src/kmcmplib/tests/fixtures/sil_khamti.kmx new file mode 100644 index 0000000000..52ed2dc0e3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_khamti.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_khmer.kmx b/developer/src/kmcmplib/tests/fixtures/sil_khmer.kmx new file mode 100644 index 0000000000..c53eb704f1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_khmer.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_khowar.kmx b/developer/src/kmcmplib/tests/fixtures/sil_khowar.kmx new file mode 100644 index 0000000000..8cd336d8e4 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_khowar.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_kmhmu.kmx b/developer/src/kmcmplib/tests/fixtures/sil_kmhmu.kmx new file mode 100644 index 0000000000..630c36cb3d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_kmhmu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_korda_jamo.kmx b/developer/src/kmcmplib/tests/fixtures/sil_korda_jamo.kmx new file mode 100644 index 0000000000..c03f35d313 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_korda_jamo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_korda_latin.kmx b/developer/src/kmcmplib/tests/fixtures/sil_korda_latin.kmx new file mode 100644 index 0000000000..e9f48e3013 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_korda_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_korean_morse.kmx b/developer/src/kmcmplib/tests/fixtures/sil_korean_morse.kmx new file mode 100644 index 0000000000..e2adba2aca Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_korean_morse.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_kvl_kayaw.kmx b/developer/src/kmcmplib/tests/fixtures/sil_kvl_kayaw.kmx new file mode 100644 index 0000000000..4dedd71853 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_kvl_kayaw.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_lepcha.kmx b/developer/src/kmcmplib/tests/fixtures/sil_lepcha.kmx new file mode 100644 index 0000000000..663bf4580e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_lepcha.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_limbu_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_limbu_phonetic.kmx new file mode 100644 index 0000000000..58ecb1a522 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_limbu_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_limbu_typewriter.kmx b/developer/src/kmcmplib/tests/fixtures/sil_limbu_typewriter.kmx new file mode 100644 index 0000000000..651bcbd28e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_limbu_typewriter.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_lisu_basic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_lisu_basic.kmx new file mode 100644 index 0000000000..d85fadca1c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_lisu_basic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_lisu_standard.kmx b/developer/src/kmcmplib/tests/fixtures/sil_lisu_standard.kmx new file mode 100644 index 0000000000..4eee9a9104 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_lisu_standard.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_lpo_plrd.kmx b/developer/src/kmcmplib/tests/fixtures/sil_lpo_plrd.kmx new file mode 100644 index 0000000000..616799187a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_lpo_plrd.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_madi.kmx b/developer/src/kmcmplib/tests/fixtures/sil_madi.kmx new file mode 100644 index 0000000000..d92aff331b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_madi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_makuri.kmx b/developer/src/kmcmplib/tests/fixtures/sil_makuri.kmx new file mode 100644 index 0000000000..eec4b8b1b7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_makuri.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_mali_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_mali_azerty.kmx new file mode 100644 index 0000000000..84dd3f53d2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_mali_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_mali_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_mali_qwerty.kmx new file mode 100644 index 0000000000..29e170f6e6 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_mali_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_mali_qwertz.kmx b/developer/src/kmcmplib/tests/fixtures/sil_mali_qwertz.kmx new file mode 100644 index 0000000000..b5bd341386 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_mali_qwertz.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_moore.kmx b/developer/src/kmcmplib/tests/fixtures/sil_moore.kmx new file mode 100644 index 0000000000..72e3778d5e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_moore.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_myanmar_my3.kmx b/developer/src/kmcmplib/tests/fixtures/sil_myanmar_my3.kmx new file mode 100644 index 0000000000..ad1cb863a9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_myanmar_my3.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_myanmar_mywinext.kmx b/developer/src/kmcmplib/tests/fixtures/sil_myanmar_mywinext.kmx new file mode 100644 index 0000000000..d19b8ecdb5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_myanmar_mywinext.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_nigeria_dot.kmx b/developer/src/kmcmplib/tests/fixtures/sil_nigeria_dot.kmx new file mode 100644 index 0000000000..d15171d8a1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_nigeria_dot.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_nigeria_odd_vowels.kmx b/developer/src/kmcmplib/tests/fixtures/sil_nigeria_odd_vowels.kmx new file mode 100644 index 0000000000..f6d6b9cb09 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_nigeria_odd_vowels.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_nigeria_underline.kmx b/developer/src/kmcmplib/tests/fixtures/sil_nigeria_underline.kmx new file mode 100644 index 0000000000..adb38082b2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_nigeria_underline.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_nko.kmx b/developer/src/kmcmplib/tests/fixtures/sil_nko.kmx new file mode 100644 index 0000000000..5616c8bb58 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_nko.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_nubian.kmx b/developer/src/kmcmplib/tests/fixtures/sil_nubian.kmx new file mode 100644 index 0000000000..bc178a0659 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_nubian.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_pan_africa_mnemonic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_pan_africa_mnemonic.kmx new file mode 100644 index 0000000000..dd3551d2ba Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_pan_africa_mnemonic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_pan_africa_positional.kmx b/developer/src/kmcmplib/tests/fixtures/sil_pan_africa_positional.kmx new file mode 100644 index 0000000000..ab7eb053d9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_pan_africa_positional.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_philippines.kmx b/developer/src/kmcmplib/tests/fixtures/sil_philippines.kmx new file mode 100644 index 0000000000..fd5db7d4f4 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_philippines.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_sahu.kmx b/developer/src/kmcmplib/tests/fixtures/sil_sahu.kmx new file mode 100644 index 0000000000..e5548549a7 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_sahu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_bsc_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_bsc_azerty.kmx new file mode 100644 index 0000000000..b7162c461f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_bsc_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_cou_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_cou_azerty.kmx new file mode 100644 index 0000000000..b74e2888f2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_cou_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_dyo_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_dyo_azerty.kmx new file mode 100644 index 0000000000..91de009800 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_dyo_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_gsl_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_gsl_azerty.kmx new file mode 100644 index 0000000000..8db0110549 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_gsl_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_krx_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_krx_azerty.kmx new file mode 100644 index 0000000000..74ec159fb0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_krx_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_ndv_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_ndv_azerty.kmx new file mode 100644 index 0000000000..0afef1c629 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_ndv_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_sav_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_sav_azerty.kmx new file mode 100644 index 0000000000..bfc3da4321 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_sav_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_snf_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_snf_azerty.kmx new file mode 100644 index 0000000000..69f9a2a067 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_snf_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_srr_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_srr_azerty.kmx new file mode 100644 index 0000000000..2d1eea7ade Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_srr_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_senegal_wo_azerty.kmx b/developer/src/kmcmplib/tests/fixtures/sil_senegal_wo_azerty.kmx new file mode 100644 index 0000000000..c041de1fce Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_senegal_wo_azerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_sgaw_karen.kmx b/developer/src/kmcmplib/tests/fixtures/sil_sgaw_karen.kmx new file mode 100644 index 0000000000..96212bf1b2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_sgaw_karen.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_shan.kmx b/developer/src/kmcmplib/tests/fixtures/sil_shan.kmx new file mode 100644 index 0000000000..35a91760f2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_shan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_tai_dam.kmx b/developer/src/kmcmplib/tests/fixtures/sil_tai_dam.kmx new file mode 100644 index 0000000000..fe7dd8513c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_tai_dam.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_lao.kmx b/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_lao.kmx new file mode 100644 index 0000000000..9e400619ea Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_lao.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_latin.kmx b/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_latin.kmx new file mode 100644 index 0000000000..e05aa9b5c1 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_typewriter.kmx b/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_typewriter.kmx new file mode 100644 index 0000000000..7db476799f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_tai_dam_typewriter.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_tawallammat.kmx b/developer/src/kmcmplib/tests/fixtures/sil_tawallammat.kmx new file mode 100644 index 0000000000..f863586f92 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_tawallammat.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_tchad.kmx b/developer/src/kmcmplib/tests/fixtures/sil_tchad.kmx new file mode 100644 index 0000000000..19802d3726 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_tchad.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_tepehuan.kmx b/developer/src/kmcmplib/tests/fixtures/sil_tepehuan.kmx new file mode 100644 index 0000000000..2a591d6463 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_tepehuan.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_torwali.kmx b/developer/src/kmcmplib/tests/fixtures/sil_torwali.kmx new file mode 100644 index 0000000000..c31bd27e43 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_torwali.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_tunisian.kmx b/developer/src/kmcmplib/tests/fixtures/sil_tunisian.kmx new file mode 100644 index 0000000000..ff3d6abdf0 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_tunisian.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_uganda_tanzania.kmx b/developer/src/kmcmplib/tests/fixtures/sil_uganda_tanzania.kmx new file mode 100644 index 0000000000..852f028d51 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_uganda_tanzania.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_vai.kmx b/developer/src/kmcmplib/tests/fixtures/sil_vai.kmx new file mode 100644 index 0000000000..eac0c3ff1e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_vai.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_wayuu.kmx b/developer/src/kmcmplib/tests/fixtures/sil_wayuu.kmx new file mode 100644 index 0000000000..a3a2499d0d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_wayuu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_ygp_plrd.kmx b/developer/src/kmcmplib/tests/fixtures/sil_ygp_plrd.kmx new file mode 100644 index 0000000000..ff801a19bb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_ygp_plrd.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_yi.kmx b/developer/src/kmcmplib/tests/fixtures/sil_yi.kmx new file mode 100644 index 0000000000..c4bb0ad3ea Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_yi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_yna_plrd.kmx b/developer/src/kmcmplib/tests/fixtures/sil_yna_plrd.kmx new file mode 100644 index 0000000000..e37835c6ed Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_yna_plrd.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_yoruba8.kmx b/developer/src/kmcmplib/tests/fixtures/sil_yoruba8.kmx new file mode 100644 index 0000000000..eee1e94330 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_yoruba8.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_yoruba_bar.kmx b/developer/src/kmcmplib/tests/fixtures/sil_yoruba_bar.kmx new file mode 100644 index 0000000000..e3c2b99799 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_yoruba_bar.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_yoruba_dot.kmx b/developer/src/kmcmplib/tests/fixtures/sil_yoruba_dot.kmx new file mode 100644 index 0000000000..b9aadb35b9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_yoruba_dot.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_yupik_cyrillic.kmx b/developer/src/kmcmplib/tests/fixtures/sil_yupik_cyrillic.kmx new file mode 100644 index 0000000000..e804035650 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_yupik_cyrillic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_yupik_cyrillic_ru.kmx b/developer/src/kmcmplib/tests/fixtures/sil_yupik_cyrillic_ru.kmx new file mode 100644 index 0000000000..d404a12d71 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_yupik_cyrillic_ru.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sil_ywq_plrd.kmx b/developer/src/kmcmplib/tests/fixtures/sil_ywq_plrd.kmx new file mode 100644 index 0000000000..a9d75854a3 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sil_ywq_plrd.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/slc_saliba.kmx b/developer/src/kmcmplib/tests/fixtures/slc_saliba.kmx new file mode 100644 index 0000000000..b74127fa0c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/slc_saliba.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/soqotri_arabic.kmx b/developer/src/kmcmplib/tests/fixtures/soqotri_arabic.kmx new file mode 100644 index 0000000000..25955c6bdb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/soqotri_arabic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/srr_ajami_qwerty.kmx b/developer/src/kmcmplib/tests/fixtures/srr_ajami_qwerty.kmx new file mode 100644 index 0000000000..12b4230ab9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/srr_ajami_qwerty.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sundanese.kmx b/developer/src/kmcmplib/tests/fixtures/sundanese.kmx new file mode 100644 index 0000000000..d1ed7f30bb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sundanese.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sundanese_latin.kmx b/developer/src/kmcmplib/tests/fixtures/sundanese_latin.kmx new file mode 100644 index 0000000000..0b4a82916a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sundanese_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/swanalekha_malayalam.kmx b/developer/src/kmcmplib/tests/fixtures/swanalekha_malayalam.kmx new file mode 100644 index 0000000000..0becf6aa5c Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/swanalekha_malayalam.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sxava.kmx b/developer/src/kmcmplib/tests/fixtures/sxava.kmx new file mode 100644 index 0000000000..7a4d834756 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sxava.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sxava_eo.kmx b/developer/src/kmcmplib/tests/fixtures/sxava_eo.kmx new file mode 100644 index 0000000000..3023034630 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sxava_eo.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/sylheti_nagri.kmx b/developer/src/kmcmplib/tests/fixtures/sylheti_nagri.kmx new file mode 100644 index 0000000000..81b39c7d47 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/sylheti_nagri.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/syriac_arabic.kmx b/developer/src/kmcmplib/tests/fixtures/syriac_arabic.kmx new file mode 100644 index 0000000000..a35c4a6663 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/syriac_arabic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/syriac_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/syriac_phonetic.kmx new file mode 100644 index 0000000000..057cadf299 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/syriac_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tagbanwa_inscript.kmx b/developer/src/kmcmplib/tests/fixtures/tagbanwa_inscript.kmx new file mode 100644 index 0000000000..ad8f6e992f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tagbanwa_inscript.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/taigi_poj.kmx b/developer/src/kmcmplib/tests/fixtures/taigi_poj.kmx new file mode 100644 index 0000000000..f0266317fb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/taigi_poj.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tainua.kmx b/developer/src/kmcmplib/tests/fixtures/tainua.kmx new file mode 100644 index 0000000000..a7c5302597 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tainua.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tangsa_lakhum.kmx b/developer/src/kmcmplib/tests/fixtures/tangsa_lakhum.kmx new file mode 100644 index 0000000000..f92abaad90 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tangsa_lakhum.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tawallammat_latin.kmx b/developer/src/kmcmplib/tests/fixtures/tawallammat_latin.kmx new file mode 100644 index 0000000000..4ffcea4767 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tawallammat_latin.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/teggargrent_lat.kmx b/developer/src/kmcmplib/tests/fixtures/teggargrent_lat.kmx new file mode 100644 index 0000000000..30988061fb Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/teggargrent_lat.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tem_kdh.kmx b/developer/src/kmcmplib/tests/fixtures/tem_kdh.kmx new file mode 100644 index 0000000000..78e7b891b8 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tem_kdh.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/thamizha_anjal_paangu.kmx b/developer/src/kmcmplib/tests/fixtures/thamizha_anjal_paangu.kmx new file mode 100644 index 0000000000..5cef67f7a9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/thamizha_anjal_paangu.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/thamizha_bamini.kmx b/developer/src/kmcmplib/tests/fixtures/thamizha_bamini.kmx new file mode 100644 index 0000000000..13b6655801 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/thamizha_bamini.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/thamizha_new_typewriter.kmx b/developer/src/kmcmplib/tests/fixtures/thamizha_new_typewriter.kmx new file mode 100644 index 0000000000..0213650e6a Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/thamizha_new_typewriter.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/thamizha_tamil99_ext.kmx b/developer/src/kmcmplib/tests/fixtures/thamizha_tamil99_ext.kmx new file mode 100644 index 0000000000..fc6a07a9c2 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/thamizha_tamil99_ext.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tibetan_direct_input.kmx b/developer/src/kmcmplib/tests/fixtures/tibetan_direct_input.kmx new file mode 100644 index 0000000000..d13c37c692 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tibetan_direct_input.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tibetan_ewts.kmx b/developer/src/kmcmplib/tests/fixtures/tibetan_ewts.kmx new file mode 100644 index 0000000000..3db3c74b93 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tibetan_ewts.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tirhuta.kmx b/developer/src/kmcmplib/tests/fixtures/tirhuta.kmx new file mode 100644 index 0000000000..722eacc10b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tirhuta.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tlahuica.kmx b/developer/src/kmcmplib/tests/fixtures/tlahuica.kmx new file mode 100644 index 0000000000..c2a4aa4a8f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tlahuica.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tsakonian.kmx b/developer/src/kmcmplib/tests/fixtures/tsakonian.kmx new file mode 100644 index 0000000000..d2530e34be Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tsakonian.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/tuareg_tifinagh.kmx b/developer/src/kmcmplib/tests/fixtures/tuareg_tifinagh.kmx new file mode 100644 index 0000000000..a007e67e55 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/tuareg_tifinagh.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/turkmen_cyrl.kmx b/developer/src/kmcmplib/tests/fixtures/turkmen_cyrl.kmx new file mode 100644 index 0000000000..805865a77f Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/turkmen_cyrl.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/txo_toto.kmx b/developer/src/kmcmplib/tests/fixtures/txo_toto.kmx new file mode 100644 index 0000000000..f54ba9b1ef Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/txo_toto.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/udi_keyboard.kmx b/developer/src/kmcmplib/tests/fixtures/udi_keyboard.kmx new file mode 100644 index 0000000000..0312e80010 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/udi_keyboard.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/ukwuani.kmx b/developer/src/kmcmplib/tests/fixtures/ukwuani.kmx new file mode 100644 index 0000000000..94f0349856 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/ukwuani.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/uma_graphic.kmx b/developer/src/kmcmplib/tests/fixtures/uma_graphic.kmx new file mode 100644 index 0000000000..a19a27489e Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/uma_graphic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/uma_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/uma_phonetic.kmx new file mode 100644 index 0000000000..74bcef0a5d Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/uma_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/urdu_phonetic.kmx b/developer/src/kmcmplib/tests/fixtures/urdu_phonetic.kmx new file mode 100644 index 0000000000..34cf644632 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/urdu_phonetic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/urdu_phonetic_crulp.kmx b/developer/src/kmcmplib/tests/fixtures/urdu_phonetic_crulp.kmx new file mode 100644 index 0000000000..ecdc3419be Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/urdu_phonetic_crulp.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/venetia_et_histria.kmx b/developer/src/kmcmplib/tests/fixtures/venetia_et_histria.kmx new file mode 100644 index 0000000000..277314fd88 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/venetia_et_histria.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/vm_tamil_modular.kmx b/developer/src/kmcmplib/tests/fixtures/vm_tamil_modular.kmx new file mode 100644 index 0000000000..3afbbac8ee Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/vm_tamil_modular.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/vm_tamil_typewriter.kmx b/developer/src/kmcmplib/tests/fixtures/vm_tamil_typewriter.kmx new file mode 100644 index 0000000000..c93a9b5f2b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/vm_tamil_typewriter.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/wakhi_anglicized.kmx b/developer/src/kmcmplib/tests/fixtures/wakhi_anglicized.kmx new file mode 100644 index 0000000000..8ff5d267c9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/wakhi_anglicized.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/wakhi_cyrillic.kmx b/developer/src/kmcmplib/tests/fixtures/wakhi_cyrillic.kmx new file mode 100644 index 0000000000..fd86f63d25 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/wakhi_cyrillic.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/wakhi_standard.kmx b/developer/src/kmcmplib/tests/fixtures/wakhi_standard.kmx new file mode 100644 index 0000000000..4ceb2540ad Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/wakhi_standard.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/wancho.kmx b/developer/src/kmcmplib/tests/fixtures/wancho.kmx new file mode 100644 index 0000000000..68ab51c6e9 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/wancho.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/warang_citi.kmx b/developer/src/kmcmplib/tests/fixtures/warang_citi.kmx new file mode 100644 index 0000000000..f36f714a86 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/warang_citi.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/wolofal.kmx b/developer/src/kmcmplib/tests/fixtures/wolofal.kmx new file mode 100644 index 0000000000..b3cc61d413 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/wolofal.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/xinaliq.kmx b/developer/src/kmcmplib/tests/fixtures/xinaliq.kmx new file mode 100644 index 0000000000..4eb748763b Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/xinaliq.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/yiddish_pasekh.kmx b/developer/src/kmcmplib/tests/fixtures/yiddish_pasekh.kmx new file mode 100644 index 0000000000..3836c816d5 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/yiddish_pasekh.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/yidgha.kmx b/developer/src/kmcmplib/tests/fixtures/yidgha.kmx new file mode 100644 index 0000000000..7544013c02 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/yidgha.kmx differ diff --git a/developer/src/kmcmplib/tests/fixtures/younger_futhark_short_twig.kmx b/developer/src/kmcmplib/tests/fixtures/younger_futhark_short_twig.kmx new file mode 100644 index 0000000000..81761ab904 Binary files /dev/null and b/developer/src/kmcmplib/tests/fixtures/younger_futhark_short_twig.kmx differ diff --git a/developer/src/kmcmplib/tests/get-test-source.sh b/developer/src/kmcmplib/tests/get-test-source.sh new file mode 100755 index 0000000000..13bea90e13 --- /dev/null +++ b/developer/src/kmcmplib/tests/get-test-source.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# +# Finds all keyboards in the keyboards repo (passed in $1) that are valid source +# keyboards (i.e. ///source/.kmn) +# +# Called from meson.build, so this script does not use build-utils.sh. Do not run this +# script directly. +# +set -eu +find "$1" -name '*.kmn' | grep -E '(release|experimental)/([a-z0-9_]+)/([a-z0-9_]+)/source/\3\.kmn$' diff --git a/developer/src/kmcmplib/tests/keyboards_commit_ref.txt b/developer/src/kmcmplib/tests/keyboards_commit_ref.txt new file mode 100644 index 0000000000..c8db9ade54 --- /dev/null +++ b/developer/src/kmcmplib/tests/keyboards_commit_ref.txt @@ -0,0 +1 @@ +965ef1941f20a3bc0cb5d405792b4984cc46cd52 diff --git a/developer/src/kmcmplib/tests/kmcompxtest.cpp b/developer/src/kmcmplib/tests/kmcompxtest.cpp new file mode 100644 index 0000000000..1ce542917d --- /dev/null +++ b/developer/src/kmcmplib/tests/kmcompxtest.cpp @@ -0,0 +1,233 @@ +/* + * Keyman is copyright (C) SIL International. MIT License. + * + * Tiny frame console app to compile a .kmx from a .kmn + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER +#else +#include +#endif + +using namespace std; + +vector < int > error_vec; + +#define CERR_FATAL 0x00008000 +#define CERR_ERROR 0x00004000 +#define CERR_WARNING 0x00002000 +#define CERR_HINT 0x00001000 + +int msgproc(int line, uint32_t dwMsgCode, char* szText, void* context) +{ + error_vec.push_back(dwMsgCode); + const char*t = "unknown"; + switch(dwMsgCode & 0xF000) { + case CERR_HINT: t=" hint"; break; + case CERR_WARNING: t="warning"; break; + case CERR_ERROR: t=" error"; break; + case CERR_FATAL: t=" fatal"; break; + } + printf("line %d %s %04.4x: %s\n", line, t, (unsigned int)dwMsgCode, szText); + return 1; +} + +#include "../src/filesystem.h" + +int main(int argc, char *argv[]) +{ + if(argc < 4) { + puts("Usage: kmcompxtest source.kmn output.kmx fixture.kmx"); + return __LINE__; + } + + char* kmn_file = argv[1]; + char* kmx_file = argv[2]; + char* reference_kmx = argv[3]; + + // Replace \ with / + for(char *p = kmn_file; *p; p++) { + if(*p == '\\') *p = '/'; + } + + for(char *p = kmx_file; *p; p++) { + if(*p == '\\') *p = '/'; + } + + for(char *p = reference_kmx; *p; p++) { + if(*p == '\\') *p = '/'; + } + + char first5[6] = "CERR_"; + char* pfirst5 = first5; + + KMCMP_COMPILER_OPTIONS kcopts; + kcopts.dwSize = sizeof(KMCMP_COMPILER_OPTIONS); + kcopts.ShouldAddCompilerVersion = false; // So we can compare against existing compiled keyboards that also don't have compiler version + if(!kmcmp_SetCompilerOptions(&kcopts)) { + return __LINE__; + } + + if(kmcmp_CompileKeyboardFile(kmn_file, kmx_file, true, false, true, msgproc, nullptr)) { + char* testname = strrchr( (char*) kmn_file, '/') + 1; + if(strncmp(testname, pfirst5, 5) == 0){ + return __LINE__; // exit code: CERR_ in Name + no Error found + } + + // On non-win32 platforms, we cannot get kmcmpdll.dll to build keyboards + // legacy-mode, so we'll compare to a hopefully existing file that we've + // been passed + FILE* fp1 = Open_File(kmx_file, "rb"); + if(!fp1) return __LINE__; + + + FILE* fp2 = Open_File(reference_kmx, "rb"); + if(!fp2) return __LINE__; // exit code: fail if no reference kmx file in build-folder + + fseek(fp1, 0, SEEK_END); + auto sz1 = ftell(fp1); + fseek(fp1, 0, SEEK_SET); + fseek(fp2, 0, SEEK_END); + auto sz2 = ftell(fp2); + fseek(fp2, 0, SEEK_SET); + if (sz1 != sz2) return __LINE__; // exit code: size of kmx-file in build differs from size of kmx-file in source folder + + char* buf1 = new char[sz1]; + char* buf2 = new char[sz1]; + fread(buf1, 1, sz1, fp1); + fread(buf2, 1, sz1, fp2); + return memcmp(buf1, buf2, sz1) ? __LINE__ : 0; // exit code: when contents of kmx-file in build differs from contents of kmx-file in source folder + // success: when contents of kmx-file in build and source folder are the same + } + else { /*if Errors found: check number (e.g. CERR_4061_balochi_phonetic.kmn should produce Error 4061)*/ + int error_val = 0; + char* testname = strrchr( (char*) kmn_file, '/') + 1; + + // Does testname contain CERR_ && contains '_' on pos 9 ? -> Get ErrorValue + if ((strncmp(testname, pfirst5, 5) == 0) && (testname[9] == '_')) { + char* ErrNr = strchr(testname, '_') +1 ; + std::istringstream(ErrNr) >> std::hex >> error_val; + + // check if error_val is in Array of Errors; if it is found return 0 (it's not an error) + for (int i = 0; i < error_vec.size() ; i++) { + if (error_vec[i] == error_val) { + return 0; // success: CERR_ in Name + Error (specified in CERR_Name) IS found + } + } + return __LINE__; // exit code: CERR_ in Name + Error (specified in CERR_Name) is NOT found + } + return __LINE__; // exit code: no correct CERR_ in Name + CompileKeyboardFile failed (i.e. test config is invalid) + } +} + + +bool equalIgnoreCase(const string& a, const string& b) +{ + return std::equal( + a.begin(), a.end(), + b.begin(), b.end(), + [](char a, char b) { + return tolower(a) == tolower(b); + } + ); +} + +// Returns TRUE if the keyboard has a &TARGETS store with +// 'any', 'windows', 'macosx', 'linux', or 'desktop' targets, +// or if no &TARGETS store exists (which is equivalent to +// 'windows'). +bool isDesktopKeyboard(FILE* fp) { + COMP_KEYBOARD fk; + + if(fseek(fp, 0, SEEK_SET) != 0) { + printf("isDesktopKeyboard: fseek(0) failed\n"); + exit(1); + } + + if(!fread(&fk, sizeof(fk), 1, fp)) { + printf("isDesktopKeyboard failed: could not read COMP_KEYBOARD\n"); + exit(1); + } + + // Note: this code assumes a valid .kmx. This is okay for a unit test + if(fseek(fp, fk.dpStoreArray, SEEK_SET) != 0) { + printf("isDesktopKeyboard failed: could not locate fk.dpStoreArray=%x\n", fk.dpStoreArray); + exit(1); + } + + PCOMP_STORE pfs = new COMP_STORE[fk.cxStoreArray]; + if(fread(pfs, sizeof(COMP_STORE), fk.cxStoreArray, fp) != fk.cxStoreArray) { + printf("isDesktopKeyboard failed: could not read fk.dpStoreArray=%x [%x]\n", fk.dpStoreArray, fk.cxStoreArray); + exit(1); + } + + PCOMP_STORE s = pfs; + + for(int i = 0; i < fk.cxStoreArray; i++, s++) { + if(s->dwSystemID != TSS_TARGETS) { + continue; + } + + // Read targets store + if(fseek(fp, s->dpString, SEEK_SET) != 0) { + printf("isDesktopKeyboard: could not seek to TSS_TARGETS.dpString %x\n", s->dpString); + exit(1); + } + + KMX_WCHAR buf[256]; + if(fread(buf, sizeof(KMX_WCHAR), 256, fp) == 0) { + printf("isDesktopKeyboard: could not read TSS_TARGETS.dpString %x\n", s->dpString); + exit(1); + } + buf[255] = 0; // sanity + + if(fseek(fp, 0, SEEK_SET) != 0) { + printf("isDesktopKeyboard: fseek(0) failed\n"); + exit(1); + } + + std::string targets1 = string_from_u16string(buf); + std::stringstream targets(targets1); + std::string target; + + printf("isDesktopKeyboard: TSS_TARGETS: %s\n", targets1.c_str()); + + delete[] pfs; + + while(targets >> target) { + //Matches KMXKeymanTargets from UKeymanTargets.pas + if(equalIgnoreCase(target, "any") || + equalIgnoreCase(target, "windows") || + equalIgnoreCase(target, "macosx") || + equalIgnoreCase(target, "linux") || + equalIgnoreCase(target, "desktop") + ) { + printf("isDesktopKeyboard: TSS_TARGETS does contain desktop target %s\n", target.c_str()); + return true; + } + } + + printf("isDesktopKeyboard: TSS_TARGETS does not contain desktop target\n"); + return false; + } + + delete[] pfs; + + if(fseek(fp, 0, SEEK_SET) != 0) { + printf("isDesktopKeyboard: fseek(0) failed\n"); + exit(1); + } + + printf("isDesktopKeyboard: TSS_TARGETS does not exist\n"); + return true; +} diff --git a/developer/src/kmcmplib/tests/meson.build b/developer/src/kmcmplib/tests/meson.build new file mode 100644 index 0000000000..71817ea3c5 --- /dev/null +++ b/developer/src/kmcmplib/tests/meson.build @@ -0,0 +1,104 @@ +# +# Keyman is copyright (C) SIL International. MIT License. +# +# Cross platform build script to compile and run tests for kmcompx +# + +fs = import('fs') + +tests_flags = [] + +input_path = meson.current_source_dir() / '../../../../core/tests/unit/kmx' +output_path = meson.current_build_dir() + +kmcompxtest = executable('kmcompxtest', 'kmcompxtest.cpp', + cpp_args: defns, + include_directories: inc, + link_args: links + tests_flags, + objects: lib.extract_all_objects()) + +# Test keyboards that we have in Core + +tests = [ + '000 - null keyboard', + '001 - basic input UnicodeI', + '002 - basic input Unicode', + '003 - nul', + '004 - basic input (shift 2)', + '005 - nul with initial context', + '006 - vkey input (shift ctrl)', + '007 - vkey input (ctrl alt)', + '008 - vkey input (ctrl alt 2)', + '012 - ralt', + '013 - deadkeys', + '014 - groups and virtual keys', + '015 - ralt 2', + '017 - space mnemonic kbd', + '018 - nul testing', + '019 - multiple deadkeys', + '020 - deadkeys and backspace', + + '021 - options', + '022 - options with preset', + '023 - options with save', + '024 - options with save and preset', + '025 - options with reset', + + '026 - system stores', + '027 - system stores 2', + + '028 - smp', + '029 - beep', + + '030 - multiple groups', + '031 - caps lock', + '032 - caps control', + '033 - caps always off', + '034 - options double set reset', + '035 - options double set staged', + '036 - options - double reset staged', + '037 - options - double reset', + '038 - punctkeys', + '039 - generic ctrlalt', + '040 - long context', + '041 - long context and deadkeys', + '042 - long context and split deadkeys', + '043 - output and keystroke', + + '044 - if and context', + '045 - deadkey and context', + '046 - deadkey and contextex', + '047 - caps always off initially on', + '048 - modifier keys keep context' +] + +foreach kbd : tests + kbd_src = join_paths(input_path, kbd) + '.kmn' + kbd_obj = join_paths(output_path, kbd) + '.kmx' + test(kbd, kmcompxtest, args: [kbd_src, kbd_obj, join_paths(input_path, kbd) + '.kmx']) +endforeach + +# Test fixtures that come from keyboards repo + +keyboards_root = meson.current_source_dir() / 'keyboards' + +if build_machine.system() == 'windows' + test_source = run_command('run-shell.bat', 'get-test-source.sh', keyboards_root, capture: true, check: true) +else + test_source = run_command('get_test_source.sh', keyboards_root, capture: true, check: true) +endif + +tests = test_source.stdout().strip().split('\n') + +foreach kbd : tests + test_basename = fs.replace_suffix(fs.name(kbd), '') + + # kbd is going to be an absolute path + kbd_obj = output_path / test_basename + '.kmx' + reference_kmx = meson.current_source_dir() / 'fixtures' / test_basename + '.kmx' + + if fs.is_file(reference_kmx) + test(test_basename, kmcompxtest, args: [kbd, kbd_obj, reference_kmx]) + endif +endforeach + diff --git a/developer/src/kmcmplib/tests/prep.sh b/developer/src/kmcmplib/tests/prep.sh new file mode 100755 index 0000000000..058d4a1b9b --- /dev/null +++ b/developer/src/kmcmplib/tests/prep.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# +# Generates fixtures for testing against the legacy compiler +# +# Assumes that the +# + +# Exit on command failure and when using unset variables: +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../../resources/build/build-utils.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +builder_describe \ +"Generates fixtures for testing against the legacy compiler. + + Developer must be built locally and binaries should be in developer/bin/. + + Assumes that the keyboards repository exists and is clean. Will record the + commit hash to allow corresponding CI builds to use the same commit hash + for validation." \ + clean \ + build \ + "--keyboards-root,-k=KEYBOARDS_ROOT Path to keyboards repository" + +builder_parse "$@" + +if ! builder_has_option --keyboards-root; then + builder_die "--keyboards-root option is required" +fi + +if [[ ! -d "$KEYBOARDS_ROOT/.git" ]] || [[ ! -f "$KEYBOARDS_ROOT/tools/regression.sh" ]]; then + builder_die "Path $KEYBOARDS_ROOT does not appear to be a valid keyboard repository" +fi + +if builder_start_action clean; then + rm -rf "$THIS_SCRIPT_PATH/fixtures" + rm -f "$THIS_SCRIPT_PATH/keyboards_commit_ref.txt" + builder_finish_action success clean +fi + +if builder_start_action build; then + # yes, remove existing fixtures before build so we don't end up with stale fixtures + rm -rf "$THIS_SCRIPT_PATH/fixtures" + + # record the revision of the keyboards repo + pushd "$KEYBOARDS_ROOT" > /dev/null + git rev-parse head > "$THIS_SCRIPT_PATH/keyboards_commit_ref.txt" + popd > /dev/null + + "$KEYBOARDS_ROOT/tools/regression.sh" --use-legacy-compiler --local "$KEYMAN_ROOT/developer/bin/" --output "$THIS_SCRIPT_PATH/fixtures/" + + cd "$THIS_SCRIPT_PATH" + + # We don't need visual keyboards + rm ./fixtures/*.kvk + # Nor do we need kmw outputs + rm ./fixtures/*.js + # Finally, we remove any keyboards over 500kb, as we won't automatically test them for now + # TODO: consider if we want to keep those large keyboards in the future + find ./fixtures/ -size +500k -exec rm {} \+ + builder_finish_action success build +fi \ No newline at end of file diff --git a/developer/src/kmcmplib/tests/run-shell.bat b/developer/src/kmcmplib/tests/run-shell.bat new file mode 100644 index 0000000000..f0a51d7869 --- /dev/null +++ b/developer/src/kmcmplib/tests/run-shell.bat @@ -0,0 +1,7 @@ +@echo off +if defined GIT_BASH_FOR_KEYMAN ( + set GIT_BASH=%GIT_BASH_FOR_KEYMAN% +) else ( + set GIT_BASH="%ProgramFiles%\git\bin\bash.exe" --init-file "%ProgramFiles%\Git\etc\profile" -l +) +%GIT_BASH% %1 %2 %3 %4 %5 %6 %7 %8 %9 \ No newline at end of file diff --git a/developer/src/kmcmplib/version.rc b/developer/src/kmcmplib/version.rc new file mode 100644 index 0000000000..b963c10ddb --- /dev/null +++ b/developer/src/kmcmplib/version.rc @@ -0,0 +1,32 @@ +#include "../../../common/windows/cpp/include/keymanversion.h" + +1 VERSIONINFO + FILEVERSION KV_FILEVERSION + PRODUCTVERSION KV_PRODUCTVERSION + FILEFLAGSMASK 0x3fL + FILEFLAGS 0x0L + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "0C0904E4" + BEGIN + VALUE "CompanyName", KV_COMPANY_NAME + VALUE "FileDescription", "Keyman compiler library\0" + VALUE "FileVersion", KV_VERSION_STRING + VALUE "InternalName", "KMCOMP\0" + VALUE "LegalCopyright", KV_LEGAL_COPYRIGHT + VALUE "LegalTrademarks", KV_LEGAL_TRADEMARKS + VALUE "OriginalFilename", "KMCOMP.DLL\0" + VALUE "ProductName", "Keyman Developer\0" + VALUE "ProductVersion", KV_VERSION_STRING + VALUE "Comments", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0xc09, 1252 + END + END diff --git a/developer/src/kmcmplib/wasm.build.linux.in b/developer/src/kmcmplib/wasm.build.linux.in new file mode 100644 index 0000000000..c5e61a9bda --- /dev/null +++ b/developer/src/kmcmplib/wasm.build.linux.in @@ -0,0 +1,4 @@ +[binaries] +c = ['$EMSCRIPTEN_BASE/emcc.py'] +cpp = ['$EMSCRIPTEN_BASE/em++.py'] +ar = ['$EMSCRIPTEN_BASE/emar.py'] diff --git a/developer/src/kmcmplib/wasm.build.mac.in b/developer/src/kmcmplib/wasm.build.mac.in new file mode 100644 index 0000000000..c5e61a9bda --- /dev/null +++ b/developer/src/kmcmplib/wasm.build.mac.in @@ -0,0 +1,4 @@ +[binaries] +c = ['$EMSCRIPTEN_BASE/emcc.py'] +cpp = ['$EMSCRIPTEN_BASE/em++.py'] +ar = ['$EMSCRIPTEN_BASE/emar.py'] diff --git a/developer/src/kmcmplib/wasm.build.win.in b/developer/src/kmcmplib/wasm.build.win.in new file mode 100644 index 0000000000..68c21fb00f --- /dev/null +++ b/developer/src/kmcmplib/wasm.build.win.in @@ -0,0 +1,4 @@ +[binaries] +c = ['python.exe', '$EMSCRIPTEN_BASE/emcc.py'] +cpp = ['python.exe', '$EMSCRIPTEN_BASE/em++.py'] +ar = ['python.exe', '$EMSCRIPTEN_BASE/emar.py'] diff --git a/developer/src/kmcmplib/wasm.defs.build b/developer/src/kmcmplib/wasm.defs.build new file mode 100644 index 0000000000..4a598a1e1c --- /dev/null +++ b/developer/src/kmcmplib/wasm.defs.build @@ -0,0 +1,18 @@ +[binaries] +c = ['emcc.py'] +cpp = ['em++.py'] +ar = ['emar.py'] +exe_wrapper = 'node' + +[properties] +root = '$EMSCRIPTEN_BASE/system' +shared_lib_suffix = 'js' +static_lib_suffix = 'js' +shared_module_suffix = 'js' +exe_suffix = 'js' + +[host_machine] +system = 'emscripten' +cpu_family = 'x86' +cpu = 'i686' +endian = 'little' diff --git a/developer/src/kmcomp/main.pas b/developer/src/kmcomp/main.pas index 4aa29cf6c1..5a29927a80 100644 --- a/developer/src/kmcomp/main.pas +++ b/developer/src/kmcomp/main.pas @@ -65,7 +65,7 @@ uses UKeymanTargets; function CompileKeyboard(FInFile, FOutFile: string; FDebug, FWarnAsError: Boolean): Boolean; forward; // I4706 -function KCSetCompilerOptions(const FInFile: string; FShouldAddCompilerVersion: Boolean): Boolean; forward; +function KCSetCompilerOptions(const FInFile: string; FShouldAddCompilerVersion, FUseKmcmpLib: Boolean): Boolean; forward; //function CompilerMessage(line: Integer; msgcode: LongWord; text: PAnsiChar): Integer; stdcall; forward; procedure FixupPathSlashes(var path: string); forward; @@ -90,6 +90,7 @@ var FParamDistribution: Boolean; FMergingValidateIds: Boolean; FShouldAddCompilerVersion: Boolean; + FUseKmcmpLib: Boolean; FJsonSchemaPath: string; FParamSourcePath: string; FParamHelpLink: string; @@ -116,6 +117,7 @@ begin FColorMode := cmDefault; FShouldAddCompilerVersion := True; + FUseKmcmpLib := True; FParamInfile := ''; FParamOutfile := ''; @@ -191,6 +193,8 @@ begin FColorMode := cmForceNoColor else if s = '-no-compiler-version' then FShouldAddCompilerVersion := False + else if s = '-use-legacy-compiler' then + FUseKmcmpLib := False else if (s = '-help') or (s = '-h') then begin // Force help @@ -219,6 +223,8 @@ begin writeln(SKeymanDeveloperName + ' Compiler (32-bit)'); {$ENDIF} writeln('Version ' + CKeymanVersionInfo.VersionWithTag + ', ' + GetVersionCopyright); + if not FUseKmcmpLib then + writeln('Note: using legacy compiler'); end; if FError or (FParamInfile = '') then @@ -228,7 +234,7 @@ begin writeln(''); writeln('Usage: '+cmd+' [-s[s]] [-nologo] [-c] [-d] [-w] [-cfc] [-v[s|d]] [-source-path path] [-schema-path path] '); writeln(' '+spc+' [-m] infile [-m infile] [-t target] [outfile.kmx|outfile.js [error.log]]'); // I4699 - writeln(' '+spc+' [-add-help-link path] [-color|-no-color] [-no-compiler-version]'); + writeln(' '+spc+' [-add-help-link path] [-color|-no-color] [-no-compiler-version] [-use-legacy-compiler]'); writeln(' '+spc+' [-extract-keyboard-info field[,field...]]'); writeln(' infile can be a .kmn file (Keyboard Source, .kps file (Package Source), or .kpj (project)'); // I4699 // I4825 writeln(' if -v specified, can also be a .keyboard_info file'); @@ -252,6 +258,7 @@ begin writeln(' uses console mode to determine whether color should be used.'); writeln; writeln(' -no-compiler-version Don''t embed the compiler version stores, useful for regression tests.'); + writeln(' -use-legacy-compiler Use legacy compiler (will be removed in 18.0)'); writeln; writeln(' JSON .keyboard_info compile targets:'); writeln(' -v[s] validate infile against source schema'); @@ -291,7 +298,7 @@ begin TProjectLogConsole.Create(FSilent, FFullySilent, hOutfile, FColorMode); - KCSetCompilerOptions(FParamInfile, FShouldAddCompilerVersion); + KCSetCompilerOptions(FParamInfile, FShouldAddCompilerVersion, FUseKmcmpLib); if FValidateRepoChanges then FError := not TValidateRepoChanges.Execute(FParamInfile, FParamOutfile) @@ -317,7 +324,7 @@ begin ExitCode := 1; end; -function KCSetCompilerOptions(const FInFile: string; FShouldAddCompilerVersion: Boolean): Boolean; +function KCSetCompilerOptions(const FInFile: string; FShouldAddCompilerVersion, FUseKmcmpLib: Boolean): Boolean; var opt: TCompilerOptions; begin @@ -325,6 +332,7 @@ begin opt.dwSize := sizeof(TCompilerOptions); opt.ShouldAddCompilerVersion := FShouldAddCompilerVersion; + opt.UseKmcmpLib := FUseKmcmpLib; Result := SetCompilerOptions(@opt, @CompilerMessageW); diff --git a/developer/src/test/auto/kmcomp/test.bat b/developer/src/test/auto/kmcomp/test.bat index 0fbaefa7f2..808c2f9068 100644 --- a/developer/src/test/auto/kmcomp/test.bat +++ b/developer/src/test/auto/kmcomp/test.bat @@ -143,26 +143,38 @@ echo %BLUE%TEST: %1 %WHITE% if exist error.log del error.log "%compiler%" -no-color -nologo -ss -w tests.kpj -t "%2" > error.log if !ERRORLEVEL! GTR 0 ( - type error.log - del error.log echo %RED%FAILED: expected %2 to be a valid keyboard.%WHITE% 1>&2 + echo --------------------------------------------------------------------------- + echo %BLUE%## error.log%WHITE% + type error.log + echo --------------------------------------------------------------------------- + del error.log exit /b 1 ) if "!outfile!" == "" ( findstr /L /C:%3 error.log > nul if !ERRORLEVEL! GTR 0 ( - type error.log - del error.log echo %RED%FAILED: expected compile results to contain message %3.%WHITE% 1>&2 + echo --------------------------------------------------------------------------- + echo %BLUE%## error.log%WHITE% + type error.log + echo --------------------------------------------------------------------------- + del error.log exit /b 1 ) ) else ( fc error.log !outfile! > nul if !ERRORLEVEL! GTR 0 ( - type error.log - del error.log echo %RED%FAILED: expected output in error.log did not match !outfile!.%WHITE% 1>&2 + echo --------------------------------------------------------------------------- + echo %BLUE%## error.log%WHITE% + type error.log + echo --------------------------------------------------------------------------- + echo %BLUE%## !outfile!%WHITE% + type !outfile! + echo --------------------------------------------------------------------------- + del error.log exit /b 1 ) ) diff --git a/developer/src/test/auto/kmcomp/test_194_Filename_case.kvk b/developer/src/test/auto/kmcomp/test_194_Filename_case.kvk index 2d494cfc2e..a46a1fffae 100644 Binary files a/developer/src/test/auto/kmcomp/test_194_Filename_case.kvk and b/developer/src/test/auto/kmcomp/test_194_Filename_case.kvk differ diff --git a/developer/src/tike/dialogs/UfrmOptions.dfm b/developer/src/tike/dialogs/UfrmOptions.dfm index 5968496f38..d20db381fd 100644 --- a/developer/src/tike/dialogs/UfrmOptions.dfm +++ b/developer/src/tike/dialogs/UfrmOptions.dfm @@ -30,7 +30,7 @@ inherited frmOptions: TfrmOptions Width = 125 Height = 25 Caption = '&Proxy Settings...' - TabOrder = 4 + TabOrder = 5 OnClick = cmdProxySettingsClick end object gbExternalEditor: TGroupBox @@ -39,7 +39,7 @@ inherited frmOptions: TfrmOptions Width = 401 Height = 45 Caption = '&External Editor Path' - TabOrder = 1 + TabOrder = 2 object editExternalEditorPath: TEdit Left = 8 Top = 16 @@ -62,7 +62,7 @@ inherited frmOptions: TfrmOptions Width = 125 Height = 25 Caption = 'S&MTP Settings...' - TabOrder = 3 + TabOrder = 6 OnClick = cmdSMTPSettingsClick end object chkOpenKeyboardFilesInSourceView: TCheckBox @@ -71,7 +71,7 @@ inherited frmOptions: TfrmOptions Width = 221 Height = 17 Caption = 'Open &keyboard files in source view' - TabOrder = 0 + TabOrder = 1 end object cmdResetToolWindows: TButton Left = 8 @@ -79,7 +79,7 @@ inherited frmOptions: TfrmOptions Width = 125 Height = 25 Caption = '&Reset tool windows' - TabOrder = 2 + TabOrder = 4 OnClick = cmdResetToolWindowsClick end object chkAllowMultipleInstances: TCheckBox @@ -88,7 +88,7 @@ inherited frmOptions: TfrmOptions Width = 289 Height = 17 Caption = '&Allow multiple instances of Keyman Developer' - TabOrder = 5 + TabOrder = 0 end object gbDefaultProjectPath: TGroupBox Left = 8 @@ -96,7 +96,7 @@ inherited frmOptions: TfrmOptions Width = 401 Height = 45 Caption = '&Default Project Folder' - TabOrder = 6 + TabOrder = 3 object editDefaultProjectPath: TEdit Left = 8 Top = 16 @@ -136,14 +136,14 @@ inherited frmOptions: TfrmOptions Width = 401 Height = 73 Caption = 'Privacy' - TabOrder = 9 + TabOrder = 10 object chkReportUsage: TCheckBox Left = 8 Top = 44 Width = 311 Height = 17 Caption = '&Share anonymous usage statistics with keyman.com' - TabOrder = 0 + TabOrder = 1 end object chkReportErrors: TCheckBox Left = 8 @@ -151,9 +151,17 @@ inherited frmOptions: TfrmOptions Width = 311 Height = 17 Caption = 'Automatically report &errors to keyman.com' - TabOrder = 1 + TabOrder = 0 end end + object chkUseLegacyCompiler: TCheckBox + Left = 152 + Top = 244 + Width = 250 + Height = 17 + Caption = 'Use legacy .kmn compiler (removing in 18.0)' + TabOrder = 9 + end end object tabEditor: TTabSheet Caption = 'Editor' diff --git a/developer/src/tike/dialogs/UfrmOptions.pas b/developer/src/tike/dialogs/UfrmOptions.pas index 77aa090ea2..3976e6ceb5 100644 --- a/developer/src/tike/dialogs/UfrmOptions.pas +++ b/developer/src/tike/dialogs/UfrmOptions.pas @@ -105,6 +105,7 @@ type gbServer: TGroupBox; chkListLocalURLs: TCheckBox; cmdConfigureServer: TButton; + chkUseLegacyCompiler: TCheckBox; procedure FormCreate(Sender: TObject); procedure cmdOKClick(Sender: TObject); procedure cmdDefaultFontClick(Sender: TObject); @@ -194,6 +195,8 @@ begin chkAutoSaveBeforeCompiling.Checked := AutoSaveBeforeCompiling; chkOSKAutoSaveBeforeImporting.Checked := OSKAutoSaveBeforeImporting; + chkUseLegacyCompiler.Checked := UseLegacyCompiler; + chkCharMapAutoLookup.Checked := CharMapAutoLookup; chkCharMapDisableDatabaseLookups.Checked := CharMapDisableDatabaseLookups; @@ -295,6 +298,8 @@ begin AutoSaveBeforeCompiling := chkAutoSaveBeforeCompiling.Checked; OSKAutoSaveBeforeImporting := chkOSKAutoSaveBeforeImporting.Checked; + UseLegacyCompiler := chkUseLegacyCompiler.Checked; + ServerUseLocalAddresses := chkListLocalURLs.Checked; CharMapAutoLookup := chkCharMapAutoLookup.Checked; diff --git a/developer/src/tike/main/KeymanDeveloperOptions.pas b/developer/src/tike/main/KeymanDeveloperOptions.pas index 677f55d590..d7068788cd 100644 --- a/developer/src/tike/main/KeymanDeveloperOptions.pas +++ b/developer/src/tike/main/KeymanDeveloperOptions.pas @@ -70,6 +70,7 @@ type FServerNgrokToken: string; FServerNgrokRegion: string; FServerKeepAlive: Boolean; + FUseLegacyCompiler: Boolean; procedure CloseRegistry; procedure OpenRegistry; function regReadString(const nm, def: string): string; @@ -104,6 +105,8 @@ type property AutoSaveBeforeCompiling: Boolean read FAutoSaveBeforeCompiling write FAutoSaveBeforeCompiling; property OSKAutoSaveBeforeImporting: Boolean read FOSKAutoSaveBeforeImporting write FOSKAutoSaveBeforeImporting; + property UseLegacyCompiler: Boolean read FUseLegacyCompiler write FUseLegacyCompiler; + property ReportErrors: Boolean read FReportErrors write FReportErrors; property ReportUsage: Boolean read FReportUsage write FReportUsage; @@ -215,6 +218,8 @@ begin FAutoSaveBeforeCompiling := regReadBool(SRegValue_IDEOptAutoSaveBeforeCompiling, False); FOSKAutoSaveBeforeImporting := regReadBool(SRegValue_IDEOptOSKAutoSaveBeforeImporting, False); + FUseLegacyCompiler := regReadBool(SRegValue_IDEOptUseLegacyCompiler, False); + FServerDefaultPort := regReadInt(SRegValue_IDEOptServerPort, 8008); FServerKeepAlive := regReadBool(SRegValue_IDEOptServerKeepAlive, False); FServerUseLocalAddresses := regReadBool(SRegValue_IDEOptServerUseLocalAddresses, True); @@ -276,6 +281,7 @@ begin regWriteBool(SRegValue_IDEOptAutoSaveBeforeCompiling, FAutoSaveBeforeCompiling); regWriteBool(SRegValue_IDEOptOSKAutoSaveBeforeImporting, FOSKAutoSaveBeforeImporting); + regWriteBool(SRegValue_IDEOptUseLegacyCompiler, FUseLegacyCompiler); regWriteInt(SRegValue_IDEOptServerPort, FServerDefaultPort); regWriteBool(SRegValue_IDEOptServerKeepAlive, FServerKeepAlive); diff --git a/developer/src/tike/project/Keyman.Developer.System.Project.kmnProjectFileAction.pas b/developer/src/tike/project/Keyman.Developer.System.Project.kmnProjectFileAction.pas index 4f0503509c..703a1e4a0b 100644 --- a/developer/src/tike/project/Keyman.Developer.System.Project.kmnProjectFileAction.pas +++ b/developer/src/tike/project/Keyman.Developer.System.Project.kmnProjectFileAction.pas @@ -19,6 +19,8 @@ type public function CompileKeyboard: Boolean; function Clean: Boolean; + function DoSetCompilerOptions(addVersion, + useLegacyCompiler: Boolean): Boolean; end; implementation @@ -106,6 +108,22 @@ begin end; end; +function TkmnProjectFileAction.DoSetCompilerOptions(addVersion: Boolean; useLegacyCompiler: Boolean): Boolean; +var + options: COMPILER_OPTIONS; +begin + TProject.CompilerMessageFile := Self; + options.dwSize := sizeof(COMPILER_OPTIONS); + options.ShouldAddCompilerVersion := addVersion; + options.UseKmcmpLib := not useLegacyCompiler; + if not SetCompilerOptions(@options, ProjectCompilerMessage) then + begin + Log(plsFatal, 'Unable to set compiler options', CERR_FATAL, 0); + Exit(False); + end; + Result := True; +end; + function TkmnProjectFileAction.CompileKeyboard: Boolean; var KMXFileName: String; diff --git a/developer/src/tike/project/Keyman.Developer.UI.Project.kmnProjectFileUI.pas b/developer/src/tike/project/Keyman.Developer.UI.Project.kmnProjectFileUI.pas index 9b2dd467c5..72c9b43fd4 100644 --- a/developer/src/tike/project/Keyman.Developer.UI.Project.kmnProjectFileUI.pas +++ b/developer/src/tike/project/Keyman.Developer.UI.Project.kmnProjectFileUI.pas @@ -130,7 +130,11 @@ begin if not FSilent then frmMessages.DoShowForm; - Result := ProjectFile.CompileKeyboard; + Result := + // Note: we do not surface the ability to exclude version information from + // the TIKE compiler; this must be done from kmcomp.exe. + ProjectFile.DoSetCompilerOptions(True, FKeymanDeveloperOptions.UseLegacyCompiler) and + ProjectFile.CompileKeyboard; if Result and TServerDebugAPI.Running and diff --git a/resources/build/meson/standard.meson.build b/resources/build/meson/standard.meson.build new file mode 100644 index 0000000000..87efed5ab5 --- /dev/null +++ b/resources/build/meson/standard.meson.build @@ -0,0 +1,86 @@ +# +# Shared configuration for all meson-based builds +# +# This file has the master location /resources/build/meson/standard.meson.build, +# and is copied into each project's /resources/meson.build in the +# configure step, so that it can be referenced by meson directly. +# +# Where possible, we want to use these flags everywhere +# + +cpp_compiler = meson.get_compiler('cpp') +c_compiler = meson.get_compiler('c') + +# Once we can assume meson 0.60 we can delete this +# (https://mesonbuild.com/Release-notes-for-0-60-0.html#msvc-compiler-now-assumes-utf8-source-code-by-default) +if cpp_compiler.get_id() == 'msvc' + add_global_arguments('/source-charset:utf-8', language: ['c', 'cpp']) +endif + +# +# Standard informational messages for our builds +# + +message('meson.project_version(): ' + meson.project_version()) +message('host_machine.system(): ' + host_machine.system()) +message('compiler.get_id(): ' + cpp_compiler.get_id()) + +# +# Standard compiler flags for all platforms +# + +warns = [] +flags = [] +links = [] +defns = [] + +if cpp_compiler.get_id() == 'gcc' or cpp_compiler.get_id() == 'clang' + warns += [ + '-Wctor-dtor-privacy', + '-Wdouble-promotion', + '-Wendif-labels', + '-Wno-unknown-pragmas', + '-Wno-missing-field-initializers', + '-Wnon-virtual-dtor', + '-Wshadow' + ] + flags += [ + '-fvisibility=hidden', + '-fvisibility-inlines-hidden' + ] + + if cpp_compiler.get_id() == 'clang' + warns += [ + '-Wimplicit-fallthrough', + '-Wno-double-promotion', + '-Wshorten-64-to-32' + ] + endif + + if host_machine.system() == 'darwin' + # TODO: this seems to be inverting above options, is this necessary, or can + # we resolve another way? + warns += [ + '-Wno-ctor-dtor-privacy', + '-Wno-non-virtual-dtor' + ] + endif +endif + +if cpp_compiler.get_id() == 'msvc' + defns += [ + '-D_SCL_SECURE_NO_WARNINGS', + '-D_CRT_SECURE_NO_WARNINGS' + ] +endif + +if cpp_compiler.get_id() == 'emscripten' + if get_option('buildtype') == 'debug' + # Enable DWARF symbols for debug builds + flags += ['-g'] + links += ['-g'] + else + flags += ['-O2'] + links += ['-O2'] + endif +endif diff --git a/windows/src/desktop/kmshell/kmshell.res b/windows/src/desktop/kmshell/kmshell.res index d1da4f0dc8..cfcbd309f1 100644 Binary files a/windows/src/desktop/kmshell/kmshell.res and b/windows/src/desktop/kmshell/kmshell.res differ