diff --git a/common/web/types/build.sh b/common/web/types/build.sh index eb983acec85..0f2b408f1e3 100755 --- a/common/web/types/build.sh +++ b/common/web/types/build.sh @@ -78,7 +78,7 @@ fi if builder_start_action test; then copy_schemas - npm test + npm test -- "${builder_extra_params[@]}" builder_finish_action success test fi diff --git a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts b/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts index a86ed0441f7..6ee01b7f8e8 100644 --- a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts +++ b/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts @@ -17,12 +17,19 @@ export class TouchLayoutFileWriter { * @param source TouchLayoutFile * @returns Uint8Array, the .keyman-touch-layout file */ - write(source: TouchLayoutFile): Uint8Array { - const output = JSON.stringify(source, null, this.options?.formatted ? 2 : undefined); + public write(source: TouchLayoutFile): Uint8Array { + const output = this.toJSONString(source); const encoder = new TextEncoder(); return encoder.encode(output); } + /** + * Gets the output as a JSON string + */ + public toJSONString(source: TouchLayoutFile): string { + return JSON.stringify(source, null, this.options?.formatted ? 2 : undefined); + } + /** * Compiles the touch layout file into a KeymanWeb-compatible JSON-style * object string. In the future, this may be optimized to remove unnecessary @@ -31,7 +38,11 @@ export class TouchLayoutFileWriter { * @param source * @returns string */ - compile(source: TouchLayoutFile): string { + public compile(source: TouchLayoutFile): string { + return this.toJSONString(this.fixup(source)); + } + + public fixup(source: TouchLayoutFile): TouchLayoutFile { // Deep copy the source source = JSON.parse(JSON.stringify(source)); @@ -40,13 +51,23 @@ export class TouchLayoutFileWriter { const fixupKey = (key: TouchLayoutKey | TouchLayoutSubKey) => { if(Object.hasOwn(key, 'pad')) (key.pad as any) = key.pad.toString(); - if(Object.hasOwn(key, 'sp')) (key.sp as any) = key.sp.toString(); + if(Object.hasOwn(key, 'sp')) { + if(key.sp == 0) { + delete key.sp; + } + else { + (key.sp as any) = key.sp.toString(); + } + } if(Object.hasOwn(key, 'width')) (key.width as any) = key.width.toString(); + if(Object.hasOwn(key, 'text') && key.text === '') delete key.text; }; const fixupPlatform = (platform: TouchLayoutPlatform) => { for(let layer of platform.layer) { for(let row of layer.row) { + // this matches the old spec for touch layout files + (row.id as any) = row.id.toString(); for(let key of row.key) { fixupKey(key); if(key.sk) { @@ -79,6 +100,6 @@ export class TouchLayoutFileWriter { fixupPlatform(source.tablet); } - return JSON.stringify(source, null, this.options?.formatted ? 2 : undefined); + return source; } }; \ No newline at end of file diff --git a/common/web/types/src/kmx/kmx-file-reader.ts b/common/web/types/src/kmx/kmx-file-reader.ts index 46cfc8eb392..45131ade770 100644 --- a/common/web/types/src/kmx/kmx-file-reader.ts +++ b/common/web/types/src/kmx/kmx-file-reader.ts @@ -1,4 +1,4 @@ -import { KMXFile, BUILDER_COMP_KEYBOARD, KEYBOARD, STORE } from "./kmx.js"; +import { KMXFile, BUILDER_COMP_KEYBOARD, KEYBOARD, STORE, GROUP, KEY } from "./kmx.js"; import * as r from 'restructure'; export class KmxFileReader { @@ -13,17 +13,60 @@ export class KmxFileReader { return this.rString.fromBuffer(source.slice(offset)); } + private processSystemStore(store: STORE, result: KEYBOARD) { + switch(store.dwSystemID) { + case KMXFile.TSS_MNEMONIC: + result.isMnemonic = store.dpString == '1'; + break; + case KMXFile.TSS_KEYBOARDVERSION: + result.keyboardVersion = store.dpString; + break; + case KMXFile.TSS_BEGIN_NEWCONTEXT: + if(store.dpString.length == 3 && store.dpString.charCodeAt(0) == 0xFFFF && store.dpString.charCodeAt(1) == KMXFile.CODE_USE) { + result.startGroup.newContext = store.dpString.charCodeAt(2) - 1; + } + else { + // TODO: error + return false; + } + break; + case KMXFile.TSS_BEGIN_POSTKEYSTROKE: + if(store.dpString.length == 3 && store.dpString.charCodeAt(0) == 0xFFFF && store.dpString.charCodeAt(1) == KMXFile.CODE_USE) { + result.startGroup.postKeystroke = store.dpString.charCodeAt(2) - 1; + } + else { + // TODO: error + return false; + } + break; + } + return true; + } + public read(source: Uint8Array): KEYBOARD { let binaryKeyboard: BUILDER_COMP_KEYBOARD; let kmx = new KMXFile(); binaryKeyboard = kmx.COMP_KEYBOARD.fromBuffer(source); if(binaryKeyboard.dwIdentifier != KMXFile.FILEID_COMPILED) { + // TODO: error return null; } - // TODO: all header fields - let result = new KEYBOARD(); + result.fileVersion = binaryKeyboard.dwFileVersion; + result.flags = binaryKeyboard.dwFlags; + result.hotkey = binaryKeyboard.dwHotKey; + result.startGroup = { + ansi: binaryKeyboard.StartGroup_ANSI == 0xFFFFFFFF ? -1 : binaryKeyboard.StartGroup_ANSI, + unicode: binaryKeyboard.StartGroup_Unicode == 0xFFFFFFFF ? -1 : binaryKeyboard.StartGroup_Unicode, + newContext: -1, //TODO + postKeystroke: -1 // TODO + } + + // Informative data + result.keyboardVersion = ''; + result.isMnemonic = false; + let offset = binaryKeyboard.dpStoreArray; for(let i = 0; i < binaryKeyboard.cxStoreArray; i++) { let binaryStore = kmx.COMP_STORE.fromBuffer(source.slice(offset)); @@ -32,13 +75,52 @@ export class KmxFileReader { store.dpName = this.readString(source, binaryStore.dpName); store.dpString = this.readString(source, binaryStore.dpString); result.stores.push(store); + + if(!this.processSystemStore(store, result)) { + return null; + } + offset += KMXFile.COMP_STORE_SIZE; } - // TODO: groups + offset = binaryKeyboard.dpGroupArray; + for(let i = 0; i < binaryKeyboard.cxGroupArray; i++) { + let binaryGroup = kmx.COMP_GROUP.fromBuffer(source.slice(offset)); + let group = new GROUP(); + group.dpMatch = this.readString(source, binaryGroup.dpMatch); + group.dpName = this.readString(source, binaryGroup.dpName); + group.dpNoMatch = this.readString(source, binaryGroup.dpNoMatch); + group.fUsingKeys = binaryGroup.fUsingKeys; + group.keys = []; + + let keyOffset = binaryGroup.dpKeyArray; + for(let j = 0; j < binaryGroup.cxKeyArray; j++) { + let binaryKey = kmx.COMP_KEY.fromBuffer(source.slice(keyOffset)); + let key = new KEY(); + key.Key = binaryKey.Key; + key.Line = binaryKey.Line; + key.ShiftFlags = binaryKey.ShiftFlags; + key.dpContext = this.readString(source, binaryKey.dpContext); + key.dpOutput = this.readString(source, binaryKey.dpOutput); + group.keys.push(key); + keyOffset += KMXFile.COMP_KEY_SIZE; + } + + result.groups.push(group); + offset += KMXFile.COMP_GROUP_SIZE; + } // TODO: KMXPlusFile + // Validate startGroup offsets + let gp: keyof KEYBOARD['startGroup']; + for(gp in result.startGroup) { + if(result.startGroup[gp] < -1 || result.startGroup[gp] >= result.groups.length) { + // TODO: error + return null; + } + } + return result; } }; \ No newline at end of file diff --git a/common/web/types/src/kmx/kmx.ts b/common/web/types/src/kmx/kmx.ts index 2f47bddcdd2..17e8b3749fa 100644 --- a/common/web/types/src/kmx/kmx.ts +++ b/common/web/types/src/kmx/kmx.ts @@ -8,9 +8,28 @@ import * as r from 'restructure'; // kmx-builder will transform these to the corresponding COMP_xxxx export class KEYBOARD { - //TODO: additional header fields + fileVersion?: number; // dwFileVersion (TSS_FILEVERSION) + + startGroup: { + ansi: number; // from COMP_KEYBOARD + unicode: number; // from COMP_KEYBOARD + newContext: number; // from TSS_BEGIN_NEWCONTEXT store + postKeystroke: number; // from TSS_BEGIN_POSTKEYSTROKE store + } = {ansi:-1, unicode:-1, newContext:-1, postKeystroke:-1}; + + flags?: number; + hotkey?: number; + + //bitmap: groups: GROUP[] = []; stores: STORE[] = []; + + // Following values are extracted from stores[] but are + // informative only + + keyboardVersion?: string; // version (TSS_KEYBOARDVERSION) + isMnemonic: boolean; // TSS_MNEMONICLAYOUT store + }; export class STORE { @@ -21,7 +40,7 @@ export class STORE { export class GROUP { dpName: string; - keys: KEY[]; + keys: KEY[] = []; dpMatch: string; dpNoMatch: string; fUsingKeys: boolean; @@ -319,6 +338,21 @@ export class KMXFile { public static readonly ISVIRTUALKEY = 0x4000; // It is a Virtual Key Sequence public static readonly VIRTUALCHARKEY = 0x8000; // Keyman 6.0: Virtual Key Cap Sequence NOT YET + public static readonly MASK_MODIFIER_CHIRAL = KMXFile.LCTRLFLAG | KMXFile.RCTRLFLAG | KMXFile.LALTFLAG | KMXFile.RALTFLAG; + public static readonly MASK_MODIFIER_SHIFT = KMXFile.K_SHIFTFLAG; + public static readonly MASK_MODIFIER_NONCHIRAL = KMXFile.K_CTRLFLAG | KMXFile.K_ALTFLAG; + + public static readonly MASK_STATEKEY = KMXFile.CAPITALFLAG | KMXFile.NOTCAPITALFLAG | + KMXFile.NUMLOCKFLAG | KMXFile.NOTNUMLOCKFLAG | + KMXFile.SCROLLFLAG | KMXFile.NOTSCROLLFLAG; + public static readonly MASK_KEYTYPE = KMXFile.ISVIRTUALKEY | KMXFile.VIRTUALCHARKEY; + + public static readonly MASK_MODIFIER = KMXFile.MASK_MODIFIER_CHIRAL | KMXFile.MASK_MODIFIER_SHIFT | KMXFile.MASK_MODIFIER_NONCHIRAL; + + public static readonly MASK_KEYS = KMXFile.MASK_MODIFIER | KMXFile.MASK_STATEKEY; + public static readonly KMX_MASK_VALID = KMXFile.MASK_KEYS | KMXFile.MASK_KEYTYPE; + + public static readonly K_MODIFIERFLAG = 0x007F; public static readonly K_NOTMODIFIERFLAG = 0xFF00; // I4548 @@ -328,12 +362,13 @@ export class KMXFile { public static readonly COMP_GROUP_SIZE = 24; public static readonly COMP_KEY_SIZE = 20; + + public static readonly VERSION_MASK_MINOR = 0x00FF; + public static readonly VERSION_MASK_MAJOR = 0xFF00; + /* In-memory representation of the keyboard */ - public keyboard: KEYBOARD = { - groups: [], - stores: [] - }; + public keyboard: KEYBOARD = new KEYBOARD(); constructor() { diff --git a/common/web/types/src/kvk/visual-keyboard.ts b/common/web/types/src/kvk/visual-keyboard.ts index c1f1d5d7e92..4965a39b52b 100644 --- a/common/web/types/src/kvk/visual-keyboard.ts +++ b/common/web/types/src/kvk/visual-keyboard.ts @@ -26,6 +26,7 @@ export class VisualKeyboardFont { name?: string; size?: number; color?: number; // unused + style?: string; // TODO: figure out style vs color issues }; export { BUILDER_KVK_KEY_FLAGS as VisualKeyboardKeyFlags } from "./kvk-file.js"; diff --git a/developer/build.sh b/developer/build.sh index 76fc3c94a72..0ad6e84bd50 100755 --- a/developer/build.sh +++ b/developer/build.sh @@ -29,6 +29,7 @@ builder_describe \ test \ ":kmcmplib=src/kmcmplib Compiler - .kmn compiler" \ ":kmc-kmn=src/kmc-kmn Compiler - .kmn wrapper Keyboard Module" \ + ":kmc-kmw=src/kmc-kmw Compiler - .kmn Javascript Keyboard Module" \ ":kmc-ldml=src/kmc-ldml Compiler - LDML Keyboard Module" \ ":kmc-model=src/kmc-model Compiler - Lexical Model Module" \ ":kmc-model-info=src/kmc-model-info Compiler - .model_info Module" \ diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts index 9962ea6abd5..5e910ff45b8 100644 --- a/developer/src/kmc-kmn/src/compiler/compiler.ts +++ b/developer/src/kmc-kmn/src/compiler/compiler.ts @@ -26,13 +26,15 @@ export interface CompilerOptions { saveDebug?: boolean; compilerWarningsAsErrors?: boolean; warnDeprecatedCode?: boolean; + target?: 'kmx' | 'js'; }; const baseOptions: CompilerOptions = { shouldAddCompilerVersion: true, saveDebug: true, compilerWarningsAsErrors: false, - warnDeprecatedCode: true + warnDeprecatedCode: true, + target: 'kmx' }; /** @@ -66,6 +68,7 @@ export class KmnCompiler { return false; } } + return this.verifyInitialized(); } diff --git a/developer/src/kmc-kmw/Makefile b/developer/src/kmc-kmw/Makefile new file mode 100644 index 00000000000..c9ae1e81a6c --- /dev/null +++ b/developer/src/kmc-kmw/Makefile @@ -0,0 +1,39 @@ +# +# Keyman Developer - kmc KMW Keyboard Compiler Makefile +# + +!include ..\Defines.mak + +# We do configure here because parent Makefile calls this first; other +# kmc and kmc-* makefiles don't do it +build: configure .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh build + +configure: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh configure + +clean: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh clean + +test: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh test + +# build.sh bundle must be run from shell as it requires a temp folder to be +# passed in. See inst/download.in.mak for instantiation. + +publish: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh publish + +signcode: + @rem nothing to do + +wrap-symbols: + @rem nothing to do + +test-manifest: + @rem nothing to do + +install: + @rem nothing to do + +!include ..\Target.mak diff --git a/developer/src/kmc-kmw/build.sh b/developer/src/kmc-kmw/build.sh new file mode 100755 index 00000000000..1e43793b16f --- /dev/null +++ b/developer/src/kmc-kmw/build.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +## 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" + +. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" + +builder_describe "Build Keyman kmc KMW Keyboard Compiler module" \ + "@/common/web/types" \ + "@/developer/src/kmc-kmn" \ + "configure" \ + "build" \ + "clean" \ + "test" \ + "pack build a local .tgz pack for testing" \ + "publish publish to npm" \ + "--dry-run,-n don't actually publish, just dry run" + +builder_describe_outputs \ + configure /node_modules \ + build build/src/main.js + +builder_parse "$@" + +#------------------------------------------------------------------------------------------------------------------- + +function copy_schema() { + # We need the schema file at runtime and bundled, so always copy it for all + # actions except `clean` and `configure` + mkdir -p "$THIS_SCRIPT_PATH/build/src/" + cp "$KEYMAN_ROOT/common/schemas/keyman-touch-layout/keyman-touch-layout.spec.json" "$THIS_SCRIPT_PATH/build/src/" + cp "$KEYMAN_ROOT/common/schemas/kvks/kvks.schema.json" "$THIS_SCRIPT_PATH/build/src/" +} + +function do_build() { + copy_schema + npm run build +} + +function do_test() { + # TODO: add c8 for coverage + copy_schema + npm test +} + +function do_publish() { + copy_schema + builder_publish_to_npm +} + +function do_pack() { + copy_schema + builder_publish_to_pack +} + +#------------------------------------------------------------------------------------------------------------------- + +builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo +builder_run_action configure verify_npm_setup +builder_run_action build do_build +builder_run_action test do_test +builder_run_action pack do_pack +builder_run_action publish do_publish diff --git a/developer/src/kmc-kmw/package.json b/developer/src/kmc-kmw/package.json new file mode 100644 index 00000000000..c1494fb1392 --- /dev/null +++ b/developer/src/kmc-kmw/package.json @@ -0,0 +1,56 @@ +{ + "name": "@keymanapp/kmc-kmw", + "description": "Keyman Developer KMW keyboard compiler", + "keywords": [ + "keyboard", + "keyman", + "ldml", + "unicode" + ], + "type": "module", + "exports": { + ".": "./build/src/main.js" + }, + "scripts": { + "build": "tsc -b", + "tsc": "tsc", + "test": "cd test && tsc -b && cd .. && mocha", + "prepublishOnly": "npm run build" + }, + "author": "Marc Durdin (https://github.com/mcdurdin)", + "license": "MIT", + "bugs": { + "url": "https://github.com/keymanapp/keyman/issues" + }, + "dependencies": { + "@keymanapp/common-types": "*", + "@keymanapp/kmc-kmn": "*", + "ajv": "^8.11.0", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "semver": "^7.3.7", + "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" + }, + "devDependencies": { + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.7", + "@types/node": "^10.14.6", + "@types/semver": "^7.3.12", + "@types/xml2js": "^0.4.5", + "c8": "^7.12.0", + "chai": "^4.3.4", + "chalk": "^2.4.2", + "mocha": "^8.4.0", + "ts-node": "^9.1.1", + "typescript": "^4.9.5" + }, + "mocha": { + "spec": "build/test/**/test-*.js", + "require": [ + "source-map-support/register" + ] + }, + "repository": { + "type": "git", + "url": "git+https://github.com/keymanapp/keyman.git" + } +} diff --git a/developer/src/kmc-kmw/src/compiler/callbacks.ts b/developer/src/kmc-kmw/src/compiler/callbacks.ts new file mode 100644 index 00000000000..bdc7a174642 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/callbacks.ts @@ -0,0 +1,14 @@ +export interface CompilerEvent { + line: number; + code: number; + message: string; +}; + +export default interface CompilerCallbacks { + loadFile(baseFilename: string, filename: string): Buffer; + loadLdmlKeyboardSchema(): Buffer; + loadKvksJsonSchema(): Buffer; + reportMessage(event: CompilerEvent): void; +}; + +// TODO: eliminate this \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/compiler-globals.ts b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts new file mode 100644 index 00000000000..bb4874a5590 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts @@ -0,0 +1,30 @@ +import { KMX, CompilerCallbacks } from "@keymanapp/common-types"; +import CompilerOptions from "./compiler-options.js"; + +export let FTabStop: string; +export let nl: string; +export let FCompilerWarningsAsErrors = false; +export let fk: KMX.KEYBOARD; +export let FMnemonic: boolean; +export let options: CompilerOptions; +export let callbacks: CompilerCallbacks; + +export function setupGlobals(_callbacks: CompilerCallbacks, _options: CompilerOptions, _tab: string, _nl: string, _keyboard: KMX.KEYBOARD) { + callbacks = _callbacks; + options = _options; + FTabStop = _tab; + nl = _nl; + fk = _keyboard; +} + +export function IsKeyboardVersion10OrLater(): boolean { + return fk.fileVersion >= KMX.KMXFile.VERSION_100; +} + +export function IsKeyboardVersion14OrLater(): boolean { + return fk.fileVersion >= KMX.KMXFile.VERSION_140; +} + +export function IsKeyboardVersion15OrLater(): boolean { + return fk.fileVersion >= KMX.KMXFile.VERSION_150; +} diff --git a/developer/src/kmc-kmw/src/compiler/compiler-options.ts b/developer/src/kmc-kmw/src/compiler/compiler-options.ts new file mode 100644 index 00000000000..bcb99c5d433 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/compiler-options.ts @@ -0,0 +1,15 @@ + + +export default interface CompilerOptions { + /** + * Add debug information to the .kmx file when compiling + */ + debug: boolean; + + /** + * Add metadata about the compiler version to .kmx file when compiling + */ + addCompilerVersion: boolean; +}; + +// TODO: we have a shared CompilerOptions intf, eliminate this \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts new file mode 100644 index 00000000000..731e8377678 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts @@ -0,0 +1,1561 @@ +import { TSentinelRecord, GetSuppChar, ExpandSentinel, incxstr, xstrlen, xstrlen_printing } from "../util/util.js"; +import { KMX } from "@keymanapp/common-types"; + +import { FMnemonic, FTabStop, IsKeyboardVersion10OrLater, IsKeyboardVersion14OrLater, nl, options } from "./compiler-globals.js"; +import { CERR_NotSupportedInKeymanWebContext, CERR_NotSupportedInKeymanWebOutput, CERR_NotSupportedInKeymanWebStore, CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, CERR_VirtualKeysNotValidForMnemonicLayouts, CHINT_UnreachableKeyCode, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, CWARN_OptionStoreNameInvalid, ReportError } from "./messages.js"; +import { FFix183_LadderLength, FormatModifierAsBitflags, RuleIsExcludedByPlatform } from "./write-compiled-keyboard.js"; + +const SValidIdentifierCharSet = /[A-Za-z0-9_]/; + +// TODO: lifecycle +let FUnreachableKeys: KMX.KEY[] = []; +let FCallFunctions: string[] = []; + +export function JavaScript_Name(i: number, pwszName: string, KeepNameForPersistentStorage: boolean = false): string { // I3659 + let FChanged: boolean = false; + let p = pwszName; + + if((pwszName == null || pwszName == undefined || pwszName == '') || (!options.debug && !KeepNameForPersistentStorage)) { // I3659 // I3681 + return i.toString(10); // for uniqueness + } + else { + let result = KeepNameForPersistentStorage // I3659 + ? '' // Potential for overlap in theory but in practice we only use this for named option stores so can never overlap + : '_'; // Ensures we cannot overlap numbered instances + while(p.length) { + let ch = p.charAt(0); + if(SValidIdentifierCharSet.test(ch)) { // I3681 + result += ch; + } else { + result += '_'; + FChanged = true; + } + p = p.substring(1); + } + if(!KeepNameForPersistentStorage) { + // Ensure each transformed name is still unique + result += '_' + i.toString(10); + if(FChanged) { + result += '/*'+pwszName.replace(/\*\//g, '*-/')+'*/'; + } + } else if(FChanged) { + // For named option stores, we are only supporting the valid identifier + // character set, which is a breaking change in 14.0. + ReportError(0, CWARN_OptionStoreNameInvalid, + `The option store ${pwszName} should be named with characters in the range A-Z, a-z, 0-9 and _ only.`); + } + return result; + } +} + +export function JavaScript_Store(fk: KMX.KEYBOARD, line: number, pwsz: string): string { + let ch: number, rec: TSentinelRecord, result: string; + const wcsentinel: string = String.fromCharCode(KMX.KMXFile.UC_SENTINEL); + let n = pwsz.indexOf(wcsentinel); + + // Start: plain text store. Always use for < 10.0, conditionally for >= 10.0. + if(n < 0 || !IsKeyboardVersion10OrLater()) { + result = '"'; + while(pwsz.length) { + if(pwsz.charCodeAt(0) == KMX.KMXFile.UC_SENTINEL) { + result += '.'; // UC_SENTINEL values are not supported in stores for KMW < 10.0. + } else { + ch = GetSuppChar(pwsz, 0); + if(ch == '"'.charCodeAt(0) || ch == '\\'.charCodeAt(0)) { + result += '\\'; + } + result += JavaScript_String(ch); // I2242 + } + + // TODO: problems with supp chars + pwsz = pwsz.substring(1); + } + result += '"'; + } + else { + result = '['; + let x = 0; + while(x < pwsz.length) { + if(result != '[') { + result += ','; + } + rec = ExpandSentinel(fk, pwsz, x); + if(rec.IsSentinel) { + if(rec.Code == KMX.KMXFile.CODE_DEADKEY) { + result += `{t:'d',d:${rec.DeadKey.DeadKey}}`; + } + else if(rec.Code == KMX.KMXFile.CODE_BEEP) { + result += `{t:'b'}`; + } + else { //if rec.Code = CODE_EXTENDED then + // At some point, we may wish to filter which codes are safe to stub out like this + // versus which ones should be an error. The commented-out-code shows the way to + // handle such cases. + result += `''`; + } +// else +// begin +// //ReportError(line, CERR_SomewhereIGotItWrong, 'Internal Error: unexpected sentinel character in store definition'); +// end; + } + else { + ch = GetSuppChar(pwsz, x); + result += '"'; + // TODO: Refactor the section below into JavaScript_String, as it's + // quite common in our code base. + if(ch == '"'.charCodeAt(0) || ch == '\\'.charCodeAt(0)) { + result += '\\'; + } + result += JavaScript_String(ch) + '"'; // I2242 + } + + x = incxstr(pwsz, x); + } + result += ']'; + } + return result; +} + +export function JavaScript_String(ch: number): string { // I2242 + if(ch < 32) { + switch(ch) { + case 9: return '\\t'; + case 10: return '\\n'; + case 13: return '\\r'; + } + return '\\x' + zeroPadHex(ch, 2); + } + else { + // Note: unpaired surrogates will be maintained + return String.fromCodePoint(ch); + } +} + +function JavaScript_Rule(FTabStops: string, FElse: string, fk: KMX.KEYBOARD, fgp: KMX.GROUP, fkp: KMX.KEY): string { + let predicate: string = '1', linecomment: string = '', FIndent: string; + let result = ''; + + if(fkp.Line > 0 && options.debug) { // I4384 + linecomment = ' // Line '+fkp.Line.toString(); // I4373 + } + + if(xstrlen(fkp.dpContext) > 0) { + predicate = JavaScript_ContextMatch(fk, fkp, fkp.dpContext); + } + + FIndent = FTabStops+FTabStop; + result = `${FTabStops}${FElse}if(${predicate}){${nl}`; + + if(fgp.fUsingKeys) { + result += `${FIndent}r=m=1;${linecomment}${JavaScript_OutputString(fk, FIndent, fkp, fkp.dpOutput, fgp)}`; // I1959 // I3681 + } + else { + result += `${FIndent}m=1;${linecomment}${JavaScript_OutputString(fk, FIndent, fkp, fkp.dpOutput, fgp)}`; // I1959 // I3681 + } + + result += `${nl}${FTabStops}}${nl}`; + return result; +} + + +export function JavaScript_Rules(keyboard: KMX.KEYBOARD, fMnemonic: boolean, fgp: KMX.GROUP): string { + let IsEqualKey = function(k1: KMX.KEY, k2: KMX.KEY): boolean { + return ( + (JavaScript_Key(k1, FMnemonic) == JavaScript_Key(k2, FMnemonic)) && + (JavaScript_Shift(k1, FMnemonic) == JavaScript_Shift(k2, FMnemonic)) + ); + } + + let result = ''; + let HasRules = false; + + let processed_rule = Array(fgp.keys.length); + for(let j = 0; j < fgp.keys.length; j++) { + processed_rule[j] = false; + } + + let j = 0; + let Counter = 0; + while(j < fgp.keys.length) { // I1964 + let fkp = fgp.keys[j]; + if(!processed_rule[j] && !RuleIsExcludedByPlatform(keyboard, fkp)) { + // Break down by key code + // We know the rules are sorted by context length and then key code. + // First pass, break the grouping down by key code. + + if(fgp.fUsingKeys) { + result += + `${FTabStop+FTabStop}${HasRules?'else ':''}`+ + `if(k.KKM(e,${JavaScript_ShiftAsString(fkp, fMnemonic)},${JavaScript_KeyAsString(fkp, fMnemonic)})) {${nl}`; + + HasRules = true; + Counter++; + + let LocalHasRules = false; + let fkp2 = fgp.keys[j]; + let j2 = j; + let LocalCounter = 0; + while (j < fgp.keys.length) { + fkp = fgp.keys[j]; + if (!processed_rule[j] && !RuleIsExcludedByPlatform(keyboard, fkp) && IsEqualKey(fkp, fkp2)) { + processed_rule[j] = true; + result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, LocalHasRules ? 'else ' : '', keyboard, fgp, fkp); + LocalCounter++; + + if (FFix183_LadderLength != 0 && (LocalCounter % FFix183_LadderLength) == 0) { + // Break if/else ladders + result += `${FTabStop+FTabStop+FTabStop}if(m) {}${nl}`; + } + LocalHasRules = true; + } + + j++; + } + + result += FTabStop + FTabStop + '}' + nl; + j = j2 + 1; + } + else { + // TODO: context character level switches instead of full context comparisons + result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, HasRules ? 'else ' : '', keyboard, fgp, fkp); + HasRules = true; + Counter++; + j++; + } + + if (FFix183_LadderLength != 0 && (Counter % FFix183_LadderLength) == 0) { + // Break if/else ladders + // We need to only match if no previous line is matched (i.e. m is false) + result += `${FTabStop+FTabStop+FTabStop}if(m) {}${nl}`; + } + } + else { + j++; + } + } + return result; +} + +const + USEnglishUnshift: string = ' `' + '1234567890' + '-' + '=' + 'qwertyuiop' + '[' + ']' + '\\' + 'asdfghjkl' + ';' + '\'' + 'zxcvbnm' + ',' + '.' + '/', + USEnglishShift: string = 0xFF + '~' + '!@#$%^&*()' + '_' + '+' + 'QWERTYUIOP' + '{' + '}' + '|' + 'ASDFGHJKL' + ':' + '"' + 'ZXCVBNM' + '<' + '>' + '?', + USEnglishValues: string = 0x20 + 0xc0 + '1234567890' + 0xbd + 0xbb + 'QWERTYUIOP' + 0xdb + 0xdd + 0xdc + 'ASDFGHJKL' + 0xba + 0xde + 'ZXCVBNM' + 0xbc + 0xbe + 0xbf, + UnreachableKeyCodes: number[] = [ // I4141 + 0x00, // &H0 + 0x01, //VK_LBUTTON, // &H1 + 0x02, //VK_RBUTTON, // &H2 + 0x03, //VK_CANCEL, // &H3 + 0x04, //VK_MBUTTON, // &H4 + 0x05, // &H5 + 0x06, // &H6 + 0x07, // &H7 + 0x0A, // &HA + 0x0B, // &HB + 0x0E, // &HE + 0x0F, // &HF + 0x10, //VK_SHIFT, // &H10 + 0x11, //VK_CONTROL, // &H11 + 0x12, //VK_MENU, // &H12 + 0x13, //VK_PAUSE, // &H13 + 0x14, //VK_CAPITAL, // &H14 + 0x1B, //VK_ESCAPE, // &H1B + + 0x90, //VK_NUMLOCK, // &H90 + 0x91 //VK_SCROLL // &H91 + ]; + +export function JavaScript_Shift(fkp: KMX.KEY, FMnemonic: boolean): number { + if (FMnemonic) { + if (fkp.ShiftFlags & KMX.KMXFile.VIRTUALCHARKEY) { + ReportError(fkp.Line, CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, 'Virtual character keys not currently supported in KeymanWeb'); // I1971 // I4061 + return 0; + } + + if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY && fkp.Key <= 255) { + // We prohibit K_ keys for mnemonic layouts. We don't block T_ and U_ keys. + // TODO: this doesn't resolve the issue of, e.g. SHIFT+K_SPACE + // https://github.com/keymanapp/keyman/issues/265 + ReportError(fkp.Line, CERR_VirtualKeysNotValidForMnemonicLayouts, 'Virtual keys are not valid for mnemonic layouts'); // I1971 // I4061 + return 0; + } + } + + if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) { + if(IsKeyboardVersion10OrLater()) { + // Full chiral modifier and state key support starts with KeymanWeb 10.0 + return fkp.ShiftFlags; + } + + // Non-chiral support only and no support for state keys + if (fkp.ShiftFlags & (KMX.KMXFile.LCTRLFLAG | KMX.KMXFile.RCTRLFLAG | KMX.KMXFile.LALTFLAG | KMX.KMXFile.RALTFLAG)) { // I4118 + ReportError(fkp.Line, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, 'Extended shift flags LALT, RALT, LCTRL, RCTRL are not supported in KeymanWeb'); + } + + if (fkp.ShiftFlags & ( + KMX.KMXFile.CAPITALFLAG | KMX.KMXFile.NOTCAPITALFLAG | KMX.KMXFile.NUMLOCKFLAG | KMX.KMXFile.NOTNUMLOCKFLAG | + KMX.KMXFile.SCROLLFLAG | KMX.KMXFile.NOTSCROLLFLAG)) { // I4118 + ReportError(fkp.Line, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, 'Extended shift flags CAPS and NCAPS are not supported in KeymanWeb'); + } + + return KMX.KMXFile.ISVIRTUALKEY | (fkp.ShiftFlags & (KMX.KMXFile.K_SHIFTFLAG | KMX.KMXFile.K_CTRLFLAG | KMX.KMXFile.K_ALTFLAG)); + } + + return USEnglishShift.includes(String.fromCharCode(fkp.Key)) ? KMX.KMXFile.ISVIRTUALKEY | KMX.KMXFile.K_SHIFTFLAG : KMX.KMXFile.ISVIRTUALKEY; +} + +/** + * Returns a Javascript representation of a key modifier state, either as a constant (debug mode) + * or as an integer. + * + * @param fkp Pointer to key record + * @param FMnemonic True if the keyboard is a mnemonic layout + * + * @return string representation of the key modifier state, e.g. + * 'modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 * /' or + * '16656' + */ +export function JavaScript_ShiftAsString(fkp: KMX.KEY, FMnemonic: boolean): string { + if(!options.debug) { + return JavaScript_Shift(fkp, FMnemonic).toString(); + } + return ' '+FormatModifierAsBitflags(JavaScript_Shift(fkp, FMnemonic)); +} + +export const VKeyNames = [ // from vkeys.h +// Key Codes +"K_?00", // &H0 +"K_LBUTTON", // &H1 +"K_RBUTTON", // &H2 +"K_CANCEL", // &H3 +"K_MBUTTON", // &H4 +"K_?05", // &H5 +"K_?06", // &H6 +"K_?07", // &H7 +"K_BKSP", // &H8 +"K_TAB", // &H9 +"K_?0A", // &HA +"K_?0B", // &HB +"K_KP5", // &HC +"K_ENTER", // &HD +"K_?0E", // &HE +"K_?0F", // &HF +"K_SHIFT", // &H10 +"K_CONTROL", // &H11 +"K_ALT", // &H12 +"K_PAUSE", // &H13 +"K_CAPS", // &H14 +"K_KANJI?15", // &H15 +"K_KANJI?16", // &H16 +"K_KANJI?17", // &H17 +"K_KANJI?18", // &H18 +"K_KANJI?19", // &H19 +"K_?1A", // &H1A +"K_ESC", // &H1B +"K_KANJI?1C", // &H1C +"K_KANJI?1D", // &H1D +"K_KANJI?1E", // &H1E +"K_KANJI?1F", // &H1F +"K_SPACE", // &H20 +"K_PGUP", // &H21 +"K_PGDN", // &H22 +"K_END", // &H23 +"K_HOME", // &H24 +"K_LEFT", // &H25 +"K_UP", // &H26 +"K_RIGHT", // &H27 +"K_DOWN", // &H28 +"K_SEL", // &H29 +"K_PRINT", // &H2A +"K_EXEC", // &H2B +"K_PRTSCN", // &H2C +"K_INS", // &H2D +"K_DEL", // &H2E +"K_HELP", // &H2F +"K_0", // &H30 +"K_1", // &H31 +"K_2", // &H32 +"K_3", // &H33 +"K_4", // &H34 +"K_5", // &H35 +"K_6", // &H36 +"K_7", // &H37 +"K_8", // &H38 +"K_9", // &H39 +"K_?3A", // &H3A +"K_?3B", // &H3B +"K_?3C", // &H3C +"K_?3D", // &H3D +"K_?3E", // &H3E +"K_?3F", // &H3F +"K_?40", // &H40 + +"K_A", // &H41 +"K_B", // &H42 +"K_C", // &H43 +"K_D", // &H44 +"K_E", // &H45 +"K_F", // &H46 +"K_G", // &H47 +"K_H", // &H48 +"K_I", // &H49 +"K_J", // &H4A +"K_K", // &H4B +"K_L", // &H4C +"K_M", // &H4D +"K_N", // &H4E +"K_O", // &H4F +"K_P", // &H50 +"K_Q", // &H51 +"K_R", // &H52 +"K_S", // &H53 +"K_T", // &H54 +"K_U", // &H55 +"K_V", // &H56 +"K_W", // &H57 +"K_X", // &H58 +"K_Y", // &H59 +"K_Z", // &H5A +"K_?5B", // &H5B +"K_?5C", // &H5C +"K_?5D", // &H5D +"K_?5E", // &H5E +"K_?5F", // &H5F +"K_NP0", // &H60 +"K_NP1", // &H61 +"K_NP2", // &H62 +"K_NP3", // &H63 +"K_NP4", // &H64 +"K_NP5", // &H65 +"K_NP6", // &H66 +"K_NP7", // &H67 +"K_NP8", // &H68 +"K_NP9", // &H69 +"K_NPSTAR", // &H6A +"K_NPPLUS", // &H6B +"K_SEPARATOR", // &H6C +"K_NPMINUS", // &H6D +"K_NPDOT", // &H6E +"K_NPSLASH", // &H6F +"K_F1", // &H70 +"K_F2", // &H71 +"K_F3", // &H72 +"K_F4", // &H73 +"K_F5", // &H74 +"K_F6", // &H75 +"K_F7", // &H76 +"K_F8", // &H77 +"K_F9", // &H78 +"K_F10", // &H79 +"K_F11", // &H7A +"K_F12", // &H7B +"K_F13", // &H7C +"K_F14", // &H7D +"K_F15", // &H7E +"K_F16", // &H7F +"K_F17", // &H80 +"K_F18", // &H81 +"K_F19", // &H82 +"K_F20", // &H83 +"K_F21", // &H84 +"K_F22", // &H85 +"K_F23", // &H86 +"K_F24", // &H87 + +"K_?88", // &H88 +"K_?89", // &H89 +"K_?8A", // &H8A +"K_?8B", // &H8B +"K_?8C", // &H8C +"K_?8D", // &H8D +"K_?8E", // &H8E +"K_?8F", // &H8F + +"K_NUMLOCK", // &H90 +"K_SCROLL", // &H91 + +"K_?92", // &H92 +"K_?93", // &H93 +"K_?94", // &H94 +"K_?95", // &H95 +"K_?96", // &H96 +"K_?97", // &H97 +"K_?98", // &H98 +"K_?99", // &H99 +"K_?9A", // &H9A +"K_?9B", // &H9B +"K_?9C", // &H9C +"K_?9D", // &H9D +"K_?9E", // &H9E +"K_?9F", // &H9F +"K_?A0", // &HA0 +"K_?A1", // &HA1 +"K_?A2", // &HA2 +"K_?A3", // &HA3 +"K_?A4", // &HA4 +"K_?A5", // &HA5 +"K_?A6", // &HA6 +"K_?A7", // &HA7 +"K_?A8", // &HA8 +"K_?A9", // &HA9 +"K_?AA", // &HAA +"K_?AB", // &HAB +"K_?AC", // &HAC +"K_?AD", // &HAD +"K_?AE", // &HAE +"K_?AF", // &HAF +"K_?B0", // &HB0 +"K_?B1", // &HB1 +"K_?B2", // &HB2 +"K_?B3", // &HB3 +"K_?B4", // &HB4 +"K_?B5", // &HB5 +"K_?B6", // &HB6 +"K_?B7", // &HB7 +"K_?B8", // &HB8 +"K_?B9", // &HB9 + +"K_COLON", // &HBA +"K_EQUAL", // &HBB +"K_COMMA", // &HBC +"K_HYPHEN", // &HBD +"K_PERIOD", // &HBE +"K_SLASH", // &HBF +"K_BKQUOTE", // &HC0 + +"K_?C1", // &HC1 +"K_?C2", // &HC2 +"K_?C3", // &HC3 +"K_?C4", // &HC4 +"K_?C5", // &HC5 +"K_?C6", // &HC6 +"K_?C7", // &HC7 +"K_?C8", // &HC8 +"K_?C9", // &HC9 +"K_?CA", // &HCA +"K_?CB", // &HCB +"K_?CC", // &HCC +"K_?CD", // &HCD +"K_?CE", // &HCE +"K_?CF", // &HCF +"K_?D0", // &HD0 +"K_?D1", // &HD1 +"K_?D2", // &HD2 +"K_?D3", // &HD3 +"K_?D4", // &HD4 +"K_?D5", // &HD5 +"K_?D6", // &HD6 +"K_?D7", // &HD7 +"K_?D8", // &HD8 +"K_?D9", // &HD9 +"K_?DA", // &HDA + +"K_LBRKT", // &HDB +"K_BKSLASH", // &HDC +"K_RBRKT", // &HDD +"K_QUOTE", // &HDE +"K_oDF", // &HDF +"K_oE0", // &HE0 +"K_oE1", // &HE1 +"K_oE2", // &HE2 +"K_oE3", // &HE3 +"K_oE4", // &HE4 + +"K_?E5", // &HE5 + +"K_oE6", // &HE6 + +"K_?E7", // &HE7 +"K_?E8", // &HE8 + +"K_oE9", // &HE9 +"K_oEA", // &HEA +"K_oEB", // &HEB +"K_oEC", // &HEC +"K_oED", // &HED +"K_oEE", // &HEE +"K_oEF", // &HEF +"K_oF0", // &HF0 +"K_oF1", // &HF1 +"K_oF2", // &HF2 +"K_oF3", // &HF3 +"K_oF4", // &HF4 +"K_oF5", // &HF5 + +"K_?F6", // &HF6 +"K_?F7", // &HF7 +"K_?F8", // &HF8 +"K_?F9", // &HF9 +"K_?FA", // &HFA +"K_?FB", // &HFB +"K_?FC", // &HFC +"K_?FD", // &HFD +"K_?FE", // &HFE +"K_?FF" // &HFF +]; + +const enum + TKeymanWebTouchStandardKey { + K_LOPT = 50001, + K_ROPT = 50002, + K_NUMERALS = 50003, + K_SYMBOLS = 50004, + K_CURRENCIES = 50005, + K_UPPER = 50006, + K_LOWER = 50007, + K_ALPHA = 50008, + K_SHIFTED = 50009, + K_ALTGR = 50010, + K_TABBACK = 50011, + K_TABFWD = 50012 + }; + +function FormatKeyForErrorMessage(fkp: KMX.KEY, FMnemonic: boolean): string { + function FormatShift(ShiftFlags: number): string { + const + mask: string[] = [ + 'LCTRL', // 0X0001 + 'RCTRL', // 0X0002 + 'LALT', // 0X0004 + 'RALT', // 0X0008 + + 'SHIFT', // 0X0010 + 'CTRL', // 0X0020 + 'ALT', // 0X0040 + + '???', // Reserved + + 'CAPS', // 0X0100 + 'NCAPS', // 0X0200 + + 'NUMLOCK', // 0X0400 + 'NNUMLOCK', // 0X0800 + + 'SCROLLLOCK', // 0X1000 + 'NSCROLLLOCK' // 0X2000 + ]; + + let result = ''; + for(let i = 0; i < mask.length; i++) { + if(ShiftFlags & (1 << i)) { + result += mask[i] + ' '; + } + } + return result; + } + + let result: string; + if(!FMnemonic) { + if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) { + if(fkp.Key < 256) { + result = `[${FormatShift(fkp.ShiftFlags)}${VKeyNames[fkp.Key]}]`; + } + else { + result = `[${FormatShift(fkp.ShiftFlags)}K_${fkp.Key.toString(16).toUpperCase()}]`; + } + } + else { + result = `'${String.fromCharCode(fkp.Key)}'`; + } + } + else { + if (fkp.ShiftFlags & KMX.KMXFile.VIRTUALCHARKEY) { + result = `[${FormatShift(fkp.ShiftFlags)}'${String.fromCharCode(fkp.Key)}']`; + } + else { + result = `'${String.fromCharCode(fkp.Key)}'`; + } + } + return result; +} + +export function JavaScript_Key(fkp: KMX.KEY, FMnemonic: boolean): number { + let Result: number; + if(!FMnemonic) { + if(fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) { + Result = fkp.Key; + } + else { + // Convert the character to a virtual key + let n = USEnglishShift.indexOf(String.fromCharCode(fkp.Key)); + if(n < 0) { + n = USEnglishUnshift.indexOf(String.fromCharCode(fkp.Key)); + } + if(n < 0) { + Result = 0; + } + else { + Result = USEnglishValues.charCodeAt(n); + } + } + } + else { + Result = fkp.Key; + } + + // Check that key is not unreachable (e.g. K_SHIFT, touch-specific special keys 50,000+) + + if(UnreachableKeyCodes.indexOf(Result) >= 0) { + Result = 0; + } + + if (Result == 0 || Result >= TKeymanWebTouchStandardKey.K_LOPT) { // I4141 + if(!FUnreachableKeys.includes(fkp)) { + ReportError(fkp.Line, CHINT_UnreachableKeyCode, + 'The rule will never be matched for key '+ + FormatKeyForErrorMessage(fkp,FMnemonic)+' because its key code is never fired.'); + FUnreachableKeys.push(fkp); + } + } + return Result; +} + +/// +/// Returns a Javascript representation of a key value, either as a constant (debug mode) +/// or as an integer. +/// +/// @param fkp Pointer to key record +/// @param FMnemonic True if the keyboard is a mnemonic layout +/// +/// @return string representation of the key value, e.g. 'keyCodes.K_A /* 0x41 */' or '65' +/// +export function JavaScript_KeyAsString(fkp: KMX.KEY, FMnemonic: boolean): string { + if(options.debug) { + return ' '+FormatKeyAsString(JavaScript_Key(fkp, FMnemonic)); + } else { + return JavaScript_Key(fkp, FMnemonic).toString(); + } +} + +export function JavaScript_ContextMatch(fk: KMX.KEYBOARD, fkp: KMX.KEY, context: string): string { + if(IsKeyboardVersion10OrLater()) { + return JavaScript_FullContextValue(fk, fkp, context); + } + else { + return JavaScript_CompositeContextValue(fk, fkp, context); + } +} + +function JavaScript_ContextLength(Context: string): number { + return xstrlen_printing(Context); +} + +const + KMXCodeNames: string[] = [ + '', + 'any', 'index', 'context', 'nul', 'use', 'return', 'beep', 'deadkey', + '', + 'extended', '', 'switch', 'key', 'clearcontext', 'call', + '', 'contextex', 'notany', + 'set', 'if', 'save', 'reset', // I3429 + 'if(&system)', 'set(&system)']; // I3430 // I3437 + +function GetCodeName(code: number): string { + if (code >= 0 && code < KMXCodeNames.length && KMXCodeNames[code] != '') { + return KMXCodeNames[code]; + } + return code.toString(); +} + +function CheckStoreForInvalidFunctions(fk: KMX.KEYBOARD, key: KMX.KEY, store: KMX.STORE) { // I1520 + let n: number, rec: TSentinelRecord; + const wcsentinel = String.fromCharCode(0xFFFF); + + n = store.dpString.indexOf(wcsentinel); + + // Disable the check with versions >= 10.0, since we now support deadkeys in stores. + if (n >= 0 && !IsKeyboardVersion10OrLater) { + rec = ExpandSentinel(fk, store.dpString, n); + ReportError(key.Line, CERR_NotSupportedInKeymanWebStore, + `${GetCodeName(rec.Code)} is not currently supported in store '${store.dpName}' when used by any or index`); + } +} + + +// Used when targeting versions prior to 10.0, before the introduction of FullContextMatch/KFCM. +function JavaScript_CompositeContextValue(fk: KMX.KEYBOARD, fkp: KMX.KEY, pwsz: string): string { +// var + // StartQuotes, Len, Cur: Integer; + // InQuotes: Boolean; + // rec: TSentinelRecord; + + let Result = ''; + + let InQuotes = false; + let Len = JavaScript_ContextLength(pwsz); + let StartQuotes = -1; + let x = 0, Cur = 0; + + while(x < pwsz.length) { + let rec = ExpandSentinel(fk, pwsz, x); + if(rec.IsSentinel) { + if(InQuotes) { + Result += `",${Cur-StartQuotes})`; + InQuotes = false; + } + if(Result != '') { + Result += '&&'; + } + + switch(rec.Code) { + case KMX.KMXFile.CODE_ANY: + CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520 + Result += `k.KA(${Cur},k.KC(${Len-Cur},1,t),this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)})`; + break; + case KMX.KMXFile.CODE_DEADKEY: + Result += `k.KDM(${Len-Cur},t,${rec.DeadKey.DeadKey})`; + Cur--; // don't increment on deadkeys -- correlates with AdjustIndex function // I3910 + break; + case KMX.KMXFile.CODE_NUL: // I2243 + Result += `k.KN(${Len-Cur},t)`; + Cur--; // don't increment on nul -- correlates with AdjustIndex function // I3910 + break; + case KMX.KMXFile.CODE_IFOPT: // I3429 + Result += `this.s${JavaScript_Name(rec.IfOpt.StoreIndex1, rec.IfOpt.Store1.dpName)}`+ + `${rec.IfOpt.IsNot == 0 ? '!==':'==='}`+ + `this.s${JavaScript_Name(rec.IfOpt.StoreIndex2,rec.IfOpt.Store2.dpName)}`; // I3429 // I3659 // I3681 + Cur--; // don't increment on ifopt -- correlates with AdjustIndex function // I3910 + break; + case KMX.KMXFile.CODE_IFSYSTEMSTORE: // I3430 + Result += `${rec.IfSystemStore.IsNot == 0 ? '!' : ''}`+ + `k.KIFS(${rec.IfSystemStore.dwSystemID},`+ + `this.s${JavaScript_Name(rec.IfSystemStore.StoreIndex,rec.IfSystemStore.Store.dpName)},t)`; + Cur--; // don't increment on ifsystemstore -- correlates with AdjustIndex function // I3910 + break; + case KMX.KMXFile.CODE_CONTEXTEX: // I3980 + Result += `k.KCCM(${Len-Cur},${Len-rec.ContextEx.Index+1},t)`; + break; + case KMX.KMXFile.CODE_NOTANY: // I3981 + CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520 + Result += `k.KC(${Len-Cur},1,t)!=""&&!k.KA(${Cur},k.KC(${Len-Cur},1,t),`+ + `this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)})`; + break; + default: + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, + `Statement ${GetCodeName(rec.Code)} is not currently supported in context`); // I1971 // I4061 + Result += '/*.*/ 0 '; + } + } + else { + if(!InQuotes) { + if(Result != '') { + Result += '&&'; + } + Result += `k.KCM(${Len-Cur},t,"`; + StartQuotes = Cur; + InQuotes = true; + } + if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0)) { + Result += '\\'; + } + Result += JavaScript_String(rec.ChrVal); // I2242 + } + + Cur++; + x = incxstr(pwsz, x); + } + + if(InQuotes) { + Result += `",${Cur - StartQuotes})`; + } + return Result; +} + +// Used when targeting versions >= 10.0, after the introduction of FullContextMatch/KFCM. +function JavaScript_FullContextValue(fk: KMX.KEYBOARD, fkp: KMX.KEY, pwsz: string): string { +/*var + Len: Integer; + rec: TSentinelRecord; + FullContext, Suffix: string; +begin*/ + let Result = ''; + let FullContext = ''; + let Suffix = ''; + let Len = xstrlen(pwsz); + let x = 0; + + while(x < pwsz.length) { + if(FullContext != '') { + FullContext += ','; + } + + let rec = ExpandSentinel(fk, pwsz, x); + if(rec.IsSentinel) { + switch(rec.Code) { + case KMX.KMXFile.CODE_ANY: + CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520 + FullContext += `{t:'a',a:this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)}}`; + break; + case KMX.KMXFile.CODE_DEADKEY: + FullContext += `{t:'d',d:${rec.DeadKey.DeadKey}}`; + break; + case KMX.KMXFile.CODE_NUL: // I2243 + FullContext += `{t:'n'}`; + break; + case KMX.KMXFile.CODE_IFOPT: // I3429 + Len--; + if(Suffix != '') { + Suffix += '&&'; + } + if(FullContext == ',') { + FullContext = ''; + } + Suffix += `this.s${JavaScript_Name(rec.IfOpt.StoreIndex1, rec.IfOpt.Store1.dpName)}`+ + `${rec.IfOpt.IsNot == 0 ? '!==' : '==='}this.s${JavaScript_Name(rec.IfOpt.StoreIndex2,rec.IfOpt.Store2.dpName)}`; // I3429 // I3659 // I3681 + break; + case KMX.KMXFile.CODE_IFSYSTEMSTORE: // I3430 + Len--; + if(Suffix != '') { + Suffix += '&&'; + } + if(FullContext == ',') { + FullContext = ''; + } + Suffix += `${rec.IfSystemStore.IsNot == 0 ? '!' : ''}k.KIFS(${rec.IfSystemStore.dwSystemID},`+ + `this.s${JavaScript_Name(rec.IfSystemStore.StoreIndex,rec.IfSystemStore.Store.dpName)},t)`; // I3430 // I3659 // I3681 + break; + case KMX.KMXFile.CODE_NOTANY: // I3981 + CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520 + FullContext += `{t:'a',a:this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)},n:1}`; + break; + case KMX.KMXFile.CODE_CONTEXTEX: + FullContext += `{t:'c',c:${rec.ContextEx.Index}}`; // I4611 + break; + case KMX.KMXFile.CODE_INDEX: + FullContext += `{t:'i',i:this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.dpName)},`+ + `o:${rec.Index.Index}}`; // I4611 + break; + default: + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, `Statement ${GetCodeName(rec.Code)} is not currently supported in context`); // I1971 // I4061 + Result += '/*.*/ 0 '; + } + } + else + { // Simple context character. + FullContext += `'`; + if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0) || rec.ChrVal == '\''.charCodeAt(0)) { + FullContext += '\\'; + } + FullContext += JavaScript_String(rec.ChrVal) + `'`; // I2242 + } + + x = incxstr(pwsz, x); + } + + if(FullContext != '') { + Result = `k.KFCM(${Len},t,[${FullContext}])`; + } + + if (Result != '' && Suffix != '') { + Result += '&&' + Suffix; + } + else if(Suffix != '') { + Result = Suffix; + } + return Result; +} + +function isGroupReadOnly(fk: KMX.KEYBOARD, fgp: KMX.GROUP) { + // TODO: export group + store metadata in debug store, use that + return false; +} + +function CallFunctionName(s: string): string { + let n: number; + n = s.indexOf(':'); + return s.substring(n+1); // not found gives -1, substring(0) is ok :grin: +} + +export function JavaScript_OutputString(fk: KMX.KEYBOARD, FTabStops: string, fkp: KMX.KEY, pwszOutput: string, fgp: KMX.GROUP): string { + let InQuotes = false; + let len = 0; + const nlt = nl + FTabStops; // I3681 + +/*var + i, n, len: Integer; + InQuotes: Boolean; + rec: TSentinelRecord; + pwszcontext,pwsz: PWideChar; + Index: Integer; // I3910 + nlt: string;*/ + + const AdjustIndex = function(pwszContext: string, Index: number): number { // I3910 + let Result = Index; + let x = 0; + for(let I = 1; I < Index; I++) { + let recContext = ExpandSentinel(fk, pwszContext, x); + + if(IsKeyboardVersion10OrLater()) { + if(recContext.IsSentinel && [KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) { + Result--; + } + } + else { + if(recContext.IsSentinel && [KMX.KMXFile.CODE_DEADKEY, KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) { + Result--; + } + } + x = incxstr(pwszContext, x); + } + return Result + 1; // 1-based + } + + const ContextChar = function(ContextIndex: number, pwszContext: string, xContext: number): string { // I4611 + let Index: number; + let Result = ''; + let recContext = ExpandSentinel(fk, pwszContext, xContext); + if(recContext.IsSentinel) { + if(InQuotes) { // I4611 + Result += '");'; + InQuotes =false; + } + + switch(recContext.Code) { + case KMX.KMXFile.CODE_ANY: + Index = AdjustIndex(fkp.dpContext, ContextIndex); // I3910 // I4611 + Result += nlt + `k.KIO(${len},this.s${JavaScript_Name(recContext.Any.StoreIndex, recContext.Any.Store.dpName)},${Index},t);`; // I4611 + break; + case KMX.KMXFile.CODE_DEADKEY: + Result += nlt + `k.KDO(${len},t,${recContext.DeadKey.DeadKey});`; // I4611 + break; + case KMX.KMXFile.CODE_NOTANY: + // #917: Minimum version required is 14.0: the KCXO function was only added for 14.0 + // Note that this is checked in compiler.cpp as well, so this error can probably never occur + if(!IsKeyboardVersion14OrLater()) { + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, `Statement notany in context() match requires version 14.0+ of KeymanWeb`); // I1971 // I4061 + } + Result += nlt + `k.KCXO(${len},t,${AdjustIndex(fkp.dpContext, xstrlen(fkp.dpContext))},${AdjustIndex(fkp.dpContext, ContextIndex)});`; + break; + case KMX.KMXFile.CODE_IFOPT: + case KMX.KMXFile.CODE_IFSYSTEMSTORE: + case KMX.KMXFile.CODE_NUL: + // These have no output for a context emit + break; + default: + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, `Statement ${GetCodeName(recContext.Code)} is not currently supported in context() match`); // I1971 // I4061 + Result += nlt + '/*.*/ '; // I4611 + } + } + else { + if(!InQuotes) { + Result += nlt + `k.KO(${len},t,"`; // I4611 + InQuotes = true; + } + + if(recContext.ChrVal == '"'.charCodeAt(0) || recContext.ChrVal == '\\'.charCodeAt(0)) { + Result += '\\'; + } + Result += JavaScript_String(recContext.ChrVal); // I2242 + } + return Result; + } + + let Result = ''; + InQuotes = false; + + let pwsz = pwszOutput; + + if(fkp != null) { + if(IsKeyboardVersion10OrLater()) { + // KMW >= 10.0 use the full, sentinel-based length for context deletions. + len = xstrlen(fkp.dpContext); + let n = len; + + let x = 0; + for(let i = 0; i < n; i++) { + let rec = ExpandSentinel(fk, fkp.dpContext, x); + if(rec.IsSentinel && [KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(rec.Code)) { + len--; + } + x = incxstr(fkp.dpContext, x); + } + } + else { + // KMW < 10.0 exclude all sentinel-based characters, including deadkeys, from direct context deletion. + // Deadkeys have alternative special handling. + len = xstrlen_printing(fkp.dpContext); + } + } + else { + len = -1; + } + + let x = 0; + if(IsKeyboardVersion10OrLater() && pwsz.length > 0) { + if(!isGroupReadOnly(fk, fgp)) { + Result += nlt+`k.KDC(${len},t);`; // I3681 + } + len = -1; + } + + while(x < pwsz.length) { + let rec = ExpandSentinel(fk, pwsz, x); + if(rec.IsSentinel) { + if(InQuotes) { + if(!isGroupReadOnly(fk, fgp)) { + Result += '");'; + } + InQuotes = false; + } + + switch(rec.Code) { + case KMX.KMXFile.CODE_CONTEXT: + if (x > 0 || len == -1) { + let xContext = 0; + let n = 0; + while(xContext < fkp.dpContext.length) { // I4611 + if(!isGroupReadOnly(fk, fgp)) { + Result += ContextChar(n, fkp.dpContext, xContext); + } + n++; + xContext = incxstr(fkp.dpContext, xContext); + } + //Result := Result + Format('k.KO(%d,t,k.KC(%d,%d,t));', [len, xstrlen_printing(fkp.dpContext), xstrlen_printing(fkp.dpContext)]); + } + // else, we don't need to output anything - just don't delete the context + len = -1; + break; + case KMX.KMXFile.CODE_CONTEXTEX: + let xContext = 0; + for(let i = 0; i < rec.ContextEx.Index; i++) { + xContext = incxstr(fkp.dpContext, xContext); + } + + if(!isGroupReadOnly(fk, fgp)) { + Result += ContextChar(rec.ContextEx.Index, fkp.dpContext, xContext); // I4611 + } + len = -1; + break; + case KMX.KMXFile.CODE_BEEP: + if(!isGroupReadOnly(fk, fgp)) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + Result += nlt+'k.KB(t);'; // I3681 + } + len = -1; + break; + case KMX.KMXFile.CODE_NUL: + if(!isGroupReadOnly(fk, fgp)) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + len = -1; + break; + case KMX.KMXFile.CODE_INDEX: + CheckStoreForInvalidFunctions(fk, fkp, rec.Index.Store); // I1520 + + // This code was wrong. We need to ignore CODE_NUL, CODE_DEADKEY in LHS context index counter. + // This is why the compiler goes wrong -- and why the previous fix was inconsistent. + // The I783 test did not test either of these cases. It seems some of the keyboards were + // compiled in-between the original fix and I783 re-fix, and then happened to work due to + // their simplicity. + + let Index = AdjustIndex(fkp.dpContext, rec.Index.Index); // I3910 + + if(!isGroupReadOnly(fk, fgp)) { + Result += nlt+`k.KIO(${len},this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.dpName)},${Index},t);`; + // I783 - was: rec.Index.Index [2007-06-04] + // I783 again. Returned to rec.Index.Index. Was previously: [2008-08-15] + // xstrlen(fkp.dpContext) + 1 - rec.Index.Index]); + // this was wrong. Can't find any reason why this change was made + // which suggests it was in response to another bug and poorly traced (bad Marc) + // and not properly tested (bad, bad Marc). Anyway, now tested with test_i783 + } + len = -1; + break; + case KMX.KMXFile.CODE_DEADKEY: + if(!isGroupReadOnly(fk, fgp)) { + Result += nlt+`k.KDO(${len},t,${rec.DeadKey.DeadKey});`; // I3681 + } + len = -1; + break; + case KMX.KMXFile.CODE_USE: + if(!isGroupReadOnly(fk, fgp)) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + Result += nlt+`r=this.g${JavaScript_Name(rec.Use.GroupIndex, rec.Use.Group.dpName)}(t,e);`; // I1959 // I3681 + Result += nlt+'m=2;'; // #5440 - match desktop behavior + len = -1; + break; + case KMX.KMXFile.CODE_CALL: + if(!isGroupReadOnly(fk, fgp)) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + let n = FCallFunctions.indexOf(CallFunctionName(rec.Call.Store.dpString)); + if(n == -1) { + n = FCallFunctions.push(CallFunctionName(rec.Call.Store.dpString)); + } + Result += nlt+`r=this.c${n}(t,e);`; // I1959 // I3681 + Result += nlt+'m=2;'; // #5440 - match desktop behavior + len = -1; + break; + case KMX.KMXFile.CODE_SETOPT: // I3429 + if(!isGroupReadOnly(fk, fgp)) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + Result += nlt+`this.s${JavaScript_Name(rec.SetOpt.StoreIndex1,rec.SetOpt.Store1.dpName)}=`+ + `this.s${JavaScript_Name(rec.SetOpt.StoreIndex2,rec.SetOpt.Store2.dpName)};`; + len = -1; + break; + case KMX.KMXFile.CODE_RESETOPT: // I3429 + if(!isGroupReadOnly(fk, fgp)) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + + Result += nlt+`this.s${JavaScript_Name(rec.ResetOpt.StoreIndex,rec.ResetOpt.Store.dpName)}=`+ + `k.KLOAD(this.KI,"${JavaScript_Name(rec.ResetOpt.StoreIndex,rec.ResetOpt.Store.dpName,true)}",`+ + `${JavaScript_Store(fk, fkp.Line, rec.ResetOpt.Store.dpString)});`; // I3429 // I3681 // I3659 + len = -1; + break; + case KMX.KMXFile.CODE_SAVEOPT: // I3429 + if(!isGroupReadOnly(fk, fgp)) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + + Result += nlt+`k.KSAVE("${JavaScript_Name(rec.SaveOpt.StoreIndex,rec.SaveOpt.Store.dpName,true)}",`+ + `this.s${JavaScript_Name(rec.SaveOpt.StoreIndex,rec.SaveOpt.Store.dpName)});`; // I3690 // I3429 // I3659 // I3681 + len = -1; + break; + case KMX.KMXFile.CODE_SETSYSTEMSTORE: // I3437 + if(!isGroupReadOnly(fk, fgp)) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + + Result += nlt+`k.KSETS(${rec.SetSystemStore.dwSystemID},`+ + `this.s${JavaScript_Name(rec.SetSystemStore.StoreIndex, rec.SetSystemStore.Store.dpName)},t);`; // I3681 + len = -1; + break; + default: + ReportError(fkp ? fkp.Line : 0, CERR_NotSupportedInKeymanWebOutput, `Statement ${GetCodeName(rec.Code)} is not currently supported in output`); // I1971 // I4061 + Result += ''; + } + } + else { + if(!InQuotes) { + if(!isGroupReadOnly(fk, fgp)) { + Result += nlt+`k.KO(${len},t,"`; // I3681 + } + InQuotes = true; len = -1; + } + + if(!isGroupReadOnly(fk, fgp)) { + if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0)) { + Result += '\\'; + } + Result += JavaScript_String(rec.ChrVal); // I2242 + } + } + + x = incxstr(pwsz, x); + } + + if(InQuotes) { + if(!isGroupReadOnly(fk, fgp)) { + Result += '");'; + } + } + return Result; +} + +export function zeroPadHex(n: number, len: number): string { + let result = n.toString(16).toUpperCase(); + if(result.length < len) { + return '0'.repeat(len - result.length) + result; + } + return result; +} + +// TODO: move elsewhere +/// +/// Virtual key names used in KeymanWeb. Blanks indicate a +/// virtual key that is not recognised by KeymanWeb. +/// +const KMWVKeyNames: string[] = [ + '', + '', + '', + '', + '', + '', + '', + '', + 'K_BKSP', + 'K_TAB', + '', + '', + '', + 'K_ENTER', + '', + '', + 'K_SHIFT', + 'K_CONTROL', + 'K_ALT', + 'K_PAUSE', + 'K_CAPS', + '', + '', + '', + '', + '', + '', + 'K_ESC', + '', + '', + '', + '', + 'K_SPACE', + 'K_PGUP', + 'K_PGDN', + 'K_END', + 'K_HOME', + 'K_LEFT', + 'K_UP', + 'K_RIGHT', + 'K_DOWN', + 'K_SEL', + 'K_PRINT', + 'K_EXEC', + '', + 'K_INS', + 'K_DEL', + 'K_HELP', + 'K_0', + 'K_1', + 'K_2', + 'K_3', + 'K_4', + 'K_5', + 'K_6', + 'K_7', + 'K_8', + 'K_9', + '', + '', + '', + '', + '', + '', + '', + 'K_A', + 'K_B', + 'K_C', + 'K_D', + 'K_E', + 'K_F', + 'K_G', + 'K_H', + 'K_I', + 'K_J', + 'K_K', + 'K_L', + 'K_M', + 'K_N', + 'K_O', + 'K_P', + 'K_Q', + 'K_R', + 'K_S', + 'K_T', + 'K_U', + 'K_V', + 'K_W', + 'K_X', + 'K_Y', + 'K_Z', + '', + '', + '', + '', + '', + 'K_NP0', + 'K_NP1', + 'K_NP2', + 'K_NP3', + 'K_NP4', + 'K_NP5', + 'K_NP6', + 'K_NP7', + 'K_NP8', + 'K_NP9', + 'K_NPSTAR', + 'K_NPPLUS', + 'K_SEPARATOR', + 'K_NPMINUS', + 'K_NPDOT', + 'K_NPSLASH', + 'K_F1', + 'K_F2', + 'K_F3', + 'K_F4', + 'K_F5', + 'K_F6', + 'K_F7', + 'K_F8', + 'K_F9', + 'K_F10', + 'K_F11', + 'K_F12', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'K_NUMLOCK', + 'K_SCROLL', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'K_LSHIFT', + 'K_RSHIFT', + 'K_LCONTROL', + 'K_RCONTROL', + 'K_LALT', + 'K_RALT', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'K_COLON', + 'K_EQUAL', + 'K_COMMA', + 'K_HYPHEN', + 'K_PERIOD', + 'K_SLASH', + 'K_BKQUOTE', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'K_LBRKT', + 'K_BKSLASH', + 'K_RBRKT', + 'K_QUOTE', + '', + '', + '', + 'K_oE2', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '' +]; + +/** + * Converts a key value into a constant + * + * @param key A virtual key code + * + * @return string of JavaScript code, e.g. 'keyCodes.K_A /* 0x41 * /' + */ +function FormatKeyAsString(key: number): string { + if(IsKeyboardVersion10OrLater()) { + // Depends on flags defined in KeymanWeb 10.0 + if (key <= 255 && KMWVKeyNames[key] != '') { + return 'keyCodes.'+KMWVKeyNames[key]+ ' /* 0x' + zeroPadHex(key, 2) + ' */'; + } + return '0x' + zeroPadHex(key, 2); + } + return '0x' + zeroPadHex(key, 2); +} diff --git a/developer/src/kmc-kmw/src/compiler/keymanweb-key-codes.ts b/developer/src/kmc-kmw/src/compiler/keymanweb-key-codes.ts new file mode 100644 index 00000000000..98e609d7476 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/keymanweb-key-codes.ts @@ -0,0 +1,271 @@ +export const + CKeymanWebKeyCodes: number[] = [ + 0xFF, // L"K_?00", // &H0 + 0xFF, // L"K_LBUTTON", // &H1 + 0xFF, // L"K_RBUTTON", // &H2 + 0xFF, // L"K_CANCEL", // &H3 + 0xFF, // L"K_MBUTTON", // &H4 + 0xFF, // L"K_?05", // &H5 + 0xFF, // L"K_?06", // &H6 + 0xFF, // L"K_?07", // &H7 + 0xFF, // L"K_BKSP", // &H8 + 0xFF, // L"K_TAB", // &H9 + 0xFF, // L"K_?0A", // &HA + 0xFF, // L"K_?0B", // &HB + 0xFF, // L"K_KP5", // &HC + 0xFF, // L"K_ENTER", // &HD + 0xFF, // L"K_?0E", // &HE + 0xFF, // L"K_?0F", // &HF + 0xFF, // L"K_SHIFT", // &H10 + 0xFF, // L"K_CONTROL", // &H11 + 0xFF, // L"K_ALT", // &H12 + 0xFF, // L"K_PAUSE", // &H13 + 0xFF, // L"K_CAPS", // &H14 + 0xFF, // L"K_KANJI?15", // &H15 + 0xFF, // L"K_KANJI?16", // &H16 + 0xFF, // L"K_KANJI?17", // &H17 + 0xFF, // L"K_KANJI?18", // &H18 + 0xFF, // L"K_KANJI?19", // &H19 + 0xFF, // L"K_?1A", // &H1A + 0xFF, // L"K_ESC", // &H1B + 0xFF, // L"K_KANJI?1C", // &H1C + 0xFF, // L"K_KANJI?1D", // &H1D + 0xFF, // L"K_KANJI?1E", // &H1E + 0xFF, // L"K_KANJI?1F", // &H1F + 0x40, // L"K_SPACE", // &H20 + 0xFF, // L"K_PGUP", // &H21 + 0xFF, // L"K_PGDN", // &H22 + 0xFF, // L"K_END", // &H23 + 0xFF, // L"K_HOME", // &H24 + 0xFF, // L"K_LEFT", // &H25 + 0xFF, // L"K_UP", // &H26 + 0xFF, // L"K_RIGHT", // &H27 + 0xFF, // L"K_DOWN", // &H28 + 0xFF, // L"K_SEL", // &H29 + 0xFF, // L"K_PRINT", // &H2A + 0xFF, // L"K_EXEC", // &H2B + 0xFF, // L"K_PRTSCN", // &H2C + 0xFF, // L"K_INS", // &H2D + 0xFF, // L"K_DEL", // &H2E + 0xFF, // L"K_HELP", // &H2F + 0x0A, // L"K_0", // &H30 + 0x01, // L"K_1", // &H31 + 0x02, // L"K_2", // &H32 + 0x03, // L"K_3", // &H33 + 0x04, // L"K_4", // &H34 + 0x05, // L"K_5", // &H35 + 0x06, // L"K_6", // &H36 + 0x07, // L"K_7", // &H37 + 0x08, // L"K_8", // &H38 + 0x09, // L"K_9", // &H39 + 0xFF, // L"K_?3A", // &H3A + 0xFF, // L"K_?3B", // &H3B + 0xFF, // L"K_?3C", // &H3C + 0xFF, // L"K_?3D", // &H3D + 0xFF, // L"K_?3E", // &H3E + 0xFF, // L"K_?3F", // &H3F + 0xFF, // L"K_?40", // &H40 + + 0x20, // L"K_A", // &H41 + 0x35, // L"K_B", // &H42 + 0x33, // L"K_C", // &H43 + 0x22, // L"K_D", // &H44 + 0x12, // L"K_E", // &H45 + 0x23, // L"K_F", // &H46 + 0x24, // L"K_G", // &H47 + 0x25, // L"K_H", // &H48 + 0x17, // L"K_I", // &H49 + 0x26, // L"K_J", // &H4A + 0x27, // L"K_K", // &H4B + 0x28, // L"K_L", // &H4C + 0x37, // L"K_M", // &H4D + 0x36, // L"K_N", // &H4E + 0x18, // L"K_O", // &H4F + 0x19, // L"K_P", // &H50 + 0x10, // L"K_Q", // &H51 + 0x13, // L"K_R", // &H52 + 0x21, // L"K_S", // &H53 + 0x14, // L"K_T", // &H54 + 0x16, // L"K_U", // &H55 + 0x34, // L"K_V", // &H56 + 0x11, // L"K_W", // &H57 + 0x32, // L"K_X", // &H58 + 0x15, // L"K_Y", // &H59 + 0x31, // L"K_Z", // &H5A + 0xFF, // L"K_?5B", // &H5B + 0xFF, // L"K_?5C", // &H5C + 0xFF, // L"K_?5D", // &H5D + 0xFF, // L"K_?5E", // &H5E + 0xFF, // L"K_?5F", // &H5F + 0xFF, // L"K_NP0", // &H60 + 0xFF, // L"K_NP1", // &H61 + 0xFF, // L"K_NP2", // &H62 + 0xFF, // L"K_NP3", // &H63 + 0xFF, // L"K_NP4", // &H64 + 0xFF, // L"K_NP5", // &H65 + 0xFF, // L"K_NP6", // &H66 + 0xFF, // L"K_NP7", // &H67 + 0xFF, // L"K_NP8", // &H68 + 0xFF, // L"K_NP9", // &H69 + 0xFF, // L"K_NPSTAR", // &H6A + 0xFF, // L"K_NPPLUS", // &H6B + 0xFF, // L"K_SEPARATOR", // &H6C + 0xFF, // L"K_NPMINUS", // &H6D + 0xFF, // L"K_NPDOT", // &H6E + 0xFF, // L"K_NPSLASH", // &H6F + 0xFF, // L"K_F1", // &H70 + 0xFF, // L"K_F2", // &H71 + 0xFF, // L"K_F3", // &H72 + 0xFF, // L"K_F4", // &H73 + 0xFF, // L"K_F5", // &H74 + 0xFF, // L"K_F6", // &H75 + 0xFF, // L"K_F7", // &H76 + 0xFF, // L"K_F8", // &H77 + 0xFF, // L"K_F9", // &H78 + 0xFF, // L"K_F10", // &H79 + 0xFF, // L"K_F11", // &H7A + 0xFF, // L"K_F12", // &H7B + 0xFF, // L"K_F13", // &H7C + 0xFF, // L"K_F14", // &H7D + 0xFF, // L"K_F15", // &H7E + 0xFF, // L"K_F16", // &H7F + 0xFF, // L"K_F17", // &H80 + 0xFF, // L"K_F18", // &H81 + 0xFF, // L"K_F19", // &H82 + 0xFF, // L"K_F20", // &H83 + 0xFF, // L"K_F21", // &H84 + 0xFF, // L"K_F22", // &H85 + 0xFF, // L"K_F23", // &H86 + 0xFF, // L"K_F24", // &H87 + + 0xFF, // L"K_?88", // &H88 + 0xFF, // L"K_?89", // &H89 + 0xFF, // L"K_?8A", // &H8A + 0xFF, // L"K_?8B", // &H8B + 0xFF, // L"K_?8C", // &H8C + 0xFF, // L"K_?8D", // &H8D + 0xFF, // L"K_?8E", // &H8E + 0xFF, // L"K_?8F", // &H8F + + 0xFF, // L"K_NUMLOCK", // &H90 + 0xFF, // L"K_SCROLL", // &H91 + + 0xFF, // L"K_?92", // &H92 + 0xFF, // L"K_?93", // &H93 + 0xFF, // L"K_?94", // &H94 + 0xFF, // L"K_?95", // &H95 + 0xFF, // L"K_?96", // &H96 + 0xFF, // L"K_?97", // &H97 + 0xFF, // L"K_?98", // &H98 + 0xFF, // L"K_?99", // &H99 + 0xFF, // L"K_?9A", // &H9A + 0xFF, // L"K_?9B", // &H9B + 0xFF, // L"K_?9C", // &H9C + 0xFF, // L"K_?9D", // &H9D + 0xFF, // L"K_?9E", // &H9E + 0xFF, // L"K_?9F", // &H9F + 0xFF, // L"K_?A0", // &HA0 + 0xFF, // L"K_?A1", // &HA1 + 0xFF, // L"K_?A2", // &HA2 + 0xFF, // L"K_?A3", // &HA3 + 0xFF, // L"K_?A4", // &HA4 + 0xFF, // L"K_?A5", // &HA5 + 0xFF, // L"K_?A6", // &HA6 + 0xFF, // L"K_?A7", // &HA7 + 0xFF, // L"K_?A8", // &HA8 + 0xFF, // L"K_?A9", // &HA9 + 0xFF, // L"K_?AA", // &HAA + 0xFF, // L"K_?AB", // &HAB + 0xFF, // L"K_?AC", // &HAC + 0xFF, // L"K_?AD", // &HAD + 0xFF, // L"K_?AE", // &HAE + 0xFF, // L"K_?AF", // &HAF + 0xFF, // L"K_?B0", // &HB0 + 0xFF, // L"K_?B1", // &HB1 + 0xFF, // L"K_?B2", // &HB2 + 0xFF, // L"K_?B3", // &HB3 + 0xFF, // L"K_?B4", // &HB4 + 0xFF, // L"K_?B5", // &HB5 + 0xFF, // L"K_?B6", // &HB6 + 0xFF, // L"K_?B7", // &HB7 + 0xFF, // L"K_?B8", // &HB8 + 0xFF, // L"K_?B9", // &HB9 + + 0x29, // L"K_COLON", // &HBA + 0x0C, // L"K_EQUAL", // &HBB + 0x38, // L"K_COMMA", // &HBC + 0x0B, // L"K_HYPHEN", // &HBD + 0x39, // L"K_PERIOD", // &HBE + 0x3A, // L"K_SLASH", // &HBF + 0x00, // L"K_BKQUOTE", // &HC0 + + 0x00, // L"K_?C1", // &HC1 + 0x00, // L"K_?C2", // &HC2 + 0x00, // L"K_?C3", // &HC3 + 0x00, // L"K_?C4", // &HC4 + 0x00, // L"K_?C5", // &HC5 + 0x00, // L"K_?C6", // &HC6 + 0x00, // L"K_?C7", // &HC7 + 0x00, // L"K_?C8", // &HC8 + 0x00, // L"K_?C9", // &HC9 + 0x00, // L"K_?CA", // &HCA + 0x00, // L"K_?CB", // &HCB + 0x00, // L"K_?CC", // &HCC + 0x00, // L"K_?CD", // &HCD + 0x00, // L"K_?CE", // &HCE + 0x00, // L"K_?CF", // &HCF + 0x00, // L"K_?D0", // &HD0 + 0x00, // L"K_?D1", // &HD1 + 0x00, // L"K_?D2", // &HD2 + 0x00, // L"K_?D3", // &HD3 + 0x00, // L"K_?D4", // &HD4 + 0x00, // L"K_?D5", // &HD5 + 0x00, // L"K_?D6", // &HD6 + 0x00, // L"K_?D7", // &HD7 + 0x00, // L"K_?D8", // &HD8 + 0x00, // L"K_?D9", // &HD9 + 0x00, // L"K_?DA", // &HDA + + 0x1A, // L"K_LBRKT", // &HDB + 0x1C, // L"K_BKSLASH", // &HDC + 0x1B, // L"K_RBRKT", // &HDD + 0x2A, // L"K_QUOTE", // &HDE + 0x00, // L"K_oDF", // &HDF + 0x00, // L"K_oE0", // &HE0 + 0x00, // L"K_oE1", // &HE1 + 0x30, // L"K_oE2", // &HE2 + 0x00, // L"K_oE3", // &HE3 + 0x00, // L"K_oE4", // &HE4 + + 0x00, // L"K_?E5", // &HE5 + + 0x00, // L"K_oE6", // &HE6 + + 0x00, // L"K_?E7", // &HE7 + 0x00, // L"K_?E8", // &HE8 + + 0x00, // L"K_oE9", // &HE9 + 0x00, // L"K_oEA", // &HEA + 0x00, // L"K_oEB", // &HEB + 0x00, // L"K_oEC", // &HEC + 0x00, // L"K_oED", // &HED + 0x00, // L"K_oEE", // &HEE + 0x00, // L"K_oEF", // &HEF + 0x00, // L"K_oF0", // &HF0 + 0x00, // L"K_oF1", // &HF1 + 0x00, // L"K_oF2", // &HF2 + 0x00, // L"K_oF3", // &HF3 + 0x00, // L"K_oF4", // &HF4 + 0x00, // L"K_oF5", // &HF5 + + 0x00, // L"K_?F6", // &HF6 + 0x00, // L"K_?F7", // &HF7 + 0x00, // L"K_?F8", // &HF8 + 0x00, // L"K_?F9", // &HF9 + 0x00, // L"K_?FA", // &HFA + 0x00, // L"K_?FB", // &HFB + 0x00, // L"K_?FC", // &HFC + 0x00, // L"K_?FD", // &HFD + 0x00, // L"K_?FE", // &HFE + 0x00 // L"K_?FF" // &HFF + ]; \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/messages.ts b/developer/src/kmc-kmw/src/compiler/messages.ts new file mode 100644 index 00000000000..07bd2794ca7 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/messages.ts @@ -0,0 +1,220 @@ +import { callbacks, FCompilerWarningsAsErrors } from "./compiler-globals.js"; + +export let FError = false; + +export function ReportError(line: number, msgcode: number, text: string) { // I1971 + let flag = CERR_FLAG | CFATAL_FLAG; + if(FCompilerWarningsAsErrors) { + flag |= CWARN_FLAG; + } + if (msgcode & flag) { + FError = true; + } + // TODO: these Codes Are All Wrong But We'll Fix It Soon + callbacks.reportMessage({code: msgcode, message: text, line}); // I3310 +} + +export const + CHINT_FLAG = 0x1000, + CWARN_FLAG = 0x2000, + CERR_FLAG = 0x4000, + CFATAL_FLAG = 0x8000, + +// Any messages from the lexical model compiler occupy this range: + CERR_LEXICAL_MODEL_MIN = 0x0800, + CERR_LEXICAL_MODEL_MAX = 0x08FF, + + CERR_None = 0x0000, + CERR_EndOfFile = 0x0001, + + CERR_BadCallParams = 0x8002, + CERR_CannotAllocateMemory = 0x9004, + CERR_InfileNotExist = 0x8005, + CERR_CannotCreateOutfile = 0x8006, + CERR_UnableToWriteFully = 0x8007, + CERR_CannotReadInfile = 0x8008, + CERR_SomewhereIGotItWrong = 0x8009, + + CERR_InvalidToken = 0x400A, + CERR_InvalidBegin = 0x400B, + CERR_InvalidName = 0x400C, + CERR_InvalidVersion = 0x400D, + CERR_InvalidLanguageLine = 0x400E, + CERR_LayoutButNoLanguage = 0x400F, + CERR_InvalidLayoutLine = 0x4010, + CERR_NoVersionLine = 0x4011, + CERR_InvalidGroupLine = 0x4012, + CERR_InvalidStoreLine = 0x4013, + CERR_InvalidCodeInKeyPartOfRule = 0x4014, + CERR_InvalidDeadkey = 0x4015, + CERR_InvalidValue = 0x4016, + CERR_ZeroLengthString = 0x4017, + CERR_TooManyIndexToKeyRefs = 0x4018, + CERR_UnterminatedString = 0x4019, + CERR_StringInVirtualKeySection = 0x401A, + CERR_AnyInVirtualKeySection = 0x401B, + CERR_InvalidAny = 0x401C, + CERR_StoreDoesNotExist = 0x401D, + CERR_BeepInVirtualKeySection = 0x401E, + CERR_IndexInVirtualKeySection = 0x401F, + CERR_InvalidIndex = 0x4020, + CERR_OutsInVirtualKeySection = 0x4021, + CERR_InvalidOuts = 0x4022, + CERR_ContextInVirtualKeySection = 0x4024, + CERR_InvalidUse = 0x4025, + CERR_GroupDoesNotExist = 0x4026, + CERR_VirtualKeyNotAllowedHere = 0x4027, + CERR_InvalidSwitch = 0x4028, + CERR_NoTokensFound = 0x4029, + CERR_InvalidLineContinuation = 0x402A, + CERR_LineTooLong = 0x402B, + CERR_InvalidCopyright = 0x402C, + CERR_CodeInvalidInThisSection = 0x402D, + CERR_InvalidMessage = 0x402E, + CERR_InvalidLanguageName = 0x402F, + CERR_InvalidBitmapLine = 0x4030, + CERR_CannotReadBitmapFile = 0x4031, + CERR_IndexDoesNotPointToAny = 0x4032, + CERR_ReservedCharacter = 0x4033, + CERR_InvalidCharacter = 0x4034, + CERR_InvalidCall = 0x4035, + CERR_CallInVirtualKeySection = 0x4036, + CERR_CodeInvalidInKeyStore = 0x4037, + CERR_CannotLoadIncludeFile = 0x4038, + + CERR_60FeatureOnly_EthnologueCode = 0x4039, + CERR_60FeatureOnly_MnemonicLayout = 0x403A, + CERR_60FeatureOnly_OldCharPosMatching = 0x403B, + CERR_60FeatureOnly_NamedCodes = 0x403C, + CERR_60FeatureOnly_Contextn = 0x403D, + CERR_501FeatureOnly_Call = 0x403E, + + CERR_InvalidNamedCode = 0x403F, + CERR_InvalidSystemStore = 0x4040, + + CERR_CallIsProfessionalFeature = 0x4041, + CERR_IncludeCodesIsProfessionalFeature = 0x4042, + CERR_MnemonicLayoutIsProfessionalFeature = 0x4043, + CERR_60FeatureOnly_VirtualCharKey = 0x4044, + + CERR_VersionAlreadyIncluded = 0x4045, + + CERR_70FeatureOnly = 0x4046, + + CERR_80FeatureOnly = 0x4047, + CERR_InvalidInVirtualKeySection = 0x4048, + CERR_InvalidIf = 0x4049, + CERR_InvalidReset = 0x404A, + CERR_InvalidSet = 0x404B, + CERR_InvalidSave = 0x404C, + + CERR_InvalidEthnologueCode = 0x404D, + + CERR_CannotCreateTempfile = 0x804E, + + CERR_90FeatureOnly_IfSystemStores = 0x404F, + CERR_IfSystemStore_NotFound = 0x4050, + CERR_90FeatureOnly_SetSystemStores = 0x4051, + CERR_SetSystemStore_NotFound = 0x4052, + CERR_90FeatureOnlyVirtualKeyDictionary = 0x4053, + + CERR_NotSupportedInKeymanWebContext = 0x4054, + CERR_NotSupportedInKeymanWebOutput = 0x4055, + CERR_NotSupportedInKeymanWebStore = 0x4056, + CERR_VirtualCharacterKeysNotSupportedInKeymanWeb = 0x4057, + CERR_VirtualKeysNotValidForMnemonicLayouts = 0x4058, + CERR_InvalidTouchLayoutFile = 0x4059, + CERR_TouchLayoutInvalidIdentifier = 0x405A, // I4142 + CERR_InvalidKeyCode = 0x405B, // I4142 + + CERR_90FeatureOnlyLayoutFile = 0x405C, + CERR_90FeatureOnlyKeyboardVersion = 0x405D, + CERR_KeyboardVersionFormatInvalid = 0x405E, + CERR_ContextExHasInvalidOffset = 0x405F, + CERR_90FeatureOnlyEmbedCSS = 0x4060, + CERR_90FeatureOnlyTargets = 0x4061, + CERR_ContextAndIndexInvalidInMatchNomatch = 0x4062, + CERR_140FeatureOnlyContextAndNotAnyWeb = 0x4063, + + CERR_ExpansionMustFollowCharacterOrVKey = 0x4064, + CERR_VKeyExpansionMustBeFollowedByVKey = 0x4065, + CERR_CharacterExpansionMustBeFollowedByCharacter = 0x4066, + CERR_VKeyExpansionMustUseConsistentShift = 0x4067, + CERR_ExpansionMustBePositive = 0x4068, + + CERR_CasedKeysMustContainOnlyVirtualKeys = 0x4069, + CERR_CasedKeysMustNotIncludeShiftStates = 0x406A, + CERR_CasedKeysNotSupportedWithMnemonicLayout = 0x406B, + + CERR_CannotUseReadWriteGroupFromReadonlyGroup = 0x406C, + CERR_StatementNotPermittedInReadonlyGroup = 0x406D, + CERR_OutputInReadonlyGroup = 0x406E, + CERR_NewContextGroupMustBeReadonly = 0x406F, + CERR_PostKeystrokeGroupMustBeReadonly = 0x4070, + + CERR_DuplicateGroup = 0x4071, + CERR_DuplicateStore = 0x4072, + + CWARN_TooManyWarnings = 0x2080, + CWARN_OldVersion = 0x2081, + CWARN_BitmapNotUsed = 0x2082, + CWARN_CustomLanguagesNotSupported = 0x2083, + CWARN_KeyBadLength = 0x2084, + CWARN_IndexStoreShort = 0x2085, + CWARN_UnicodeInANSIGroup = 0x2086, + CWARN_ANSIInUnicodeGroup = 0x2087, + CWARN_UnicodeSurrogateUsed = 0x2088, + CWARN_ReservedCharacter = 0x2089, + CWARN_Info = 0x208A, + CWARN_VirtualKeyWithMnemonicLayout = 0x208B, + CWARN_VirtualCharKeyWithPositionalLayout = 0x208C, + CWARN_StoreAlreadyUsedAsOptionOrCall = 0x208D, + CWARN_StoreAlreadyUsedAsStoreOrCall = 0x208E, + CWARN_StoreAlreadyUsedAsStoreOrOption = 0x208F, + + CWARN_PunctuationInEthnologueCode = 0x2090, + + CWARN_TouchLayoutMissingLayer = 0x2091, + CWARN_TouchLayoutCustomKeyNotDefined = 0x2092, + CWARN_TouchLayoutMissingRequiredKeys = 0x2093, + CWARN_HelpFileMissing = 0x2094, + CWARN_EmbedJsFileMissing = 0x2095, + CWARN_TouchLayoutFileMissing = 0x2096, + CWARN_VisualKeyboardFileMissing = 0x2097, + CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb = 0x2098, // I4118 + CWARN_TouchLayoutUnidentifiedKey = 0x2099, // I4142 + CHINT_UnreachableKeyCode = 0x109A, // I4141 + + CWARN_CouldNotCopyJsonFile = 0x209B, // I4688 + CWARN_PlatformNotInTargets = 0x209C, + + CWARN_HeaderStatementIsDeprecated = 0x209D, + CWARN_UseNotLastStatementInRule = 0x209E, + + CWARN_TouchLayoutFontShouldBeSameForAllPlatforms = 0x209F, // I4872 + CWARN_InvalidJSONMetadataFile = 0x20A0, // I4872 + CWARN_JSONMetadataOSKFontShouldMatchTouchFont = 0x20A1, // I4872 + + CWARN_DontMixChiralAndNonChiralModifiers = 0x20A3, + CWARN_MixingLeftAndRightModifiers = 0x20A4, + + CWARN_LanguageHeadersDeprecatedInKeyman10 = 0x20A5, + + CHINT_NonUnicodeFile = 0x10A6, + + CWARN_TooManyErrorsOrWarnings = 0x20A7, + + CWARN_HotkeyHasInvalidModifier = 0x20A8, + + CWARN_TouchLayoutSpecialLabelOnNormalKey = 0x20A9, + + CWARN_OptionStoreNameInvalid = 0x20AA, + + CWARN_NulNotFirstStatementInContext = 0x20AB, + CWARN_IfShouldBeAtStartOfContext = 0x20AC, + + CWARN_KeyShouldIncludeNCaps = 0x20AD, + + CHINT_UnreachableRule = 0x10AE, + CHINT_FilenameHasDifferingCase = 0x10AF, + CWARN_MissingFile = 0x20B0; diff --git a/developer/src/kmc-kmw/src/compiler/validate-layout-file.ts b/developer/src/kmc-kmw/src/compiler/validate-layout-file.ts new file mode 100644 index 00000000000..30d6f660d90 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/validate-layout-file.ts @@ -0,0 +1,280 @@ +import { KMX, TouchLayout, TouchLayoutFileReader, TouchLayoutFileWriter } from "@keymanapp/common-types"; +import { callbacks, IsKeyboardVersion14OrLater, IsKeyboardVersion15OrLater } from "./compiler-globals.js"; +import { JavaScript_Key, VKeyNames } from "./javascript-strings.js"; + + +interface VLFOutput { + output: string; + result: boolean; +}; + +function IsValidUnicodeValue(ch: number): boolean { // I4198 + return ((ch >= 0x0020) && (ch <= 0x007F)) || + ((ch >= 0x00A0) && (ch <= 0x10FFFF)); +} + +enum TKeyIdType { Key_Invalid, Key_Constant, Key_Touch, Key_Unicode, Key_Unicode_Multi }; // I4142 + +function GetKeyIdUnicodeType(value: string): TKeyIdType { + let values = value.split('_'); + for(let v of values) { + if(!IsValidUnicodeValue(parseInt(v,16))) { + return TKeyIdType.Key_Invalid; + } + } + if(values.length > 1) { + return TKeyIdType.Key_Unicode_Multi; + } + return TKeyIdType.Key_Unicode; +} + +function KeyIdType(FId: string): TKeyIdType { // I4142 + FId = FId.toUpperCase(); + switch(FId.charAt(0)) { + case 'T': + return TKeyIdType.Key_Touch; + case 'U': + if(FId.startsWith('U_')) { + return GetKeyIdUnicodeType(FId.substring(2)); + } + default: + // Note: can't use indexOf because some VKeyNames are mixed case, e.g. K_oE2 + if(VKeyNames.find(key => key.toUpperCase() == FId)) { + return TKeyIdType.Key_Constant; + } + } + return TKeyIdType.Key_Invalid; +} + +enum TRequiredKey { K_LOPT, K_BKSP, K_ENTER }; // I4447 + +const + CRequiredKeys: TRequiredKey[] = [TRequiredKey.K_LOPT, TRequiredKey.K_BKSP, TRequiredKey.K_ENTER]; // I4447 + + // See also builder.js: specialCharacters; web/source/osk/oskKey.ts: specialCharacters +const + CSpecialText10: string = + '*Shift*\0*Enter*\0*Tab*\0*BkSp*\0*Menu*\0*Hide*\0*Alt*\0*Ctrl*\0*Caps*\0'+ + '*ABC*\0*abc*\0*123*\0*Symbol*\0*Currency*\0*Shifted*\0*AltGr*\0*TabLeft*', + + // these names were added in Keyman 14 + CSpecialText14: string = + '*LTREnter*\0*LTRBkSp*\0*RTLEnter*\0*RTLBkSp*\0*ShiftLock*\0*ShiftedLock*\0*ZWNJ*\0*ZWNJiOS*\0*ZWNJAndroid*', + CSpecialText14ZWNJ: string = + '*ZWNJ*\0*ZWNJiOS*\0*ZWNJAndroid*', + + CSpecialText14Map: string[][] = [ + ['*LTREnter*', '*Enter*'], + ['*LTRBkSp*', '*BkSp*'], + ['*RTLEnter*', '*Enter*'], + ['*RTLBkSp*', '*BkSp*'], + ['*ShiftLock*', '*Shift*'], + ['*ShiftedLock*', '*Shifted*'], + ['*ZWNJ*', '<|>'], + ['*ZWNJiOS*', '<|>'], + ['*ZWNJAndroid*', '<|>'] + ]; + +// TODO lifecycle + +function CheckKey(FPlatform: TouchLayout.TouchLayoutPlatform, + FId: string, FText: string, FNextLayer: string, FKeyType: TouchLayout.TouchLayoutKeySp, + FRequiredKeys: TRequiredKey[], FDictionary: string[]) { // I4119 + + // + // Check that each touch layer has K_LOPT, [K_ROPT,] K_BKSP, K_ENTER + // + + for(let key of CRequiredKeys) { + if(TRequiredKey[key].toLowerCase() == FId.toLowerCase()) { + FRequiredKeys.push(key); + break; + } + } + + // + // Check that each layer referenced exists + // + + if(typeof FNextLayer == 'string' && FNextLayer.length > 0) { + if(FPlatform.layer.find(l => l.id.toLowerCase() == FNextLayer.toLowerCase()) == undefined) { + // TODO: callbacks.reportMessage() ReportError(0, CWARN_TouchLayoutMissingLayer, 'Key "'+FId+'" on platform "'+FPlatform.Name+'", layer "'+FLayer.Id+'", platform "'+FPlatform.Name+'", references a missing layer "'+FNextLayer+'".'); + } + } + + // + // Check that the key has a valid id // I4142 + // + + if(FId.trim() == '') { + if(!(FKeyType in [TouchLayout.TouchLayoutKeySp.blank, TouchLayout.TouchLayoutKeySp.spacer]) && FNextLayer == '') { + // TODO: ReportError(0, CWARN_TouchLayoutUnidentifiedKey, 'A key on layer "'+FLayer.Id+'" has no identifier.'); + } + return; + } + + let FValid = KeyIdType(FId); + + if(FValid == TKeyIdType.Key_Invalid) { + // TODO: ReportError(0, CERR_TouchLayoutInvalidIdentifier, 'Key "'+FId+'" on "'+FPlatform.Name+'", layer "'+FLayer.Id+'" has an invalid identifier.'); + } + else if (FValid == TKeyIdType.Key_Unicode_Multi && !IsKeyboardVersion15OrLater()) { + // TODO: ReportError(0, CERR_TouchLayoutInvalidIdentifier, 'Key "'+FId+'" on "'+FPlatform.Name+'", layer "'+FLayer.Id+'" has a multi-part identifier which requires version 15.0 or newer.'); + } + + // + // Check that each custom key code has at least *a* rule associated with it + // + + if (FValid == TKeyIdType.Key_Touch && FNextLayer == '' && FKeyType in [TouchLayout.TouchLayoutKeySp.normal, TouchLayout.TouchLayoutKeySp.deadkey]) { + // Search for the key in the key dictionary - ignore K_LOPT, K_ROPT... + if(FDictionary.indexOf(FId) < 0) { + // TODO: ReportError(0, CWARN_TouchLayoutCustomKeyNotDefined, 'Key "'+FId+'" on layer "'+FLayer.Id+'", platform "'+FPlatform.Name+'", is a custom key but has no corresponding rule in the source.'); + } + } + + // + // Check that if the key has a *special* label, it is available in the target version + // + if(FText.startsWith('*') && FText.endsWith('*') && FText.length > 2) { + // Keyman versions before 14 do not support '*special*' labels on non-special keys. + // ZWNJ use, however, is safe because it will be transformed in function + // TransformSpecialKeys14 to '<|>', which does not require the custom OSK font. + if((CSpecialText10.includes(FText) || CSpecialText14.includes(FText)) && + !CSpecialText14ZWNJ.includes(FText) && + !IsKeyboardVersion14OrLater() && + !(FKeyType in [TouchLayout.TouchLayoutKeySp.special, TouchLayout.TouchLayoutKeySp.specialActive])) { + // TODO: ReportError(0, CWARN_TouchLayoutSpecialLabelOnNormalKey, + // Format('Key "%s" on layout "%s", platform "%s" does not have the key type "Special" or "Special (active)" but has the label "%s". This feature is only supported in Keyman 14 or later', [ + // FId, FLayer.Id, FPlatform.Name, FText + // ])); + } + } +} + +function CheckDictionaryKeyValidity(fk: KMX.KEYBOARD, FDictionary: string[]) { // I4142 + + // TODO: O(eeek) performance here + + for(let i = 0; i < FDictionary.length; i++) { + if(FDictionary[i] == '') { + continue; + } + + if(KeyIdType(FDictionary[i]) in [TKeyIdType.Key_Invalid, TKeyIdType.Key_Constant]) { + for(let fgp of fk.groups) { + if(fgp.fUsingKeys) { + for(let fkp of fgp.keys) { + if(JavaScript_Key(fkp, fk.isMnemonic) == i+256) { + // TODO: ReportError(fkp.Line, CERR_InvalidKeyCode, 'Invalid key identifier "'+FDictionary[i]+'"'); + } + } + } + } + } + } +} + +function TransformSpecialKeys14(FDebug: boolean, sLayoutFile: string): string { + // Rewrite Special key labels that are only supported in Keyman 14+ + // This code is a little ugly but effective. + if(!IsKeyboardVersion14OrLater()) { + for(let i = 0; i < CSpecialText14Map.length; i++) { + // Assumes the JSON output format will not change + if(FDebug) { + sLayoutFile = sLayoutFile.replace('"text": "'+CSpecialText14Map[i][0]+'"', '"text": this._v>13 ? "'+CSpecialText14Map[i][0]+'" : "'+CSpecialText14Map[i][1]+'"'); + } else { + sLayoutFile = sLayoutFile.replace('"text":"'+CSpecialText14Map[i][0]+'"', '"text":this._v>13?"'+CSpecialText14Map[i][0]+'":"'+CSpecialText14Map[i][1]+'"'); + } + } + } + return sLayoutFile; +} + +export function ValidateLayoutFile(fk: KMX.KEYBOARD, FDebug: boolean, sLayoutFile: string, sVKDictionary: string): VLFOutput { // I4060 // I4139 + +/* +var + FPlatform: TTouchLayoutPlatform; + FLayer: TTouchLayoutLayer; + FRow: TTouchLayoutRow; + FKey: TTouchLayoutKey; + FSubKey: TTouchLayoutSubKey; + FRequiredKeys: set of TRequiredKey; + FDictionary: TStringList; + FDirection: TTouchLayoutFlickDirection; + +*/ + + let FDictionary: string[] = sVKDictionary.split(/\s+/); + + CheckDictionaryKeyValidity(fk, FDictionary); // I4142 + + let reader = new TouchLayoutFileReader(); + let data = reader.read(callbacks.loadFile(sLayoutFile)); + if(!data) { + // TODO: ReportError(0, CERR_InvalidTouchLayoutFile, sMsg); + return {output:null, result: false}; + } + + let FTouchLayoutFont = ''; // I4872 + let pid: keyof TouchLayout.TouchLayoutFile; + for(pid in data) { + let platform = data[pid]; + + // Test that the font matches on all platforms // I4872 + + if(FTouchLayoutFont == '') { + FTouchLayoutFont = platform.font; + } + else if(platform.font.toLowerCase() != FTouchLayoutFont) { + // TODO: ReportError(0, CWARN_TouchLayoutFontShouldBeSameForAllPlatforms, 'The touch layout font should be the same for all platforms.'); + // TODO: why support multiple font values if it has to be the same across all platforms?! + } + + // Test that all required keys are present + for(let layer of platform.layer) { + let FRequiredKeys: TRequiredKey[] = []; + for(let row of layer.row) { + for(let key of row.key) { + CheckKey(platform, key.id, key.text, key.nextlayer, key.sp, FRequiredKeys, FDictionary); // I4119 + if(key.sk) { + for(let subkey of key.sk) { + CheckKey(platform, subkey.id, subkey.text, subkey.nextlayer, subkey.sp, FRequiredKeys, FDictionary); + } + } + let direction: keyof TouchLayout.TouchLayoutFlick; + if(key.flick) { + for(direction in key.flick) { + CheckKey(platform, key.flick[direction].id, key.flick[direction].text, + key.flick[direction].nextlayer, key.flick[direction].sp, FRequiredKeys, FDictionary); + } + } + + if(key.multitap) { + for(let subkey of key.multitap) { + CheckKey(platform, subkey.id, subkey.text, subkey.nextlayer, subkey.sp, FRequiredKeys, FDictionary); + } + } + } + } + + if(FRequiredKeys.length != CRequiredKeys.length) { + // TODO: ReportError(0, CWARN_TouchLayoutMissingRequiredKeys, 'Layer "'+FLayer.Id+'" on platform "'+FPlatform.Name+'" is missing the required key(s) '+RequiredKeysToString(CRequiredKeys-FRequiredKeys)+'.'); + } + } + } + + // If not debugging, then this strips out formatting for a big saving in file size + // This also normalises any values such as Pad or Width which should be strings + let writer = new TouchLayoutFileWriter({formatted: FDebug}); + + sLayoutFile = writer.compile(data); + + sLayoutFile = TransformSpecialKeys14(FDebug, sLayoutFile); + + return { + output: sLayoutFile, + result: true + } +} \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/visual-keyboard-compiler.ts b/developer/src/kmc-kmw/src/compiler/visual-keyboard-compiler.ts new file mode 100644 index 00000000000..6dc7cf31787 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/visual-keyboard-compiler.ts @@ -0,0 +1,163 @@ +import { KMX, KvkFile, VisualKeyboard } from "@keymanapp/common-types"; +import { FTabStop, nl } from "./compiler-globals.js"; +import { CKeymanWebKeyCodes } from "./keymanweb-key-codes.js"; +import { RequotedString } from "./write-compiled-keyboard.js"; + +interface VKFFResult { + result: string; + displayUnderling: boolean; +} + +export function VisualKeyboardFromFile(visualKeyboard: VisualKeyboard.VisualKeyboard, debug: boolean): VKFFResult { + let fbold = ''; // TODO 'bold ' if visualKeyboard.header.unicodeFont.style + let fitalic = ''; // TODO 'italic ' if visualKeyboard.header.unicodeFont.style + let f102 = visualKeyboard.header.flags & KvkFile.BUILDER_KVK_HEADER_FLAGS.kvkh102 ? '1' : '0'; + + let result = `{F:'${fbold}${fitalic} 1em "${RequotedString(visualKeyboard.header.unicodeFont.name)}"',K102:${f102}}` + + `;` + VisualKeyboardToKLS(visualKeyboard) + + ';' + BuildBKFromKLS(debug); + + return { + result: result, + // TODO: this can go in caller, later + displayUnderling: !!(visualKeyboard.header.flags & KvkFile.BUILDER_KVK_HEADER_FLAGS.kvkhDisplayUnderlying) + } +} + +function WideQuote(s: string): string { + let result = ''; + for(let i = 0; i < s.length; i++) { + if(s[i] == '"' || s[i] == '\\') { + result += '\\' + s[i]; + } else { + result += s[i]; + } + } + return result; +} + +function VkShiftStateToKmxShiftState(ShiftState: number): number { + + interface TVKToKMX { + VK: number; KMX: number; + } + + const Map: TVKToKMX[] = [ + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_SHIFT, KMX: KMX.KMXFile.K_SHIFTFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_CTRL, KMX: KMX.KMXFile.K_CTRLFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_ALT, KMX: KMX.KMXFile.K_ALTFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_LCTRL, KMX: KMX.KMXFile.LCTRLFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_RCTRL, KMX: KMX.KMXFile.RCTRLFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_LALT, KMX: KMX.KMXFile.LALTFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_RALT, KMX: KMX.KMXFile.RALTFLAG} + ]; + + let result = 0; + for(let i = 0; i < Map.length; i++) { + if (ShiftState & Map[i].VK) { + result |= Map[i].KMX; + } + } + + return result; +} + + +function VKShiftToLayerName(shift: number): string { + + const masks: string[] = [ + 'leftctrl', + 'rightctrl', + 'leftalt', + 'rightalt', + 'shift', + 'ctrl', + 'alt' + ]; + + shift = VkShiftStateToKmxShiftState(shift); + if(shift == 0) { + return 'default'; + } + + let result = ''; + for(let i = 0; i < masks.length; i++) { + if(shift & (1 << i)) { + result += masks[i] + '-'; + } + } + return result.substring(0, result.length - 1); +} + + +function VisualKeyboardToKLS(FVK: VisualKeyboard.VisualKeyboard): string { + + interface TLayer { + shift: number; + name: string; + keys: string[]; + }; + + let layers: TLayer[] = []; + + // Discover the layers used in the visual keyboard + for(let key of FVK.keys) { + if(key.flags & KvkFile.BUILDER_KVK_KEY_FLAGS.kvkkUnicode) { + // Find the index of the key in KMW VK arrays + let n = CKeymanWebKeyCodes[key.vkey]; + if(n == 0xFF) { + continue; + } + + let layer = layers.find(layer => layer.shift == key.shift); + if(!layer) { + // 0-64 covers all possible VirtualKeyCodes in CKemyanWebKeyCodes + layer = { shift: key.shift, name: '', keys: new Array(65)}; + layers.push(layer); + } + layer.keys[n] = key.text; + } + } + + // Build the layer array + + let result = nl+FTabStop+'this.KV.KLS={'+nl; + + for(let i = 0; i < layers.length; i++) { + let layer = layers[i]; + result += `${FTabStop}${FTabStop}"${VKShiftToLayerName(layer.shift)}": [`; + for(let j = 0; j < layer.keys.length - 1; j++) { + result += '"'+WideQuote(layer.keys[j] ?? '')+'",'; + } + result += '"'+WideQuote(layer.keys[layer.keys.length-1] ?? '')+'"]'; + if(i < layers.length - 1) { + result += ',' + nl; + } + } + result += nl+FTabStop+'}'; + return result; +} + +function BuildBKFromKLS(debug: boolean): string { + const func = + 'function(x){var e=Array.apply(null,Array(65)).map(String.prototype.valueOf,"")'+ + ',r=[],v,i,m=[\'default\',\'shift\',\'ctrl\',\'shift-ctrl\',\'alt\',\'shift-alt\','+ + '\'ctrl-alt\',\'shift-ctrl-alt\'];for(i=m.length-1;i>=0;i--)if((v=x[m[i]])||r.length)'+ + 'r=(v?v:e).slice().concat(r);return r}'; + const func_debug = + 'function(x){'+nl+ + ' var'+nl+ + ' empty=Array.apply(null, Array(65)).map(String.prototype.valueOf,""),'+nl+ + ' result=[], v, i,'+nl+ + ' modifiers=[\'default\',\'shift\',\'ctrl\',\'shift-ctrl\',\'alt\',\'shift-alt\',\'ctrl-alt\',\'shift-ctrl-alt\'];'+nl+ + ' for(i=modifiers.length-1;i>=0;i--) {'+nl+ + ' v = x[modifiers[i]];'+nl+ + ' if(v || result.length > 0) {'+nl+ + ' result=(v ? v : empty).slice().concat(result);'+nl+ + ' }'+nl+ + ' }'+nl+ + ' return result;'+nl+ + ' }'; + + return nl+FTabStop+'this.KV.BK=('+(debug ? func_debug : func)+')(this.KV.KLS)'; +} diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts new file mode 100644 index 00000000000..082c7a1881d --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -0,0 +1,665 @@ +import { VisualKeyboard } from "@keymanapp/common-types"; +import { KMX, CompilerCallbacks, KvkFileReader, KvksFileReader } from "@keymanapp/common-types"; +import { ExpandSentinel, incxstr, xstrlen } from "../util/util.js"; +// import { KEY, KEYBOARD, KMX.KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx.js"; +import { options, nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater } from "./compiler-globals.js"; +import CompilerOptions from "./compiler-options.js"; +import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store, zeroPadHex } from './javascript-strings.js'; +import { CERR_InvalidBegin, CWARN_DontMixChiralAndNonChiralModifiers, ReportError } from "./messages.js"; +import { ValidateLayoutFile } from "./validate-layout-file.js"; +import { VisualKeyboardFromFile } from "./visual-keyboard-compiler.js"; + +export let FFix183_LadderLength: number = 100; // TODO: option + +function requote(s: string): string { + return "'" + s.replaceAll(/(['\\])/, "\\$1") + "'"; +} + +export function RequotedString(s: string, RequoteSingleQuotes: boolean = false): string { + // TODO: use a JSON encode + let i: number = 0; + while(i < s.length) { + if (s.charAt(i) == '"' || s.charAt(i) == '\\') { + s = s.substring(0, i) + '\\' + s.substring(i); + i++; + } + else if (s.charAt(i) == '\'' && RequoteSingleQuotes) { + s = s.substring(0, i) + '\\' + s.substring(i); + i++; + } + else if(s.charAt(i) == '\n') { + s = s.substring(0, i) + '\\n' + s.substring(i + 1); + } + else if(s.charAt(i) == '\r') { + s = s.substring(0, i) + ' ' + s.substring(i + 1); + } + i++; + } + return s; +} + +export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: string, kmxfile: string, name: string, keyboard: KMX.KEYBOARD, FDebug: boolean = false): string { + let opts: CompilerOptions = { + addCompilerVersion: false, + debug: FDebug + }; + setupGlobals(callbacks, opts, FDebug?' ':'', FDebug?'\r\n':'', keyboard); + + // let fgp: GROUP; + + // let fsp: STORE; + // let fkp: KEY; + + // let j: number; + // let n: number; + + let vMnemonic: number = 0; + let /*s: string,*/ sRTL: string = "", sHelp: string = "''", sHelpFile: string = "", + sEmbedJS: string = "", sEmbedCSS: string = ""; + let sVisualKeyboard: string = "", sFullName: string = ""; + let sBegin_NewContext: string = "", sBegin_PostKeystroke: string = ""; + let sLayoutFile: string = "", sVKDictionary: string; + let linecomment: string; // I3438 + // let HasRules: boolean; + let sModifierBitmask: string; + let FOptionStores: string; + let FKeyboardVersion = "1.0"; + // let rec: TSentinelRecord; + + let result = ""; + // Locate the name of the keyboard + for(let i = 0; i < keyboard.stores.length; i++) { + const fsp = keyboard.stores[i]; + if(fsp.dwSystemID == KMX.KMXFile.TSS_NAME) { + sFullName = fsp.dpString; + } + else if(fsp.dwSystemID == KMX.KMXFile.TSS_KEYBOARDVERSION) { // I4155 + FKeyboardVersion = fsp.dpString; + } + else if (fsp.dpName == 'HelpFile' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_HELPFILE) { + sHelpFile = fsp.dpString; + } + else if (fsp.dpName == 'Help' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_HELPTEXT) { + sHelp = '"'+RequotedString(fsp.dpString)+'"'; + } + else if (fsp.dpName == 'VisualKeyboard' || fsp.dwSystemID == KMX.KMXFile.TSS_VISUALKEYBOARD) { + sVisualKeyboard = fsp.dpString; + } + else if (fsp.dpName == 'EmbedJS' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_EMBEDJS) { + sEmbedJS = fsp.dpString; + } + else if (fsp.dpName == 'EmbedCSS' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_EMBEDCSS) { // I4368 + sEmbedCSS = fsp.dpString; + } + else if (fsp.dpName == 'RTL' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_RTL) { + sRTL = fsp.dpString == '1' ? FTabStop+'this.KRTL=1;'+nl : ''; // I3681 + } + else if (fsp.dwSystemID == KMX.KMXFile.TSS_MNEMONIC) { + vMnemonic = fsp.dpString == '1' ? 1 : 0; + } + else if (fsp.dwSystemID == KMX.KMXFile.TSS_VKDICTIONARY) { // I3438 + sVKDictionary = fsp.dpString; + } + else if (fsp.dwSystemID == KMX.KMXFile.TSS_LAYOUTFILE) { // I3483 + sLayoutFile = fsp.dpString; + } + else if (fsp.dwSystemID == KMX.KMXFile.TSS_BEGIN_NEWCONTEXT) { + sBegin_NewContext = fsp.dpString; + } + else if (fsp.dwSystemID == KMX.KMXFile.TSS_BEGIN_POSTKEYSTROKE) { + sBegin_PostKeystroke = fsp.dpString; + } + } + + const sName = 'Keyboard_'+name; //TODO: verify --> GetKeymanWebCompiledNameFromFileName(FInFile); + + if (sHelpFile != '') { + sHelp = ''; + //TODO: load sHelpFile from file + /*with TStringList.Create do + try + try + LoadFromFile(ExtractFilePath(FInFile) + sHelpFile, TEncoding.UTF8); // I3337 + for n := 0 to Count - 1 do + sHelp := sHelp + Strings[n] + ' '; + except + on E:EFOpenError do + begin + ReportError(0, CWARN_HelpFileMissing, E.Message); // I1971 // I4061 + sHelp := ''; + end; + end; + finally + Free; + end;*/ + + sHelp = requote(sHelp); + } + + if (sEmbedJS != '') { + //TODO: load sEmbedJS from file + /*try + with TStringList.Create do + try + LoadFromFile(ExtractFilePath(FInFile) + sEmbedJS, TEncoding.UTF8); // I3337 + sEmbedJS := Text; + finally + Free; + end; + except + on E:EFOpenError do // I3683 + begin + ReportError(0, CWARN_EmbedJsFileMissing, E.Message); // I4061 + sEmbedJS := ''; + end; + end;*/ + } + + if (sEmbedCSS != '') { // I4368 + //TODO: load sEmbedCSS from file + /*try + with TStringList.Create do + try + LoadFromFile(ExtractFilePath(FInFile) + sEmbedCSS, TEncoding.UTF8); // I3337 + sEmbedCSS := Text; + finally + Free; + end; + except + on E:EFOpenError do // I3683 + begin + ReportError(0, CWARN_EmbedJsFileMissing, E.Message); // I4061 + sEmbedCSS := ''; + end; + end;*/ + } + + if (sLayoutFile != '') { // I3483 + let path = callbacks.resolveFilename(kmnfile, sLayoutFile); + + let result = ValidateLayoutFile(keyboard, options.debug, path, sVKDictionary); + if(!result.result) { + sLayoutFile = ''; + // TODO: error + // ReportError(0, CWARN_TouchLayoutFileInvalid, 'Touch layout file is not valid'); + } else { + // TODO: reusing the same variable here is ugly + sLayoutFile = result.output; + } + } + + // Default to hide underlying layout characters. This is overridden by touch + // layout platform.displayUnderlying property or, if that is not present for + // the given platform, by the OSK property. + let fDisplayUnderlying = false; + + if (sVisualKeyboard != '') { + // TODO: stop reusing sVisualKeyboard for both filename and content + let path = callbacks.resolveFilename(kmnfile, sVisualKeyboard); + + let kvk: VisualKeyboard.VisualKeyboard; + if(path.match(/\.kvks$/i)) { + let reader = new KvksFileReader(); + let source = reader.read(callbacks.loadFile(path)); + reader.validate(source, callbacks.loadSchema("kvks")); // TODO: handle exceptions + kvk = reader.transform(source); + // TODO: log errors + } + else { + // Note: very old keyboard sources may still have .kvk as an xml + // file, but we'll treat that as an error rather than silently + // falling back to KvksFileReader + let reader = new KvkFileReader(); + kvk = reader.read(callbacks.loadFile(path)); + } + + let result = VisualKeyboardFromFile(kvk, options.debug); + if(!result.result) { + // TODO: error + sVisualKeyboard = 'null'; + } + else { + sVisualKeyboard = result.result; + } + } + else { + sVisualKeyboard = 'null'; + } + + + const fMnemonic = vMnemonic == 1; + + sModifierBitmask = GetKeyboardModifierBitmask(keyboard, fMnemonic); + + result += + `${JavaScript_SetupProlog()}${nl}` + + `KeymanWeb.KR(new ${sName}());${nl}` + + `${JavaScript_SetupEpilog()}${nl}` + + `function ${sName}()${nl}` + + `{${nl}` + + `${FTabStop}${JavaScript_SetupDebug()}${nl}` + + // Following line caches the Keyman major version + `${FTabStop}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` + + `${FTabStop}this.KI="${sName}";${nl}` + + `${FTabStop}this.KN="${RequotedString(sFullName)}";${nl}` + + `${FTabStop}this.KMINVER="${(keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MAJOR) >> 8}.${keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MINOR}";${nl}` + + `${FTabStop}this.KV=${sVisualKeyboard};${nl}` + + `${FTabStop}this.KDU=${fDisplayUnderlying?'1':'0'};${nl}` + + `${FTabStop}this.KH=${sHelp};${nl}` + + `${FTabStop}this.KM=${vMnemonic};${nl}` + + `${FTabStop}this.KBVER="${FKeyboardVersion}";${nl}` + // I4155 + `${FTabStop}this.KMBM=${sModifierBitmask};${nl}` + + `${sRTL}`; // I3681 + + if (HasSupplementaryPlaneChars()) { + result += `${FTabStop}this.KS=1;${nl}`; + } + + if (sVKDictionary != '') { // I3438 + result += `${FTabStop}this.KVKD="${RequotedString(sVKDictionary)}";${nl}`; // I3681 + } + + if (sLayoutFile != '') { // I3483 + result += `${FTabStop}this.KVKL=${sLayoutFile};${nl}`; // I3681 + } + + if (sEmbedCSS != '') { // I4368 + result += `${FTabStop}this.KCSS="${RequotedString(sEmbedCSS)}";${nl}`; + } + + function isDebugStore(fsp: KMX.STORE) { + return fsp.dwSystemID == KMX.KMXFile.TSS_DEBUG_LINE; + } + + function isReservedStore(fsp: KMX.STORE) { + return fsp.dwSystemID != KMX.KMXFile.TSS_NONE; + } + + function isOptionStore(fsp: KMX.STORE) { + // TODO: how do we determine this, see CheckStoreUsage() + return false; + } + + // Write the stores out + FOptionStores = ''; + for(let i = 0; i < keyboard.stores.length; i++) { + let fsp = keyboard.stores[i]; + // I3438 - Save all system stores to the keyboard, for now // I3684 + + if (!isDebugStore(fsp)) { // and not (fsp.dwSystemID in [TSS_BITMAP, TSS_NAME, TSS_VERSION, TSS_CUSTOMKEYMANEDITION, TSS_CUSTOMKEYMANEDITIONNAME, TSS_KEYMANCOPYRIGHT]) then + if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPARISON) { + result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)};${nl}`; + } + else if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPILEDVERSION) { + result += `${FTabStop}this.KVER=${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)};${nl}`; + } + //else if fsp.dwSystemID = TSS_VKDICTIONARY then // I3438, required for vkdictionary + // Result := Result + Format('%sthis.s%s=%s;%s', [FTabStop, JavaScript_Name(i, fsp.szName), JavaScript_Store(fsp.line, fsp.dpString), nl]) + else if (isOptionStore(fsp) && !isReservedStore(fsp)) { + result += `${FTabStop}this.s${JavaScript_Name(i,fsp.dpName)}=KeymanWeb.KLOAD(this.KI,"${JavaScript_Name(i,fsp.dpName,true)}",`+ + `${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)});${nl}`; + + if (FOptionStores != '') { + FOptionStores += ','; + } + FOptionStores += `'s${JavaScript_Name(i, fsp.dpName)}`; + } + else if (fsp.dwSystemID == KMX.KMXFile.TSS_NONE /* aka not fsp.fIsReserved */) { + result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)};${nl}`; // I3681 + } + } + } + + result += `${FTabStop}this.KVS=[${FOptionStores}];${nl}`; + + // Write the groups out + + // I853 - begin unicode missing causes crash + if (keyboard.startGroup.unicode == 0xFFFFFFFF) { + ReportError(0, CERR_InvalidBegin, 'A "begin unicode" statement is required to compile a KeymanWeb keyboard'); + return null; + } + + result += WriteBeginStatement(keyboard, 'gs', keyboard.startGroup.unicode); + + let rec = ExpandSentinel(keyboard, sBegin_NewContext, 0); + if(rec.Code == KMX.KMXFile.CODE_USE) { + result += WriteBeginStatement(keyboard, 'gn', rec.Use.GroupIndex); + } + rec = ExpandSentinel(keyboard, sBegin_PostKeystroke, 0); + if(rec.Code == KMX.KMXFile.CODE_USE) { + result += WriteBeginStatement(keyboard, 'gpk', rec.Use.GroupIndex); + } + + let fgp = keyboard.groups[keyboard.startGroup.unicode]; + result += + `${FTabStop}this.gs=function(t,e) {${nl}` + + `${FTabStop+FTabStop}return this.g${JavaScript_Name(keyboard.startGroup.unicode, fgp.dpName)}(t,e);${nl}` + + `${FTabStop}};${nl}`; // I3681 + + for(let i = 0; i < keyboard.groups.length; i++) { // I1964 + let fgp = keyboard.groups[i]; + /* + Note on `r` and `m` variables in a group function: + + `m` can have one of three values: + 0: no rule from this group was matched + 1: a rule from this group was matched and did not include a `use` + statement + 2: a rule from this group matched and did include a `use` statement + (#5440) + + `m` is only used within a rule group to control the firing of the + `match` and `nomatch` rules. + + `r` can have one of two values: + 0: no rule from the final group matched (even if a rule from an + higher-level group did) + 1: a rule from the final group did match; + + `r` serves as the rule group's return value and is forwarded + recursively, best serving as a flag for whether or not default + output for a key should be emitted (0 means yes, emit the + default character output for that key). + */ + + result += + `${FTabStop}this.g${JavaScript_Name(i, fgp.dpName)}=function(t,e) {${nl}` + + `${FTabStop+FTabStop}var k=KeymanWeb,r=${fgp.fUsingKeys?0:1},m=0;${nl}`; //I1959 + + // fkp := fgp.dpKeyArray; + let HasRules = false; + + if (FFix183_LadderLength != 0) { + result += JavaScript_Rules(keyboard, fMnemonic, fgp); + } + else { + for (let j = 0; j < fgp.keys.length; j++) { // I1964 + let fkp = fgp.keys[j]; + if (!RuleIsExcludedByPlatform(keyboard, fkp)) { + result += FTabStop+FTabStop; // I3681 + if (HasRules) { + result += 'else '; + } + HasRules = true; + + if (fgp.fUsingKeys) { + result += `if(k.KKM(e,${JavaScript_ShiftAsString(fkp, fMnemonic)},${JavaScript_KeyAsString(fkp, fMnemonic)})`; + } + + if (xstrlen(fkp.dpContext) > 0) { + result += fgp.fUsingKeys ? '&&' : 'if('; + result += JavaScript_ContextMatch(keyboard, fkp, fkp.dpContext); + } + else if (!fgp.fUsingKeys) { + result += 'if(1'; + } + + linecomment = (fkp.Line > 0 && FDebug) ? ` // Line ${fkp.Line}` : ''; + + result += + `) {${linecomment}${nl}` + + FTabStop+FTabStop+FTabStop; + if (fgp.fUsingKeys) { // I1959 + result += 'r=m=1;' + JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 + } + else { + result += 'm=1;' + JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 + } + result += `${nl}${FTabStop}${FTabStop}}${nl}`; // I3681 + } + } + } + + if(fgp.dpMatch) { + result += + `${FTabStop+FTabStop}if(m==1) {${nl}`+ + `${FTabStop+FTabStop}${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop}}${nl}`; + } + if(fgp.dpNoMatch) { + if(fgp.fUsingKeys) { // I1382 - fixup m=1 to m=g() + result += + `${FTabStop+FTabStop}if(!m&&k.KIK(e)) {${nl}`+ + `${FTabStop+FTabStop+FTabStop}r=1;${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop}}${nl}`; // I1959. part 2, I2224 // I3681 + } + else { + result += + `${FTabStop+FTabStop}if(!m) {${nl}`+ + `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop}}${nl}`; + } + } + result += + `${FTabStop+FTabStop}return r;${nl}`+ + `${FTabStop}};${nl}`; + } + +/* TODO + for(let n = 0 to FCallFunctions.Count - 1 do + begin + s := ExtractFilePath(FInFile) + FCallFunctions[n] + '.call_js'; + if FileExists(s) then + with TStringList.Create do + try + LoadFromFile(s, TEncoding.UTF8); // I3337 + Result := Result + Format('%sthis.c%d=function(t,e){%s};%s', [FTabstop, n, Trim(Text), nl]); // I3681 + finally + Free; + end + else + Result := Result + Format('%sthis.c%d=function(t,e){alert("call(%s) not defined");};%s', [FTabstop, n, FCallFunctions[n], nl]); // I3681 + end; +*/ + result += sEmbedJS + '}' + nl; // I3681 + return result; +} + +/// +/// Determine the modifiers used in the target keyboard and return a bitmask +/// representing them, or an number value when not in debug mode +/// +/// @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 */' +/// +function GetKeyboardModifierBitmask(keyboard: KMX.KEYBOARD, fMnemonic: boolean): string { + let bitMask = 0; + for(let gp of keyboard.groups) { + if(gp.fUsingKeys) { + for(let kp of gp.keys) { + if(!RuleIsExcludedByPlatform(keyboard, kp)) { + bitMask |= JavaScript_Shift(kp, fMnemonic); + } + } + } + } + + if ((bitMask & KMX.KMXFile.MASK_MODIFIER_CHIRAL) && (bitMask & KMX.KMXFile.MASK_MODIFIER_NONCHIRAL)) { + ReportError(0, CWARN_DontMixChiralAndNonChiralModifiers, 'This keyboard contains Ctrl,Alt and LCtrl,LAlt,RCtrl,RAlt sets of modifiers. Use only one or the other set for web target.'); + } + + if(options.debug) { + return FormatModifierAsBitflags(bitMask & KMX.KMXFile.MASK_KEYS); // Exclude KMX_ISVIRTUALKEY, KMX_VIRTUALCHARKEY + } + + return '0x'+(bitMask & KMX.KMXFile.MASK_KEYS).toString(16).toUpperCase(); +} + + +/// +/// If debug mode, then returns Javascript code necessary for +/// accessing constants in the compiled keyboard +/// +/// @return string of JavaScript code +/// +function JavaScript_SetupDebug() { + if(IsKeyboardVersion10OrLater()) { + if(options.debug) { + return 'var modCodes = keyman.osk.modifierCodes;'+nl+ + FTabStop+'var keyCodes = keyman.osk.keyCodes;'+nl; + } + } + return ''; +} + +function JavaScript_SetupProlog() { + if(IsKeyboardVersion10OrLater()) { + return 'if(typeof keyman === \'undefined\') {'+nl+ + FTabStop+'console.log(\'Keyboard requires KeymanWeb 10.0 or later\');'+nl+ + FTabStop+'if(typeof tavultesoft !== \'undefined\') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");'+nl+ + '} else {'; + } + return ''; +} + +function JavaScript_SetupEpilog() { + if(IsKeyboardVersion10OrLater()) { + return '}'; + } + return ''; +} + +function HasSupplementaryPlaneChars() { + return false; // TODO +/* function StringHasSuppChars(p: PWideChar): Boolean; + begin + if not Assigned(p) then + Exit(False); + + while p^ <> #0 do + begin + if Char.IsSurrogate(p, 0) then + Exit(True); + p := incxstr(p); + end; + + Result := False; + end; + +var + I: number; + fsp: PFILE_STORE; + fgp: PFILE_GROUP; + j: number; + fkp: PFILE_KEY; +begin + fsp := fk.dpStoreArray; + for i := 0 to number(fk.cxStoreArray) - 1 do + begin + if StringHasSuppChars(fsp.dpString) then + Exit(True); + Inc(fsp); + end; + + fgp := fk.dpGroupArray; + for i := 0 to number(fk.cxGroupArray) - 1 do + begin + fkp := fgp.dpKeyArray; + for j := 0 to number(fgp.cxKeyArray) - 1 do + begin + if StringHasSuppChars(fkp.dpContext) or + StringHasSuppChars(fkp.dpOutput) then + Exit(True); + Inc(fkp); + end; + + if StringHasSuppChars(fgp.dpMatch) or + StringHasSuppChars(fgp.dpNoMatch) then + Exit(True); + + Inc(fgp); + end; + + Result := False; +end;*/ +} + +export function RuleIsExcludedByPlatform(keyboard: KMX.KEYBOARD, fkp: KMX.KEY): boolean { + if(fkp.dpContext == null || fkp.dpContext == '') { + return false; + } + + let x = 0; + while(x < fkp.dpContext.length) { + let rec = ExpandSentinel(keyboard, fkp.dpContext, x); + if(rec.IsSentinel && + (rec.Code == KMX.KMXFile.CODE_IFSYSTEMSTORE) && + (rec.IfSystemStore.dwSystemID == KMX.KMXFile.TSS_PLATFORM) && + rec.IfSystemStore.Store.dpString.includes('native')) { + if(rec.IfSystemStore.Store.dpString.match(/windows|desktop|macosx|linux/)) { + return true; + } + } + x = incxstr(fkp.dpContext, x); + } + + return false; +} + +function WriteBeginStatement(keyboard: KMX.KEYBOARD, name: string, groupIndex: number): string { + const fgp = keyboard.groups[groupIndex]; + return `${FTabStop}this.${name}=function(t,e) {${nl}`+ + `${FTabStop+FTabStop}return this.g${JavaScript_Name(groupIndex, fgp.dpName)}(t,e);${nl}`+ + `${FTabStop}};${nl}`; +} + +/** + * Converts a modifier bit mask integer into its component bit flags + * + * @param FBitMask A KMX modifier bitmask value + * + * @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 ./' +**/ +export function FormatModifierAsBitflags(FBitMask: number): string { + const mask: string[] = [ + 'LCTRL', // 0X0001 + 'RCTRL', // 0X0002 + 'LALT', // 0X0004 + 'RALT', // 0X0008 + + 'SHIFT', // 0X0010 + 'CTRL', // 0X0020 + 'ALT', // 0X0040 + + '???', // Reserved + + 'CAPS', // 0X0100 + 'NO_CAPS', // 0X0200 + + 'NUM_LOCK', // 0X0400 + 'NO_NUM_LOCK', // 0X0800 + + 'SCROLL_LOCK', // 0X1000 + 'NO_SCROLL_LOCK', // 0X2000 + + 'VIRTUAL_KEY' // 0X4000 + ]; + + let i: number; + let result = ''; + + //TODO: We need to think about mnemonic layouts which are incompletely supported at present + //tavultesoft.keymanweb.osk. + + if(IsKeyboardVersion10OrLater()) { + // This depends on flags defined in KeymanWeb 10.0 + result = ''; + + for(i = 0; i < mask.length; i++) { + if(FBitMask & (1 << i)) { + if(result != '') result += ' | '; + result += 'modCodes.'+mask[i]; + } + } + + if(result == '') { + result = '0'; + } + + result += ' /* 0x' + zeroPadHex(FBitMask, 4) + ' */'; + } + else { + result = '0x'+zeroPadHex(FBitMask, 4); + } + return result; +} diff --git a/developer/src/kmc-kmw/src/main.ts b/developer/src/kmc-kmw/src/main.ts new file mode 100644 index 00000000000..35d6846bce7 --- /dev/null +++ b/developer/src/kmc-kmw/src/main.ts @@ -0,0 +1,2 @@ + +export { WriteCompiledKeyboard } from './compiler/write-compiled-keyboard.js'; diff --git a/developer/src/kmc-kmw/src/util/util.ts b/developer/src/kmc-kmw/src/util/util.ts new file mode 100644 index 00000000000..21aa9d3c14d --- /dev/null +++ b/developer/src/kmc-kmw/src/util/util.ts @@ -0,0 +1,293 @@ +import { KMX } from "@keymanapp/common-types"; + +/** + * Verifies that value is an item in the enumeration. + */ +export function isValidEnumValue(enu: T, value: string) { + return (Object.values(enu) as string[]).includes(value); +} + +export interface TSentinelRecord { + IsSentinel: boolean; + Code?: number; + + Any?: { + StoreIndex: number; + Store: KMX.STORE; + }; + Index?: { + StoreIndex: number; + Store: KMX.STORE; + Index: number; + }; + DeadKey?: { + DeadKey: number; + }; + Use?: { + GroupIndex: number; + Group: KMX.GROUP; + }; + Call?: { + StoreIndex: number; + Store: KMX.STORE; + }; + ContextEx?: { + Index: number; + }; + IfOpt?: { + StoreIndex1: number; + Store1: KMX.STORE; + StoreIndex2: number; + Store2: KMX.STORE; + IsNot: number; + }; + IfSystemStore?: { + dwSystemID: number; + SystemStore: KMX.STORE; + StoreIndex: number; + Store: KMX.STORE; + IsNot: number; + }; + SetOpt?: { + StoreIndex1: number; + Store1: KMX.STORE; + StoreIndex2: number; + Store2: KMX.STORE; + }; + SetSystemStore?: { + dwSystemID: number; + SystemStore: KMX.STORE; + StoreIndex: number; + Store: KMX.STORE; + }; + ResetOpt?: { + StoreIndex: number; + Store: KMX.STORE; + }; + SaveOpt?: { + StoreIndex: number; + Store: KMX.STORE; + }; + ChrVal?: number; +}; + + +export function ExpandSentinel(fk: KMX.KEYBOARD, pwsz: string, x: number): TSentinelRecord { + let result: TSentinelRecord = { + IsSentinel: false + }; + if(pwsz.charCodeAt(x) == KMX.KMXFile.UC_SENTINEL) { + result.IsSentinel = true; + x++; + result.Code = pwsz.charCodeAt(x); + x++; + switch(result.Code) { + case KMX.KMXFile.CODE_ANY: + case KMX.KMXFile.CODE_NOTANY: // I3981 + let anyIdx = pwsz.charCodeAt(x) - 1; + result.Any = { + StoreIndex: anyIdx, + Store: fk.stores[anyIdx] + } + break; + case KMX.KMXFile.CODE_INDEX: + let indexIdx = pwsz.charCodeAt(x) - 1; + x++; + result.Index = { + StoreIndex: indexIdx, + Store: fk.stores[indexIdx], + Index: pwsz.charCodeAt(x) - 1 + } + break; + case KMX.KMXFile.CODE_DEADKEY: + result.DeadKey = { DeadKey: pwsz.charCodeAt(x) - 1 }; + break; + case KMX.KMXFile.CODE_USE: + let useIdx = pwsz.charCodeAt(x) - 1; + result.Use = { + GroupIndex: useIdx, + Group: fk.groups[useIdx] + }; + break; + case KMX.KMXFile.CODE_CALL: + let callIdx = pwsz.charCodeAt(x) - 1; + result.Call = { + StoreIndex: callIdx, + Store: fk.stores[callIdx] + } + break; + case KMX.KMXFile.CODE_CONTEXTEX: + result.ContextEx = { Index: pwsz.charCodeAt(x) - 1 }; + break; + case KMX.KMXFile.CODE_SETOPT: // I3429 + let setIdx1 = pwsz.charCodeAt(x) - 1; + x++; + let setIdx2 = pwsz.charCodeAt(x) - 1; + result.SetOpt = { + StoreIndex1: setIdx1, + Store1: fk.stores[setIdx1], + StoreIndex2: setIdx2, + Store2: fk.stores[setIdx2] + }; + break; + case KMX.KMXFile.CODE_SETSYSTEMSTORE: // I3437 + let setsIdx1 = pwsz.charCodeAt(x) - 1; + x++; + let setsIdx2 = pwsz.charCodeAt(x) - 1; + result.SetSystemStore = { + dwSystemID: setsIdx1, + SystemStore: fk.stores.find(s => s.dwSystemID == setsIdx1) || null, + StoreIndex: setsIdx2, + Store: fk.stores[setsIdx2] + }; + break; + case KMX.KMXFile.CODE_RESETOPT: // I3429 + result.ResetOpt = { + StoreIndex: pwsz.charCodeAt(x) - 1, + Store: fk.stores[result.ResetOpt.StoreIndex] + }; + break; + case KMX.KMXFile.CODE_SAVEOPT: // I3429 + result.SaveOpt = { + StoreIndex: pwsz.charCodeAt(x) - 1, + Store: fk.stores[result.SaveOpt.StoreIndex] + }; + break; + case KMX.KMXFile.CODE_IFOPT: // I3429 + let ifIdx1 = pwsz.charCodeAt(x) - 1; + x++; + let ifNot = pwsz.charCodeAt(x) - 1; + x++; + let ifIdx2 = pwsz.charCodeAt(x) - 1; + result.IfOpt = { + StoreIndex1: ifIdx1, + Store1: fk.stores[ifIdx1], + IsNot: ifNot, // I3429 + StoreIndex2: ifIdx2, + Store2: fk.stores[ifIdx2] + }; + break; + case KMX.KMXFile.CODE_IFSYSTEMSTORE: // I3430 + let ifsSystemID = pwsz.charCodeAt(x) - 1; + x++; + let ifsNot = pwsz.charCodeAt(x) - 1; + x++; + let ifsIdx2 = pwsz.charCodeAt(x) - 1; + result.IfSystemStore = { + dwSystemID: ifsSystemID, + SystemStore: fk.stores.find(s => s.dwSystemID == ifsSystemID) || null, + IsNot: ifsNot, + StoreIndex: ifsIdx2, + Store: fk.stores[ifsIdx2] + }; + break; + case KMX.KMXFile.CODE_NUL: + case KMX.KMXFile.CODE_CONTEXT: + case KMX.KMXFile.CODE_RETURN: + case KMX.KMXFile.CODE_BEEP: + case KMX.KMXFile.CODE_EXTENDED: + // No additional detail needed, or outside scope + break; + default: + throw new Error(`Unrecognized system store value ${result.Code}`); + } + } + else { + result.ChrVal = GetSuppChar(pwsz, x); + } + return result; +} + +export function GetSuppChar(p: string, x: number): number { + return p.codePointAt(x); +} + +export function incxstr(p: string, x: number): number { + if(x >= p.length) { + return p.length; + } + + let ch = p.charCodeAt(x); + if(ch != KMX.KMXFile.UC_SENTINEL) { + if(ch >= 0xD800 && ch <= 0xDBFF) { + x++; + if(x == p.length) { + return x; + } + ch = p.charCodeAt(x); + if (ch >= 0xDC00 && ch <= 0xDFFF) { + x++; + } + } + else { + x++; + } + return x; + } + + x++; + if(x == p.length) { + return x; + } + + switch(p.charCodeAt(x)) { + case KMX.KMXFile.CODE_ANY: x += 2; break; + case KMX.KMXFile.CODE_INDEX: x += 3; break; + case KMX.KMXFile.CODE_USE: x += 2; break; + case KMX.KMXFile.CODE_DEADKEY: x += 2; break; + case KMX.KMXFile.CODE_EXTENDED: + x += 3; + while(x <= p.length && p.charCodeAt(x) != KMX.KMXFile.UC_SENTINEL_EXTENDEDEND) { + x++; + } + x++; + break; + case KMX.KMXFile.CODE_CALL: x += 2; break; + case KMX.KMXFile.CODE_CONTEXTEX: x += 2; break; + case KMX.KMXFile.CODE_NOTANY: x += 2; break; + + case KMX.KMXFile.CODE_CLEARCONTEXT: x += 2; break; + case KMX.KMXFile.CODE_IFOPT: x += 4; break; + case KMX.KMXFile.CODE_IFSYSTEMSTORE: x += 4; break; + case KMX.KMXFile.CODE_SETOPT: x += 3; break; + case KMX.KMXFile.CODE_SETSYSTEMSTORE: x += 3; break; + case KMX.KMXFile.CODE_RESETOPT: x += 2; break; + case KMX.KMXFile.CODE_SAVEOPT: x += 2; break; + + default: x++; + } + + if(x >= p.length) { + return p.length; + } + + return x; +} + +export function xstrlen(p: string): number { + let result = 0, x = 0; + while(x < p.length) { + x = incxstr(p, x); + result++; + } + return result; +} + +export function xstrlen_printing(p: string): number { + let result = 0, x = 0; + while(x < p.length) { + if(x + 1 < p.length && p.charCodeAt(x) == KMX.KMXFile.UC_SENTINEL) { + switch(p.charCodeAt(x+1)) { + case KMX.KMXFile.CODE_DEADKEY: + case KMX.KMXFile.CODE_NUL: + case KMX.KMXFile.CODE_IFOPT: + case KMX.KMXFile.CODE_IFSYSTEMSTORE: + result--; + break; + } + } + x = incxstr(p, x); + result++; + } + return result; +} diff --git a/developer/src/kmc-kmw/test/README.md b/developer/src/kmc-kmw/test/README.md new file mode 100644 index 00000000000..e1ccf019ac4 --- /dev/null +++ b/developer/src/kmc-kmw/test/README.md @@ -0,0 +1,7 @@ +Keyman kmn kmw Keyboard Compiler Tests +====================================== + +Test +---- + + ../build.sh test diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.ico b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.ico new file mode 100644 index 00000000000..42c90c398da Binary files /dev/null and b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.ico differ diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.js b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.js new file mode 100644 index 00000000000..e2296a99e8a --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.js @@ -0,0 +1,5463 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_khmer_angkor()); +} +function Keyboard_khmer_angkor() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_khmer_angkor"; + this.KN="Khmer Angkor"; + this.KMINVER="10.0"; + this.KV={F:' 1em "Khmer Busra Kbd"',K102:0}; + this.KV.KLS={ + "rightalt": ["‍","‌","@","","$","€","៙","៚","*","{","}","≈","","","","","ៜ","","ឯ","ឫ","ឨ","[","]","ឦ","ឱ","ឰ","ឩ","ឳ","\\","","","","+","-","×","÷",":","‘","’","ឝ","៘","៖","ៈ","","","","","","","<",">","#","&","ឞ",";","",",",".","/","","","","",""," "], + "rightalt-shift": ["","៱","៲","៳","៴","៵","៶","៷","៸","៹","៰","","","","","","᧠","᧡","᧢","᧣","᧤","᧥","᧦","᧧","᧨","᧩","᧪","᧫","","","","","᧬","᧭","᧮","᧯","᧰","᧱","᧲","᧳","᧴","᧵","᧶","","","","","","","᧷","᧸","᧹","᧺","᧻","᧼","᧽","᧾","᧿","","","","","","",""], + "default": ["«","១","២","៣","៤","៥","៦","៧","៨","៩","០","ឥ","ឲ","","","","ឆ","","","រ","ត","យ","","","","ផ","","ឪ","ឮ","","","","","ស","ដ","ថ","ង","ហ","","ក","ល","","","","","","","","","ឋ","ខ","ច","វ","ប","ន","ម","","។","","","","","","","​"], + "shift": ["»","!","ៗ","\"","៛","%","","","","(",")","","=","","","","ឈ","","","ឬ","ទ","","","","","ភ","","ឧ","ឭ","","","","","","ឌ","ធ","អ","ះ","ញ","គ","ឡ","","","","","","","","","ឍ","ឃ","ជ","","ព","ណ","","","៕","?","","","","","",""] + }; + this.KV.BK=(function(x){ + var + empty=Array.apply(null, Array(65)).map(String.prototype.valueOf,""), + result=[], v, i, + modifiers=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt']; + for(i=modifiers.length-1;i>=0;i--) { + v = x[modifiers[i]]; + if(v || result.length > 0) { + result=(v ? v : empty).slice().concat(result); + } + } + return result; + })(this.KV.KLS); + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.3"; + this.KMBM=modCodes.RALT | modCodes.SHIFT /* 0x0018 */; + this.KVKD="T_17D2_1780 T_17D2_1781 T_17D2_1782 T_17D2_1783 T_17D2_1784 T_17D2_1785 T_17D2_1786 T_17D2_1787 T_17D2_1788 T_17D2_1789 T_17D2_178A T_17D2_178B T_17D2_178C T_17D2_178D T_17D2_178E T_17D2_178F T_17D2_1790 T_17D2_1791 T_17D2_1792 T_17D2_1793 T_17D2_1794 T_17D2_1795 T_17D2_1796 T_17D2_1797 T_17D2_1798 T_17D2_1799 T_17D2_179A T_17D2_179B T_17D2_179C T_17D2_179D T_17D2_179E T_17D2_179F T_17D2_17A0 T_17D2_17A1 T_17D2_17A2 U_0030 U_0031 U_0032 U_0033 U_0034 U_0035 U_0036 U_0037 U_0038 U_0039"; + this.KVKL={ + "phone": { + "font": "Khmer Busra Kbd", + "fontsize": "0.8em", + "displayUnderlying": false, + "layer": [ + { + "id": "default", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_Q", + "text": "\u1786", + "sk": [ + { + "layer": "shift", + "id": "K_Q", + "text": "\u1788" + }, + { + "id": "T_17D2_1786", + "text": "\uEF86" + }, + { + "id": "T_17D2_1788", + "text": "\uEF88" + } + ] + }, + { + "id": "K_W", + "text": "\uEFB9", + "sk": [ + { + "layer": "shift", + "id": "K_W", + "text": "\uEFBA" + } + ] + }, + { + "id": "K_E", + "text": "\uEFC1", + "sk": [ + { + "layer": "shift", + "id": "K_E", + "text": "\uEFC2" + }, + { + "layer": "shift", + "id": "K_S", + "text": "\uEFC3" + }, + { + "layer": "shift", + "id": "K_V", + "text": "\uEF12" + }, + { + "id": "U_17AF", + "text": "\u17AF" + }, + { + "id": "U_17B0", + "text": "\u17B0" + } + ] + }, + { + "id": "K_R", + "text": "\u179A", + "sk": [ + { + "id": "T_17D2_179A", + "text": "\uEF9A" + }, + { + "id": "U_17AB", + "text": "\u17AB" + }, + { + "id": "U_17AC", + "text": "\u17AC" + } + ] + }, + { + "id": "K_T", + "text": "\u178F", + "sk": [ + { + "layer": "shift", + "id": "K_T", + "text": "\u1791" + }, + { + "id": "T_17D2_178F", + "text": "\uEF8F" + }, + { + "layer": "default", + "id": "T_17D2_1791", + "text": "\uEF91" + } + ] + }, + { + "id": "K_Y", + "text": "\u1799", + "sk": [ + { + "id": "T_17D2_1799", + "text": "\uEF99" + } + ] + }, + { + "id": "K_U", + "text": "\uEFBB", + "sk": [ + { + "layer": "shift", + "id": "K_U", + "text": "\uEFBC" + }, + { + "layer": "shift", + "id": "K_Y", + "text": "\uEFBD" + }, + { + "id": "U_17A7", + "text": "\u17A7" + }, + { + "layer": "shift", + "id": "U_17AA", + "text": "\u17AA" + }, + { + "layer": "shift", + "id": "U_17A9", + "text": "\u17A9" + }, + { + "id": "U_17A8", + "text": "\u17A8" + } + ] + }, + { + "id": "K_I", + "text": "\uEFB7", + "sk": [ + { + "layer": "shift", + "id": "K_I", + "text": "\uEFB8" + }, + { + "id": "U_17A5", + "text": "\u17A5" + }, + { + "layer": "shift", + "id": "U_17A6", + "text": "\u17A6" + } + ] + }, + { + "id": "K_O", + "text": "\uEFC4", + "sk": [ + { + "layer": "shift", + "id": "K_O", + "text": "\uEFC5" + }, + { + "id": "K_LBRKT", + "text": "\uEFC0" + }, + { + "layer": "shift", + "id": "K_LBRKT", + "text": "\uEFBF" + }, + { + "layer": "shift", + "id": "K_COLON", + "text": "\uEF14" + }, + { + "id": "U_17B1", + "text": "\u17B1" + }, + { + "id": "U_17B2", + "text": "\u17B2" + }, + { + "layer": "shift", + "id": "U_17B3", + "text": "\u17B3" + } + ] + }, + { + "id": "K_P", + "text": "\u1795", + "sk": [ + { + "layer": "shift", + "id": "K_P", + "text": "\u1797" + }, + { + "id": "T_17D2_1795", + "text": "\uEF95" + }, + { + "layer": "default", + "id": "T_17D2_1797", + "text": "\uEF97" + } + ] + } + ] + }, + { + "id": "2", + "key": [ + { + "width": "100", + "id": "K_A", + "text": "\uEFB6", + "sk": [ + { + "layer": "shift", + "id": "K_A", + "text": "\uEF11" + } + ] + }, + { + "id": "K_S", + "text": "\u179F", + "sk": [ + { + "id": "T_17D2_179F", + "text": "\uEF9F" + }, + { + "id": "U_179D", + "text": "\u179D" + }, + { + "id": "U_179E", + "text": "\u179E" + } + ] + }, + { + "id": "K_D", + "text": "\u178A", + "sk": [ + { + "layer": "shift", + "id": "K_D", + "text": "\u178C" + }, + { + "id": "T_17D2_178A", + "text": "\uEF8A" + }, + { + "layer": "default", + "id": "T_17D2_178C", + "text": "\uEF8C" + } + ] + }, + { + "id": "K_F", + "text": "\u1790", + "sk": [ + { + "layer": "shift", + "id": "K_F", + "text": "\u1792" + }, + { + "id": "T_17D2_1790", + "text": "\uEF90" + }, + { + "layer": "default", + "id": "T_17D2_1792", + "text": "\uEF92" + } + ] + }, + { + "id": "K_G", + "text": "\u1784", + "sk": [ + { + "layer": "shift", + "id": "K_G", + "text": "\u17A2" + }, + { + "id": "T_17D2_1784", + "text": "\uEF84" + }, + { + "layer": "default", + "id": "T_17D2_17A2", + "text": "\uEFA2" + } + ] + }, + { + "id": "K_H", + "text": "\u17A0", + "sk": [ + { + "id": "T_17D2_17A0", + "text": "\uEFA0" + }, + { + "layer": "shift", + "id": "K_H", + "text": "\u17C7" + }, + { + "id": "U_17C8", + "text": "\u17C8" + } + ] + }, + { + "layer": "shift", + "id": "K_J", + "text": "\u1789", + "sk": [ + { + "id": "T_17D2_1789", + "text": "\uEF89" + } + ] + }, + { + "id": "K_K", + "text": "\u1780", + "sk": [ + { + "layer": "shift", + "id": "K_K", + "text": "\u1782" + }, + { + "id": "T_17D2_1780", + "text": "\uEF80" + }, + { + "id": "T_17D2_1782", + "text": "\uEF82" + } + ] + }, + { + "id": "K_L", + "text": "\u179B", + "sk": [ + { + "layer": "shift", + "id": "K_L", + "text": "\u17A1" + }, + { + "id": "T_17D2_179B", + "text": "\uEF9B" + }, + { + "id": "U_17AD", + "text": "\u17AD" + }, + { + "id": "U_17AE", + "text": "\u17AE" + } + ] + }, + { + "id": "K_COLON", + "text": "\uEFBE" + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_Z", + "text": "\u178B", + "sk": [ + { + "layer": "shift", + "id": "K_Z", + "text": "\u178D" + }, + { + "id": "T_17D2_178B", + "text": "\uEF8B" + }, + { + "layer": "default", + "id": "T_17D2_178D", + "text": "\uEF8D" + } + ] + }, + { + "id": "K_X", + "text": "\u1781", + "sk": [ + { + "layer": "shift", + "id": "K_X", + "text": "\u1783" + }, + { + "id": "T_17D2_1781", + "text": "\uEF81" + }, + { + "layer": "default", + "id": "T_17D2_1783", + "text": "\uEF83" + } + ] + }, + { + "id": "K_C", + "text": "\u1785", + "sk": [ + { + "layer": "shift", + "id": "K_C", + "text": "\u1787" + }, + { + "id": "T_17D2_1785", + "text": "\uEF85" + }, + { + "layer": "default", + "id": "T_17D2_1787", + "text": "\uEF87" + } + ] + }, + { + "id": "K_V", + "text": "\u179C", + "sk": [ + { + "id": "T_17D2_179C", + "text": "\uEF9C" + } + ] + }, + { + "id": "K_B", + "text": "\u1794", + "sk": [ + { + "layer": "shift", + "id": "K_B", + "text": "\u1796" + }, + { + "id": "T_17D2_1794", + "text": "\uEF94" + }, + { + "layer": "default", + "id": "T_17D2_1796", + "text": "\uEF96" + } + ] + }, + { + "id": "K_N", + "text": "\u1793", + "sk": [ + { + "layer": "shift", + "id": "K_N", + "text": "\u178E" + }, + { + "id": "T_17D2_1793", + "text": "\uEF93" + }, + { + "layer": "default", + "id": "T_17D2_178E", + "text": "\uEF8E" + } + ] + }, + { + "id": "K_M", + "text": "\u1798", + "sk": [ + { + "id": "T_17D2_1798", + "text": "\uEF98" + }, + { + "layer": "shift", + "id": "K_M", + "text": "\uEFC6" + } + ] + }, + { + "id": "K_COMMA", + "text": "\uEF10", + "sk": [ + { + "layer": "shift", + "id": "K_COMMA", + "text": "\uEF13" + }, + { + "layer": "shift", + "id": "K_6", + "text": "\uEFCD" + }, + { + "layer": "shift", + "id": "K_7", + "text": "\uEFD0" + }, + { + "layer": "shift", + "id": "K_8", + "text": "\uEFCF" + }, + { + "layer": "shift", + "id": "K_HYPHEN", + "text": "\uEFCC" + }, + { + "layer": "shift", + "id": "U_17D1", + "text": "\uEFD1" + }, + { + "layer": "shift", + "id": "U_17DD", + "text": "\uEFDD" + }, + { + "layer": "shift", + "id": "U_17CE", + "text": "\uEFCE" + } + ] + }, + { + "width": "100", + "id": "K_QUOTE", + "text": "\uEFCB", + "sk": [ + { + "layer": "shift", + "id": "K_QUOTE", + "text": "\uEFC9" + }, + { + "id": "K_SLASH", + "text": "\uEFCA" + } + ] + }, + { + "width": "100", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "numeric", + "width": "140", + "id": "K_NUMLOCK", + "sp": "1", + "text": "\u17E1\u17E2\u17E3" + }, + { + "width": "120", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "width": "555", + "id": "K_SPACE", + "text": "\u200B", + "sk": [ + { + "layer": "default", + "id": "U_0020", + "text": " " + } + ] + }, + { + "width": "120", + "id": "K_PERIOD", + "text": "\u17D4", + "sk": [ + { + "layer": "shift", + "id": "K_PERIOD", + "text": "\u17D5" + }, + { + "id": "U_0021", + "text": "!" + }, + { + "id": "U_003F", + "text": "?" + } + ] + }, + { + "width": "140", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "numeric", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_1", + "text": "\u17E1", + "sk": [ + { + "id": "U_0031", + "text": "1" + } + ] + }, + { + "id": "K_2", + "text": "\u17E2", + "sk": [ + { + "id": "U_0032", + "text": "2" + } + ] + }, + { + "id": "K_3", + "text": "\u17E3", + "sk": [ + { + "id": "U_0033", + "text": "3" + } + ] + }, + { + "id": "K_4", + "text": "\u17E4", + "sk": [ + { + "id": "U_0034", + "text": "4" + } + ] + }, + { + "id": "K_5", + "text": "\u17E5", + "sk": [ + { + "id": "U_0035", + "text": "5" + } + ] + }, + { + "id": "K_6", + "text": "\u17E6", + "sk": [ + { + "id": "U_0036", + "text": "6" + } + ] + }, + { + "id": "K_7", + "text": "\u17E7", + "sk": [ + { + "id": "U_0037", + "text": "7" + } + ] + }, + { + "id": "K_8", + "text": "\u17E8", + "sk": [ + { + "id": "U_0038", + "text": "8" + } + ] + }, + { + "id": "K_9", + "text": "\u17E9", + "sk": [ + { + "id": "U_0039", + "text": "9" + } + ] + }, + { + "id": "K_0", + "text": "\u17E0", + "sk": [ + { + "id": "U_0030", + "text": "0" + }, + { + "id": "U_17D3", + "text": "\uEFD3" + } + ] + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "U_0040", + "text": "@", + "sk": [ + { + "id": "U_00A9", + "text": "\u00A9" + }, + { + "id": "U_00AE", + "text": "\u00AE" + } + ] + }, + { + "id": "U_0023", + "text": "#", + "sk": [ + { + "id": "U_2116", + "text": "\u2116" + }, + { + "id": "U_007E", + "text": "~" + } + ] + }, + { + "id": "U_17DB", + "text": "\u17DB", + "sk": [ + { + "id": "U_0024", + "text": "$" + }, + { + "id": "U_0E3F", + "text": "\u0E3F" + }, + { + "id": "U_00A2", + "text": "\u00A2" + }, + { + "id": "U_00A3", + "text": "\u00A3" + }, + { + "id": "U_00A5", + "text": "\u00A5" + } + ] + }, + { + "id": "U_0026", + "text": "&" + }, + { + "id": "U_0025", + "text": "%", + "sk": [ + { + "id": "U_2030", + "text": "\u2030" + }, + { + "id": "U_2031", + "text": "\u2031" + } + ] + }, + { + "id": "U_002B", + "text": "+", + "sk": [ + { + "id": "U_002D", + "text": "-" + }, + { + "id": "U_00D7", + "text": "\u00D7" + }, + { + "id": "U_00F7", + "text": "\u00F7" + }, + { + "id": "U_00B1", + "text": "\u00B1" + } + ] + }, + { + "id": "U_003D", + "text": "=", + "sk": [ + { + "id": "U_005F", + "text": "_" + }, + { + "id": "U_2260", + "text": "\u2260" + } + ] + }, + { + "id": "U_002A", + "text": "*", + "sk": [ + { + "id": "U_005E", + "text": "^" + } + ] + }, + { + "id": "U_003F", + "text": "?", + "sk": [ + { + "id": "U_00BF", + "text": "\u00BF" + } + ] + }, + { + "id": "U_0021", + "text": "!", + "sk": [ + { + "id": "U_00A1", + "text": "\u00A1" + } + ] + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "U_2018", + "text": "\u2018", + "sk": [ + { + "id": "U_2019", + "text": "\u2019" + } + ] + }, + { + "id": "U_201C", + "text": "\u201C", + "sk": [ + { + "id": "U_201D", + "text": "\u201D" + } + ] + }, + { + "id": "U_00AB", + "text": "\u00AB", + "sk": [ + { + "id": "U_00BB", + "text": "\u00BB" + } + ] + }, + { + "id": "U_002F", + "text": "/", + "sk": [ + { + "id": "U_005C", + "text": "\\" + }, + { + "id": "U_007C", + "text": "|" + }, + { + "id": "U_00A6", + "text": "\u00A6" + } + ] + }, + { + "id": "U_0028", + "text": "(", + "sk": [ + { + "id": "U_0029", + "text": ")" + }, + { + "id": "U_005B", + "text": "[" + }, + { + "id": "U_005D", + "text": "]" + }, + { + "id": "U_007B", + "text": "{" + }, + { + "id": "U_007D", + "text": "}" + } + ] + }, + { + "id": "U_17D9", + "text": "\u17D9", + "sk": [ + { + "id": "U_17DA", + "text": "\u17DA" + }, + { + "id": "U_17DC", + "text": "\u17DC" + }, + { + "id": "U_00A7", + "text": "\u00A7" + }, + { + "id": "U_00D8", + "text": "\u00D8" + } + ] + }, + { + "id": "U_17D7", + "text": "\u17D7" + }, + { + "id": "U_003C", + "text": "<", + "sk": [ + { + "id": "U_2264", + "text": "\u2264" + }, + { + "id": "U_003E", + "text": ">" + }, + { + "id": "U_2265", + "text": "\u2265" + } + ] + }, + { + "id": "U_17D6", + "text": "\u17D6", + "sk": [ + { + "id": "U_003A", + "text": ":" + }, + { + "id": "U_003B", + "text": ";" + }, + { + "id": "U_2026", + "text": "\u2026" + } + ] + }, + { + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "default", + "width": "140", + "id": "K_LCONTROL", + "sp": "2", + "text": "\u17E1\u17E2\u17E3" + }, + { + "width": "120", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "layer": "shift", + "width": "555", + "id": "K_SPACE", + "text": "\u200B" + }, + { + "width": "120", + "id": "K_PERIOD", + "text": "\u17D4", + "sk": [ + { + "layer": "shift", + "id": "K_PERIOD", + "text": "\u17D5" + }, + { + "id": "U_0021", + "text": "!" + }, + { + "id": "U_003F", + "text": "?" + } + ] + }, + { + "width": "140", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + } + ] + }, + "tablet": { + "font": "Khmer Busra Kbd", + "fontsize": "0.8em", + "displayUnderlying": false, + "layer": [ + { + "id": "default", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_1", + "text": "\u17E1" + }, + { + "id": "K_2", + "text": "\u17E2" + }, + { + "id": "K_3", + "text": "\u17E3" + }, + { + "id": "K_4", + "text": "\u17E4" + }, + { + "id": "K_5", + "text": "\u17E5" + }, + { + "id": "K_6", + "text": "\u17E6" + }, + { + "id": "K_7", + "text": "\u17E7" + }, + { + "id": "K_8", + "text": "\u17E8" + }, + { + "id": "K_9", + "text": "\u17E9" + }, + { + "id": "K_0", + "text": "\u17E0" + }, + { + "id": "K_HYPHEN", + "text": "\u17A5" + }, + { + "id": "K_EQUAL", + "text": "\u17B2" + }, + { + "width": "100", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "K_Q", + "pad": "75", + "text": "\u1786" + }, + { + "id": "K_W", + "text": "\uEFB9" + }, + { + "id": "K_E", + "text": "\uEFC1" + }, + { + "id": "K_R", + "text": "\u179A" + }, + { + "id": "K_T", + "text": "\u178F" + }, + { + "id": "K_Y", + "text": "\u1799" + }, + { + "id": "K_U", + "text": "\uEFBB" + }, + { + "id": "K_I", + "text": "\uEFB7" + }, + { + "id": "K_O", + "text": "\uEFC4" + }, + { + "id": "K_P", + "text": "\u1795" + }, + { + "id": "K_LBRKT", + "text": "\uEFC0" + }, + { + "id": "K_RBRKT", + "text": "\u17AA" + }, + { + "width": "10", + "id": "T_new_138", + "sp": "10" + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_BKQUOTE", + "text": "\u00AB" + }, + { + "id": "K_A", + "text": "\uEFB6" + }, + { + "id": "K_S", + "text": "\u179F" + }, + { + "id": "K_D", + "text": "\u178A" + }, + { + "id": "K_F", + "text": "\u1790" + }, + { + "id": "K_G", + "text": "\u1784" + }, + { + "id": "K_H", + "text": "\u17A0" + }, + { + "id": "K_J", + "text": "\uEFD2" + }, + { + "id": "K_K", + "text": "\u1780" + }, + { + "id": "K_L", + "text": "\u179B" + }, + { + "id": "K_COLON", + "text": "\uEFBE" + }, + { + "id": "K_QUOTE", + "text": "\uEFCB" + }, + { + "id": "K_BKSLASH", + "text": "\u17AE" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "shift", + "width": "160", + "id": "K_SHIFT", + "sp": "1", + "text": "*Shift*" + }, + { + "id": "K_oE2" + }, + { + "id": "K_Z", + "text": "\u178B" + }, + { + "id": "K_X", + "text": "\u1781" + }, + { + "id": "K_C", + "text": "\u1785" + }, + { + "id": "K_V", + "text": "\u179C" + }, + { + "id": "K_B", + "text": "\u1794" + }, + { + "id": "K_N", + "text": "\u1793" + }, + { + "id": "K_M", + "text": "\u1798" + }, + { + "id": "K_COMMA", + "text": "\uEF10" + }, + { + "id": "K_PERIOD", + "text": "\u17D4" + }, + { + "id": "K_SLASH", + "text": "\uEFCA" + }, + { + "width": "10", + "id": "T_new_164", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "rightalt", + "width": "160", + "id": "K_LCONTROL", + "sp": "1", + "text": "*AltGr*" + }, + { + "width": "160", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "width": "930", + "id": "K_SPACE", + "text": "\u200B" + }, + { + "width": "160", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "rightalt", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_1", + "text": "\u200C" + }, + { + "id": "K_2", + "text": "@" + }, + { + "id": "K_3", + "text": "\uEFD1" + }, + { + "id": "K_4", + "text": "$" + }, + { + "id": "K_5", + "text": "\u20AC" + }, + { + "id": "K_6", + "text": "\u17D9" + }, + { + "id": "K_7", + "text": "\u17DA" + }, + { + "id": "K_8", + "text": "*" + }, + { + "id": "K_9", + "text": "{" + }, + { + "id": "K_0", + "text": "}" + }, + { + "id": "K_HYPHEN", + "text": "\u2248" + }, + { + "id": "K_EQUAL", + "text": "\uEFCE" + }, + { + "width": "100", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "K_Q", + "pad": "75", + "text": "\u17DC" + }, + { + "id": "K_W", + "text": "\uEFDD" + }, + { + "id": "K_E", + "text": "\u17AF" + }, + { + "id": "K_R", + "text": "\u17AB" + }, + { + "id": "K_T", + "text": "\u17A8" + }, + { + "id": "K_Y", + "text": "[" + }, + { + "id": "K_U", + "text": "]" + }, + { + "id": "K_I", + "text": "\u17A6" + }, + { + "id": "K_O", + "text": "\u17B1" + }, + { + "id": "K_P", + "text": "\u17B0" + }, + { + "id": "K_LBRKT", + "text": "\u17A9" + }, + { + "id": "K_RBRKT", + "text": "\u17B3" + }, + { + "width": "10", + "id": "T_new_307", + "sp": "10" + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_BKQUOTE", + "text": "\u200D" + }, + { + "id": "K_A", + "text": "+" + }, + { + "id": "K_S", + "text": "-" + }, + { + "id": "K_D", + "text": "\u00D7" + }, + { + "id": "K_F", + "text": "\u00F7" + }, + { + "id": "K_G", + "text": ":" + }, + { + "id": "K_H", + "text": "\u2018" + }, + { + "id": "K_J", + "text": "\u2019" + }, + { + "id": "K_K", + "text": "\u179D" + }, + { + "id": "K_L", + "text": "\u17D8" + }, + { + "id": "K_COLON", + "text": "\u17D6" + }, + { + "id": "K_QUOTE", + "text": "\u17C8" + }, + { + "id": "K_BKSLASH", + "text": "\\" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "shift", + "width": "160", + "id": "K_SHIFT", + "sp": "1", + "text": "*Shift*" + }, + { + "id": "K_oE2" + }, + { + "id": "K_Z", + "text": "<" + }, + { + "id": "K_X", + "text": ">" + }, + { + "id": "K_C", + "text": "#" + }, + { + "id": "K_V", + "text": "&" + }, + { + "id": "K_B", + "text": "\u179E" + }, + { + "id": "K_N", + "text": ";" + }, + { + "id": "K_M", + "text": "\uEFD3" + }, + { + "id": "K_COMMA", + "text": "," + }, + { + "id": "K_PERIOD", + "text": "." + }, + { + "id": "K_SLASH", + "text": "/" + }, + { + "width": "10", + "id": "T_new_333", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "default", + "width": "160", + "id": "K_LCONTROL", + "sp": "2", + "text": "*AltGr*" + }, + { + "width": "160", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "width": "930", + "id": "K_SPACE", + "text": "\u00A0" + }, + { + "width": "160", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "shift", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_1", + "text": "!" + }, + { + "id": "K_2", + "text": "\u17D7" + }, + { + "id": "K_3", + "text": "\"" + }, + { + "id": "K_4", + "text": "\u17DB" + }, + { + "id": "K_5", + "text": "%" + }, + { + "id": "K_6", + "text": "\uEFCD" + }, + { + "id": "K_7", + "text": "\uEFD0" + }, + { + "id": "K_8", + "text": "\uEFCF" + }, + { + "id": "K_9", + "text": "(" + }, + { + "id": "K_0", + "text": ")" + }, + { + "id": "K_HYPHEN", + "text": "\uEFCC" + }, + { + "id": "K_EQUAL", + "text": "=" + }, + { + "width": "100", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "K_Q", + "pad": "75", + "text": "\u1788" + }, + { + "id": "K_W", + "text": "\uEFBA" + }, + { + "id": "K_E", + "text": "\uEFC2" + }, + { + "id": "K_R", + "text": "\u17AC" + }, + { + "id": "K_T", + "text": "\u1791" + }, + { + "id": "K_Y", + "text": "\uEFBD" + }, + { + "id": "K_U", + "text": "\uEFBC" + }, + { + "id": "K_I", + "text": "\uEFB8" + }, + { + "id": "K_O", + "text": "\uEFC5" + }, + { + "id": "K_P", + "text": "\u1797" + }, + { + "id": "K_LBRKT", + "text": "\uEFBF" + }, + { + "id": "K_RBRKT", + "text": "\u17A7" + }, + { + "width": "10", + "id": "T_new_364", + "sp": "10" + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_BKQUOTE", + "text": "\u00BB" + }, + { + "id": "K_A", + "text": "\uEF11" + }, + { + "id": "K_S", + "text": "\uEFC3" + }, + { + "id": "K_D", + "text": "\u178C" + }, + { + "id": "K_F", + "text": "\u1792" + }, + { + "id": "K_G", + "text": "\u17A2" + }, + { + "id": "K_H", + "text": "\u17C7" + }, + { + "id": "K_J", + "text": "\u1789" + }, + { + "id": "K_K", + "text": "\u1782" + }, + { + "id": "K_L", + "text": "\u17A1" + }, + { + "id": "K_COLON", + "text": "\uEF14" + }, + { + "id": "K_QUOTE", + "text": "\uEFC9" + }, + { + "id": "K_BKSLASH", + "text": "\u17AD" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "default", + "width": "160", + "id": "K_SHIFT", + "sp": "2", + "text": "*Shift*" + }, + { + "id": "K_oE2" + }, + { + "id": "K_Z", + "text": "\u178D" + }, + { + "id": "K_X", + "text": "\u1783" + }, + { + "id": "K_C", + "text": "\u1787" + }, + { + "id": "K_V", + "text": "\uEF12" + }, + { + "id": "K_B", + "text": "\u1796" + }, + { + "id": "K_N", + "text": "\u178E" + }, + { + "id": "K_M", + "text": "\uEFC6" + }, + { + "id": "K_COMMA", + "text": "\uEF13" + }, + { + "id": "K_PERIOD", + "text": "\u17D5" + }, + { + "id": "K_SLASH", + "text": "?" + }, + { + "width": "10", + "id": "T_new_390", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "rightalt", + "width": "160", + "id": "K_LCONTROL", + "sp": "1", + "text": "*AltGr*" + }, + { + "width": "160", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "width": "930", + "id": "K_SPACE" + }, + { + "width": "160", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + } + ] + } +} +; + this.s_c_key_11=['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']; + this.s_c_out_12="កខគឃងចឆជឈញដឋឌឍណតថទធនបផពភមយរលវសហឡអឝឞ"; + this.s_v_gen_key_13=['','','','','','','','','','','','','','','','']; + this.s_v_gen_14="ាិីឹឺុូួើឿៀេែៃោៅ"; + this.s_v_pseudo_key_15=['','','']; + this.s_v_pseudo_16="ំះៈ"; + this.s_v_key_17=['','','','','','','','','','','','','','','','','','','']; + this.s_v_out_18="ាិីឹឺុូួើឿៀេែៃោៅំះៈ"; + this.s_v_any_19="ាិីឹឺុូួើឿៀេែៃោៅំះៈ"; + this.s_v_combo_R_20="េោុិីឹែ"; + this.s_v_combo_N_21="ាុ"; + this.s_v_combo_22="េោុិីឹែាុ"; + this.s_ind_v_key_23=['','','','','','','','','','','','','','','']; + this.s_ind_v_out_24="ឥឦឧឨឩឪឫឬឭឮឯឰឱឲឳ"; + this.s_diacritic_key_25=['','','','','','','','','','','']; + this.s_diacritic_out_26="់័៌៏៍ៈ៎៑៝ៜ្"; + this.s_c_shifter_key_27=['','']; + this.s_c_shifter_28="៉៊"; + this.s_punct_key_29=['','','','','','','','']; + this.s_punct_out_30="។៕៖ៗ៘៙៚៓"; + this.s_latin_punct_key_31=['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']; + this.s_latin_punct_out_32="«»()!\"%=?{}\\@*,×./[]‍‌+-÷:≈‘’;<>#&"; + this.s_spaces_key_33=['','','']; + this.s_spaces_out_34="​  "; + this.s_currency_key_35=['','','']; + this.s_currency_out_36="៛$€"; + this.s_digit_key_37=['','','','','','','','','','']; + this.s_digit_out_38="០១២៣៤៥៦៧៨៩"; + this.s_lek_attak_key_39=['','','','','','','','','','']; + this.s_lek_attak_out_40="៰៱៲៳៴៵៶៷៸៹"; + this.s_lunar_date_key_41=['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']; + this.s_lunar_date_out_42="᧬᧻᧹᧮᧢᧯᧰᧱᧧᧲᧳᧴᧽᧼᧨᧩᧠᧣᧭᧤᧦᧺᧡᧸᧥᧷᧵᧾᧿᧪᧫᧶"; + this.s_input_subcons_43=['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']; + this.s_subcons_44="កខគឃងចឆជឈញដឋឌឍណតថទធនបផពភមយរលវឝឞសហឡអ"; + this.s_arabic_digit_key_45=['','','','','','','','','','']; + this.s_arabic_digit_out_46="0123456789"; + this.s_v_above_47="ិីឹឺើ័"; + this.s_shiftable_c_1st_48="សហអ"; + this.s_shiftable_BA_49="ប"; + this.s_shiftable_c_2nd_50="ងញមយរវនល"; + this.s_shiftable_c_2nd_with_BA_51="ងញមយរវនលប"; + this.s_c_2nd_combo_LO_52="យមងបវ"; + this.s_c_2nd_combo_MO_53="យលងរ"; + this.s_c_1st_combo_LO_54="បហអ"; + this.s_c_1st_combo_MO_55="ហសអ"; + this.s_c_combo_SA_56="បយលមនញងរវអ"; + this.s_c_combo_QA_57="ឆឈបផតទ"; + this.s_c_combo_HA_58="វឣ"; + this.s62="touch"; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKSP /* 0x08 */)) { + if(k.KFCM(2,t,['្',{t:'a',a:this.s_c_out_12}])&&k.KIFS(31,this.s62,t)){ + r=m=1; // Line 266 + k.KDC(2,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_combo_N_21},'ំ'])){ + r=m=1; // Line 229 + k.KDC(2,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_combo_R_20},'ះ'])){ + r=m=1; // Line 230 + k.KDC(2,t); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឞ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឝ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_QUOTE /* 0xDE */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ៈ"); + } + else if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"ៈ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឯ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឦ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឱ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឰ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឫ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឨ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_LBRKT /* 0xDB */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឩ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_RBRKT /* 0xDD */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឳ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៑"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_Q /* 0x51 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"ៜ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៝"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_EQUAL /* 0xBB */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៎"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៙"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៚"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៘"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៓"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_COLON /* 0xBA */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៖"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"}"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"‌"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"@"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"*"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"{"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"+"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"#"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"×"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"÷"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,":"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_H /* 0x48 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"‘"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"’"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,";"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_S /* 0x53 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"-"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_U /* 0x55 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"]"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"&"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_X /* 0x58 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,">"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"["); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"<"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_COMMA /* 0xBC */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,","); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"≈"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_PERIOD /* 0xBE */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"."); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_SLASH /* 0xBF */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"/"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_BKQUOTE /* 0xC0 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"‍"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_BKSLASH /* 0xDC */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"\\"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 195 + k.KDC(0,t); + k.KO(-1,t,"$"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 195 + k.KDC(0,t); + k.KO(-1,t,"€"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៰"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៱"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៲"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៳"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៴"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៵"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៶"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៷"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៸"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៹"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧬"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧻"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧹"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧮"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧢"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧯"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧰"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_H /* 0x48 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧱"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧧"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧲"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧳"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧴"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧽"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧼"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧨"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧩"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_Q /* 0x51 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧠"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧣"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_S /* 0x53 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧭"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧤"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_U /* 0x55 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧦"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧺"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧡"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_X /* 0x58 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧸"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧥"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧷"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_COLON /* 0xBA */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧵"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_COMMA /* 0xBC */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧾"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_PERIOD /* 0xBE */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧿"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_LBRKT /* 0xDB */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧪"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_RBRKT /* 0xDD */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧫"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_QUOTE /* 0xDE */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧶"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_SPACE /* 0x20 */)) { + if(1){ + r=m=1; // Line 199 + k.KDC(0,t); + k.KO(-1,t," "); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x100)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ក"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x101)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ខ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x102)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្គ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x103)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឃ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x104)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ង"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x105)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ច"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x106)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឆ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x107)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ជ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x108)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឈ"); + } + } + if(m) {} + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x109)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ញ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10A)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ដ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10B)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឋ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10C)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឌ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10D)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឍ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10E)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ណ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10F)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ត"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x110)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ថ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x111)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ទ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x112)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ធ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x113)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ន"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x114)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ប"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x115)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ផ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x116)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ព"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x117)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ភ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x118)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ម"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x119)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្យ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11A)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្រ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11B)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ល"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11C)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្វ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11D)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឝ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11E)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឞ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11F)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ស"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x120)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ហ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x121)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឡ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x122)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្អ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPSTAR /* 0x6A */)) { + if(1){ + r=m=1; // Line 268 + k.KDC(0,t); + k.KO(-1,t,"*"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPSTAR /* 0x6A */)) { + if(1){ + r=m=1; // Line 269 + k.KDC(0,t); + k.KO(-1,t,"*"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPPLUS /* 0x6B */)) { + if(1){ + r=m=1; // Line 270 + k.KDC(0,t); + k.KO(-1,t,"+"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPPLUS /* 0x6B */)) { + if(1){ + r=m=1; // Line 271 + k.KDC(0,t); + k.KO(-1,t,"+"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPMINUS /* 0x6D */)) { + if(1){ + r=m=1; // Line 272 + k.KDC(0,t); + k.KO(-1,t,"-"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPMINUS /* 0x6D */)) { + if(1){ + r=m=1; // Line 273 + k.KDC(0,t); + k.KO(-1,t,"-"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPDOT /* 0x6E */)) { + if(1){ + r=m=1; // Line 274 + k.KDC(0,t); + k.KO(-1,t,"."); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPDOT /* 0x6E */)) { + if(1){ + r=m=1; // Line 275 + k.KDC(0,t); + k.KO(-1,t,"."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPSLASH /* 0x6F */)) { + if(1){ + r=m=1; // Line 276 + k.KDC(0,t); + k.KO(-1,t,"/"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPSLASH /* 0x6F */)) { + if(1){ + r=m=1; // Line 277 + k.KDC(0,t); + k.KO(-1,t,"/"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_SPACE /* 0x20 */)) { + if(k.KFCM(1,t,['​'])){ + r=m=1; // Line 225 + k.KDC(1,t); + k.KO(-1,t," "); + } + else if(1){ + r=m=1; // Line 199 + k.KDC(0,t); + k.KO(-1,t,"​"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_SPACE /* 0x20 */)) { + if(1){ + r=m=1; // Line 199 + k.KDC(0,t); + k.KO(-1,t," "); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"!"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_QUOTE /* 0xDE */)) { + if(k.KFCM(3,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ'])){ + r=m=1; // Line 244 + k.KDC(3,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្អ៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54}])){ + r=m=1; // Line 245 + k.KDC(3,t); + k.KO(-1,t,"ល្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55}])){ + r=m=1; // Line 246 + k.KDC(3,t); + k.KO(-1,t,"ម្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56}])){ + r=m=1; // Line 247 + k.KDC(3,t); + k.KO(-1,t,"ស្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៉"); + k.KB(t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ'])){ + r=m=1; // Line 248 + k.KDC(3,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្ហ៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['អ','្','ង'])){ + r=m=1; // Line 249 + k.KDC(3,t); + k.KO(-1,t,"អ្ង៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['អ','្','វ'])){ + r=m=1; // Line 250 + k.KDC(3,t); + k.KO(-1,t,"អ្វ៉"); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_c_shifter_28}])){ + r=m=1; // Line 215 + k.KDC(1,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_shiftable_c_1st_48}])){ + r=m=1; // Line 239 + k.KDC(1,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៉"); + k.KB(t); + } + else if(1){ + r=m=1; // Line 192 + k.KDC(0,t); + k.KO(-1,t,"៉"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"\""); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 195 + k.KDC(0,t); + k.KO(-1,t,"៛"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"%"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"័"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_QUOTE /* 0xDE */)) { + if(k.KFCM(2,t,['្',{t:'a',a:this.s_c_out_12}])){ + r=m=1; // Line 214 + k.KDC(2,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_out_12,2,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_v_gen_14}])){ + r=m=1; // Line 211 + k.KDC(1,t); + k.KIO(-1,this.s_v_gen_14,1,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_v_pseudo_16}])){ + r=m=1; // Line 212 + k.KDC(1,t); + k.KIO(-1,this.s_v_pseudo_16,1,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_c_shifter_28}])){ + r=m=1; // Line 213 + k.KDC(1,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KB(t); + } + else if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"់"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"("); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,")"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៏"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_EQUAL /* 0xBB */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"="); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_COMMA /* 0xBC */)) { + if(1){ + r=m=1; // Line 206 + k.KDC(0,t); + k.KO(-1,t,"ុំ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឥ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_PERIOD /* 0xBE */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"។"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_SLASH /* 0xBF */)) { + if(k.KFCM(3,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52}])){ + r=m=1; // Line 254 + k.KDC(3,t); + k.KO(-1,t,"ល្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៊"); + k.KB(t); + } + else if(k.KFCM(3,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53}])){ + r=m=1; // Line 255 + k.KDC(3,t); + k.KO(-1,t,"ម្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៊"); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_c_shifter_28}])){ + r=m=1; // Line 215 + k.KDC(1,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51}])){ + r=m=1; // Line 240 + k.KDC(1,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៊"); + k.KB(t); + } + else if(1){ + r=m=1; // Line 192 + k.KDC(0,t); + k.KO(-1,t,"៊"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"០"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"១"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"២"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៣"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៤"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៥"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៦"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៧"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៨"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៩"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_COLON /* 0xBA */)) { + if(1){ + r=m=1; // Line 205 + k.KDC(0,t); + k.KO(-1,t,"ោះ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_COLON /* 0xBA */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ើ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_COMMA /* 0xBC */)) { + if(1){ + r=m=1; // Line 207 + k.KDC(0,t); + k.KO(-1,t,"ុះ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_EQUAL /* 0xBB */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឲ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_PERIOD /* 0xBE */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៕"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_SLASH /* 0xBF */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"?"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"ៗ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 203 + k.KDC(0,t); + k.KO(-1,t,"ាំ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ព"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ជ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឌ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ែ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ធ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"អ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_H /* 0x48 */)) { + if(k.KFCM(1,t,['ះ'])){ + r=m=1; // Line 219 + k.KDC(1,t); + k.KO(-1,t,"ៈ"); + } + else if(k.KFCM(1,t,['ៈ'])){ + r=m=1; // Line 220 + k.KDC(1,t); + k.KO(-1,t,"ះ"); + } + else if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ះ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ី"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ញ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"គ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឡ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ំ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ណ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ៅ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ភ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Q /* 0x51 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឈ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឬ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_S /* 0x53 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ៃ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ទ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_U /* 0x55 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ូ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 204 + k.KDC(0,t); + k.KO(-1,t,"េះ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ឺ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_X /* 0x58 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឃ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ួ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឍ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_LBRKT /* 0xDB */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ៀ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKSLASH /* 0xDC */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឮ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_RBRKT /* 0xDD */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឪ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៍"); + } + } + if(m) {} + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៌"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKQUOTE /* 0xC0 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"«"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ា"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ប"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ច"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ដ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"េ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ថ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ង"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_H /* 0x48 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ហ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ិ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"្"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ក"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ល"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ម"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ន"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ោ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ផ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Q /* 0x51 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឆ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"រ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_S /* 0x53 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ស"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ត"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_U /* 0x55 */)) { + if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ា','ំ'])){ + r=m=1; // Line 234 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ា','ំ'])){ + r=m=1; // Line 235 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ុ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"វ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ឹ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_X /* 0x58 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ខ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"យ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឋ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_LBRKT /* 0xDB */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ឿ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_BKSLASH /* 0xDC */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឭ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_RBRKT /* 0xDD */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឧ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_BKQUOTE /* 0xC0 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"»"); + } + } + if(m==1) { + + k.KDC(-1,t); + r=this.g_normalise_1(t,e); + m=2; + } + return r; + }; + this.g_normalise_1=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(7,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ','ំ','ា','ំ'])){ + m=1; // Line 376 + k.KDC(7,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ','ំ','ា','ំ'])){ + m=1; // Line 381 + k.KDC(7,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ','ំ','ា','ំ'])){ + m=1; // Line 386 + k.KDC(7,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ស','្','ប','ុ','ំ','ា','ំ'])){ + m=1; // Line 391 + k.KDC(7,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ','ំ','ា','ំ'])){ + m=1; // Line 396 + k.KDC(7,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ','ំ','ា','ំ'])){ + m=1; // Line 401 + k.KDC(7,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['អ','្','ង','ុ','ំ','ា','ំ'])){ + m=1; // Line 406 + k.KDC(7,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['អ','្','វ','ុ','ំ','ា','ំ'])){ + m=1; // Line 411 + k.KDC(7,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ហ','្','ប','ុ','ំ','ា','ំ'])){ + m=1; // Line 416 + k.KDC(7,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ហ','្',{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ំ','ា','ំ'])){ + m=1; // Line 422 + k.KDC(7,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ','ំ','ា','ំ'])){ + m=1; // Line 429 + k.KDC(7,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ','ំ','ា','ំ'])){ + m=1; // Line 434 + k.KDC(7,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['្','ដ',{t:'a',a:this.s_v_combo_N_21},'ំ','្','រ'])){ + m=1; // Line 340 + k.KDC(6,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_N_21,3,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['្','ដ',{t:'a',a:this.s_v_combo_R_20},'ះ','្','រ'])){ + m=1; // Line 341 + k.KDC(6,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_R_20,3,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(6,t,['្','រ',{t:'a',a:this.s_v_combo_N_21},'ំ','្','ដ'])){ + m=1; // Line 344 + k.KDC(6,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_N_21,3,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['្','រ',{t:'a',a:this.s_v_combo_R_20},'ះ','្','ដ'])){ + m=1; // Line 345 + k.KDC(6,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_R_20,3,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(6,t,['្','រ',{t:'a',a:this.s_v_combo_N_21},'ំ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 350 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,6,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_N_21,3,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['្','រ',{t:'a',a:this.s_v_combo_R_20},'ះ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 351 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,6,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_R_20,3,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ','ា','ំ'])){ + m=1; // Line 374 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ','ា','ំ'])){ + m=1; // Line 379 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ','ា','ំ'])){ + m=1; // Line 384 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្','ប','ុ','ា','ំ'])){ + m=1; // Line 389 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ','ា','ំ'])){ + m=1; // Line 394 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ','ា','ំ'])){ + m=1; // Line 399 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','ង','ុ','ា','ំ'])){ + m=1; // Line 404 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','វ','ុ','ា','ំ'])){ + m=1; // Line 409 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ហ','្','ប','ុ','ា','ំ'])){ + m=1; // Line 414 + k.KDC(6,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ប"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ហ','្',{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ា','ំ'])){ + m=1; // Line 420 + k.KDC(6,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ','ា','ំ'])){ + m=1; // Line 427 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ','ា','ំ'])){ + m=1; // Line 432 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'៊',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 454 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_gen_14,5,t); + k.KIO(-1,this.s_v_pseudo_16,6,t); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'៊',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 455 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_gen_14,5,t); + k.KIO(-1,this.s_v_pseudo_16,6,t); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','៉','ា','ំ'])){ + m=1; // Line 489 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'៉','ា','ំ'])){ + m=1; // Line 490 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'៉','ា','ំ'])){ + m=1; // Line 491 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្','ប','៉','ា','ំ'])){ + m=1; // Line 492 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'៉','ា','ំ'])){ + m=1; // Line 493 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','៉','ា','ំ'])){ + m=1; // Line 494 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','ង','៉','ា','ំ'])){ + m=1; // Line 495 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','វ','៉','ា','ំ'])){ + m=1; // Line 496 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ា','ុ','ំ'])){ + m=1; // Line 503 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ','ំ','ា'])){ + m=1; // Line 504 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ា','ុ','ំ'])){ + m=1; // Line 506 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ','ំ','ា'])){ + m=1; // Line 507 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ា','ុ','ំ'])){ + m=1; // Line 509 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ','ំ','ា'])){ + m=1; // Line 510 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ា','ុ','ំ'])){ + m=1; // Line 512 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ','ំ','ា'])){ + m=1; // Line 513 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ា','ុ','ំ'])){ + m=1; // Line 515 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ','ំ','ា'])){ + m=1; // Line 516 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','ង','ា','ុ','ំ'])){ + m=1; // Line 518 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','ង','ុ','ំ','ា'])){ + m=1; // Line 519 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','វ','ា','ុ','ំ'])){ + m=1; // Line 521 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','វ','ុ','ំ','ា'])){ + m=1; // Line 522 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ុ"); + k.KO(-1,t,"ា"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ា','ុ','ំ'])){ + m=1; // Line 529 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ','ំ','ា'])){ + m=1; // Line 530 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ា','ុ','ំ'])){ + m=1; // Line 532 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ','ំ','ា'])){ + m=1; // Line 533 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','េ','ុ','ី'])){ + m=1; // Line 541 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ','េ','ី'])){ + m=1; // Line 542 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','៉','េ','ី'])){ + m=1; // Line 543 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'េ','ុ','ី'])){ + m=1; // Line 545 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ','េ','ី'])){ + m=1; // Line 546 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'៉','េ','ី'])){ + m=1; // Line 547 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'េ','ុ','ី'])){ + m=1; // Line 549 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ','េ','ី'])){ + m=1; // Line 550 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'៉','េ','ី'])){ + m=1; // Line 551 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'េ','ុ','ី'])){ + m=1; // Line 553 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ','េ','ី'])){ + m=1; // Line 554 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'៉','េ','ី'])){ + m=1; // Line 555 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','េ','ុ','ី'])){ + m=1; // Line 557 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ','េ','ី'])){ + m=1; // Line 558 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','៉','េ','ី'])){ + m=1; // Line 559 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','ង','េ','ុ','ី'])){ + m=1; // Line 561 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','ង','ុ','េ','ី'])){ + m=1; // Line 562 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','ង','៉','េ','ី'])){ + m=1; // Line 563 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','វ','េ','ុ','ី'])){ + m=1; // Line 565 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','វ','ុ','េ','ី'])){ + m=1; // Line 566 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','វ','៉','េ','ី'])){ + m=1; // Line 567 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'េ','ុ','ី'])){ + m=1; // Line 575 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ','េ','ី'])){ + m=1; // Line 576 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'៊','េ','ី'])){ + m=1; // Line 577 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'េ','ុ','ី'])){ + m=1; // Line 579 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ','េ','ី'])){ + m=1; // Line 580 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'៊','េ','ី'])){ + m=1; // Line 581 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['្','យ','្',{t:'a',a:this.s_c_out_12},'េ','ឺ'])){ + m=1; // Line 631 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_out_12,4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(6,t,['្','យ','្',{t:'a',a:this.s_c_out_12},'េ','ឹ'])){ + m=1; // Line 632 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_out_12,4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(6,t,['្','យ','្',{t:'a',a:this.s_c_out_12},'េ','ី'])){ + m=1; // Line 633 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_out_12,4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_combo_N_21},'ំ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 331 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,5,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KIO(-1,this.s_v_combo_N_21,2,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_combo_R_20},'ះ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 332 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,5,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KIO(-1,this.s_v_combo_R_20,2,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(5,t,['្','ដ',{t:'a',a:this.s_v_any_19},'្','រ'])){ + m=1; // Line 339 + k.KDC(5,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_any_19,3,t); + } + else if(k.KFCM(5,t,['្','រ',{t:'a',a:this.s_v_any_19},'្','ដ'])){ + m=1; // Line 343 + k.KDC(5,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_any_19,3,t); + } + else if(k.KFCM(5,t,['្','រ',{t:'a',a:this.s_c_shifter_28},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 347 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,5,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_c_shifter_28,3,t); + } + else if(k.KFCM(5,t,['្','រ',{t:'a',a:this.s_v_any_19},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 349 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,5,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_any_19,3,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 373 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 375 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 378 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 380 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 383 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 385 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + if(m) {} + else if(k.KFCM(5,t,['ស','្','ប','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 388 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ស','្','ប',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 390 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 393 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 395 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 398 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 400 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['អ','្','ង','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 403 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['អ','្','ង',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 405 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['អ','្','វ','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 408 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['អ','្','វ',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 410 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ហ','្','ប','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 413 + k.KDC(5,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ហ','្','ប',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 415 + k.KDC(5,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ហ','្',{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 419 + k.KDC(5,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ហ','្',{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 421 + k.KDC(5,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 426 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 428 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 431 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 433 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ','ំ','ា','ំ'])){ + m=1; // Line 441 + k.KDC(5,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ំ','ា','ំ'])){ + m=1; // Line 448 + k.KDC(5,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'៊',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 452 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'៊',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 453 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['្',{t:'a',a:this.s_shiftable_c_2nd_50},'៊',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 463 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_50,2,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_gen_14,4,t); + k.KIO(-1,this.s_v_pseudo_16,5,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 481 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 482 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 483 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ស','្','ប','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 484 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 485 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 486 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['អ','្','ង','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 487 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['អ','្','វ','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 488 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ព','័','ន','្','ឋ'])){ + m=1; // Line 619 + k.KDC(5,t); + k.KO(-1,t,"ព"); + k.KO(-1,t,"័"); + k.KO(-1,t,"ន"); + k.KO(-1,t,"្ធ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 312 + k.KDC(4,t); + k.KIO(-1,this.s_v_gen_14,3,t); + k.KIO(-1,this.s_v_pseudo_16,4,t); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_v_combo_N_21},'ំ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 325 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,4,t); + k.KIO(-1,this.s_v_combo_N_21,1,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_v_combo_R_20},'ះ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 326 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,4,t); + k.KIO(-1,this.s_v_combo_R_20,1,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_any_19},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 330 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,4,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KIO(-1,this.s_v_any_19,2,t); + } + else if(k.KFCM(4,t,['្','ដ','្','រ'])){ + m=1; // Line 336 + k.KDC(4,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + } + else if(k.KFCM(4,t,['្','រ','្','ដ'])){ + m=1; // Line 337 + k.KDC(4,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + } + else if(k.KFCM(4,t,['្','រ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 348 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,4,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 362 + k.KDC(4,t); + k.KIO(-1,this.s_v_gen_14,2,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ','ា','ំ'])){ + m=1; // Line 439 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ា','ំ'])){ + m=1; // Line 446 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'៊',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 460 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_gen_14,3,t); + k.KIO(-1,this.s_v_pseudo_16,4,t); + } + else if(k.KFCM(4,t,['្',{t:'a',a:this.s_shiftable_c_2nd_50},'៊',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 462 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_50,2,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(4,t,['ប','្','យ',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 467 + k.KDC(4,t); + k.KO(-1,t,"ប្យ"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ស','្','ប',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 468 + k.KDC(4,t); + k.KO(-1,t,"ស្ប"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ឆ','្','ប',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 469 + k.KDC(4,t); + k.KO(-1,t,"ឆ្ប"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ប','្','យ',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 470 + k.KDC(4,t); + k.KO(-1,t,"ប្យ"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ស','្','ប',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 471 + k.KDC(4,t); + k.KO(-1,t,"ស្ប"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ឆ','្','ប',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 472 + k.KDC(4,t); + k.KO(-1,t,"ឆ្ប"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'៉',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 477 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_gen_14,3,t); + k.KIO(-1,this.s_v_pseudo_16,4,t); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ា','ុ','ំ'])){ + m=1; // Line 500 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ','ំ','ា'])){ + m=1; // Line 501 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ា','ុ','ំ'])){ + m=1; // Line 526 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ំ','ា'])){ + m=1; // Line 527 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'េ','ុ','ី'])){ + m=1; // Line 537 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ','េ','ី'])){ + m=1; // Line 538 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'៉','េ','ី'])){ + m=1; // Line 539 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'េ','ុ','ី'])){ + m=1; // Line 571 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'ុ','េ','ី'])){ + m=1; // Line 572 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'៊','េ','ី'])){ + m=1; // Line 573 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(4,t,['ព','ន','្','ឋ'])){ + m=1; // Line 618 + k.KDC(4,t); + k.KO(-1,t,"ព"); + k.KO(-1,t,"ន"); + k.KO(-1,t,"្ធ"); + } + else if(k.KFCM(4,t,['្','យ','េ','ឺ'])){ + m=1; // Line 627 + k.KDC(4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(4,t,['្','យ','េ','ឹ'])){ + m=1; // Line 628 + k.KDC(4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(4,t,['្','យ','េ','ី'])){ + m=1; // Line 629 + k.KDC(4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_gen_14}])){ + m=1; // Line 308 + k.KDC(3,t); + k.KIO(-1,this.s_v_gen_14,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 309 + k.KDC(3,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 310 + k.KDC(3,t); + k.KIO(-1,this.s_v_gen_14,2,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 311 + k.KDC(3,t); + k.KIO(-1,this.s_v_gen_14,2,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + } + else if(k.KFCM(3,t,['្',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 320 + k.KDC(3,t); + k.KIO(-1,this.s_v_gen_14,2,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_any_19},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 324 + k.KDC(3,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,3,t); + k.KIO(-1,this.s_v_any_19,1,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_c_shifter_28},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 355 + k.KDC(3,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,3,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 360 + k.KDC(3,t); + k.KIO(-1,this.s_c_shifter_28,3,t); + k.KIO(-1,this.s_v_gen_14,1,t); + k.KIO(-1,this.s_v_pseudo_16,2,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_any_19},{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 361 + k.KDC(3,t); + k.KIO(-1,this.s_c_shifter_28,3,t); + k.KIO(-1,this.s_v_any_19,2,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 438 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_1st_48},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 440 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,2,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 445 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 447 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,2,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'៊',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 459 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_1st_48},'៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 476 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_c_out_12},{t:'a',a:this.s_v_gen_14},'៌'])){ + m=1; // Line 585 + k.KDC(3,t); + k.KIO(-1,this.s_c_out_12,1,t); + k.KO(-1,t,"៌"); + k.KIO(-1,this.s_v_gen_14,2,t); + } + else if(k.KFCM(3,t,['ណ','្','ត'])){ + m=1; // Line 589 + k.KDC(3,t); + k.KO(-1,t,"ណ"); + k.KO(-1,t,"្ដ"); + } + else if(k.KFCM(3,t,['ន','្','ដ'])){ + m=1; // Line 590 + k.KDC(3,t); + k.KO(-1,t,"ន"); + k.KO(-1,t,"្ត"); + } + else if(k.KFCM(3,t,['ទ','្','ប'])){ + m=1; // Line 594 + k.KDC(3,t); + k.KO(-1,t,"ឡ"); + } + else if(k.KFCM(3,t,['ប','្','ញ'])){ + m=1; // Line 596 + k.KDC(3,t); + k.KO(-1,t,"ឫ"); + } + else if(k.KFCM(3,t,['ព','្','ញ'])){ + m=1; // Line 602 + k.KDC(3,t); + k.KO(-1,t,"ឭ"); + } + else if(k.KFCM(3,t,['ព','្','ឋ'])){ + m=1; // Line 605 + k.KDC(3,t); + k.KO(-1,t,"ឰ"); + } + else if(k.KFCM(3,t,['ដ','្','ធ'])){ + m=1; // Line 613 + k.KDC(3,t); + k.KO(-1,t,"ដ្ឋ"); + } + else if(k.KFCM(3,t,['ទ','្','ឋ'])){ + m=1; // Line 614 + k.KDC(3,t); + k.KO(-1,t,"ទ្ធ"); + } + else if(k.KFCM(3,t,['ឪ','្','យ'])){ + m=1; // Line 622 + k.KDC(3,t); + k.KO(-1,t,"ឱ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"យ"); + } + else if(k.KFCM(3,t,['ឳ','្','យ'])){ + m=1; // Line 623 + k.KDC(3,t); + k.KO(-1,t,"ឱ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"យ"); + } + else if(k.KFCM(3,t,['ញ','្','វ'])){ + m=1; // Line 625 + k.KDC(3,t); + k.KO(-1,t,"ព"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វា"); + } + else if(k.KFCM(2,t,['េ','ា'])){ + m=1; // Line 291 + k.KDC(2,t); + k.KO(-1,t,"ោ"); + } + else if(k.KFCM(2,t,['ា','េ'])){ + m=1; // Line 292 + k.KDC(2,t); + k.KO(-1,t,"ោ"); + } + else if(k.KFCM(2,t,['េ','ី'])){ + m=1; // Line 293 + k.KDC(2,t); + k.KO(-1,t,"ើ"); + } + else if(k.KFCM(2,t,['ី','េ'])){ + m=1; // Line 294 + k.KDC(2,t); + k.KO(-1,t,"ើ"); + } + else if(k.KFCM(2,t,['ំ','ុ'])){ + m=1; // Line 298 + k.KDC(2,t); + k.KO(-1,t,"ុំ"); + } + else if(k.KFCM(2,t,['ំ','ា'])){ + m=1; // Line 299 + k.KDC(2,t); + k.KO(-1,t,"ាំ"); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_gen_14}])){ + m=1; // Line 304 + k.KDC(2,t); + k.KIO(-1,this.s_v_gen_14,2,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 313 + k.KDC(2,t); + k.KIO(-1,this.s_v_pseudo_16,2,t); + } + if(m) {} + else if(k.KFCM(2,t,['្','្'])){ + m=1; // Line 318 + k.KDC(2,t); + k.KO(-1,t,"្"); + } + else if(k.KFCM(2,t,['្',{t:'a',a:this.s_v_any_19}])){ + m=1; // Line 319 + k.KDC(2,t); + k.KIO(-1,this.s_v_any_19,2,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_any_19},{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 359 + k.KDC(2,t); + k.KIO(-1,this.s_c_shifter_28,2,t); + k.KIO(-1,this.s_v_any_19,1,t); + } + else if(k.KFCM(2,t,['ឫ','ុ'])){ + m=1; // Line 597 + k.KDC(2,t); + k.KO(-1,t,"ឬ"); + } + else if(k.KFCM(2,t,['ឭ','ា'])){ + m=1; // Line 599 + k.KDC(2,t); + k.KO(-1,t,"ញ"); + } + else if(k.KFCM(2,t,['ឮ','ា'])){ + m=1; // Line 600 + k.KDC(2,t); + k.KO(-1,t,"ញ"); + } + else if(k.KFCM(2,t,['ឭ','ុ'])){ + m=1; // Line 603 + k.KDC(2,t); + k.KO(-1,t,"ឮ"); + } + else if(k.KFCM(2,t,['ឧ','ិ'])){ + m=1; // Line 607 + k.KDC(2,t); + k.KO(-1,t,"ឱ"); + } + else if(k.KFCM(2,t,['ឧ','៌'])){ + m=1; // Line 608 + k.KDC(2,t); + k.KO(-1,t,"ឱ"); + } + else if(k.KFCM(2,t,['ឧ','៍'])){ + m=1; // Line 609 + k.KDC(2,t); + k.KO(-1,t,"ឱ"); + } + return r; + }; +} diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.keyman-touch-layout b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.keyman-touch-layout new file mode 100644 index 00000000000..711f8490083 --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.keyman-touch-layout @@ -0,0 +1,1950 @@ +{ + "tablet": { + "displayUnderlying": false, + "layer": [ + { + "id": "default", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "១" + }, + { + "id": "K_2", + "text": "២" + }, + { + "id": "K_3", + "text": "៣" + }, + { + "id": "K_4", + "text": "៤" + }, + { + "id": "K_5", + "text": "៥" + }, + { + "id": "K_6", + "text": "៦" + }, + { + "id": "K_7", + "text": "៧" + }, + { + "id": "K_8", + "text": "៨" + }, + { + "id": "K_9", + "text": "៩" + }, + { + "id": "K_0", + "text": "០" + }, + { + "id": "K_HYPHEN", + "text": "ឥ" + }, + { + "id": "K_EQUAL", + "text": "ឲ" + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "100", + "sp": "1" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_Q", + "text": "ឆ", + "pad": "75" + }, + { + "id": "K_W", + "text": "" + }, + { + "id": "K_E", + "text": "" + }, + { + "id": "K_R", + "text": "រ" + }, + { + "id": "K_T", + "text": "ត" + }, + { + "id": "K_Y", + "text": "យ" + }, + { + "id": "K_U", + "text": "" + }, + { + "id": "K_I", + "text": "" + }, + { + "id": "K_O", + "text": "" + }, + { + "id": "K_P", + "text": "ផ" + }, + { + "id": "K_LBRKT", + "text": "" + }, + { + "id": "K_RBRKT", + "text": "ឪ" + }, + { + "id": "T_new_138", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_BKQUOTE", + "text": "«" + }, + { + "id": "K_A", + "text": "" + }, + { + "id": "K_S", + "text": "ស" + }, + { + "id": "K_D", + "text": "ដ" + }, + { + "id": "K_F", + "text": "ថ" + }, + { + "id": "K_G", + "text": "ង" + }, + { + "id": "K_H", + "text": "ហ" + }, + { + "id": "K_J", + "text": "" + }, + { + "id": "K_K", + "text": "ក" + }, + { + "id": "K_L", + "text": "ល" + }, + { + "id": "K_COLON", + "text": "" + }, + { + "id": "K_QUOTE", + "text": "" + }, + { + "id": "K_BKSLASH", + "text": "ឮ" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": "160", + "sp": "1", + "nextlayer": "shift" + }, + { + "id": "K_oE2", + "text": "" + }, + { + "id": "K_Z", + "text": "ឋ" + }, + { + "id": "K_X", + "text": "ខ" + }, + { + "id": "K_C", + "text": "ច" + }, + { + "id": "K_V", + "text": "វ" + }, + { + "id": "K_B", + "text": "ប" + }, + { + "id": "K_N", + "text": "ន" + }, + { + "id": "K_M", + "text": "ម" + }, + { + "id": "K_COMMA", + "text": "" + }, + { + "id": "K_PERIOD", + "text": "។" + }, + { + "id": "K_SLASH", + "text": "" + }, + { + "id": "T_new_164", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_LCONTROL", + "text": "*AltGr*", + "width": "160", + "sp": "1", + "nextlayer": "rightalt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "160", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": "​", + "width": "930" + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "160", + "sp": "1" + } + ] + } + ] + }, + { + "id": "rightalt", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "‌" + }, + { + "id": "K_2", + "text": "@" + }, + { + "id": "K_3", + "text": "" + }, + { + "id": "K_4", + "text": "$" + }, + { + "id": "K_5", + "text": "€" + }, + { + "id": "K_6", + "text": "៙" + }, + { + "id": "K_7", + "text": "៚" + }, + { + "id": "K_8", + "text": "*" + }, + { + "id": "K_9", + "text": "{" + }, + { + "id": "K_0", + "text": "}" + }, + { + "id": "K_HYPHEN", + "text": "≈" + }, + { + "id": "K_EQUAL", + "text": "" + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "100", + "sp": "1" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_Q", + "text": "ៜ", + "pad": "75" + }, + { + "id": "K_W", + "text": "" + }, + { + "id": "K_E", + "text": "ឯ" + }, + { + "id": "K_R", + "text": "ឫ" + }, + { + "id": "K_T", + "text": "ឨ" + }, + { + "id": "K_Y", + "text": "[" + }, + { + "id": "K_U", + "text": "]" + }, + { + "id": "K_I", + "text": "ឦ" + }, + { + "id": "K_O", + "text": "ឱ" + }, + { + "id": "K_P", + "text": "ឰ" + }, + { + "id": "K_LBRKT", + "text": "ឩ" + }, + { + "id": "K_RBRKT", + "text": "ឳ" + }, + { + "id": "T_new_307", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_BKQUOTE", + "text": "‍" + }, + { + "id": "K_A", + "text": "+" + }, + { + "id": "K_S", + "text": "-" + }, + { + "id": "K_D", + "text": "×" + }, + { + "id": "K_F", + "text": "÷" + }, + { + "id": "K_G", + "text": ":" + }, + { + "id": "K_H", + "text": "‘" + }, + { + "id": "K_J", + "text": "’" + }, + { + "id": "K_K", + "text": "ឝ" + }, + { + "id": "K_L", + "text": "៘" + }, + { + "id": "K_COLON", + "text": "៖" + }, + { + "id": "K_QUOTE", + "text": "ៈ" + }, + { + "id": "K_BKSLASH", + "text": "\\" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": "160", + "sp": "1", + "nextlayer": "shift" + }, + { + "id": "K_oE2", + "text": "" + }, + { + "id": "K_Z", + "text": "<" + }, + { + "id": "K_X", + "text": ">" + }, + { + "id": "K_C", + "text": "#" + }, + { + "id": "K_V", + "text": "&" + }, + { + "id": "K_B", + "text": "ឞ" + }, + { + "id": "K_N", + "text": ";" + }, + { + "id": "K_M", + "text": "" + }, + { + "id": "K_COMMA", + "text": "," + }, + { + "id": "K_PERIOD", + "text": "." + }, + { + "id": "K_SLASH", + "text": "/" + }, + { + "id": "T_new_333", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_LCONTROL", + "text": "*AltGr*", + "width": "160", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "160", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": " ", + "width": "930" + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "160", + "sp": "1" + } + ] + } + ] + }, + { + "id": "shift", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "!" + }, + { + "id": "K_2", + "text": "ៗ" + }, + { + "id": "K_3", + "text": "\"" + }, + { + "id": "K_4", + "text": "៛" + }, + { + "id": "K_5", + "text": "%" + }, + { + "id": "K_6", + "text": "" + }, + { + "id": "K_7", + "text": "" + }, + { + "id": "K_8", + "text": "" + }, + { + "id": "K_9", + "text": "(" + }, + { + "id": "K_0", + "text": ")" + }, + { + "id": "K_HYPHEN", + "text": "" + }, + { + "id": "K_EQUAL", + "text": "=" + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "100", + "sp": "1" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_Q", + "text": "ឈ", + "pad": "75" + }, + { + "id": "K_W", + "text": "" + }, + { + "id": "K_E", + "text": "" + }, + { + "id": "K_R", + "text": "ឬ" + }, + { + "id": "K_T", + "text": "ទ" + }, + { + "id": "K_Y", + "text": "" + }, + { + "id": "K_U", + "text": "" + }, + { + "id": "K_I", + "text": "" + }, + { + "id": "K_O", + "text": "" + }, + { + "id": "K_P", + "text": "ភ" + }, + { + "id": "K_LBRKT", + "text": "" + }, + { + "id": "K_RBRKT", + "text": "ឧ" + }, + { + "id": "T_new_364", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_BKQUOTE", + "text": "»" + }, + { + "id": "K_A", + "text": "" + }, + { + "id": "K_S", + "text": "" + }, + { + "id": "K_D", + "text": "ឌ" + }, + { + "id": "K_F", + "text": "ធ" + }, + { + "id": "K_G", + "text": "អ" + }, + { + "id": "K_H", + "text": "ះ" + }, + { + "id": "K_J", + "text": "ញ" + }, + { + "id": "K_K", + "text": "គ" + }, + { + "id": "K_L", + "text": "ឡ" + }, + { + "id": "K_COLON", + "text": "" + }, + { + "id": "K_QUOTE", + "text": "" + }, + { + "id": "K_BKSLASH", + "text": "ឭ" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": "160", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_oE2", + "text": "" + }, + { + "id": "K_Z", + "text": "ឍ" + }, + { + "id": "K_X", + "text": "ឃ" + }, + { + "id": "K_C", + "text": "ជ" + }, + { + "id": "K_V", + "text": "" + }, + { + "id": "K_B", + "text": "ព" + }, + { + "id": "K_N", + "text": "ណ" + }, + { + "id": "K_M", + "text": "" + }, + { + "id": "K_COMMA", + "text": "" + }, + { + "id": "K_PERIOD", + "text": "៕" + }, + { + "id": "K_SLASH", + "text": "?" + }, + { + "id": "T_new_390", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_LCONTROL", + "text": "*AltGr*", + "width": "160", + "sp": "1", + "nextlayer": "rightalt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "160", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": "", + "width": "930" + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "160", + "sp": "1" + } + ] + } + ] + } + ], + "font": "Khmer Busra Kbd", + "fontsize": "0.8em" + }, + "phone": { + "layer": [ + { + "id": "default", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_Q", + "text": "ឆ", + "pad": "", + "sk": [ + { + "text": "ឈ", + "id": "K_Q", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1786" + }, + { + "text": "", + "id": "T_17D2_1788" + } + ] + }, + { + "id": "K_W", + "text": "", + "sk": [ + { + "text": "", + "id": "K_W", + "layer": "shift" + } + ] + }, + { + "id": "K_E", + "text": "", + "sk": [ + { + "text": "", + "id": "K_E", + "layer": "shift" + }, + { + "text": "", + "id": "K_S", + "layer": "shift" + }, + { + "text": "", + "id": "K_V", + "layer": "shift" + }, + { + "text": "ឯ", + "id": "U_17AF" + }, + { + "text": "ឰ", + "id": "U_17B0" + } + ] + }, + { + "id": "K_R", + "text": "រ", + "sk": [ + { + "text": "", + "id": "T_17D2_179A" + }, + { + "text": "ឫ", + "id": "U_17AB" + }, + { + "text": "ឬ", + "id": "U_17AC" + } + ] + }, + { + "id": "K_T", + "text": "ត", + "sk": [ + { + "text": "ទ", + "id": "K_T", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_178F" + }, + { + "text": "", + "id": "T_17D2_1791", + "layer": "default" + } + ] + }, + { + "id": "K_Y", + "text": "យ", + "sk": [ + { + "text": "", + "id": "T_17D2_1799" + } + ] + }, + { + "id": "K_U", + "text": "", + "sk": [ + { + "text": "", + "id": "K_U", + "layer": "shift" + }, + { + "text": "", + "id": "K_Y", + "layer": "shift" + }, + { + "text": "ឧ", + "id": "U_17A7" + }, + { + "text": "ឪ", + "id": "U_17AA", + "layer": "shift" + }, + { + "text": "ឩ", + "id": "U_17A9", + "layer": "shift" + }, + { + "text": "ឨ", + "id": "U_17A8" + } + ] + }, + { + "id": "K_I", + "text": "", + "sk": [ + { + "text": "", + "id": "K_I", + "layer": "shift" + }, + { + "text": "ឥ", + "id": "U_17A5" + }, + { + "text": "ឦ", + "id": "U_17A6", + "layer": "shift" + } + ] + }, + { + "id": "K_O", + "text": "", + "sk": [ + { + "text": "", + "id": "K_O", + "layer": "shift" + }, + { + "text": "", + "id": "K_LBRKT" + }, + { + "text": "", + "id": "K_LBRKT", + "layer": "shift" + }, + { + "text": "", + "id": "K_COLON", + "layer": "shift" + }, + { + "text": "ឱ", + "id": "U_17B1" + }, + { + "text": "ឲ", + "id": "U_17B2" + }, + { + "text": "ឳ", + "id": "U_17B3", + "layer": "shift" + } + ] + }, + { + "id": "K_P", + "text": "ផ", + "sk": [ + { + "text": "ភ", + "id": "K_P", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1795" + }, + { + "text": "", + "id": "T_17D2_1797", + "layer": "default" + } + ] + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_A", + "text": "", + "pad": "", + "width": "100", + "sk": [ + { + "text": "", + "id": "K_A", + "layer": "shift" + } + ] + }, + { + "id": "K_S", + "text": "ស", + "sk": [ + { + "text": "", + "id": "T_17D2_179F" + }, + { + "text": "ឝ", + "id": "U_179D" + }, + { + "text": "ឞ", + "id": "U_179E" + } + ] + }, + { + "id": "K_D", + "text": "ដ", + "sk": [ + { + "text": "ឌ", + "id": "K_D", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_178A" + }, + { + "text": "", + "id": "T_17D2_178C", + "layer": "default" + } + ] + }, + { + "id": "K_F", + "text": "ថ", + "sk": [ + { + "text": "ធ", + "id": "K_F", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1790" + }, + { + "text": "", + "id": "T_17D2_1792", + "layer": "default" + } + ] + }, + { + "id": "K_G", + "text": "ង", + "sk": [ + { + "text": "អ", + "id": "K_G", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1784" + }, + { + "text": "", + "id": "T_17D2_17A2", + "layer": "default" + } + ] + }, + { + "id": "K_H", + "text": "ហ", + "sk": [ + { + "text": "", + "id": "T_17D2_17A0" + }, + { + "text": "ះ", + "id": "K_H", + "layer": "shift" + }, + { + "text": "ៈ", + "id": "U_17C8" + } + ] + }, + { + "id": "K_J", + "text": "ញ", + "layer": "shift", + "sk": [ + { + "text": "", + "id": "T_17D2_1789" + } + ] + }, + { + "id": "K_K", + "text": "ក", + "sk": [ + { + "text": "គ", + "id": "K_K", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1780" + }, + { + "text": "", + "id": "T_17D2_1782" + } + ] + }, + { + "id": "K_L", + "text": "ល", + "sk": [ + { + "text": "ឡ", + "id": "K_L", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_179B" + }, + { + "text": "ឭ", + "id": "U_17AD" + }, + { + "text": "ឮ", + "id": "U_17AE" + } + ] + }, + { + "id": "K_COLON", + "text": "" + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_Z", + "text": "ឋ", + "pad": "", + "width": "", + "sk": [ + { + "text": "ឍ", + "id": "K_Z", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_178B" + }, + { + "text": "", + "id": "T_17D2_178D", + "layer": "default" + } + ] + }, + { + "id": "K_X", + "text": "ខ", + "sk": [ + { + "text": "ឃ", + "id": "K_X", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1781" + }, + { + "text": "", + "id": "T_17D2_1783", + "layer": "default" + } + ] + }, + { + "id": "K_C", + "text": "ច", + "sk": [ + { + "text": "ជ", + "id": "K_C", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1785" + }, + { + "text": "", + "id": "T_17D2_1787", + "layer": "default" + } + ] + }, + { + "id": "K_V", + "text": "វ", + "sk": [ + { + "text": "", + "id": "T_17D2_179C" + } + ] + }, + { + "id": "K_B", + "text": "ប", + "sk": [ + { + "text": "ព", + "id": "K_B", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1794" + }, + { + "text": "", + "id": "T_17D2_1796", + "layer": "default" + } + ] + }, + { + "id": "K_N", + "text": "ន", + "sk": [ + { + "text": "ណ", + "id": "K_N", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1793" + }, + { + "text": "", + "id": "T_17D2_178E", + "layer": "default" + } + ] + }, + { + "id": "K_M", + "text": "ម", + "sk": [ + { + "text": "", + "id": "T_17D2_1798" + }, + { + "text": "", + "id": "K_M", + "layer": "shift" + } + ] + }, + { + "id": "K_COMMA", + "text": "", + "sk": [ + { + "text": "", + "id": "K_COMMA", + "layer": "shift" + }, + { + "text": "", + "id": "K_6", + "layer": "shift" + }, + { + "text": "", + "id": "K_7", + "layer": "shift" + }, + { + "text": "", + "id": "K_8", + "layer": "shift" + }, + { + "text": "", + "id": "K_HYPHEN", + "layer": "shift" + }, + { + "text": "", + "id": "U_17D1", + "layer": "shift" + }, + { + "text": "", + "id": "U_17DD", + "layer": "shift" + }, + { + "text": "", + "id": "U_17CE", + "layer": "shift" + } + ] + }, + { + "id": "K_QUOTE", + "text": "", + "width": "100", + "sk": [ + { + "text": "", + "id": "K_QUOTE", + "layer": "shift" + }, + { + "text": "", + "id": "K_SLASH" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "100", + "sp": "1" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_NUMLOCK", + "text": "១២៣", + "width": "140", + "sp": "1", + "nextlayer": "numeric" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "120", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": "​", + "width": "555", + "sp": "0", + "sk": [ + { + "text": " ", + "id": "U_0020", + "layer": "default" + } + ] + }, + { + "id": "K_PERIOD", + "text": "។", + "width": "120", + "sk": [ + { + "text": "៕", + "id": "K_PERIOD", + "layer": "shift" + }, + { + "text": "!", + "id": "U_0021" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "140", + "sp": "1" + } + ] + } + ] + }, + { + "id": "numeric", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "១", + "pad": "", + "sk": [ + { + "text": "1", + "id": "U_0031" + } + ] + }, + { + "id": "K_2", + "text": "២", + "sk": [ + { + "text": "2", + "id": "U_0032" + } + ] + }, + { + "id": "K_3", + "text": "៣", + "sk": [ + { + "text": "3", + "id": "U_0033" + } + ] + }, + { + "id": "K_4", + "text": "៤", + "sk": [ + { + "text": "4", + "id": "U_0034" + } + ] + }, + { + "id": "K_5", + "text": "៥", + "sk": [ + { + "text": "5", + "id": "U_0035" + } + ] + }, + { + "id": "K_6", + "text": "៦", + "sk": [ + { + "text": "6", + "id": "U_0036" + } + ] + }, + { + "id": "K_7", + "text": "៧", + "sk": [ + { + "text": "7", + "id": "U_0037" + } + ] + }, + { + "id": "K_8", + "text": "៨", + "sk": [ + { + "text": "8", + "id": "U_0038" + } + ] + }, + { + "id": "K_9", + "text": "៩", + "sk": [ + { + "text": "9", + "id": "U_0039" + } + ] + }, + { + "id": "K_0", + "text": "០", + "sk": [ + { + "text": "0", + "id": "U_0030" + }, + { + "text": "", + "id": "U_17D3" + } + ] + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "U_0040", + "text": "@", + "pad": "", + "sk": [ + { + "text": "©", + "id": "U_00A9" + }, + { + "text": "®", + "id": "U_00AE" + } + ] + }, + { + "id": "U_0023", + "text": "#", + "sk": [ + { + "text": "№", + "id": "U_2116" + }, + { + "text": "~", + "id": "U_007E" + } + ] + }, + { + "id": "U_17DB", + "text": "៛", + "sk": [ + { + "text": "$", + "id": "U_0024" + }, + { + "text": "฿", + "id": "U_0E3F" + }, + { + "text": "¢", + "id": "U_00A2" + }, + { + "text": "£", + "id": "U_00A3" + }, + { + "text": "¥", + "id": "U_00A5" + } + ] + }, + { + "id": "U_0026", + "text": "&" + }, + { + "id": "U_0025", + "text": "%", + "sk": [ + { + "text": "‰", + "id": "U_2030" + }, + { + "text": "‱", + "id": "U_2031" + } + ] + }, + { + "id": "U_002B", + "text": "+", + "sk": [ + { + "text": "-", + "id": "U_002D" + }, + { + "text": "×", + "id": "U_00D7" + }, + { + "text": "÷", + "id": "U_00F7" + }, + { + "text": "±", + "id": "U_00B1" + } + ] + }, + { + "id": "U_003D", + "text": "=", + "sk": [ + { + "text": "_", + "id": "U_005F" + }, + { + "text": "≠", + "id": "U_2260" + } + ] + }, + { + "id": "U_002A", + "text": "*", + "sk": [ + { + "text": "^", + "id": "U_005E" + } + ] + }, + { + "id": "U_003F", + "text": "?", + "sk": [ + { + "text": "¿", + "id": "U_00BF" + } + ] + }, + { + "id": "U_0021", + "text": "!", + "sk": [ + { + "text": "¡", + "id": "U_00A1" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "U_2018", + "text": "‘", + "sk": [ + { + "text": "’", + "id": "U_2019" + } + ] + }, + { + "id": "U_201C", + "text": "“", + "sk": [ + { + "text": "”", + "id": "U_201D" + } + ] + }, + { + "id": "U_00AB", + "text": "«", + "pad": "", + "sk": [ + { + "text": "»", + "id": "U_00BB" + } + ] + }, + { + "id": "U_002F", + "text": "/", + "sk": [ + { + "text": "\\", + "id": "U_005C" + }, + { + "text": "|", + "id": "U_007C" + }, + { + "text": "¦", + "id": "U_00A6" + } + ] + }, + { + "id": "U_0028", + "text": "(", + "sk": [ + { + "text": ")", + "id": "U_0029" + }, + { + "text": "[", + "id": "U_005B" + }, + { + "text": "]", + "id": "U_005D" + }, + { + "text": "{", + "id": "U_007B" + }, + { + "text": "}", + "id": "U_007D" + } + ] + }, + { + "id": "U_17D9", + "text": "៙", + "sk": [ + { + "text": "៚", + "id": "U_17DA" + }, + { + "text": "ៜ", + "id": "U_17DC" + }, + { + "text": "§", + "id": "U_00A7" + }, + { + "text": "Ø", + "id": "U_00D8" + } + ] + }, + { + "id": "U_17D7", + "text": "ៗ" + }, + { + "id": "U_003C", + "text": "<", + "sk": [ + { + "text": "≤", + "id": "U_2264" + }, + { + "text": ">", + "id": "U_003E" + }, + { + "text": "≥", + "id": "U_2265" + } + ] + }, + { + "id": "U_17D6", + "text": "៖", + "sk": [ + { + "text": ":", + "id": "U_003A" + }, + { + "text": ";", + "id": "U_003B" + }, + { + "text": "…", + "id": "U_2026" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "", + "sp": "1" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_LCONTROL", + "text": "១២៣", + "width": "140", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "120", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": "​", + "width": "555", + "sp": "0", + "layer": "shift", + "sk": [] + }, + { + "id": "K_PERIOD", + "text": "។", + "width": "120", + "sk": [ + { + "text": "៕", + "id": "K_PERIOD", + "layer": "shift" + }, + { + "text": "!", + "id": "U_0021" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "140", + "sp": "1" + } + ] + } + ] + } + ], + "displayUnderlying": false, + "font": "Khmer Busra Kbd", + "fontsize": "0.8em" + } +} \ No newline at end of file diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kmn b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kmn new file mode 100644 index 00000000000..b7919afca3e --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kmn @@ -0,0 +1,642 @@ +store(&VERSION) '10.0' +store(&NAME) "Khmer Angkor" +store(©RIGHT) '© 2015-2022 SIL International' +store(&MESSAGE) "More than just a Khmer Unicode keyboard." +store(&TARGETS) 'any' +store(&LAYOUTFILE) 'khmer_angkor.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.3' +store(&BITMAP) 'khmer_angkor.ico' +store(&VISUALKEYBOARD) 'khmer_angkor.kvks' + +begin Unicode > use(main) + + + +c ==============================================STORES============================================== + + + +c 33 consonants and two deprecated consonants + +store(c_key) [K_K] [K_X] [SHIFT K_K] [SHIFT K_X] [K_G] \ + [K_C] [K_Q] [SHIFT K_C] [SHIFT K_Q] [SHIFT K_J] \ + [K_D] [K_Z] [SHIFT K_D] [SHIFT K_Z] [SHIFT K_N] \ + [K_T] [K_F] [SHIFT K_T] [SHIFT K_F] [K_N] \ + [K_B] [K_P] [SHIFT K_B] [SHIFT K_P] [K_M] \ + [K_Y] [K_R] [K_L] [K_V] [K_S] [K_H] [SHIFT K_L] [SHIFT K_G] \ + [RALT K_K] [RALT K_B] +store(c_out) U+1780 U+1781 U+1782 U+1783 U+1784 \ + U+1785 U+1786 U+1787 U+1788 U+1789 \ + U+178A U+178B U+178C U+178D U+178E \ + U+178F U+1790 U+1791 U+1792 U+1793 \ + U+1794 U+1795 U+1796 U+1797 U+1798 \ + U+1799 U+179A U+179B U+179C U+179F U+17A0 U+17A1 U+17A2 \ + U+179D U+179E c deprecated, but they are used in minority languages + +c All genuine dependent vowels + +store(v_gen_key) [K_A] [K_I] [SHIFT K_I] [K_W] [SHIFT K_W] [K_U] [SHIFT K_U] [SHIFT K_Y] \ + [K_COLON] [SHIFT K_LBRKT] [K_LBRKT] [K_E] [SHIFT K_E] [SHIFT K_S] [K_O] [SHIFT K_O] +store(v_gen) U+17B6 U+17B7 U+17B8 U+17B9 U+17BA U+17BB U+17BC U+17BD \ + U+17BE U+17BF U+17C0 U+17C1 U+17C2 U+17C3 U+17C4 U+17C5 + +c All pseudo dependent vowels + +store(v_pseudo_key) [SHIFT K_M] [SHIFT K_H] [RALT K_QUOTE] +store(v_pseudo) U+17C6 U+17C7 U+17C8 + +c Both genuine and pseudo vowels + +store(v_key) outs(v_gen_key) outs(v_pseudo_key) +store(v_out) outs(v_gen) outs(v_pseudo) +store(v_any) outs(v_out) + +c These seven vowels can be concatenated with Reahmuk (U+17C7) to make េះ ោះ ុះ ិះ ីះ ឹះ and ែះ. + +store(v_combo_R) U+17C1 U+17C4 U+17BB U+17B7 U+17B8 U+17B9 U+17C2 + +c these two vowels can be concatenated with Nikahit (U+17C6) to make ាំ and ុំ. + +store(v_combo_N) U+17B6 U+17BB +store(v_combo) outs(v_combo_R) outs(v_combo_N) + +c Independent vowels + +store(ind_v_key) [K_HYPHEN] [RALT K_I] [SHIFT K_RBRKT] [RALT K_T] [RALT K_LBRKT] [K_RBRKT] [RALT K_R] [SHIFT K_R] \ + [SHIFT K_BKSLASH] [K_BKSLASH] [RALT K_E] [RALT K_P] [RALT K_O] [K_EQUAL] [RALT K_RBRKT] +store(ind_v_out) U+17A5 U+17A6 U+17A7 U+17A8 U+17A9 U+17AA U+17AB U+17AC \ + U+17AD U+17AE U+17AF U+17B0 U+17B1 U+17B2 U+17B3 + +c Diacritics + +store(diacritic_key) [K_QUOTE] [SHIFT K_7] [SHIFT K_HYPHEN] [SHIFT K_8] [SHIFT K_6] [RALT K_QUOTE] \ + [RALT K_EQUAL] [RALT K_3] [RALT K_W] [RALT K_Q] [K_J] +store(diacritic_out) U+17CB U+17D0 U+17CC U+17CF U+17CD U+17C8 \ + U+17CE U+17D1 U+17DD U+17DC U+17D2 + +c Consonant shifter--Muusikatoan(U+17C9) and Triisap(U+17CA) + +store(c_shifter_key) [SHIFT K_QUOTE] [K_SLASH] +store(c_shifter) U+17C9 U+17CA + +c punctuations + +store(punct_key) [K_PERIOD] [SHIFT K_PERIOD] [RALT K_COLON] [SHIFT K_2] [RALT K_L] [RALT K_6] [RALT K_7] [RALT K_M] +store(punct_out) U+17D4 U+17D5 U+17D6 U+17D7 U+17D8 U+17D9 U+17DA U+17D3 + +store(latin_punct_key) [K_BKQUOTE] [SHIFT K_BKQUOTE] [SHIFT K_9] [SHIFT K_0] [SHIFT K_1] [SHIFT K_3] \ + [SHIFT K_5] [SHIFT K_EQUAL] [SHIFT K_SLASH] [RALT K_9] [RALT K_0] [RALT K_BKSLASH] \ + [RALT K_2] [RALT K_8] [RALT K_COMMA] [RALT K_D] [RALT K_PERIOD] [RALT K_SLASH] \ + [RALT K_Y] [RALT K_U] [RALT K_BKQUOTE] [RALT K_1] [RALT K_A] [RALT K_S] \ + [RALT K_F] [RALT K_G] [RALT K_HYPHEN] [RALT K_H] [RALT K_J] [RALT K_N] \ + [RALT K_Z] [RALT K_X] [RALT K_C] [RALT K_V] +store(latin_punct_out) U+00AB U+00BB U+0028 U+0029 U+0021 U+0022 \ + U+0025 U+003D U+003F U+007B U+007D U+005C \ + U+0040 U+002A U+002C U+00D7 U+002E U+002F \ + U+005B U+005D U+200D U+200C U+002B U+002D \ + U+00F7 U+003A U+2248 U+2018 U+2019 U+003B \ + U+003C U+003E U+0023 U+0026 +c white space, ZWSP, ZWJ +store(spaces_key) [K_SPACE] [SHIFT K_SPACE] [RALT K_SPACE] +store(spaces_out) U+200B U+0020 U+00A0 + +c Currency: Riel, Dollar and Euro + +store(currency_key) [SHIFT K_4] [RALT K_4] [RALT K_5] +store(currency_out) U+17DB U+0024 U+20AC + +c Khmer digits 0 through 9 + +store(digit_key) [K_0] [K_1] [K_2] [K_3] [K_4] [K_5] [K_6] [K_7] [K_8] [K_9] +store(digit_out) U+17E0 U+17E1 U+17E2 U+17E3 U+17E4 U+17E5 U+17E6 U+17E7 U+17E8 U+17E9 + +c Khmer Lek Attak (a.k.a. divination lore) +store(lek_attak_key) [SHIFT RALT K_0] [SHIFT RALT K_1] [SHIFT RALT K_2] [SHIFT RALT K_3] [SHIFT RALT K_4] \ + [SHIFT RALT K_5] [SHIFT RALT K_6] [SHIFT RALT K_7] [SHIFT RALT K_8] [SHIFT RALT K_9] +store(lek_attak_out) U+17F0 U+17F1 U+17F2 U+17F3 U+17F4 \ + U+17F5 U+17F6 U+17F7 U+17F8 U+17F9 + +c Lunar date format (Khmer style) + +store(lunar_date_key) [SHIFT RALT K_A] [SHIFT RALT K_B] [SHIFT RALT K_C] [SHIFT RALT K_D] [SHIFT RALT K_E] \ + [SHIFT RALT K_F] [SHIFT RALT K_G] [SHIFT RALT K_H] [SHIFT RALT K_I] [SHIFT RALT K_J] \ + [SHIFT RALT K_K] [SHIFT RALT K_L] [SHIFT RALT K_M] [SHIFT RALT K_N] [SHIFT RALT K_O] \ + [SHIFT RALT K_P] [SHIFT RALT K_Q] [SHIFT RALT K_R] [SHIFT RALT K_S] [SHIFT RALT K_T] \ + [SHIFT RALT K_U] [SHIFT RALT K_V] [SHIFT RALT K_W] [SHIFT RALT K_X] [SHIFT RALT K_Y] \ + [SHIFT RALT K_Z] [SHIFT RALT K_COLON] [SHIFT RALT K_COMMA] [SHIFT RALT K_PERIOD] [SHIFT RALT K_LBRKT] \ + [SHIFT RALT K_RBRKT] [SHIFT RALT K_QUOTE] +store(lunar_date_out) U+19EC U+19FB U+19F9 U+19EE U+19E2 \ + U+19EF U+19F0 U+19F1 U+19E7 U+19F2 \ + U+19F3 U+19F4 U+19FD U+19FC U+19E8 \ + U+19E9 U+19E0 U+19E3 U+19ED U+19E4 \ + U+19E6 U+19FA U+19E1 U+19F8 U+19E5 \ + U+19F7 U+19F5 U+19FE U+19FF U+19EA \ + U+19EB U+19F6 + +c Subscripts​ for mobile/table layouts + +store(input_subcons) \ + [T_17D2_1780] [T_17D2_1781] [T_17D2_1782] [T_17D2_1783] [T_17D2_1784] [T_17D2_1785] [T_17D2_1786] [T_17D2_1787] \ + [T_17D2_1788] [T_17D2_1789] [T_17D2_178A] [T_17D2_178B] [T_17D2_178C] [T_17D2_178D] [T_17D2_178E] [T_17D2_178F] \ + [T_17D2_1790] [T_17D2_1791] [T_17D2_1792] [T_17D2_1793] [T_17D2_1794] [T_17D2_1795] [T_17D2_1796] [T_17D2_1797] \ + [T_17D2_1798] [T_17D2_1799] [T_17D2_179A] [T_17D2_179B] [T_17D2_179C] [T_17D2_179D] [T_17D2_179E] [T_17D2_179F] \ + [T_17D2_17A0] [T_17D2_17A1] [T_17D2_17A2] + +store(subcons) \ + U+1780 U+1781 U+1782 U+1783 U+1784 U+1785 U+1786 U+1787 \ + U+1788 U+1789 U+178A U+178B U+178C U+178D U+178E U+178F \ + U+1790 U+1791 U+1792 U+1793 U+1794 U+1795 U+1796 U+1797 \ + U+1798 U+1799 U+179A U+179B U+179C U+179D U+179E U+179F \ + U+17A0 U+17A1 U+17A2 + +c Arabic digits 0 through 9 + +store(arabic_digit_key) [U_0030] [U_0031] [U_0032] [U_0033] [U_0034] [U_0035] [U_0036] [U_0037] [U_0038] [U_0039] +store(arabic_digit_out) U+0030 U+0031 U+0032 U+0033 U+0034 U+0035 U+0036 U+0037 U+0038 U+0039 + +c These stores are for consonant (cluster) and consonant shifter configuration + +store(v_above) U+17B7 U+17B8 U+17B9 U+17BA \ + U+17BE U+17D0 c These vowels are rendered above the base consonant. +store(shiftable_c_1st) U+179F U+17A0 U+17A2 c These consonants shift to the 2nd series when adding U+17CA to them. +store(shiftable_BA) U+1794 c BA is unique because it can be used with both U+17CA (shift to 2nd) and and U+179C (shift to PA, still in 1st series). +store(shiftable_c_2nd) U+1784 U+1789 U+1798 U+1799 \ + U+179A U+179C U+1793 U+179B c These consonants shift to the 1st series when adding U+17C9 to them. +store(shiftable_c_2nd_with_BA) outs(shiftable_c_2nd) outs(shiftable_BA) +store(c_2nd_combo_LO) U+1799 U+1798 U+1784 U+1794 \ + U+179C c These can be combined with U+179B to make a 2nd series consonant cluster. +store(c_2nd_combo_MO) U+1799 U+179B U+1784 U+179A c These can be combined with U+1798 to make a 2nd series consonant cluster. +store(c_1st_combo_LO) U+1794 U+17A0 U+17A2 c they can be combined with U+179B to make a 1st series consonant cluster. +store(c_1st_combo_MO) U+17A0 U+179F U+17A2 c they can be combined with U+1798 to make a 1st series consonant cluster. +store(c_combo_SA) U+1794 U+1799 U+179B U+1798 \ + U+1793 U+1789 U+1784 U+179A \ + U+179C U+17A2 c they can be combined with U+179F to make a 1st series consonant cluster. +store(c_combo_QA) U+1786 U+1788 U+1794 U+1795 \ + U+178F U+1791 c they can be combined with U+17A2 to make a 1st series consonant cluster. +store(c_combo_HA) U+179C U+17A3 c they can be combined with U+17A0 to make a 1st series consonant cluster. + + + +c ==============================================BASIC RULES & CONSTRAINTS/ROTATIONS============================================== + + + +group(main) using keys + +c Basic rules with RALT key + + + any(c_key) > index(c_out,1) + + any(v_key) > index(v_out,1) + + any(ind_v_key) > index(ind_v_out,1) + + any(diacritic_key) > index(diacritic_out,1) + + any(c_shifter_key) > index(c_shifter,1) + + any(punct_key) > index(punct_out,1) + + any(latin_punct_key) > index(latin_punct_out,1) + + any(currency_key) > index(currency_out,1) + + any(digit_key) > index(digit_out,1) + + any(lek_attak_key) > index(lek_attak_out,1) + + any(lunar_date_key) > index(lunar_date_out,1) + + any(spaces_key) > index(spaces_out,1) + +c two-unicode-code-point vowels + ++ [SHIFT K_A] > U+17B6 U+17C6 ++ [SHIFT K_V] > U+17C1 U+17C7 ++ [SHIFT K_COLON] > U+17C4 U+17C7 ++ [K_COMMA] > U+17BB U+17C6 ++ [SHIFT K_COMMA] > U+17BB U+17C7 + +c Constraints + +any(v_gen) + [K_QUOTE] > context beep c no Bantoc after any genuine vowel +any(v_pseudo) + [K_QUOTE] > context beep c no Bantoc after any pseudo vowel +any(c_shifter) + [K_QUOTE] > context beep c no Bantoc after Triisap/Muusikatoan +U+17D2 any(c_out) + [K_QUOTE] > context beep c no Bantoc on a subscript +any(c_shifter) + any(c_shifter_key) > context beep c no two Triisap/Muusikatoan + +c Rotation + +U+17C7 + [SHIFT K_H] > U+17C8 c U+17C7 is changed to U+17C8 when pressing [SHIFT K_H]. +U+17C8 + [SHIFT K_H] > U+17C7 c U+17C8 is changed to U+17C7 when K_H is pressed. +c any(v_gen) U+17C7 + [SHIFT K_H] > context beep c Don't rotate between U+17C7 and U+17C8. + +c Press Space twice to get a White Space + +U+200B + [K_SPACE] > U+0020 + +c One backspace deletes a two-part vowels (i.e. psuedoVowel + U+17C7) + +any(v_combo_N) U+17C6 + [K_BKSP] > nul +any(v_combo_R) U+17C7 + [K_BKSP] > nul + +c When pressing [K_U] after ាំ and ុំ, the U+17BB is converted to a respective consonant shifter placing before them (ាំ and ុំ). + +any(shiftable_c_1st) U+17B6 U+17C6 + [K_U] > context(1) U+17CA context(2) context(3) c fix ស ាំ ុ > ស៊ាំ +any(shiftable_c_2nd_with_BA) U+17B6 U+17C6 + [K_U] > context(1) U+17C9 context(2) context(3) c fix ម ាំ ុ > ម៉ាំ + +c Consonant shifter constraints (beep when the consonant shifter is used in inappropriate environment) + +any(shiftable_c_1st) + [SHIFT K_QUOTE] > context U+17C9 beep +any(shiftable_c_2nd_with_BA) + [K_SLASH] > context U+17CA beep + +c 1st series consonant clusters + +any(c_combo_QA) U+17D2 U+17A2 + [SHIFT K_QUOTE] > context U+17C9 beep +U+179B U+17D2 any(c_1st_combo_LO) + [SHIFT K_QUOTE] > context U+17C9 beep +U+1798 U+17D2 any(c_1st_combo_MO) + [SHIFT K_QUOTE] > context U+17C9 beep +U+179F U+17D2 any(c_combo_SA) + [SHIFT K_QUOTE] > context U+17C9 beep +any(c_combo_HA) U+17D2 U+17A0 + [SHIFT K_QUOTE] > context U+17C9 beep +U+17A2 U+17D2 U+1784 + [SHIFT K_QUOTE] > context U+17C9 beep +U+17A2 U+17D2 U+179C + [SHIFT K_QUOTE] > context U+17C9 beep + +c 2nd series consonant clusters + +U+179B U+17D2 any(c_2nd_combo_LO) + [K_SLASH] > context U+17CA beep +U+1798 U+17D2 any(c_2nd_combo_MO) + [K_SLASH] > context U+17CA beep + + +c ==============================================MOBILE/TABLET TOUCH LAYOUT============================================== + + + ++ any(input_subcons) > U+17D2 index(subcons, 1) + +c delete a subscript (a subscript sign + a consonant) upon a backspace + +platform('touch') U+17D2 any(c_out) + [K_BKSP] > nul c working OK + + + [K_NPSTAR] > U+002A + + [SHIFT K_NPSTAR] > U+002A + + [K_NPPLUS] > U+002B + + [SHIFT K_NPPLUS] > U+002B + + [K_NPMINUS] > U+002D + + [SHIFT K_NPMINUS] > U+002D + + [K_NPDOT] > U+002E + + [SHIFT K_NPDOT] > U+002E + + [K_NPSLASH] > U+002F + + [SHIFT K_NPSLASH] > U+002F + + + +c ==============================================NORMALIZATION============================================== + + + +match > use(normalise) + +group(normalise) + +c Illegitimate vowel combinations should be transformed to the legitimate ones (Case #6 and #7). + +U+17C1 U+17B6 > U+17C4 c when type េ and ា, tranform them to ោ +U+17B6 U+17C1 > U+17C4 c when type ា and េ, tranform them to ោ +U+17C1 U+17B8 > U+17BE c when type េ and ី , tranform them to ើ +U+17B8 U+17C1 > U+17BE c when type ី and េ, tranform them to ើ + +c Illegitimate vowel combinations should be transformed to the legitimate ones (Case #5). + +U+17C6 U+17BB > U+17BB U+17C6 c when type ំ and ុ , tranform them to ុំ +U+17C6 U+17B6 > U+17B6 U+17C6 c when type ំ and ា, tranform them to ាំ + + +c Rotate vowels + +any(v_gen) any(v_gen) > context(2) c the last vowel stroke replaces the previous one. + +c Rotation of two-part vowels + +any(v_gen) any(v_pseudo) any(v_gen) > context(3) c a two-part vowel rotates to a genuine vowel. +any(v_gen) any(v_pseudo) any(v_pseudo) > context(3) c a two-part vowel rotates to a pseudo vowel. +any(v_gen) any(v_gen) any(v_pseudo) > context(2) context(3) c a genuine vowel rotates to a two-part vowel. +any(v_pseudo) any(v_gen) any(v_pseudo) > context(2) context(3) c a pseudo vowel roates to a two-part vowel. +any(v_gen) any(v_pseudo) any(v_gen) any(v_pseudo) > context(3) context(4) c a two-part vowel rotates to another two-part vowel. +any(v_pseudo) any(v_pseudo) > context(2) c a pseudo vowel rotates to another pseudo vowel. +c any(v_pseudo) any(v_gen) > context(2) c a pseudo vowel roates to a genuine vowel. + +c Delete extraneous coeng markers + +U+17D2 U+17D2 > context(1) c no two coengs are allowed. +U+17D2 any(v_any) > context(2) c The coeng is deleted when a vowel is put after it. +U+17D2 any(v_gen) any(v_pseudo) > context(2) context(3) c The coeng is deleted when a pseudo vowel is put after it. + +c Case #1: when a subscript is typed after a vowel, the subscript should be automatically moved to before the vowel. + +any(v_any) U+17D2 any(subcons) > context(2) context(3) context(1) c a vowel has to come after a subscript. +any(v_combo_N) U+17C6 U+17D2 any(subcons) > context(3) context(4) context(1) context(2) c these two-part vowels have to come after a subscript. +any(v_combo_R) U+17C7 U+17D2 any(subcons) > context(3) context(4) context(1) context(2) c these two-part vowels have to come after a subscript. + +c a subscript placed after a shifter and a vowel (a genuine/pseudo vowel or a two-part vowel) has to move to before them. + +any(c_shifter) any(v_any) U+17D2 any(subcons) > context(3) context(4) context(1) context(2) c after a genuine/pseudo vowel +any(c_shifter) any(v_combo_N) U+17C6 U+17D2 any(subcons) > context(4) context(5) context(1) context(2) context(3) c after a two-part vowel +any(c_shifter) any(v_combo_R) U+17C7 U+17D2 any(subcons) > context(4) context(5) context(1) context(2) context(3) c after a two-part vowel + +c Case #2: when [D2+9A] is typed before a subscript, it should be moved to after it. + +U+17D2 U+178A U+17D2 U+179A > context(1) U+178F context(3) context(4) c change subscript ្ដ to ្ត after ្រ +U+17D2 U+179A U+17D2 U+178A > context(3) U+178F context(1) context(2) c ្ដ placed after ្រ has to be changed to ្ត and placed before ្រ + +U+17D2 U+178A any(v_any) U+17D2 U+179A > context(1) U+178F context(4) context(5) context(3) c fixed 6e +U+17D2 U+178A any(v_combo_N) U+17C6 U+17D2 U+179A > context(1) U+178F context(5) context(6) context(3) context(4) +U+17D2 U+178A any(v_combo_R) U+17C7 U+17D2 U+179A > context(1) U+178F context(5) context(6) context(3) context(4) + +U+17D2 U+179A any(v_any) U+17D2 U+178A > context(1) U+178F context(4) context(2) context(3) c fixed 6g +U+17D2 U+179A any(v_combo_N) U+17C6 U+17D2 U+178A > context(1) U+178F context(5) context(2) context(3) context(4) +U+17D2 U+179A any(v_combo_R) U+17C7 U+17D2 U+178A > context(1) U+178F context(5) context(2) context(3) context(4) + +U+17D2 U+179A any(c_shifter) U+17D2 any(subcons) > context(4) context(5) context(1) context(2) context(3) c when a shifter intervenes, move it to the end. +U+17D2 U+179A U+17D2 any(subcons) > context(3) context(4) context(1) context(2) c move any subscript placed after [D2+DA] to before them +U+17D2 U+179A any(v_any) U+17D2 any(subcons) > context(4) context(5) context(1) context(2) context(3) c when a vowel intervenes, move it to the end +U+17D2 U+179A any(v_combo_N) U+17C6 U+17D2 any(subcons) > context(5) context(6) context(1) context(2) context(3) context(4) c when a two-part vowel intervenes, move it to the end too. +U+17D2 U+179A any(v_combo_R) U+17C7 U+17D2 any(subcons) > context(5) context(6) context(1) context(2) context(3) context(4) c (same as stated right above) + +c when a subscript is placed after a consonant shifter, they should be reversed. (Case #3) + +any(c_shifter) U+17D2 any(subcons) > context(2) context(3) context(1) + +c Reordering - Triisap and Muusikatoan store before a vowel and a vowelcomboR and pseudo vowel. + +any(v_any) any(c_shifter) > context(2) context(1) c place either a enguine or pseudo vowel after a consonant shifter +any(v_gen) any(v_pseudo) any(c_shifter) > context(3) context(1) context(2) c place a two-part vowel after a consonant shifter(i.e. មោះ៉ ) +any(c_shifter) any(v_any) any(c_shifter) > context(3) context(2) c when either a genuine or pseudo vowel is in between two consonant shifters, replace the one on the left with the one on the right. +any(c_shifter) any(v_gen) any(v_pseudo) any(c_shifter) > context(2) context(3) context(4) c when a two-part vowel is in between two consonants shifter, replace the one on the left with the one the right. + +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +c + when [BB] is place either before or after an above vowel (ិ ី ឹ ឺ ើ and ាំ) and a Samyok Sannya (Case #4) + +c + the [BB] should transform to a respective consonant shifter placed before the vowel. + +c + the consonant shifter is a Trisap if the base consonant is ស ហ អ + +c + the consonant shifter is a Muusikatoan if the base consonant is ង ញ ម យ រ វ ប and ន ល + +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +c consonant clusters --1st > 2nd series (with U+17BB) + +any(c_combo_QA) U+17D2 U+17A2 U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +any(c_combo_QA) U+17D2 U+17A2 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +any(c_combo_QA) U+17D2 U+17A2 any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +any(c_combo_QA) U+17D2 U+17A2 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+179B U+17D2 any(c_1st_combo_LO) U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+179B U+17D2 any(c_1st_combo_LO) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+179B U+17D2 any(c_1st_combo_LO) any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+179B U+17D2 any(c_1st_combo_LO) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+1798 U+17D2 any(c_1st_combo_MO) any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+179F U+17D2 U+1794 U+17BB any(v_above) > context(1) context(2) context(3) U+17C9 context(5) c prevent ស្បុិ from transforming to ស្ប៊ិ​​​, but produce ស្ប៉ិ instead because ប never have Triisap shifted down. +U+179F U+17D2 U+1794 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(5) context(6) +U+179F U+17D2 U+1794 any(v_above) U+17BB > context(1) context(2) context(3) U+17C9 context(4) +U+179F U+17D2 U+1794 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(6) context(7) + +U+179F U+17D2 any(c_combo_SA) U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+179F U+17D2 any(c_combo_SA) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+179F U+17D2 any(c_combo_SA) any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+179F U+17D2 any(c_combo_SA) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +any(c_combo_HA) U+17D2 U+17A0 U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +any(c_combo_HA) U+17D2 U+17A0 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +any(c_combo_HA) U+17D2 U+17A0 any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +any(c_combo_HA) U+17D2 U+17A0 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+17A2 U+17D2 U+1784 U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+17A2 U+17D2 U+1784 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+17A2 U+17D2 U+1784 any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+17A2 U+17D2 U+1784 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+17A2 U+17D2 U+179C U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+17A2 U+17D2 U+179C U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+17A2 U+17D2 U+179C any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+17A2 U+17D2 U+179C U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+17A0 U+17D2 U+1794 U+17BB any(v_above) > context(1) context(2) context(3) U+17C9 context(5) c change U+17BB preceded by HA and coeng BA to U+17C9 before the above vowel +U+17A0 U+17D2 U+1794 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(3) context(6) c change U+17BB preceded by HA and coeng BA to U+17C9 before ាំ +U+17A0 U+17D2 U+1794 any(v_above) U+17BB > context(1) context(2) context(3) U+17C9 context(4) c change U+17BB preceded by HA and coeng BA to U+17C9 before the above vowel +U+17A0 U+17D2 U+1794 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(6) context(7) c change U+17BB preceded by HA and coeng BA to U+17C9 before U+17B6 U+17C6 + + +U+17A0 U+17D2 any(shiftable_c_2nd_with_BA) U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) c change U+17BB preceded by HA and coeng shiftable_c_2nd to U+17CA before the above vowel +U+17A0 U+17D2 any(shiftable_c_2nd_with_BA) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(3) context(6) c change U+17BB preceded by HA and coeng shiftable_c_2nd to U+17CA before ាំ +U+17A0 U+17D2 any(shiftable_c_2nd_with_BA) any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) c change U+17BB preceded by HA and coeng shiftable_c_2nd to U+17CA before the above vowel +U+17A0 U+17D2 any(shiftable_c_2nd_with_BA) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) c change U+17BB preceded by HA and coeng shiftable_c_2nd to U+17CA before U+17B6 U+17C6 + +c consonant clusters --2nd > 1st series (with U+17BB) + +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB any(v_above) > context(1) context(2) context(3) U+17C9 context(5) +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(5) context(6) +U+179B U+17D2 any(c_2nd_combo_LO) any(v_above) U+17BB > context(1) context(2) context(3) U+17C9 context(4) +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(6) context(7) + +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB any(v_above) > context(1) context(2) context(3) U+17C9 context(5) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(5) context(6) +U+1798 U+17D2 any(c_2nd_combo_MO) any(v_above) U+17BB > context(1) context(2) context(3) U+17C9 context(4) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(6) context(7) + +c single consonants --1st > 2nd series (with U+17BB) + +any(shiftable_c_1st) U+17BB any(v_above) > context(1) U+17CA context(3) c change U+17BB to U+17CA before the above vowel +any(shiftable_c_1st) U+17BB U+17B6 U+17C6 > context(1) U+17CA context(3) context(4) c change U+17BB to U+17CA before ាំ +any(shiftable_c_1st) any(v_above) U+17BB > context(1) U+17CA context(2) c change U+17BB to U+17CA and place it before the above vowel +any(shiftable_c_1st) U+17BB U+17C6 U+17B6 U+17C6 > context(1) U+17CA context(4) context(5) c change U+17BB U+17C6 to U+17CA + +c single consonants --2nd > 1st series (with U+17BB) + +any(shiftable_c_2nd_with_BA) U+17BB any(v_above) > context(1) U+17C9 context(3) c change U+17BB to U+17C9 before the above vowel +any(shiftable_c_2nd_with_BA) U+17BB U+17B6 U+17C6 > context(1) U+17C9 context(3) context(4) c change U+17BB to U+17C9 before ាំ +any(shiftable_c_2nd_with_BA) any(v_above) U+17BB > context(1) U+17C9 context(2) c change U+17BB to U+17C9 before the above vowel +any(shiftable_c_2nd_with_BA) U+17BB U+17C6 U+17B6 U+17C6 > context(1) U+17C9 context(4) context(5) c change U+17BB U+17C6 to U+17C9 + +c prevent incorrect use of consonant shifter with 2nd series consonant clusters (without U+17BB) + +U+179B U+17D2 any(c_2nd_combo_LO) U+17CA any(v_above) > context(1) context(2) context(3) U+17C9 context(5) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17CA any(v_above) > context(1) context(2) context(3) U+17C9 context(5) +U+179B U+17D2 any(c_2nd_combo_LO) U+17CA any(v_gen) any(v_pseudo) > context(1) context(2) context(3) U+17C9 context(5) context(6) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17CA any(v_gen) any(v_pseudo) > context(1) context(2) context(3) U+17C9 context(5) context(6) + +c single consonants --2nd > 1st series (without U+17BB) + +any(shiftable_c_2nd) U+17CA any(v_above) > context(1) U+17C9 context(3) c change U+17CA to U+17C9 before the above vowel +any(shiftable_c_2nd) U+17CA any(v_gen) any(v_pseudo) > context(1) U+17C9 context(3) context(4) c change U+17CA to U+17C9 before ាំ + +U+17D2 any(shiftable_c_2nd) U+17CA any(v_above) > context c stop ស្រ៊ី from becoming ស្រ៉ី +U+17D2 any(shiftable_c_2nd) U+17CA any(v_gen) any(v_pseudo) > context + +c SPECIAL CASE -- the following clusters may accept either of the two consonant shifters. + +U+1794 U+17D2 U+1799 any(c_shifter) > context +U+179F U+17D2 U+1794 any(c_shifter) > context +U+1786 U+17D2 U+1794 any(c_shifter) > context +U+1794 U+17D2 U+1799 any(c_shifter) > context +U+179F U+17D2 U+1794 any(c_shifter) > context +U+1786 U+17D2 U+1794 any(c_shifter) > context + +c single --1st > 2nd series (without U+17BB) + +any(shiftable_c_1st) U+17C9 any(v_above) > context(1) U+17CA context(3) c change U+17C9 to U+17CA before the above vowel +any(shiftable_c_1st) U+17C9 any(v_gen) any(v_pseudo) > context(1) U+17CA context(3) context(4) c change U+17C9 to U+17CA before ាំ + +c consonant clusters --1st > 2nd series (without U+17BB) + +any(c_combo_QA) U+17D2 U+17A2 U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+179B U+17D2 any(c_1st_combo_LO) U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+1798 U+17D2 any(c_1st_combo_MO) U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+179F U+17D2 U+1794 U+17C9 any(v_above) > context(1) context(2) context(3) U+17C9 context(5) c prevent ស្ប៉ី from transforming to ស្ប៊ី +U+179F U+17D2 any(c_combo_SA) U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +any(c_combo_HA) U+17D2 U+17A0 U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+17A2 U+17D2 U+1784 U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+17A2 U+17D2 U+179C U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +any(c_combo_QA) U+17D2 U+17A2 U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+179B U+17D2 any(c_1st_combo_LO) U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+1798 U+17D2 any(c_1st_combo_MO) U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+179F U+17D2 U+1794 U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(5) context(6) c prevent ស្ប៉ាំ from transforming to ស្ប៊ាំ +U+179F U+17D2 any(c_combo_SA) U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +any(c_combo_HA) U+17D2 U+17A0 U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+17A2 U+17D2 U+1784 U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+17A2 U+17D2 U+179C U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) + +c U+17B6 U+17BB and U+17C6 in that order preceeded by any first series consonant (cluster) are transformed to U+17CA U+17B6 and U+17C6 + +any(shiftable_c_1st) U+17B6 U+17BB U+17C6 > context(1) U+17CA context(2) context(4) +any(shiftable_c_1st) U+17BB U+17C6 U+17B6 > context(1) U+17CA context(4) context(3) + +any(c_combo_QA) U+17D2 U+17A2 U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +any(c_combo_QA) U+17D2 U+17A2 U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+179B U+17D2 any(c_1st_combo_LO) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+179B U+17D2 any(c_1st_combo_LO) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+1798 U+17D2 any(c_1st_combo_MO) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+179F U+17D2 any(c_combo_SA) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+179F U+17D2 any(c_combo_SA) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +any(c_combo_HA) U+17D2 U+17A0 U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +any(c_combo_HA) U+17D2 U+17A0 U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+17A2 U+17D2 U+1784 U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+17A2 U+17D2 U+1784 U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+17A2 U+17D2 U+179C U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+17A2 U+17D2 U+179C U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(4) context(6) + +c U+17B6 U+17BB and U+17C6 in that order preceeded by any second series consonant (cluster) are transformed to U+17C9 U+17B6 and U+17C6 + +any(shiftable_c_2nd_with_BA) U+17B6 U+17BB U+17C6 > context(1) U+17C9 context(2) context(4) +any(shiftable_c_2nd_with_BA) U+17BB U+17C6 U+17B6 > context(1) U+17C9 context(4) context(3) + +U+179B U+17D2 any(c_2nd_combo_LO) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17C9 context(4) context(6) +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17C9 context(6) context(5) + +U+1798 U+17D2 any(c_2nd_combo_MO) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17C9 context(4) context(6) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17C9 context(6) context(5) + +c េុី/ុេី/៉េី > ៊ើ + +any(shiftable_c_1st) U+17C1 U+17BB U+17B8 > context(1) U+17CA U+17BE c cancel out by vowel rotation +any(shiftable_c_1st) U+17BB U+17C1 U+17B8 > context(1) U+17CA U+17BE c cancel out by vowel rotation +any(shiftable_c_1st) U+17C9 U+17C1 U+17B8 > context(1) U+17CA U+17BE + +any(c_combo_QA) U+17D2 U+17A2 U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +any(c_combo_QA) U+17D2 U+17A2 U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +any(c_combo_QA) U+17D2 U+17A2 U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+179B U+17D2 any(c_1st_combo_LO) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+179B U+17D2 any(c_1st_combo_LO) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+179B U+17D2 any(c_1st_combo_LO) U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+1798 U+17D2 any(c_1st_combo_MO) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+1798 U+17D2 any(c_1st_combo_MO) U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+179F U+17D2 any(c_combo_SA) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+179F U+17D2 any(c_combo_SA) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+179F U+17D2 any(c_combo_SA) U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +any(c_combo_HA) U+17D2 U+17A0 U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +any(c_combo_HA) U+17D2 U+17A0 U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +any(c_combo_HA) U+17D2 U+17A0 U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+17A2 U+17D2 U+1784 U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+17A2 U+17D2 U+1784 U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+17A2 U+17D2 U+1784 U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+17A2 U+17D2 U+179C U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+17A2 U+17D2 U+179C U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+17A2 U+17D2 U+179C U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +c េុី/ុេី/៊េី > ៉ើ + +any(shiftable_c_2nd) U+17C1 U+17BB U+17B8 > context(1) U+17C9 U+17BE c cancel out by vowel rotation +any(shiftable_c_2nd) U+17BB U+17C1 U+17B8 > context(1) U+17C9 U+17BE c cancel out by vowel rotation +any(shiftable_c_2nd) U+17CA U+17C1 U+17B8 > context(1) U+17C9 U+17BE + +U+179B U+17D2 any(c_2nd_combo_LO) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE c cancel out by vowel rotation +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE c cancel out by vowel rotation +U+179B U+17D2 any(c_2nd_combo_LO) U+17CA U+17C1 U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE + +U+1798 U+17D2 any(c_2nd_combo_MO) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE c cancel out by vowel rotation +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE c cancel out by vowel rotation +U+1798 U+17D2 any(c_2nd_combo_MO) U+17CA U+17C1 U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE + +c place Robat after a base before any vowel + +any(c_out) any(v_gen) U+17CC > context(1) context(3) context(2) + +c Use appropriate identical subscript in two separate contexts. (Case #8) + +U+178E U+17D2 U+178F > context(1) context(2) U+178A +U+1793 U+17D2 U+178A > context(1) context(2) U+178F + +c BONUSES​(note that these combinations are invalid and they can't be found in the CN dictionary 1967 nor RH 1997, but users think they are) + +U+1791 U+17D2 U+1794 > U+17A1 c ទ្ប transforms to ឡ + +U+1794 U+17D2 U+1789 > U+17AB c ប្ញ transforms to ឫ +U+17AB U+17BB > U+17AC c ឫុ transforms to ឬ + +U+17AD U+17B6 > U+1789 c ឭា transforms to ញ +U+17AE U+17B6 > U+1789 c ឮា transforms to ញ + +U+1796 U+17D2 U+1789 > U+17AD c ព្ញ transforms to ឭ +U+17AD U+17BB > U+17AE c ឭុ transforms to ឮ + +U+1796 U+17D2 U+178B > U+17B0 c ព្ឋ transforms to ឰ + +U+17A7 U+17B7 > U+17B1 c ឧិ transforms to ឱ +U+17A7 U+17CC > U+17B1 c ឧ៌ transforms to ឱ +U+17A7 U+17CD > U+17B1 c ឧ៍ transforms to ឱ + +c U+17D4 U+179B U+17D4 > U+17D8 c ។ល។ transforms to U+17D8 + +U+178A U+17D2 U+1792 > U+178A U+17D2 U+178B c ដ្ធ > ដ្ឋ +U+1791 U+17D2 U+178B > U+1791 U+17D2 U+1792 c ទ្ឋ > ទ្ធ + +c additional rules + +U+1796 U+1793 U+17D2 U+178B > context(1) context(2) context(3) U+1792 c ពន្ឋ > ពន្ធ +U+1796 U+17D0 U+1793 U+17D2 U+178B > context(1) context(2) context(3) context(4) U+1792 c ព័ន្ឋ > ព័ន្ធ + + +U+17AA U+17D2 U+1799 > U+17B1 context(2) context(3) c ឪ្យ > ឱ្យ +U+17B3 U+17D2 U+1799 > U+17B1 context(2) context(3) c ឳ្យ > ឱ្យ + +U+1789 U+17D2 U+179C > U+1796 context(2) context(3) U+17B6 c ញ្វ (as in សញ្វវុធ) > ព្វា as in សញ្វវុធ + +U+17D2 U+1799 U+17C1 U+17BA > U+17BF c េ្យឺ > ឿ +U+17D2 U+1799 U+17C1 U+17B9 > U+17BF c េ្យឹ > ឿ +U+17D2 U+1799 U+17C1 U+17B8 > U+17BF c េ្យី > ឿ + +U+17D2 U+1799 U+17D2 any(c_out) U+17C1 U+17BA > context(3) context(4) U+17BF c គ្រេ្យឺង > គ្រឿង +U+17D2 U+1799 U+17D2 any(c_out) U+17C1 U+17B9 > context(3) context(4) U+17BF c គ្រេ្យឹង > គ្រឿង +U+17D2 U+1799 U+17D2 any(c_out) U+17C1 U+17B8 > context(3) context(4) U+17BF c គ្រេ្យីង > គ្រឿង + +c In everyday practice, both 'regular space' and 'no-break space' are not used before punctuation, i.e. ។ ! etc. +c An annoying issue of having line broken up at the end of the line dropping the punctuation (។, ! and also ៗ) to the next line. +c It may be helpful to include a rule where a 'Zero Width No-Break Space' should be output together with those punct. +c ref: https://www.unicode.org/L2/L2020/20008-core-text.pdf +c ref: https://www.unicode.org/versions/Unicode12.0.0/ch23.pdf#G12985 +c ref: https://www.compart.com/en/unicode/U+FEFF + +c EOF diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kvks b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kvks new file mode 100644 index 00000000000..e9c38a464dd --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kvks @@ -0,0 +1,206 @@ + + +
+ 10.0 + khmer_angkor + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + ] + [ + / + . + + + + & + + * + @ + \ + } + { + - + ÷ + : + , + + ; + < + # + > + × + $ + +   + + + + + + + + + + + + + ᧿ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + « + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ! + + " + + % + + ( + ) + + = + + + ? + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + » + + + +
diff --git a/developer/src/kmc-kmw/test/test-compiler-manual.ts b/developer/src/kmc-kmw/test/test-compiler-manual.ts new file mode 100644 index 00000000000..39869657f44 --- /dev/null +++ b/developer/src/kmc-kmw/test/test-compiler-manual.ts @@ -0,0 +1,55 @@ +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import fs from 'fs'; +import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; +import { KmnCompiler } from '@keymanapp/kmc-kmn'; +import { KMX, KmxFileReader } from '@keymanapp/common-types'; +import { WriteCompiledKeyboard } from '../src/compiler/write-compiled-keyboard.js'; +import { extractTouchLayout } from './util.js'; + +const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/'); +const fixturesDir = __dirname + '/../../test/fixtures/'; +const fixtureName = fixturesDir + 'khmer_angkor.js'; +const infile = fixturesDir + 'khmer_angkor.kmn'; +const outfile = fixturesDir + 'khmer_angkor.kmx'; // intermediate outfile +const testOutfile = fixturesDir + 'khmer_angkor.test.js'; + +if(fs.existsSync(testOutfile)) { + fs.unlinkSync(testOutfile); +} + +const callbacks = new TestCompilerCallbacks(); + +const kmnCompiler = new KmnCompiler(); +if(!await kmnCompiler.init(callbacks)) { + console.error('kmx compiler failed to init'); + process.exit(1); +} + +// TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, etc) +if(!kmnCompiler.run(infile, outfile, { + shouldAddCompilerVersion: false, + saveDebug: true, + target: 'js' +})) { + callbacks.printMessages(); + process.exit(1); +} + +const reader = new KmxFileReader(); +const keyboard: KMX.KEYBOARD = reader.read(callbacks.loadFile(outfile)); + +const js = WriteCompiledKeyboard(callbacks, infile, outfile, 'khmer_angkor', keyboard, true); + +callbacks.printMessages(); + +const fjs = fs.readFileSync(fixtureName, 'utf8'); + +const expected = extractTouchLayout(fjs); +const actual = extractTouchLayout(js); + +if(expected.js !== actual.js) { + fs.writeFileSync(testOutfile, js); + console.error('JS not equal'); + process.exit(1); +} diff --git a/developer/src/kmc-kmw/test/test-compiler.ts b/developer/src/kmc-kmw/test/test-compiler.ts new file mode 100644 index 00000000000..7f086ca0ad3 --- /dev/null +++ b/developer/src/kmc-kmw/test/test-compiler.ts @@ -0,0 +1,65 @@ +import 'mocha'; +import { assert } from 'chai'; +// import sinonChai from 'sinon-chai'; +import { WriteCompiledKeyboard } from '../src/compiler/write-compiled-keyboard.js'; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import fs from 'fs'; +import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; +import { KmnCompiler } from '@keymanapp/kmc-kmn'; +import { KMX, KmxFileReader } from '@keymanapp/common-types'; +import { extractTouchLayout } from './util.js'; + +const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/'); +const fixturesDir = __dirname + '/../../test/fixtures/'; +//const baselineDir = __dirname + '/../../../../../common/test/keyboards/baseline/'; +// chai.use(sinonChai); + +describe('Compiler class', function() { + const callbacks = new TestCompilerCallbacks(); + + this.afterEach(function() { + callbacks.printMessages(); + callbacks.clear(); + }); + + it('should compile a basic keyboard', async function() { + // const compiler = new KeymanWebCompiler(callbacks, {addCompilerVersion: false, debug: true}); + + const fixtureName = fixturesDir + 'khmer_angkor.js'; + const infile = fixturesDir + 'khmer_angkor.kmn'; + const outfile = fixturesDir + 'khmer_angkor.kmx'; // intermediate outfile + const testOutfile = fixturesDir + 'khmer_angkor.test.js'; + + if(fs.existsSync(testOutfile)) { + fs.unlinkSync(testOutfile); + } + + const kmnCompiler = new KmnCompiler(); + assert.isTrue(await kmnCompiler.init(callbacks)); + + // TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, visual keyboard source filename, etc) + assert.isTrue(kmnCompiler.run(infile, outfile, { + shouldAddCompilerVersion: false, + saveDebug: true, + target: 'js' + })); + + const reader = new KmxFileReader(); + const keyboard: KMX.KEYBOARD = reader.read(callbacks.loadFile(outfile)); + + const js = WriteCompiledKeyboard(callbacks, infile, outfile, 'khmer_angkor', keyboard, true); + + const fjs = fs.readFileSync(fixtureName, 'utf8'); + + const expected = extractTouchLayout(fjs); + const actual = extractTouchLayout(js); + + fs.writeFileSync(testOutfile + '.strip.js', actual.js); + fs.writeFileSync(fixtureName + '.strip.js', expected.js); + fs.writeFileSync(testOutfile, js); + + assert.deepEqual(actual.js, expected.js); + assert.deepEqual(JSON.parse(actual.touchLayout), JSON.parse(expected.touchLayout)); + }); +}); \ No newline at end of file diff --git a/developer/src/kmc-kmw/test/tsconfig.json b/developer/src/kmc-kmw/test/tsconfig.json new file mode 100644 index 00000000000..3159c14bfd6 --- /dev/null +++ b/developer/src/kmc-kmw/test/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../kmc/tsconfig.kmc-base.json", + + "compilerOptions": { + "rootDir": ".", + "rootDirs": ["./", "../src/"], + "outDir": "../build/test", + "baseUrl": ".", + "allowSyntheticDefaultImports": true, // for chai + "paths": { + "@keymanapp/common-types": ["../../../../common/web/types/src/main"], + "@keymanapp/developer-test-helpers": ["../../common/web/test-helpers/index"], + "@keymanapp/kmc-kmn": ["../../kmc-kmn/src/main"], + }, + }, + "include": [ + "**/test-*.ts", + "util.ts" + ], + "references": [ + { "path": "../../../../common/web/types/" }, + { "path": "../../kmc-kmn/" }, + { "path": "../../common/web/test-helpers/" }, + { "path": "../" } + ] +} \ No newline at end of file diff --git a/developer/src/kmc-kmw/test/util.ts b/developer/src/kmc-kmw/test/util.ts new file mode 100644 index 00000000000..f63e8dd26e7 --- /dev/null +++ b/developer/src/kmc-kmw/test/util.ts @@ -0,0 +1,19 @@ + +interface ETLResult { + js: string; + touchLayout: string; +} + +export function extractTouchLayout(js: string): ETLResult|null { + let m = /KVKL=(?.+?);[\r\n]/ds.exec(js); + if(!m) { + return null; + } + + let kvkl = (m).indices.groups.kvkl; + + return { + js: js.substring(0, kvkl[0]) + 'null' + js.substring(kvkl[1]), + touchLayout: m.groups?.['kvkl'] ?? '' + }; +} diff --git a/developer/src/kmc-kmw/tsconfig.json b/developer/src/kmc-kmw/tsconfig.json new file mode 100644 index 00000000000..4fabe4a39da --- /dev/null +++ b/developer/src/kmc-kmw/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.esm-base.json", + + "compilerOptions": { + "outDir": "build/src/", + "rootDir": "src/", + "baseUrl": ".", + "paths": { + "@keymanapp/common-types": ["../../../common/web/types/src/main"], + "@keymanapp/kmc-kmn": ["../kmc-kmn/src/main"], + }, + + }, + "include": [ + "src/**/*.ts" + ], + "references": [ + { "path": "../../../common/web/types/" }, + { "path": "../kmc-kmn/" }, + { "path": "../../../core/include/ldml/"}, + ] +} diff --git a/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js b/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js index 177d55963ee..48317a457ad 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js +++ b/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js @@ -1 +1 @@ -if(typeof keyman === 'undefined') {console.error('Keyboard requires KeymanWeb 16.0 or later');} else {KeymanWeb.KR(new Keyboard_basic());}function Keyboard_basic() {this.KI="Keyboard_basic";this.KN={"value":"TestKbd"};this.KMINVER="16.0";this.KV={F: '10pt "Arial"', K102: 0};this.KV.KLS={TODO_LDML: 2};this.KDU=1;this.KH="";this.KM=0;this.KBVER="1.0.0";this.KMBM=0;this.KVKL={"desktop":{"defaultHint":"none","layer":[{"id":"base","row":[{"id":0,"key":[{"id":"T_hmaqtugha","text":"ħ"},{"id":"T_that","text":"ថា"}]}]}]}};this.gs=function(t,e){return 0;};} \ No newline at end of file +if(typeof keyman === 'undefined') {console.error('Keyboard requires KeymanWeb 16.0 or later');} else {KeymanWeb.KR(new Keyboard_basic());}function Keyboard_basic() {this.KI="Keyboard_basic";this.KN={"value":"TestKbd"};this.KMINVER="16.0";this.KV={F: '10pt "Arial"', K102: 0};this.KV.KLS={TODO_LDML: 2};this.KDU=1;this.KH="";this.KM=0;this.KBVER="1.0.0";this.KMBM=0;this.KVKL={"desktop":{"defaultHint":"none","layer":[{"id":"base","row":[{"id":"0","key":[{"id":"T_hmaqtugha","text":"ħ"},{"id":"T_that","text":"ថា"}]}]}]}};this.gs=function(t,e){return 0;};} \ No newline at end of file diff --git a/developer/src/kmc-ldml/test/fixtures/basic.js b/developer/src/kmc-ldml/test/fixtures/basic.js index 59a1902ee67..179fa0dc063 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic.js +++ b/developer/src/kmc-ldml/test/fixtures/basic.js @@ -24,7 +24,7 @@ function Keyboard_basic() { "id": "base", "row": [ { - "id": 0, + "id": "0", "key": [ { "id": "T_hmaqtugha", diff --git a/developer/src/kmc/build.sh b/developer/src/kmc/build.sh index 61ccd3bdca7..6b62da5ae90 100755 --- a/developer/src/kmc/build.sh +++ b/developer/src/kmc/build.sh @@ -21,6 +21,7 @@ builder_describe "Build Keyman Keyboard Compiler kmc" \ "@/common/web/keyman-version" \ "@/common/web/types" \ "@/developer/src/kmc-kmn" \ + "@/developer/src/kmc-kmw" \ "@/developer/src/kmc-ldml" \ "@/developer/src/kmc-model" \ "@/developer/src/kmc-model-info" \ @@ -113,6 +114,7 @@ readonly PACKAGES=( common/models/types core/include/ldml developer/src/kmc-kmn + developer/src/kmc-kmw developer/src/kmc-ldml developer/src/kmc-model developer/src/kmc-model-info diff --git a/developer/src/kmc/package.json b/developer/src/kmc/package.json index 695ebc96e35..0c9c2cece2b 100644 --- a/developer/src/kmc/package.json +++ b/developer/src/kmc/package.json @@ -40,6 +40,7 @@ "@keymanapp/keyman-version": "*", "@keymanapp/common-types": "*", "@keymanapp/kmc-kmn": "*", + "@keymanapp/kmc-kmw": "*", "@keymanapp/kmc-ldml": "*", "@keymanapp/kmc-model": "*", "@keymanapp/kmc-model-info": "*", diff --git a/developer/src/kmc/tsconfig.json b/developer/src/kmc/tsconfig.json index 9b6eb601acd..777d73e648a 100644 --- a/developer/src/kmc/tsconfig.json +++ b/developer/src/kmc/tsconfig.json @@ -8,6 +8,7 @@ "paths": { "@keymanapp/common-types": [ "../../../common/web/types/src/main" ], "@keymanapp/kmc-kmn": [ "../kmc-kmn/src/main" ], + "@keymanapp/kmc-kmw": [ "../kmc-kmw/src/main" ], "@keymanapp/kmc-ldml": [ "../kmc-ldml/src/main" ], "@keymanapp/kmc-model": [ "../kmc-model/src/main" ], "@keymanapp/kmc-model-info": [ "../kmc-model-info/src/model-info-compiler" ], @@ -21,6 +22,7 @@ { "path": "../../../common/web/keyman-version/tsconfig.esm.json" }, { "path": "../../../common/web/types" }, { "path": "../kmc-kmn" }, + { "path": "../kmc-kmw" }, { "path": "../kmc-ldml" }, { "path": "../kmc-model" }, { "path": "../kmc-model-info" }, diff --git a/package-lock.json b/package-lock.json index 75d9e1abef1..fbd15530d66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "core/include/ldml", "developer/src/common/web/test-helpers", "developer/src/kmc-kmn", + "developer/src/kmc-kmw", "developer/src/kmc-ldml", "developer/src/kmc-model", "developer/src/kmc-model-info", @@ -635,6 +636,7 @@ "@keymanapp/common-types": "*", "@keymanapp/keyman-version": "*", "@keymanapp/kmc-kmn": "*", + "@keymanapp/kmc-kmw": "*", "@keymanapp/kmc-ldml": "*", "@keymanapp/kmc-model": "*", "@keymanapp/kmc-model-info": "*", @@ -1029,6 +1031,261 @@ "node": ">=0.3.1" } }, + "developer/src/kmc-kmw": { + "name": "@keymanapp/kmc-kmw", + "license": "MIT", + "dependencies": { + "@keymanapp/common-types": "*", + "@keymanapp/kmc-kmn": "*", + "ajv": "^8.11.0", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "semver": "^7.3.7", + "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" + }, + "devDependencies": { + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.7", + "@types/node": "^10.14.6", + "@types/semver": "^7.3.12", + "@types/xml2js": "^0.4.5", + "c8": "^7.12.0", + "chai": "^4.3.4", + "chalk": "^2.4.2", + "mocha": "^8.4.0", + "ts-node": "^9.1.1", + "typescript": "^4.9.5" + } + }, + "developer/src/kmc-kmw/node_modules/@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "developer/src/kmc-kmw/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "dev": true + }, + "developer/src/kmc-kmw/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "developer/src/kmc-kmw/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "developer/src/kmc-kmw/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "developer/src/kmc-kmw/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "developer/src/kmc-kmw/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "developer/src/kmc-kmw/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "developer/src/kmc-kmw/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "developer/src/kmc-kmw/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "developer/src/kmc-kmw/node_modules/mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "developer/src/kmc-kmw/node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "developer/src/kmc-kmw/node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "developer/src/kmc-kmw/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "developer/src/kmc-kmw/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "developer/src/kmc-kmw/node_modules/supports-color/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "developer/src/kmc-kmw/node_modules/ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "dev": true, + "dependencies": { + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "developer/src/kmc-kmw/node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "developer/src/kmc-ldml": { "name": "@keymanapp/kmc-ldml", "license": "MIT", @@ -2322,6 +2579,10 @@ "resolved": "developer/src/kmc-kmn", "link": true }, + "node_modules/@keymanapp/kmc-kmw": { + "resolved": "developer/src/kmc-kmw", + "link": true + }, "node_modules/@keymanapp/kmc-ldml": { "resolved": "developer/src/kmc-ldml", "link": true diff --git a/package.json b/package.json index 7a2b53d50d5..9b62b5a3413 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "core/include/ldml", "developer/src/common/web/test-helpers", "developer/src/kmc-kmn", + "developer/src/kmc-kmw", "developer/src/kmc-ldml", "developer/src/kmc-model", "developer/src/kmc-model-info", diff --git a/tsconfig.esm.json b/tsconfig.esm.json index 44bf4011df9..63001931f1a 100644 --- a/tsconfig.esm.json +++ b/tsconfig.esm.json @@ -8,10 +8,14 @@ { "path": "./core/include/ldml/tsconfig.json" }, //{ "path": "./developer/src/kmc/test/tsconfig.json" }, + { "path": "./developer/src/common/web/test-helpers/tsconfig.json" }, + { "path": "./developer/src/kmc/tsconfig.json" }, { "path": "./developer/src/kmc-kmn/test/tsconfig.json" }, { "path": "./developer/src/kmc-kmn/tsconfig.json" }, + { "path": "./developer/src/kmc-kmw/test/tsconfig.json" }, + { "path": "./developer/src/kmc-kmw/tsconfig.json" }, { "path": "./developer/src/kmc-ldml/test/tsconfig.json" }, { "path": "./developer/src/kmc-ldml/tsconfig.json" }, { "path": "./developer/src/kmc-model/test/tsconfig.json" },