diff --git a/HISTORY.md b/HISTORY.md index 56e8f96c954..e22d0e994b0 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,30 @@ # Keyman Version History +## 17.0.186 alpha 2023-10-04 + +* feat(developer): show an INFO message when warnings have failed a build (#9652) +* chore(developer): reduce duplicate words warning to hint (#9653) +* feat(developer): issue hint if package includes keyboard source files (#9658) +* chore(developer): switch on code coverage reporting for kmc (#9662) +* fix(core): clean cached ICU in core (#9668) +* feat(developer): warn if .kps includes a .js which is not touch-capable (#9667) + +## 17.0.185 alpha 2023-10-03 + +* chore(web): Add non-printing characters to the OSK (#9547) +* feat(developer): support `store(&version) '17.0'` (#9656) +* chore(developer): add test for `checkFilenameConventions == false` or unset (#9661) +* feat(developer): ldml scan codes support (#9615) + +## 17.0.184 alpha 2023-10-02 + +* fix(web): fixes toolbar refocus timing after a keyboard change (#9618) + +## 17.0.183 alpha 2023-09-29 + +* feat(web): browser-KMW support for default subkeys (#9496) +* refactor(linux): Add more tests for `keymanutil.c` ️ (#9595) + ## 17.0.182 alpha 2023-09-28 * chore(web): builds that output to web/build/publish should also clean it (#9613) diff --git a/VERSION.md b/VERSION.md index 8bf382e6d5e..8eb52f8484b 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.183 \ No newline at end of file +17.0.187 \ No newline at end of file diff --git a/android/Tests/KeyboardHarness/app/src/main/assets/keyboardharness.kmp b/android/Tests/KeyboardHarness/app/src/main/assets/keyboardharness.kmp index 3a8f1cb624c..30a4f87663b 100644 Binary files a/android/Tests/KeyboardHarness/app/src/main/assets/keyboardharness.kmp and b/android/Tests/KeyboardHarness/app/src/main/assets/keyboardharness.kmp differ diff --git a/android/Tests/KeyboardHarness/app/src/main/assets/test9469.kmp b/android/Tests/KeyboardHarness/app/src/main/assets/test9469.kmp index 100cc1d70b6..8390d5dee31 100644 Binary files a/android/Tests/KeyboardHarness/app/src/main/assets/test9469.kmp and b/android/Tests/KeyboardHarness/app/src/main/assets/test9469.kmp differ diff --git a/android/Tests/KeyboardHarness/readme.md b/android/Tests/KeyboardHarness/readme.md index 1e00343bf55..898d9926382 100644 --- a/android/Tests/KeyboardHarness/readme.md +++ b/android/Tests/KeyboardHarness/readme.md @@ -10,6 +10,8 @@ and consists of these engineering keyboards: * web/testing/chirality/chirality.js * web/testing/platform/platformtest.js +test9469.kmp is another engineering keyboard to show non-printing characters on the OSK. + ### Compiling From Command Line 1. Launch a command prompt to the `android/` folder 2. Compile KMEA. This will build and copy `keyman-engine.aar` to the Samples and Test projects diff --git a/common/include/km_types.h b/common/include/km_types.h index d81f2672384..aa7fb2e5182 100644 --- a/common/include/km_types.h +++ b/common/include/km_types.h @@ -28,14 +28,14 @@ typedef uint8_t KMX_BYTE; typedef uint16_t KMX_WORD; #if defined(__cplusplus) -typedef char16_t km_kbp_cp; -typedef char32_t km_kbp_usv; +typedef char16_t km_core_cp; +typedef char32_t km_core_usv; #else -typedef uint16_t km_kbp_cp; // code point -typedef uint32_t km_kbp_usv; // Unicode Scalar Value +typedef uint16_t km_core_cp; // code point +typedef uint32_t km_core_usv; // Unicode Scalar Value #endif -typedef km_kbp_cp KMX_WCHAR; // wc, 16-bit UNICODE character +typedef km_core_cp KMX_WCHAR; // wc, 16-bit UNICODE character typedef KMX_WCHAR* PKMX_WCHAR; typedef char KMX_CHAR; @@ -60,7 +60,7 @@ typedef KMX_DWORD* PKMX_DWORD; #ifdef USE_CHAR16_T #define lpuch(x) u ## x -typedef km_kbp_cp KMX_UCHAR; +typedef km_core_cp KMX_UCHAR; #else #define lpuch(x) L ## x typedef wchar_t KMX_UCHAR; diff --git a/common/include/kmx_file.h b/common/include/kmx_file.h index b689ba685ad..243e5e0d638 100644 --- a/common/include/kmx_file.h +++ b/common/include/kmx_file.h @@ -68,9 +68,10 @@ namespace kmx { #define VERSION_150 0x00000F00 #define VERSION_160 0x00001000 +#define VERSION_170 0x00001100 #define VERSION_MIN VERSION_50 -#define VERSION_MAX VERSION_160 +#define VERSION_MAX VERSION_170 // // Backspace types diff --git a/common/include/test_assert.h b/common/include/test_assert.h index 655074ba8b2..8cc0f3b624d 100644 --- a/common/include/test_assert.h +++ b/common/include/test_assert.h @@ -30,7 +30,7 @@ #endif #define try_status(expr) { \ auto __s = (expr); \ - if (__s != KM_KBP_STATUS_OK) { \ + if (__s != KM_CORE_STATUS_OK) { \ _assert_failed(__s, u ## #expr); \ } \ } diff --git a/common/models/templates/package.json b/common/models/templates/package.json index 0bec0fc88fa..33f89cca706 100644 --- a/common/models/templates/package.json +++ b/common/models/templates/package.json @@ -21,9 +21,7 @@ "exports": { ".": "./build/obj/index.js", "./lib": { - "types": "./build/lib/index.d.ts", - "import": "./build/lib/index.mjs", - "require": "./build/lib/index.cjs" + "types": "./build/lib/index.d.ts" }, "./obj/*.js": "./build/obj/*.js" }, diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index bd8d0157fbd..7a03dc9e8fb 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -19,8 +19,7 @@ "exports": { ".": "./build/obj/index.js", "./lib": { - "import": "./build/lib/index.mjs", - "require": "./build/lib/index.cjs" + "types": "./build/lib/index.d.ts" }, "./obj/*.js": "./build/obj/*.js" }, diff --git a/common/predictive-text/testing/index.html b/common/predictive-text/testing/index.html deleted file mode 100644 index 8a00094b701..00000000000 --- a/common/predictive-text/testing/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - LMLayer Testing - - - -

Language-Modeling Layer module testing

-

A simple basic WebWorker.

Designed as a baseline functionality test we can run against various platforms as a first-stage canary of sorts. -

An embedded WebWorker prototype.

A prototype for directly embedding a WebWorker's code within a "master" script. -

A better embedded WebWorker prototype.

A prototype for two-stage compilation of a master/slave main-script/WebWorker pair. -

Sending code via a Blob URI

A prototype for sending code over to a WebWorker via a Blob URI reference. - - diff --git a/common/predictive-text/testing/one-stage-embedded-webworker/.gitignore b/common/predictive-text/testing/one-stage-embedded-webworker/.gitignore deleted file mode 100644 index df6361deda9..00000000000 --- a/common/predictive-text/testing/one-stage-embedded-webworker/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -main.js -main.js.map \ No newline at end of file diff --git a/common/predictive-text/testing/one-stage-embedded-webworker/build.sh b/common/predictive-text/testing/one-stage-embedded-webworker/build.sh deleted file mode 100755 index f1f727b8c03..00000000000 --- a/common/predictive-text/testing/one-stage-embedded-webworker/build.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env bash -# -# Compiles the Language Modeling Layer for common use in predictive text and autocorrective applications. -# Designed for optimal compatibility with the Keyman Suite. -# - -## START STANDARD BUILD SCRIPT INCLUDE -# adjust relative paths as necessary -THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../../resources/build/build-utils.sh" -. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" -## END STANDARD BUILD SCRIPT INCLUDE - -display_usage ( ) { - echo "build.sh [-clean]" - echo - echo " -clean to erase pre-existing build products before a re-build" -} - -SOURCE="testing/one-stage-embedded-webworker" - -echo "Node.js + dependencies check" -npm install --no-optional - -if [ $? -ne 0 ]; then - builder_die "Build environment setup error detected! Please ensure Node.js is installed!" -fi - -# A nice, extensible method for -clean operations. Add to this as necessary. -clean ( ) { - rm -rf "./*.js" - if [ $? -ne 0 ]; then - builder_die "Failed to erase the prior build." - fi -} - -# Process command-line arguments -while [[ $# -gt 0 ]] ; do - key="$1" - case $key in - -clean) - clean - ;; - esac - shift # past the processed argument -done - -npm run tsc -- -p $SOURCE/tsconfig.json - -if [ $? -ne 0 ]; then - builder_die "Compilation failed." -fi - -echo "Typescript compilation successful." \ No newline at end of file diff --git a/common/predictive-text/testing/one-stage-embedded-webworker/index.html b/common/predictive-text/testing/one-stage-embedded-webworker/index.html deleted file mode 100644 index 244f4aa2833..00000000000 --- a/common/predictive-text/testing/one-stage-embedded-webworker/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - Embedded WebWorker test - - - - - - - - - -

LM Layer Testing - One-Stage Embedded WebWorkers

-

This page serves as a prototype for embedding a WebWorker's code within its "master" script - across the TypeScript transpilation boundary.

-
- - - -

Return to testing home page

- - diff --git a/common/predictive-text/testing/one-stage-embedded-webworker/main.ts b/common/predictive-text/testing/one-stage-embedded-webworker/main.ts deleted file mode 100644 index 5d15ae88b58..00000000000 --- a/common/predictive-text/testing/one-stage-embedded-webworker/main.ts +++ /dev/null @@ -1,52 +0,0 @@ -// Useful for passing class constructors -type Workable = { - new (...args: any[]): T; - // Requires a static implementation. - onmessage(e: any): void; -}; - -class A { - a(x: number, y: number):number { - return x + y; - } -} - -var WorkerGlobals = { - counter: 0, - a: A -} - -class WorkerCore { - static WorkerGlobals = WorkerGlobals; - //static counter: number; - - static onmessage(e: any) { - WorkerGlobals.counter++; - - console.log("Message received from main page: ", e.data); - - // Forces TypeScript to interpret this line as plain JavaScript, as it uses a non-Worker definition. - // @ts-ignore - postMessage(WorkerGlobals.counter); - } -} - -function createWorkerFromClasses(globals: object, fn: Workable): Worker { - var sep = ";\n"; - let glb = "var WorkerGlobals = " + JSON.stringify(globals); - let wc = "var onmessage = " + fn.onmessage.toString(); - var blob = new Blob([glb, sep, wc], { type: 'text/javascript' }); - let url = URL.createObjectURL(blob); - - return new Worker(url); -} - -var canaryWorker = createWorkerFromClasses(WorkerGlobals, WorkerCore); - -canaryWorker.onmessage = function(e) { - var counter = e.data; // Number of times the WebWorker has been messaged. - console.log("Received message from the WebWorker: " + e.data); - - var txtFeedback = document.getElementById("txtFeedback"); - txtFeedback.value = counter + " click(s)"; -} diff --git a/common/predictive-text/testing/one-stage-embedded-webworker/tsconfig.json b/common/predictive-text/testing/one-stage-embedded-webworker/tsconfig.json deleted file mode 100644 index f1e9be86003..00000000000 --- a/common/predictive-text/testing/one-stage-embedded-webworker/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "allowJs": false, - "module": "none", - "outDir": "./", - "inlineSources": true, - "sourceMap": true, - "target": "es5" - }, - "files" : [ - "main.ts" - ] -} diff --git a/common/predictive-text/testing/post-blob-webworker/canaryWorker.js b/common/predictive-text/testing/post-blob-webworker/canaryWorker.js deleted file mode 100644 index 5c69deace8e..00000000000 --- a/common/predictive-text/testing/post-blob-webworker/canaryWorker.js +++ /dev/null @@ -1,5 +0,0 @@ -// receive a message and execute its uri -onmessage = function (e) { - let uri = e.data.uri; - importScripts(uri); -}; diff --git a/common/predictive-text/testing/post-blob-webworker/index.html b/common/predictive-text/testing/post-blob-webworker/index.html deleted file mode 100644 index a04b6be377b..00000000000 --- a/common/predictive-text/testing/post-blob-webworker/index.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - Blob URI test - - - - - - - - - -

LM Layer Testing - Sending a function to a WebWorker via a Blob URI test

-

This page sends a function over to the Worker via a Blob URI, and - expects the function to reply back. -

-
- - - -

Return to testing home page

- - diff --git a/common/predictive-text/testing/simple-webworker/canaryWorker.js b/common/predictive-text/testing/simple-webworker/canaryWorker.js deleted file mode 100644 index cf8674d3304..00000000000 --- a/common/predictive-text/testing/simple-webworker/canaryWorker.js +++ /dev/null @@ -1,9 +0,0 @@ -var counter = 0; - -onmessage = function(e) { - counter++; - - console.log("Message received from main page: ", e.data); - - postMessage(counter); -} \ No newline at end of file diff --git a/common/predictive-text/testing/simple-webworker/index.html b/common/predictive-text/testing/simple-webworker/index.html deleted file mode 100644 index adbcd30d3e6..00000000000 --- a/common/predictive-text/testing/simple-webworker/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - Basic WebWorker test - - - - - - - - - -

LM Layer Testing - basic WebWorker canary

-

This page uses a simple WebWorker useful for ensuring functionality on various platforms.

-
- - - -

Return to testing home page

- - diff --git a/common/predictive-text/testing/two-stage-embedded-webworker/.gitignore b/common/predictive-text/testing/two-stage-embedded-webworker/.gitignore deleted file mode 100644 index 20efd1ec834..00000000000 --- a/common/predictive-text/testing/two-stage-embedded-webworker/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -**/*.js -**/*.js.map \ No newline at end of file diff --git a/common/predictive-text/testing/two-stage-embedded-webworker/build.sh b/common/predictive-text/testing/two-stage-embedded-webworker/build.sh deleted file mode 100755 index dd1854ec00b..00000000000 --- a/common/predictive-text/testing/two-stage-embedded-webworker/build.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env bash -# -# Compiles the Language Modeling Layer for common use in predictive text and autocorrective applications. -# Designed for optimal compatibility with the Keyman Suite. -# - -## START STANDARD BUILD SCRIPT INCLUDE -# adjust relative paths as necessary -THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../../resources/build/build-utils.sh" -. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" -## END STANDARD BUILD SCRIPT INCLUDE - -display_usage ( ) { - echo "build.sh [-clean]" - echo - echo " -clean to erase pre-existing build products before a re-build" -} - -SOURCE="testing/two-stage-embedded-webworker" - -COMPILED_WORKER="worker.js" -EMBEDDED_WORKER="embedded_worker.js" - -echo "Node.js + dependencies check" -npm install --no-optional - -if [ $? -ne 0 ]; then - builder_die "Build environment setup error detected! Please ensure Node.js is installed!" -fi - -# A nice, extensible method for -clean operations. Add to this as necessary. -clean ( ) { - rm -rf "./*.js" - if [ $? -ne 0 ]; then - builder_die "Failed to erase the prior build." - fi -} - -# Process command-line arguments -while [[ $# -gt 0 ]] ; do - key="$1" - case $key in - -clean) - clean - ;; - esac - shift # past the processed argument -done - -npm run tsc -- -p $SOURCE/worker/tsconfig.json -if [ $? -ne 0 ]; then - builder_die "Worker compilation failed." -fi - -rm $EMBEDDED_WORKER &> /dev/null - -echo "var LMLayerWorker = function() {" >> $EMBEDDED_WORKER -cat $COMPILED_WORKER >> $EMBEDDED_WORKER -echo "" >> $EMBEDDED_WORKER -echo "}" >> $EMBEDDED_WORKER - -npm run tsc -- -p $SOURCE/tsconfig.json -if [ $? -ne 0 ]; then - builder_die "Final compilation failed." -fi - -echo "Typescript compilation successful." \ No newline at end of file diff --git a/common/predictive-text/testing/two-stage-embedded-webworker/index.html b/common/predictive-text/testing/two-stage-embedded-webworker/index.html deleted file mode 100644 index 244f4aa2833..00000000000 --- a/common/predictive-text/testing/two-stage-embedded-webworker/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - Embedded WebWorker test - - - - - - - - - -

LM Layer Testing - One-Stage Embedded WebWorkers

-

This page serves as a prototype for embedding a WebWorker's code within its "master" script - across the TypeScript transpilation boundary.

-
- - - -

Return to testing home page

- - diff --git a/common/predictive-text/testing/two-stage-embedded-webworker/main.ts b/common/predictive-text/testing/two-stage-embedded-webworker/main.ts deleted file mode 100644 index 9eb276d3794..00000000000 --- a/common/predictive-text/testing/two-stage-embedded-webworker/main.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Provides the final source for our compiled WebWorker within a wrapping function. -/// - -function createWorker(fn: Function): Worker { - var str_fn = fn.toString(); - - // We now unwrap our WebWorker from its function. - var str_lines = str_fn.split("\n"); - var blob_lines = [] - - for(var i=1; i < str_lines.length -1; i++) { - blob_lines.push(str_lines[i] + "\n"); - } - // Unwrapping complete. - - var blob = new Blob(blob_lines, { type: 'text/javascript' }); - let url = URL.createObjectURL(blob); - - return new Worker(url); -} - -var canaryWorker = createWorker(LMLayerWorker); - -canaryWorker.onmessage = function(e) { - var counter = e.data; // Number of times the WebWorker has been messaged. - console.log("Received message from the WebWorker: " + e.data); - - var txtFeedback = document.getElementById("txtFeedback"); - txtFeedback.value = counter + " click(s)"; -} diff --git a/common/predictive-text/testing/two-stage-embedded-webworker/tsconfig.json b/common/predictive-text/testing/two-stage-embedded-webworker/tsconfig.json deleted file mode 100644 index a25930a70e6..00000000000 --- a/common/predictive-text/testing/two-stage-embedded-webworker/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "module": "none", - "outFile": "./main.js", - "inlineSources": true, - "inlineSourceMap": true, - "target": "es5" - }, - "files" : [ - "main.ts" - ] -} diff --git a/common/predictive-text/testing/two-stage-embedded-webworker/worker/canaryWorker.ts b/common/predictive-text/testing/two-stage-embedded-webworker/worker/canaryWorker.ts deleted file mode 100644 index cf8674d3304..00000000000 --- a/common/predictive-text/testing/two-stage-embedded-webworker/worker/canaryWorker.ts +++ /dev/null @@ -1,9 +0,0 @@ -var counter = 0; - -onmessage = function(e) { - counter++; - - console.log("Message received from main page: ", e.data); - - postMessage(counter); -} \ No newline at end of file diff --git a/common/predictive-text/testing/two-stage-embedded-webworker/worker/tsconfig.json b/common/predictive-text/testing/two-stage-embedded-webworker/worker/tsconfig.json deleted file mode 100644 index ca8006ba440..00000000000 --- a/common/predictive-text/testing/two-stage-embedded-webworker/worker/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "allowJs": false, - "module": "none", - "outFile": "../worker.js", - "inlineSources": true, - "sourceMap": true, - "lib": ["webworker", "es6"], - "target": "es5" - } -} diff --git a/common/tools/hextobin/build.sh b/common/tools/hextobin/build.sh index 702e6610f01..8df4f9b83a3 100755 --- a/common/tools/hextobin/build.sh +++ b/common/tools/hextobin/build.sh @@ -1,11 +1,4 @@ #!/usr/bin/env bash -# -# Builds hextobin.js -# - -# Exit on command failure and when using unset variables: -set -eu - ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" @@ -22,21 +15,10 @@ cd "$THIS_SCRIPT_PATH" builder_describe "Build hextobin" clean configure build builder_describe_outputs \ configure /node_modules \ - build build/index.js -builder_parse "$@" + build /common/tools/hextobin/build/index.js -if builder_start_action clean; then - npm run clean - builder_finish_action success clean -fi - -if builder_start_action configure; then - verify_npm_setup - builder_finish_action success configure -fi - -if builder_start_action build; then - npm run build - builder_finish_action success build -fi +builder_parse "$@" +builder_run_action clean rm -rf build/ node_modules/ +builder_run_action configure verify_npm_setup +builder_run_action build tsc --build diff --git a/common/tools/hextobin/hextobin.ts b/common/tools/hextobin/hextobin.ts index 503b18d4b1a..6bf56c79533 100644 --- a/common/tools/hextobin/hextobin.ts +++ b/common/tools/hextobin/hextobin.ts @@ -1,11 +1,11 @@ #!/usr/bin/env node -import * as fs from 'fs'; -import * as rd from 'readline'; -import * as program from 'commander'; +import { Command } from 'commander'; +import hextobin from './index.js'; let inputFilename: string = ""; let outputFilename: string = ""; +const program = new Command(); program .description( `Will convert the input file which is a hex dump to the output file. Hex dump can contain @@ -43,6 +43,4 @@ function exitDueToUsageError(message: string): never { return process.exit(64); // SysExits.EX_USAGE } -import hextobin from './index'; - hextobin(inputFilename, outputFilename, {silent: false}); diff --git a/common/tools/hextobin/package.json b/common/tools/hextobin/package.json index 155f8297597..2ebb0e9f4e1 100644 --- a/common/tools/hextobin/package.json +++ b/common/tools/hextobin/package.json @@ -1,6 +1,8 @@ { "name": "@keymanapp/hextobin", "description": "hextobin conversion tool", + "type": "module", + "private": true, "keywords": [ "keyman", "hex", @@ -14,14 +16,6 @@ "bin": { "hextobin": "build/hextobin.js" }, - "scripts": { - "clean": "tsc -b --clean", - "build": "tsc -b" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/keymanapp/keyman.git" - }, "devDependencies": { "@types/node": "^18.7.18" } diff --git a/common/tools/hextobin/tsconfig.json b/common/tools/hextobin/tsconfig.json index e32831fe737..55e3f66308e 100644 --- a/common/tools/hextobin/tsconfig.json +++ b/common/tools/hextobin/tsconfig.json @@ -1,19 +1,9 @@ { - "extends": "../../../tsconfig-base.json", - "compilerOptions": { - "composite": true, - "declaration": true, - "target": "ES2020", - "module": "CommonJS", - "moduleResolution": "node", - "rootDir": ".", - "outDir": "build/", - }, - "exclude": [ - "node_modules" - ], - "files": [ - "index.ts", - "hextobin.ts" - ] + "extends": "../../../tsconfig.base.json", + "compilerOptions": { + "rootDir": ".", + "outDir": "build/" + }, + "exclude": ["node_modules"], + "files": ["index.ts", "hextobin.ts"] } diff --git a/common/tools/sourcemap-path-remapper/src/convert-source-map.d.ts b/common/tools/sourcemap-path-remapper/src/convert-source-map.d.ts new file mode 100644 index 00000000000..15a4da3c643 --- /dev/null +++ b/common/tools/sourcemap-path-remapper/src/convert-source-map.d.ts @@ -0,0 +1 @@ +declare module 'convert-source-map'; \ No newline at end of file diff --git a/common/tools/sourcemap-path-remapper/tsconfig.json b/common/tools/sourcemap-path-remapper/tsconfig.json index f9b531b311a..e207097f614 100644 --- a/common/tools/sourcemap-path-remapper/tsconfig.json +++ b/common/tools/sourcemap-path-remapper/tsconfig.json @@ -1,12 +1,11 @@ { - "extends": "../../../tsconfig-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "allowJs": false, "allowSyntheticDefaultImports": true, "declaration": true, - "module": "es6", - "moduleResolution": "node", + "sourceMap": false, "inlineSourceMap": true, "inlineSources": true, "sourceRoot": "/common/tools/sourcemap-path-remapper/src", diff --git a/common/web/es-bundling/tsconfig.json b/common/web/es-bundling/tsconfig.json index d2ab738acfb..a5149b51c6f 100644 --- a/common/web/es-bundling/tsconfig.json +++ b/common/web/es-bundling/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.esm-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "baseUrl": "./", "outDir": "build/", diff --git a/common/web/keyboard-processor/src/keyboards/activeLayout.ts b/common/web/keyboard-processor/src/keyboards/activeLayout.ts index e6d2ab9f157..9050d393a19 100644 --- a/common/web/keyboard-processor/src/keyboards/activeLayout.ts +++ b/common/web/keyboard-processor/src/keyboards/activeLayout.ts @@ -48,6 +48,12 @@ export class ActiveKey implements LayoutKey { _baseKeyEvent: KeyEvent; isMnemonic: boolean = false; + /** + * Only available on subkeys, but we don't distinguish between base keys and subkeys + * at this level yet in KMW. + */ + default?: boolean; + proportionalPad: number; proportionalX: number; proportionalWidth: number; diff --git a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts b/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts index 8d187ac8544..7e0153d0a52 100644 --- a/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts +++ b/common/web/keyboard-processor/src/keyboards/defaultLayouts.ts @@ -22,6 +22,7 @@ export type LayoutKey = { "nextlayer"?: string, "pad"?: string | number, "sk"?: LayoutKey[] + "default"?: boolean } export type LayoutRow = { diff --git a/common/web/keyman-version/build-bundler.js b/common/web/keyman-version/build-bundler.js deleted file mode 100644 index a5f26a44df9..00000000000 --- a/common/web/keyman-version/build-bundler.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Bundles @keymanapp/keyman-version as a single-file CommonJS module for components - * still in need of it. - */ - -import esbuild from 'esbuild'; - -// Bundles to a compact ESModule -esbuild.buildSync({ - entryPoints: ['build/version.inc.js'], - bundle: true, - sourcemap: true, - //minify: true, // No need to minify a module. - //keepNames: true, - format: "cjs", - // Sets 'common/web' as a root folder for module resolution; - // this allows the keyman-version import to resolve. - nodePaths: ['..'], - outfile: "build/version.inc.cjs", - tsconfig: 'tsconfig.json', - target: "es5" -}); \ No newline at end of file diff --git a/common/web/keyman-version/build.sh b/common/web/keyman-version/build.sh index 939709732c2..d4a07e4c762 100755 --- a/common/web/keyman-version/build.sh +++ b/common/web/keyman-version/build.sh @@ -1,11 +1,4 @@ #!/usr/bin/env bash -# -# Builds the include script for the current Keyman version. -# - -# Exit on command failure and when using unset variables: -set -eu - ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" @@ -13,6 +6,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" # This script runs from its own folder cd "$THIS_SCRIPT_PATH" @@ -25,8 +19,7 @@ builder_describe "Build the include script for current Keyman version" \ build \ "pack build a local .tgz pack for testing" \ "publish publish to npm" \ - test \ - --dry-run + test builder_describe_outputs \ configure "/node_modules" \ @@ -34,21 +27,7 @@ builder_describe_outputs \ builder_parse "$@" - -if builder_start_action configure; then - verify_npm_setup - builder_finish_action success configure -fi - -if builder_start_action clean; then - npm run clean - rm -f ./version.inc.ts - rm -f ./keyman-version.mts - rm -rf build - builder_finish_action success clean -fi - -if builder_start_action build; then +function do_build() { # Generate version.inc.ts echo " // Generated by common/web/keyman-version/build.sh @@ -72,22 +51,11 @@ export class KEYMAN_VERSION { export default KEYMAN_VERSION; " > ./version.inc.ts - tsc -b $builder_verbose - # kmlmc (the lexical model compiler) relies on a Node-based import, but after some of the earlier - # ES-modularization work, our main output's an ES module. Fortunately, esbuild can provide an easy stopgap. - - # Generates a CommonJS variant (in case other modules still need it). - node ./build-bundler.js - - builder_finish_action success build -fi + tsc --build $builder_verbose +} -if builder_start_action publish; then - . "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" - builder_publish_to_npm - builder_finish_action success publish -elif builder_start_action pack; then - . "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" - builder_publish_to_pack - builder_finish_action success pack -fi +builder_run_action clean rm -rf version.inc.ts keyman-version.mts build/ +builder_run_action configure verify_npm_setup +builder_run_action build do_build +builder_run_action publish builder_publish_to_npm +builder_run_action pack builder_publish_to_pack diff --git a/common/web/keyman-version/package.json b/common/web/keyman-version/package.json index 0ec9c1322be..ded749528c4 100644 --- a/common/web/keyman-version/package.json +++ b/common/web/keyman-version/package.json @@ -1,26 +1,15 @@ { "name": "@keymanapp/keyman-version", "description": "Keyman global version data", - "main": "./build/version.inc.cjs", "exports": { - ".": { - "import": "./build/version.inc.js", - "require": "./build/version.inc.cjs" - }, - "./build/version.inc.cjs": "./build/version.inc.cjs" + ".": "./build/version.inc.js" }, "files": [ "/build/" ], - "scripts": { - "build": "echo 'Building @keymanapp/keyman-version' && tsc -b", - "clean": "tsc -b --clean", - "tsc": "tsc" - }, "license": "MIT", "type": "module", "devDependencies": { - "@types/node": "^20.4.1", "typescript": "^4.9.5" } } diff --git a/common/web/keyman-version/tsconfig.json b/common/web/keyman-version/tsconfig.json index 8618c6dd922..a5808c432ee 100644 --- a/common/web/keyman-version/tsconfig.json +++ b/common/web/keyman-version/tsconfig.json @@ -1,17 +1,12 @@ { - "extends": "../../../tsconfig-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { - "allowJs": false, - "declaration": true, - "module": "es6", - "sourceMap": true, "outDir": "./build", - "lib": ["es6"], "target": "es5", - "downlevelIteration": true, "rootDir": "." }, + "include": [ "version.inc.ts" ] diff --git a/common/web/lm-message-types/tsconfig.json b/common/web/lm-message-types/tsconfig.json index 124def350d2..f9d427f0bfc 100644 --- a/common/web/lm-message-types/tsconfig.json +++ b/common/web/lm-message-types/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "declaration": true, "module": "none", diff --git a/common/web/sentry-manager/src/tsconfig.json b/common/web/sentry-manager/src/tsconfig.json index 490c315dc90..1b438c93c4b 100644 --- a/common/web/sentry-manager/src/tsconfig.json +++ b/common/web/sentry-manager/src/tsconfig.json @@ -1,13 +1,22 @@ { - "extends": "../../../../tsconfig-base.json", + "extends": "../../../../tsconfig.base.json", "compilerOptions": { + + // TODO: These override /tsconfig.base.json settings, and so should be removed if possible, + // but existing code in web/ breaks some of these settinsg + "noImplicitThis": false, + "noImplicitReturns": false, + "noImplicitAny": false, + "strictFunctionTypes": false, + "noUnusedLocals": false, + + "allowJs": true, "allowSyntheticDefaultImports": true, "baseUrl": "./", "inlineSources": true, "lib": ["es6", "dom"], "module": "es6", - "moduleResolution": "Node16", "outDir": "../build/obj", "rootDir": "./", "sourceMap": true, diff --git a/common/web/types/src/consts/virtual-key-constants.ts b/common/web/types/src/consts/virtual-key-constants.ts index f93155f1ff5..3347660f015 100644 --- a/common/web/types/src/consts/virtual-key-constants.ts +++ b/common/web/types/src/consts/virtual-key-constants.ts @@ -122,8 +122,8 @@ export const USVirtualKeyCodes = { */ K_oE2:226, K_OE2:226, - k_oC1:193, // ISO B11, ABNT-2 key to left of right shift, not on US keyboard - k_OC1:193, + K_oC1:193, // ISO B11, ABNT-2 key to left of right shift, not on US keyboard + K_OC1:193, 'K_?C1':193, 'k_?C1':193, K_oDF:0xDF, @@ -144,125 +144,90 @@ export const USVirtualKeyCodes = { const k = USVirtualKeyCodes; -export type KeyMap = number[][]; +/** Map a CLDR scancode to a US VKey ala USVirtualKeyCodes */ +export const CLDRScanToUSVirtualKeyCodes = { + 0x02: k.K_1, + 0x03: k.K_2, + 0x04: k.K_3, + 0x05: k.K_4, + 0x06: k.K_5, + 0x07: k.K_6, + 0x08: k.K_7, + 0x09: k.K_8, + 0x0A: k.K_9, + 0x0B: k.K_0, + 0x0C: k.K_HYPHEN, + 0x0D: k.K_EQUAL, -export const USVirtualKeyMap: KeyMap = [ - // ` 1 2 3 4 5 6 7 8 9 0 - = [bksp] - [ k.K_BKQUOTE, k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL ], - // [tab] Q W E R T Y U I O P [ ] \ - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_LBRKT, k.K_RBRKT, k.K_BKSLASH ], - // [caps] A S D F G H J K L ; ' [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE ], - // [shift] Z X C V B N M , . / [shift] *=oE2 - [ k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH ], - // space - [ k.K_SPACE ], -]; + 0x10: k.K_Q, + 0x11: k.K_W, + 0x12: k.K_E, + 0x13: k.K_R, + 0x14: k.K_T, + 0x15: k.K_Y, + 0x16: k.K_U, + 0x17: k.K_I, + 0x18: k.K_O, + 0x19: k.K_P, + 0x1A: k.K_LBRKT, + 0x1B: k.K_RBRKT, -export const ISOVirtualKeyMap: KeyMap = [ - // ` 1 2 3 4 5 6 7 8 9 0 - = [bksp] - [ k.K_BKQUOTE, k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL ], - // [tab] Q W E R T Y U I O P [ ] - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_LBRKT, k.K_RBRKT ], - // [caps] A S D F G H J K L ; ' \ [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE, k.K_BKSLASH ], - // [shift] * Z X C V B N M , . / [shift] *=oE2 - [ k.K_oE2, k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH ], - // space - [ k.K_SPACE ], -]; + 0x1E: k.K_A, + 0x1F: k.K_S, + 0x20: k.K_D, + 0x21: k.K_F, + 0x22: k.K_G, + 0x23: k.K_H, + 0x24: k.K_J, + 0x25: k.K_K, + 0x26: k.K_L, + 0x27: k.K_COLON, + 0x28: k.K_QUOTE, + 0x29: k.K_BKQUOTE, -export const JISVirtualKeyMap: KeyMap = [ - // [Hankaku/Zenkaku] 1 2 3 4 5 6 7 8 9 0 - ^ ¥ [bksp] - [ k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL, k.K_BKSLASH /* YEN */ ], - // [tab] Q W E R T Y U I O P @«`» [ [enter] - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_BKQUOTE, k.K_LBRKT ], - // [caps] A S D F G H J K L ; : ] [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE, k.K_RBRKT ], - // [shift] Z X C V B N M , . / _ [shift] - [ k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH, k.K_oE2 /* ろ */ ], - // space - [ k.K_SPACE ], -]; + 0x2B: k.K_BKSLASH, + 0x2C: k.K_Z, + 0x2D: k.K_X, + 0x2E: k.K_C, + 0x2F: k.K_V, + 0x30: k.K_B, + 0x31: k.K_N, + 0x32: k.K_M, + 0x33: k.K_COMMA, + 0x34: k.K_PERIOD, + 0x35: k.K_SLASH, -export const ABNT2VirtualKeyMap: KeyMap = [ - // ' 1 2 3 4 5 6 7 8 9 0 - = [bksp] - [ k.K_BKQUOTE, k.K_1, k.K_2, k.K_3, k.K_4, k.K_5, k.K_6, k.K_7, k.K_8, k.K_9, k.K_0, k.K_HYPHEN, k.K_EQUAL ], - // [tab] Q W E R T Y U I O P ´ [ - [ k.K_Q, k.K_W, k.K_E, k.K_R, k.K_T, k.K_Y, k.K_U, k.K_I, k.K_O, k.K_P, k.K_LBRKT, k.K_RBRKT ], - // [caps] A S D F G H J K L ç ~ ] [enter] - [ k.K_A, k.K_S, k.K_D, k.K_F, k.K_G, k.K_H, k.K_J, k.K_K, k.K_L, k.K_COLON, k.K_QUOTE, k.K_BKSLASH ], - // [shift] \ Z X C V B N M , . ; / [shift] - [ k.K_oE2, k.K_Z, k.K_X, k.K_C, k.K_V, k.K_B, k.K_N, k.K_M, k.K_COMMA, k.K_PERIOD, k.K_SLASH, k.k_oC1 /* ABNT2 */ ], - // space - [ k.K_SPACE ], -]; + 0x39: k.K_SPACE, -/** - * Map from a hardware constant to a keymap - * For the 'key' see constants.layr_list_hardware_map - */ -export const HardwareToKeymap: Map = new Map( - [ - ["us", USVirtualKeyMap], - ["iso", ISOVirtualKeyMap], - ["jis", JISVirtualKeyMap], - ["abnt2", ABNT2VirtualKeyMap], - ] -); + 0x56: k.K_oE2, // << Same as 0x7D; found on iso, abnt2 + 0x73: k.K_oC1, + 0x7D: k.K_oE2, // << Same as 0x56; found on jis + +}; + +export type KeyMap = number[][]; /** - * Maps LDML VKey Names from CLDR VKey Enum in TR35 to Keyman virtual key codes + * Convert a scan code numerical KeyMap to VKeys + * @param scans keymap to convert + * @param badScans output: set of not-found scancodes + * @returns */ -export const LdmlVkeyNames: Record = { - 'SPACE': k.K_SPACE, // 0x20, // A03 - '0': k.K_0, // 0x30, // E10 - '1': k.K_1, // 0x31, // E01 - '2': k.K_2, // 0x32, // E02 - '3': k.K_3, // 0x33, // E03 - '4': k.K_4, // 0x34, // E04 - '5': k.K_5, // 0x35, // E05 - '6': k.K_6, // 0x36, // E06 - '7': k.K_7, // 0x37, // E07 - '8': k.K_8, // 0x38, // E08 - '9': k.K_9, // 0x39, // E09 - 'A': k.K_A, // 0x41, // C01 - 'B': k.K_B, // 0x42, // B05 - 'C': k.K_C, // 0x43, // B03 - 'D': k.K_D, // 0x44, // C03 - 'E': k.K_E, // 0x45, // D03 - 'F': k.K_F, // 0x46, // C04 - 'G': k.K_G, // 0x47, // C05 - 'H': k.K_H, // 0x48, // C06 - 'I': k.K_I, // 0x49, // D08 - 'J': k.K_J, // 0x4A, // C07 - 'K': k.K_K, // 0x4B, // C08 - 'L': k.K_L, // 0x4C, // C09 - 'M': k.K_M, // 0x4D, // B07 - 'N': k.K_N, // 0x4E, // B06 - 'O': k.K_O, // 0x4F, // D09 - 'P': k.K_P, // 0x50, // D10 - 'Q': k.K_Q, // 0x51, // D01 - 'R': k.K_R, // 0x52, // D04 - 'S': k.K_S, // 0x53, // C02 - 'T': k.K_T, // 0x54, // D05 - 'U': k.K_U, // 0x55, // D07 - 'V': k.K_V, // 0x56, // B05 - 'W': k.K_W, // 0x57, // D02 - 'X': k.K_X, // 0x58, // B02 - 'Y': k.K_Y, // 0x59, // D06 - 'Z': k.K_Z, // 0x5A, // B01 - 'SEMICOLON': k.K_COLON, // 0xBA, // C10 - 'EQUAL': k.K_EQUAL, // 0xBB, // E12 - 'COMMA': k.K_COMMA, // 0xBC, // B08 - 'HYPHEN': k.K_HYPHEN, // 0xBD, // E11 - 'PERIOD': k.K_PERIOD, // 0xBE, // B09 - 'SLASH': k.K_SLASH, // 0xBF, // B10 - 'GRAVE': k.K_BKQUOTE, // 0xC0, // E00 - 'LBRACKET': k.K_LBRKT, // 0xDB, // D11 - 'BACKSLASH': k.K_BKSLASH, // 0xDC, // D13 - 'RBRACKET': k.K_RBRKT, // 0xDD, // D12 - 'QUOTE': k.K_QUOTE, // 0xDE, // C11 - 'LESS-THAN': k.K_oE2, // 0xE2, // B00 102nd key on European layouts, right of left shift. - 'ABNT2': k.k_oC1, // 0xC1, // B11 Extra key, left of right-shift, ABNT2 -}; +export function CLDRScanToKeyMap(scans: KeyMap, badScans?: Set): KeyMap { + return scans.map((row) => row.map((scan) => CLDRScanToVkey(scan, badScans))); +} + +/** Convert one scan code to vkey, or undefined */ +export function CLDRScanToVkey(scan: number, badScans?: Set): number { + /** typescript fun to index the scan table */ + function hasScanCode(key: PropertyKey): key is keyof typeof CLDRScanToUSVirtualKeyCodes { + return key in CLDRScanToUSVirtualKeyCodes; + } + if (hasScanCode(scan)) { + return CLDRScanToUSVirtualKeyCodes[scan]; + } else { + badScans?.add(scan); + return undefined; + } +} + diff --git a/common/web/types/src/kmx/element-string.ts b/common/web/types/src/kmx/element-string.ts index ed64a498ff8..ebf4d398e55 100644 --- a/common/web/types/src/kmx/element-string.ts +++ b/common/web/types/src/kmx/element-string.ts @@ -31,11 +31,11 @@ export class ElementString extends Array { * @param source if a string array, does not get reinterpreted as UnicodeSet. This is used with vars, etc. Or pass `["str"]` for an explicit 1-element elem. * If it is a string, will be interpreted per reorder element rules. */ - constructor(sections: DependencySections, source: string | string[], order?: string, tertiary?: string, tertiary_base?: string, prebase?: string) { - super(); - //TODO-LDML: full UnicodeSet and parsing + static fromStrings(sections: DependencySections, source: string | string[], order?: string, tertiary?: string, tertiary_base?: string, prebase?: string) : ElementString { + // the returned array + const array = new ElementString(); if(!source) { - return; + return array; } let items : ElementSegment[]; @@ -80,16 +80,16 @@ export class ElementString extends Array { throw Error(`Could not parse uset ${item.segment}`); } elem.uset = sections.uset.allocUset(uset, sections); - elem.value = sections.strs.allocString('', true); // no string + elem.value = sections.strs.allocString('', {singleOk: true}); // no string } else if (item.type === ElementType.codepoint || item.type === ElementType.escaped || item.type === ElementType.string) { // some kind of a string let str = item.segment; if (item.type === ElementType.escaped && !MATCH_HEX_ESCAPE.test(str)) { str = unescapeOneQuadString(str); // TODO-LDML: any other escape forms here? - elem.value = sections.strs.allocString(str, true); + elem.value = sections.strs.allocString(str, { singleOk: true }); } else { - elem.value = sections.strs.allocAndUnescapeString(str, true); + elem.value = sections.strs.allocString(str, { unescape: true, singleOk: true }); } // Now did we end up with one char or no? if (elem.value.isOneChar) { @@ -104,8 +104,9 @@ export class ElementString extends Array { (ElemElementFlags.type & typeFlag) | (tertiary_bases?.[i] == '1' /* TODO-LDML: or 'true'? */ ? ElemElementFlags.tertiary_base : 0) | (prebases?.[i] == '1' /* TODO-LDML: or 'true'? */ ? ElemElementFlags.prebase : 0); - this.push(elem); + array.push(elem); }; + return array; } isEqual(a: ElementString): boolean { if (a.length != this.length) { diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-layr.ts b/common/web/types/src/kmx/kmx-plus-builder/build-layr.ts index 057158f1865..c0038246e27 100644 --- a/common/web/types/src/kmx/kmx-plus-builder/build-layr.ts +++ b/common/web/types/src/kmx/kmx-plus-builder/build-layr.ts @@ -13,7 +13,7 @@ import { BUILDER_SECTION } from "./builder-section.js"; * List of layers, the element */ interface BUILDER_LAYR_LIST { - hardware: number; // hardware indicator + hardware: BUILDER_STR_REF; // hardware or 'touch' layer: number; // index of first layer in the list, in the count: number; // number of layer entries in the list minDeviceWidth: number; // width in millimeters @@ -82,7 +82,7 @@ export function build_layr(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l layr.lists = kmxplus.layr.lists.map((list) => { const blist: BUILDER_LAYR_LIST = { - hardware: list.hardware, + hardware: build_strs_index(sect_strs, list.hardware), layer: null, // to be set below _layers: list.layers, count: list.layers.length, @@ -92,6 +92,7 @@ export function build_layr(kmxplus: KMXPlusData, sect_strs: BUILDER_STRS, sect_l }); // now sort the lists layr.lists.sort((a, b) => { + // sort by string # if (a.hardware < b.hardware) { return -1; } else if (a.hardware > b.hardware) { diff --git a/common/web/types/src/kmx/kmx-plus-builder/build-vkey.ts b/common/web/types/src/kmx/kmx-plus-builder/build-vkey.ts deleted file mode 100644 index 0a4863beabd..00000000000 --- a/common/web/types/src/kmx/kmx-plus-builder/build-vkey.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { constants } from '@keymanapp/ldml-keyboard-constants'; -import { KMXPlusData } from "../kmx-plus.js"; -import { BUILDER_SECTION } from './builder-section.js'; - -/* ------------------------------------------------------------------ - * vkey section - ------------------------------------------------------------------ */ - -/** - * Builder for the 'vkey' section - */ -interface BUILDER_VKEY_ITEM { - vkey: number; - target: number; -}; - -export interface BUILDER_VKEY extends BUILDER_SECTION { - count: number; - items: BUILDER_VKEY_ITEM[]; -}; - -export function build_vkey(kmxplus: KMXPlusData): BUILDER_VKEY { - if(!kmxplus.vkey.vkeys.length) { - return null; - } - - let vkey: BUILDER_VKEY = { - ident: constants.hex_section_id(constants.section.vkey), - size: constants.length_vkey + constants.length_vkey_item * kmxplus.vkey.vkeys.length, - _offset: 0, - count: kmxplus.vkey.vkeys.length, - items: [] - }; - - for(let item of kmxplus.vkey.vkeys) { - vkey.items.push({ - vkey: item.vkey, - target: item.target - }); - } - - return vkey; -} diff --git a/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts b/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts index 3cc58c9fe75..e77c60fbe7e 100644 --- a/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts +++ b/common/web/types/src/kmx/kmx-plus-builder/kmx-plus-builder.ts @@ -15,7 +15,6 @@ import { BUILDER_STRS, build_strs } from './build-strs.js'; import { BUILDER_TRAN, build_tran } from './build-tran.js'; import { BUILDER_USET, build_uset } from './build-uset.js'; import { BUILDER_VARS, build_vars } from './build-vars.js'; -import { BUILDER_VKEY, build_vkey } from './build-vkey.js'; type BUILDER_BKSP = BUILDER_TRAN; // type BUILDER_FINL = BUILDER_TRAN; @@ -36,7 +35,6 @@ type SectionBuilders = { tran?: BUILDER_TRAN; uset?: BUILDER_USET; vars?: BUILDER_VARS; - vkey?: BUILDER_VKEY; }; export default class KMXPlusBuilder { @@ -73,7 +71,6 @@ export default class KMXPlusBuilder { this.emitSection(file, this.file.COMP_PLUS_TRAN, this.sect.tran); this.emitSection(file, this.file.COMP_PLUS_USET, this.sect.uset); this.emitSection(file, this.file.COMP_PLUS_VARS, this.sect.vars); - this.emitSection(file, this.file.COMP_PLUS_VKEY, this.sect.vkey); return file; } @@ -100,7 +97,6 @@ export default class KMXPlusBuilder { this.sect.tran = build_tran(this.file.kmxplus.tran, this.sect.strs, this.sect.elem); this.sect.uset = build_uset(this.file.kmxplus, this.sect.strs); this.sect.vars = build_vars(this.file.kmxplus, this.sect.strs, this.sect.elem, this.sect.list); - this.sect.vkey = build_vkey(this.file.kmxplus); // Finalize the sect (index) section @@ -138,7 +134,6 @@ export default class KMXPlusBuilder { offset = this.finalize_sect_item(this.sect.tran, offset); offset = this.finalize_sect_item(this.sect.uset, offset); offset = this.finalize_sect_item(this.sect.vars, offset); - offset = this.finalize_sect_item(this.sect.vkey, offset); this.sect.sect.total = offset; } diff --git a/common/web/types/src/kmx/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus.ts index eba1324b857..1060e50fba8 100644 --- a/common/web/types/src/kmx/kmx-plus.ts +++ b/common/web/types/src/kmx/kmx-plus.ts @@ -35,14 +35,14 @@ export class Elem extends Section { strings: ElementString[] = []; constructor(sections: DependencySections) { super(); - this.strings.push(new ElementString(sections, '')); // C7043: null element string + this.strings.push(ElementString.fromStrings(sections, '')); // C7043: null element string } /** * @param source if a string array, does not get reinterpreted as UnicodeSet. This is used with vars, etc. Or pass `["str"]` for an explicit 1-element elem. * If it is a string, will be interpreted per reorder element ruls. */ allocElementString(sections: DependencySections, source: string | string[], order?: string, tertiary?: string, tertiary_base?: string, prebase?: string): ElementString { - let s = new ElementString(sections, source, order, tertiary, tertiary_base, prebase); + let s = ElementString.fromStrings(sections, source, order, tertiary, tertiary_base, prebase); let result = this.strings.find(item => item.isEqual(s)); if(result === undefined) { result = s; @@ -143,45 +143,67 @@ export class CharStrsItem extends StrsItem { } }; +/** class for string manipulation options. These are in order of the pipeline. */ +export interface StrsOptions { + /** apply string variables (requires sections) */ + stringVariables?: boolean; + /** apply markers (requires sections) */ + markers?: boolean; + /** unescape with unescapeString */ + unescape?: boolean; + /** string can be stored as a single CharStrsItem, not in strs table. */ + singleOk?: boolean; +}; + export class Strs extends Section { strings: StrsItem[] = [ new StrsItem('') ]; // C7043: The null string is always requierd /** * Allocate a StrsItem given the string, unescaping if necessary. * @param s escaped string - * @param singleOk if true, allocate a CharStrsItem (not in strs table) if single-char capable. - * @returns - */ - allocAndUnescapeString(s?: string, singleOk?: boolean): StrsItem { - return this.allocString(unescapeString(s), singleOk); - } - /** - * Allocate a StrsItem given the string. - * @param s string - * @param singleOk if true, allocate a CharStrsItem (not in strs table) if single-char capable. - * @returns + * @param opts options for allocation + * @param sections other sections, if needed + * @returns StrsItem */ - allocString(s?: string, singleOk?: boolean): StrsItem { - if(s === undefined || s === null) { - // undefined or null are always equivalent to empty string, see C7043 - s = ''; - } - - if(typeof s !== 'string') { - throw new Error('alloc_string: s must be a string, undefined, or null.'); - } + allocString(s?: string, opts?: StrsOptions, sections?: DependencySections): StrsItem { + // Run the string processing pipeline + s = Strs.processString(s, opts, sections); - // if it's a single char, don't push it into the list - if (singleOk && isOneChar(s)) { + // if it's a single char, don't push it into the strs table + if (opts?.singleOk && isOneChar(s)) { return new CharStrsItem(s); } + // default: look to see if the string is already present let result = this.strings.find(item => item.value === s); if(result === undefined) { + // only add if not already present result = new StrsItem(s); this.strings.push(result); } return result; } + + /** process everything according to opts */ + static processString(s: string, opts: StrsOptions, sections: DependencySections) { + s = s ?? ''; + // type check everything else + if (typeof s !== 'string') { + throw new Error('alloc_string: s must be a string, undefined, or null.'); + } + // substitute variables + if (opts?.stringVariables) { + s = sections.vars.substituteStrings(s, sections); + } + // substitute markers + if (opts?.markers) { + s = sections.vars.substituteMarkerString(s); + } + // unescape \u{…} + if (opts?.unescape) { + s = unescapeString(s); + } + return s; + } }; /** @@ -234,6 +256,7 @@ export class Vars extends Section { }); } substituteStrings(str: string, sections: DependencySections): string { + if (!str) return str; return str.replaceAll(VariableParser.STRING_REFERENCE, (_entire, id) => { const val = this.findStringVariableValue(id); if (val === null) { @@ -293,8 +316,8 @@ export class Vars extends Section { return v[0]; } } - substituteMarkerString(s : string) : string { - return MarkerParser.toSentinelString(s, this.markers); + substituteMarkerString(s : string, forMatch? : boolean) : string { + return MarkerParser.toSentinelString(s, this.markers, forMatch); } }; @@ -309,7 +332,7 @@ export class VarsItem extends Section { constructor(id: string, value: string, sections: DependencySections) { super(); this.id = sections.strs.allocString(id); - this.value = sections.strs.allocAndUnescapeString(value); + this.value = sections.strs.allocString(value, {unescape: true}); } valid() : boolean { @@ -404,17 +427,6 @@ export class Bksp extends Tran { } }; -// 'vkey' - -export class VkeyItem { - vkey: number; - target: number; -} - -export class Vkey extends Section { - vkeys: VkeyItem[] = []; -}; - // 'disp' export class DispItem { to: StrsItem; @@ -433,7 +445,7 @@ export class Disp extends Section { * In-memory `` */ export class LayrList { - hardware: number; + hardware: StrsItem; layers: LayrEntry[] = []; minDeviceWidth: number; // millimeters }; @@ -510,19 +522,14 @@ export class List extends Section { * Allocate a list from a space-separated list of items. * Note that passing undefined or null or `''` will * end up being the same as the empty list `[]` - * @param strs Strs section for allocation * @param s space-separated list of items + * @param opts string options + * @param sections sections * @returns a List object */ - allocListFromSpaces(strs: Strs, s?: string): ListItem { + allocListFromSpaces(s: string, opts: StrsOptions, sections: DependencySections): ListItem { s = s ?? ''; - return this.allocList(strs, s.split(' ')); - } - allocListFromEscapedSpaces(strs: Strs, s?: string): ListItem { - if(s === undefined || s === null) { - s = ''; - } - return this.allocList(strs, s.split(' ').map(unescapeString)); + return this.allocList(s.split(' '), opts, sections); } /** * Return a List object referring to the string list. @@ -532,7 +539,7 @@ export class List extends Section { * @param s string list to allocate * @returns */ - allocList(strs: Strs, s?: string[]): ListItem { + allocList(s: string[], opts: StrsOptions, sections: DependencySections): ListItem { // Special case the 'null' list for [] or [''] if (!s || (s.length === 1 && s[0] === '')) { return this.lists[0]; @@ -540,14 +547,14 @@ export class List extends Section { let result = this.lists.find(item => item.isEqual(s)); if(result === undefined) { // allocate a new ListItem - result = new ListItem(strs, s); + result = ListItem.fromStrings(s, opts, sections); this.lists.push(result); } return result; } constructor(strs: Strs) { super(); - this.lists.push(new ListItem(strs, [])); // C7043: null element string + this.lists.push(ListItem.fromStrings([], {}, { strs })); // C7043: null element string } lists: ListItem[] = []; }; @@ -569,7 +576,6 @@ export interface KMXPlusData { tran?: Tran; uset?: Uset; // uset is ignored in-memory vars?: Vars; - vkey?: Vkey; }; export class KMXPlusFile extends KMXFile { @@ -720,7 +726,7 @@ export class KMXPlusFile extends KMXFile { }); this.COMP_PLUS_LAYR_LIST = new r.Struct({ - hardware: r.uint32le, //enum + hardware: STR_REF, // str: hardware name layer: r.uint32le, // index into layers count: r.uint32le, minDeviceWidth: r.uint32le, // integer: millimeters diff --git a/common/web/types/src/kmx/kmx.ts b/common/web/types/src/kmx/kmx.ts index 8a2c3e47aaa..6102a69cf55 100644 --- a/common/web/types/src/kmx/kmx.ts +++ b/common/web/types/src/kmx/kmx.ts @@ -144,9 +144,10 @@ export class KMXFile { public static readonly VERSION_150 = 0x00000F00; public static readonly VERSION_160 = 0x00001000; + public static readonly VERSION_170 = 0x00001100; public static readonly VERSION_MIN = this.VERSION_50; - public static readonly VERSION_MAX = this.VERSION_160; + public static readonly VERSION_MAX = this.VERSION_170; // // Backspace types diff --git a/common/web/types/src/kmx/string-list.ts b/common/web/types/src/kmx/string-list.ts index f9f4b46e912..411c940acf1 100644 --- a/common/web/types/src/kmx/string-list.ts +++ b/common/web/types/src/kmx/string-list.ts @@ -1,5 +1,5 @@ import { OrderedStringList } from 'src/ldml-keyboard/pattern-parser.js'; -import { Strs, StrsItem } from './kmx-plus.js'; +import { DependencySections, StrsItem, StrsOptions } from './kmx-plus.js'; /** * A single entry in a ListItem. @@ -27,20 +27,22 @@ export class ListItem extends Array implements OrderedStringList { /** * Construct a new list from an array of strings. * Use List. This is meant to be called by the List.allocString*() functions. - * @param strs the Strs section is needed to construct this object. * @param source array of strings + * @param opts string handling options + * @param sections the Strs section is needed to construct this object, and other sections may + * be needed depending on the options * @returns */ - constructor(strs: Strs, source: Array) { - super(); - if(!source) { - return; + static fromStrings(source: Array, opts: StrsOptions, sections: DependencySections) : ListItem { + const a = new ListItem(); + if (!source) { + return a; } - for (const str of source) { - let index = new ListIndex(strs.allocString(str)); - this.push(index); + let index = new ListIndex(sections.strs.allocString(str, opts, sections)); + a.push(index); } + return a; } getItemOrder(item: string): number { return this.findIndex(({value}) => value.value === item); @@ -72,12 +74,13 @@ export class ListItem extends Array implements OrderedStringList { return 0; } } - /** for debugging, print as single string */ + /** for debugging and tests, print as single string */ toString(): string { return this.toStringArray().join(' '); } - /** for debugging, map to string array */ + /** for debugging and tests, map to string array */ toStringArray(): string[] { - return this.map(v => v.value.value); + // TODO-LDML: this crashes: return this.map(v => v.toString()); + return Array.from(this.values()).map(v => v.toString()); } }; diff --git a/common/web/types/src/kvk/kvk-file.ts b/common/web/types/src/kvk/kvk-file.ts index ca3f522e72d..ff99adca5df 100644 --- a/common/web/types/src/kvk/kvk-file.ts +++ b/common/web/types/src/kvk/kvk-file.ts @@ -49,6 +49,7 @@ export interface BUILDER_KVK_KEY { export const BUILDER_KVK_KEY_Size = 9; // size of fixed elements of BUILDER_KVK_KEY export const enum BUILDER_KVK_HEADER_FLAGS { + kvkhNone = 0x00, // no flags kvkh102 = 0x01, kvkhDisplayUnderlying = 0x02, kvkhUseUnderlying = 0x04, @@ -122,4 +123,4 @@ export default class KVKFile { }); } -}; \ No newline at end of file +}; diff --git a/common/web/types/src/ldml-keyboard/ldml-keyboard-xml-reader.ts b/common/web/types/src/ldml-keyboard/ldml-keyboard-xml-reader.ts index 3fdd9a74025..66f8fdbe560 100644 --- a/common/web/types/src/ldml-keyboard/ldml-keyboard-xml-reader.ts +++ b/common/web/types/src/ldml-keyboard/ldml-keyboard-xml-reader.ts @@ -1,5 +1,5 @@ import * as xml2js from 'xml2js'; -import { LDMLKeyboardXMLSourceFile, LKImport } from './ldml-keyboard-xml.js'; +import { LDMLKeyboardXMLSourceFile, LKImport, ImportStatus } from './ldml-keyboard-xml.js'; import { default as AjvModule } from 'ajv'; const Ajv = AjvModule.default; // The actual expected Ajv type. import { boxXmlArray } from '../util/util.js'; @@ -49,11 +49,18 @@ export class LDMLKeyboardXMLSourceFileReader { if (!source.keyboard3.keys.import) { source.keyboard3.keys.import = []; } + if (!source.keyboard3.forms) { + source.keyboard3.forms = { + form: [], + }; + } + if (!source.keyboard3.forms.import) { + source.keyboard3.forms.import = []; + } } boxXmlArray(source?.keyboard3, 'layers'); boxXmlArray(source?.keyboard3?.displays, 'display'); boxXmlArray(source?.keyboard3?.names, 'name'); - boxXmlArray(source?.keyboard3?.vkeys, 'vkey'); boxXmlArray(source?.keyboard3?.keys, 'key'); boxXmlArray(source?.keyboard3?.keys, 'flicks'); boxXmlArray(source?.keyboard3?.locales, 'locale'); @@ -68,6 +75,12 @@ export class LDMLKeyboardXMLSourceFileReader { } } } + if(source?.keyboard3?.forms?.form) { + boxXmlArray(source?.keyboard3?.forms, 'form'); + for(let form of source?.keyboard3?.forms?.form) { + boxXmlArray(form, 'scanCodes'); + } + } if(source?.keyboard3?.keys?.flicks) { for(let flicks of source?.keyboard3?.keys?.flicks) { boxXmlArray(flicks, 'flick'); @@ -149,7 +162,15 @@ export class LDMLKeyboardXMLSourceFileReader { if (!this.resolveOneImport(obj, subtag, { base: constants.cldr_import_base, path: constants.cldr_implied_keys_import - })) { + }, true)) { + return false; + } + } else if (subtag === 'forms') { + // + if (!this.resolveOneImport(obj, subtag, { + base: constants.cldr_import_base, + path: constants.cldr_implied_forms_import + }, true)) { return false; } } @@ -160,9 +181,10 @@ export class LDMLKeyboardXMLSourceFileReader { * @param obj the object being imported into * @param subtag obj's element tag, e.g. `keys` * @param asImport the import structure + * @param implied true if it is an implied import * @returns true on success, false on failure */ - private resolveOneImport(obj: any, subtag: string, asImport: LKImport) : boolean { + private resolveOneImport(obj: any, subtag: string, asImport: LKImport, implied? : boolean) : boolean { const { base, path } = asImport; if (base !== constants.cldr_import_base) { this.callbacks.reportMessage(CommonTypesMessages.Error_ImportInvalidBase({base, path, subtag})); @@ -189,12 +211,20 @@ export class LDMLKeyboardXMLSourceFileReader { // pull all children of importXml[subtag] into obj for (const subsubtag of Object.keys(importRootNode).reverse()) { // e.g. const subsubval = importRootNode[subsubtag]; + const basePath = `${base}/${path}`; if (!Array.isArray(subsubval)) { // This is somewhat of an internal error, indicating that a non-mergeable XML file was imported // Not exercisable with the standard LDML imports. this.callbacks.reportMessage(CommonTypesMessages.Error_ImportMergeFail({base, path, subtag, subsubtag})); return false; } + // Mark all children as an import + subsubval.forEach(o => o[ImportStatus.import] = basePath); + if (implied) { + // mark all children as an implied import + subsubval.forEach(o => o[ImportStatus.impliedImport] = basePath); + } + if (!obj[subsubtag]) { obj[subsubtag] = []; // start with empty array } diff --git a/common/web/types/src/ldml-keyboard/ldml-keyboard-xml.ts b/common/web/types/src/ldml-keyboard/ldml-keyboard-xml.ts index 629b8e8aa24..83720312dd8 100644 --- a/common/web/types/src/ldml-keyboard/ldml-keyboard-xml.ts +++ b/common/web/types/src/ldml-keyboard/ldml-keyboard-xml.ts @@ -12,7 +12,7 @@ export interface LDMLKeyboardXMLSourceFile { * -- the root element. */ keyboard3: LKKeyboard; -} +}; export interface LKKeyboard { locale?: string; @@ -24,9 +24,9 @@ export interface LKKeyboard { names?: LKNames; settings?: LKSettings; keys?: LKKeys; + forms?: LKForms; displays?: LKDisplays; layers?: LKLayers[]; - vkeys?: LKVkeys; variables?: LKVariables; transforms?: LKTransforms[]; }; @@ -128,15 +128,6 @@ export interface LKRow { keys?: string; }; -export interface LKVkeys { - vkey?: LKVkey[]; -}; - -export interface LKVkey { - from?: string; - to?: string; -}; - export interface LKVariables { string?: LKString[]; set?: LKSet[]; @@ -193,3 +184,36 @@ export interface LKDisplays { display?: LKDisplay[]; displayOptions?: LKDisplayOptions; }; + +export interface LKForms { + form?: LKForm[]; +}; + +export interface LKForm { + id?: string; + scanCodes?: LKScanCodes[]; +}; + +export interface LKScanCodes { + codes?: string; +}; + +/** + * Utilities for determining the import status of items + */ +export class ImportStatus { + /** item came in via implied (spec based) import, such as keys-Latn-implied.xml */ + static impliedImport = Symbol('LDML implied import'); + /** item came in via import */ + static import = Symbol('LDML import'); + + /** @returns true if the object was loaded through an implied import */ + static isImpliedImport(o : any) : boolean { + return o && !!o[ImportStatus.impliedImport]; + } + /** @returns true if the object was loaded through an explicit import */ + static isImport(o : any) : boolean { + return o && !!o[ImportStatus.import]; + } +}; + diff --git a/common/web/types/src/ldml-keyboard/pattern-parser.ts b/common/web/types/src/ldml-keyboard/pattern-parser.ts index f6013248d26..b0d6fb07962 100644 --- a/common/web/types/src/ldml-keyboard/pattern-parser.ts +++ b/common/web/types/src/ldml-keyboard/pattern-parser.ts @@ -65,6 +65,15 @@ export class MarkerParser { /** Max count of markers */ public static readonly MAX_MARKER_COUNT = constants.marker_max_count; + private static anyMarkerMatch() : string { + const start = (`0000` + (this.MIN_MARKER_INDEX).toString(16)).slice(-4); + const end = (`0000` + (this.MAX_MARKER_INDEX).toString(16)).slice(-4); + return `${this.SENTINEL}${this.MARKER_CODE}[\\u${start}-\\u${end}]`; + } + + /** Expression that matches any marker */ + public static readonly ANY_MARKER_MATCH = MarkerParser.anyMarkerMatch(); + /** * Pattern for matching a marker reference, OR the special marker \m{.} */ @@ -91,10 +100,13 @@ export class MarkerParser { } /** @returns all marker strings as sentinel values */ - public static toSentinelString(s: string, markers?: OrderedStringList) : string { + public static toSentinelString(s: string, markers?: OrderedStringList, forMatch?: boolean) : string { if (!s) return s; return s.replaceAll(this.REFERENCE, (sub, arg) => { if (arg === MarkerParser.ANY_MARKER_ID) { + if (forMatch) { + return this.ANY_MARKER_MATCH; + } return MarkerParser.markerOutput(MarkerParser.ANY_MARKER_INDEX); } if (!markers) { @@ -103,10 +115,10 @@ export class MarkerParser { const order = markers.getItemOrder(arg); if (order === -1) { throw RangeError(`Internal Error: Could not find marker \\m{${arg}}`); - } else if(order >= MarkerParser.MAX_MARKER_INDEX) { + } else if(order > MarkerParser.MAX_MARKER_INDEX) { throw RangeError(`Internal Error: marker \\m{${arg}} has out of range index ${order}`); } else { - return MarkerParser.markerOutput(order+1); + return MarkerParser.markerOutput(order + 1); } }); } diff --git a/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts b/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts index 4da7a006636..43429676a0a 100644 --- a/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts +++ b/common/web/types/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts @@ -1,8 +1,9 @@ -import { LKKey } from './../../src/ldml-keyboard/ldml-keyboard-xml.js'; +import { LKKey, ImportStatus } from './../../src/ldml-keyboard/ldml-keyboard-xml.js'; import 'mocha'; import {assert} from 'chai'; import { CommonTypesMessages } from '../../src/util/common-events.js'; import { testReaderCases } from '../helpers/reader-callback-test.js'; +import { CLDRScanToVkey, CLDRScanToKeyMap, USVirtualKeyCodes } from '../../src/consts/virtual-key-constants.js'; function pluckKeysFromKeybag(keys: LKKey[], ids: string[]) { return keys.filter(({id}) => ids.indexOf(id) !== -1); @@ -40,6 +41,9 @@ describe('ldml keyboard xml reader tests', function () { {id: 'b', to: 'b'}, {id: 'c', to: 'c'}, ]); + // all of the keys are implied imports here + assert.isTrue(ImportStatus.isImpliedImport(source?.keyboard3?.keys.key.find(({id}) => id === 'a'))); + assert.isTrue(ImportStatus.isImport(source?.keyboard3?.keys.key.find(({id}) => id === 'a'))); }, }, { @@ -81,6 +85,15 @@ describe('ldml keyboard xml reader tests', function () { {id: 'zz', to: 'zz'}, // new key {id: 'hash', to: '##'}, // override ]); + // 'a' is an implied import + assert.isTrue(ImportStatus.isImpliedImport(k.find(({id}) => id === 'a'))); + assert.isTrue(ImportStatus.isImport(k.find(({id}) => id === 'a'))); + // 'hash' is an import but not implied + assert.isFalse(ImportStatus.isImpliedImport(k.find(({id}) => id === 'hash'))); + assert.isTrue(ImportStatus.isImport(k.find(({id}) => id === 'hash'))); + // 'zz' is not imported + assert.isFalse(ImportStatus.isImpliedImport(k.find(({id}) => id === 'zz'))); + assert.isFalse(ImportStatus.isImport(k.find(({id}) => id === 'zz'))); }, }, { @@ -129,3 +142,41 @@ describe('ldml keyboard xml reader tests', function () { }, ]); }); + +describe('check scan code routines', () => { + it('should be able to detect bad single scancodes', () => { + const badScans = new Set(); + const ckey = CLDRScanToVkey(0xFF, badScans); + assert.isUndefined(ckey, `expected undefined 0xFF`); + assert.equal(badScans.size, 1); + assert.sameDeepMembers(Array.from(badScans.values()), [0xFF]); + }); + it('should be able to detect bad list scancodes', () => { + const badScans = new Set(); + const ckeys = CLDRScanToKeyMap([[0x02, 0xFF]], badScans); + assert.sameDeepMembers(ckeys, [[49, undefined]]); + assert.equal(badScans.size, 1); + assert.sameDeepMembers(Array.from(badScans.values()), [0xFF]); + }); + it('CLDRScanToUSVirtualKeyCodes should be 1:1', () => { + const vkeyToScan = new Map(); + // check all scancodes + for (let scan = 0; scan <= 0xFF; scan++) { + const vkey = CLDRScanToVkey(scan); + if (vkey === undefined) { + // not mapped, which is OK + continue; + } + if (scan === 0x56 || scan === 0x7D) { + // These both can map to this scancode + assert.equal(vkey, USVirtualKeyCodes.K_oE2); + } else { + // don't check those exceptions + assert.isFalse(vkeyToScan.has(vkey), + `vkey ${vkey} mapped from more than one scancode: ${Number(vkeyToScan.get(vkey)).toString(16)} and ${Number(scan).toString(16)}`); + } + // do make sure nothing else maps to that vkey + vkeyToScan.set(vkey, scan); + } + }); +}); diff --git a/common/web/types/test/ldml-keyboard/test-pattern-parser.ts b/common/web/types/test/ldml-keyboard/test-pattern-parser.ts index e7f06a1c557..0274f2a5c27 100644 --- a/common/web/types/test/ldml-keyboard/test-pattern-parser.ts +++ b/common/web/types/test/ldml-keyboard/test-pattern-parser.ts @@ -75,6 +75,7 @@ describe('Test of Pattern Parsers', () => { 'a': 0, 'b': 1, 'c': 2, + 'zz': MarkerParser.MAX_MARKER_INDEX - 1, // this is an ordering, so needs to be -1 'zzz': 0x2FFFFF, }; const o = m[item]; @@ -103,6 +104,21 @@ describe('Test of Pattern Parsers', () => { markers ) ); + // verify the matching behavior of these + assert.isTrue(new RegExp(MarkerParser.toSentinelString(`^Q\\m{a}$`, markers, true), 'u') + .test(MarkerParser.toSentinelString(`Q\\m{a}`, markers, false)), `Q\\m{a} did not match`); + assert.isFalse(new RegExp(MarkerParser.toSentinelString(`^Q\\m{a}$`, markers, true), 'u') + .test(MarkerParser.toSentinelString(`Q\\m{b}`, markers, false)), `Q\\m{a} should not match Q\\m{b}`); + assert.isTrue(new RegExp(MarkerParser.toSentinelString(`^Q\\m{.}$`, markers, true), 'u') + .test(MarkerParser.toSentinelString(`Q\\m{a}`, markers, false)), `Q\\m{.} did not match Q\\m{a}`); + assert.isTrue(new RegExp(MarkerParser.toSentinelString(`^Q\\m{.}$`, markers, true), 'u') + .test(MarkerParser.toSentinelString(`Q\\m{zz}`, markers, false)), `Q\\m{.} did not match Q\\m{zz} (max marker)`); + assert.isFalse(new RegExp(MarkerParser.toSentinelString(`^Q\\m{.}$`, markers, true), 'u') + .test(MarkerParser.toSentinelString(`\\m{a}`, markers, false)), `Q\\m{.} did not match \\m{a}`); + assert.isTrue(new RegExp(MarkerParser.toSentinelString(`^\\m{.}$`, markers, true), 'u') + .test(MarkerParser.toSentinelString(`\\m{a}`, markers, false)), `\\m{.} did not match \\m{a}`); + assert.isFalse(new RegExp(MarkerParser.toSentinelString(`^\\m{.}$`, markers, true), 'u') + .test(MarkerParser.toSentinelString(`\\m{a}\\m{b}`, markers, false)), `\\m{.} did not match \\m{a}\\m{b}`); }); it('should match some marker constants', () => { assert.equal(constants.uc_sentinel, KMXFile.UC_SENTINEL); diff --git a/common/web/types/test/tsconfig.json b/common/web/types/test/tsconfig.json index c522129c99a..ee468c7fbd6 100644 --- a/common/web/types/test/tsconfig.json +++ b/common/web/types/test/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../../tsconfig.esm-base.json", + "extends": "../../../../tsconfig.base.json", "compilerOptions": { "rootDir": ".", diff --git a/common/web/types/tsconfig.json b/common/web/types/tsconfig.json index 5059030c0f8..730244e67c9 100644 --- a/common/web/types/tsconfig.json +++ b/common/web/types/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.esm-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "build/src/", diff --git a/common/windows/cpp/include/legacy_kmx_file.h b/common/windows/cpp/include/legacy_kmx_file.h index 6be4b3b9861..9b8f6a59fb1 100644 --- a/common/windows/cpp/include/legacy_kmx_file.h +++ b/common/windows/cpp/include/legacy_kmx_file.h @@ -74,8 +74,9 @@ #define VERSION_140 0x00000E00 #define VERSION_150 0x00000F00 #define VERSION_160 0x00001000 +#define VERSION_170 0x00001100 #define VERSION_MIN VERSION_50 -#define VERSION_MAX VERSION_160 +#define VERSION_MAX VERSION_170 /* Special flag for WM_CHAR/WM_KEY???/WM_SYSKEY???: says that key has been diff --git a/common/windows/delphi/ext/sentry/test/Makefile b/common/windows/delphi/ext/sentry/test/Makefile index 63fc664b011..b2e92bb8964 100644 --- a/common/windows/delphi/ext/sentry/test/Makefile +++ b/common/windows/delphi/ext/sentry/test/Makefile @@ -4,7 +4,8 @@ !include ..\..\..\Defines.mak -build: dirs # version.res manifest.res +build: dirs +# version.res manifest.res $(DELPHI_MSBUILD) SentryClientTest.dproj "/p:Platform=Win32" $(DELPHI_MSBUILD) SentryClientVclTest.dproj "/p:Platform=Win32" diff --git a/common/windows/delphi/keyboards/kmxfileconsts.pas b/common/windows/delphi/keyboards/kmxfileconsts.pas index e08feb65641..966dada8827 100644 --- a/common/windows/delphi/keyboards/kmxfileconsts.pas +++ b/common/windows/delphi/keyboards/kmxfileconsts.pas @@ -99,9 +99,10 @@ interface VERSION_140 = $00000E00; VERSION_150 = $00000F00; VERSION_160 = $00001000; + VERSION_170 = $00001100; VERSION_MIN = VERSION_50; - VERSION_MAX = VERSION_160; + VERSION_MAX = VERSION_170; VERSION_MASK_MINOR = $00FF; VERSION_MASK_MAJOR = $FF00; diff --git a/common/windows/delphi/tools/Makefile b/common/windows/delphi/tools/Makefile index a9c1151473a..2ea11ab2372 100644 --- a/common/windows/delphi/tools/Makefile +++ b/common/windows/delphi/tools/Makefile @@ -7,7 +7,7 @@ NOTARGET_SIGNCODE=yes !ifdef NODELPHI TARGETS=.virtual !else -TARGETS=build_standards_data buildunidata devtools sentrytool test-klog +TARGETS=build_standards_data buildunidata devtools sentrytool test-klog verify_signatures !endif CLEANS=clean-tools @@ -28,6 +28,10 @@ buildunidata: .virtual cd $(COMMON_ROOT)\tools\buildunidata $(MAKE) $(TARGET) +verify_signatures: .virtual + cd $(COMMON_ROOT)\tools\verify_signatures + $(MAKE) $(TARGET) + devtools: .virtual !ifdef NODELPHI echo Skipping devtools diff --git a/common/windows/delphi/tools/verify_signatures/Makefile b/common/windows/delphi/tools/verify_signatures/Makefile new file mode 100644 index 00000000000..0f67747665e --- /dev/null +++ b/common/windows/delphi/tools/verify_signatures/Makefile @@ -0,0 +1,13 @@ +# +# test for signatures and version information being correct in ?install directory or ?bin directory +# + +!include ..\..\Defines.mak + +build: + $(DELPHI_MSBUILD) verify_signatures.dproj + copy sigcheck.bin $(WIN32_TARGET_PATH)\sigcheck.exe + +clean: def-clean + +!include ..\..\Target.mak diff --git a/windows/src/test/test_i3633/sigcheck.bin b/common/windows/delphi/tools/verify_signatures/sigcheck.bin similarity index 100% rename from windows/src/test/test_i3633/sigcheck.bin rename to common/windows/delphi/tools/verify_signatures/sigcheck.bin diff --git a/windows/src/test/test_i3633/verify.dpr b/common/windows/delphi/tools/verify_signatures/verify_signatures.dpr similarity index 86% rename from windows/src/test/test_i3633/verify.dpr rename to common/windows/delphi/tools/verify_signatures/verify_signatures.dpr index b3707d84617..49478ac3edf 100644 --- a/windows/src/test/test_i3633/verify.dpr +++ b/common/windows/delphi/tools/verify_signatures/verify_signatures.dpr @@ -1,4 +1,4 @@ -program verify; +program verify_signatures; {$APPTYPE CONSOLE} @@ -36,6 +36,7 @@ begin Delete(s,1,1); end; + // TODO: sign these files and move the check down to the EndsWith node test if str[0].ToLower.Contains('sentry.') or str[0].ToLower.Contains('crashpad_handler') or str[0].ToLower.Contains('keymanmc') then // We don't verify sentry.dll or sentry.x64.dll or crashpad_handler.exe because they're not our files // We don't verify keymanmc.dll because it has no version resources, as it is mc-generated @@ -62,6 +63,14 @@ begin end; end; + if str[0].ToLower.EndsWith('node') then + begin + // It's one of the node addons -- in developer server at time of writing + // we don't have a version resource but we have signed it, so treat it + // as valid + Exit(''); + end; + if str[3] <> 'SIL International' then begin Exit('File has wrong company name'); @@ -90,7 +99,7 @@ begin if (ParamStr(1) = '-?') or (ParamCount < 1) then begin - writeln('verify [-d] VERSION.md: Verify the output of sigcheck to ensure all executables are signed and have proper version.'); + writeln('verify_signatures [-d] VERSION.md: Verify the output of sigcheck to ensure all executables are signed and have proper version.'); writeln(' -d: Check the timestamp on the signature is less than 2 days old.'); writeln(' VERSION.md: path to the version to verify against'); Halt(2); diff --git a/windows/src/test/test_i3633/verify.dproj b/common/windows/delphi/tools/verify_signatures/verify_signatures.dproj similarity index 99% rename from windows/src/test/test_i3633/verify.dproj rename to common/windows/delphi/tools/verify_signatures/verify_signatures.dproj index e23aeb3a4d8..323353c79b9 100644 --- a/windows/src/test/test_i3633/verify.dproj +++ b/common/windows/delphi/tools/verify_signatures/verify_signatures.dproj @@ -3,7 +3,7 @@ {A6DCA558-8DD0-4FFF-8DAE-F305AB8D2AF4} 18.8 None - verify.dpr + verify_signatures.dpr True Debug Win32 @@ -45,7 +45,7 @@ true - verify + verify_signatures $(BDS)\bin\delphi_PROJECTICNS.icns $(BDS)\bin\delphi_PROJECTICON.ico bindcompfmx;fmx;rtl;dbrtl;DbxClientDriver;bindcomp;inetdb;DBXInterBaseDriver;xmlrtl;DbxCommonDriver;DBXMySQLDriver;dbxcds;soaprtl;bindengine;CustomIPTransport;dsnap;fmxase;inet;fmxobj;inetdbxpress;fmxdae;dbexpress;$(DCC_UsePackage) @@ -161,7 +161,7 @@ - verify.dpr + verify_signatures.dpr Microsoft Office 2000 Sample Automation Server Wrapper Components diff --git a/windows/src/test/test_i3633/verify.res b/common/windows/delphi/tools/verify_signatures/verify_signatures.res similarity index 100% rename from windows/src/test/test_i3633/verify.res rename to common/windows/delphi/tools/verify_signatures/verify_signatures.res diff --git a/core/commands.inc.sh b/core/commands.inc.sh index 6916b61a9d9..2d3bccc4c08 100644 --- a/core/commands.inc.sh +++ b/core/commands.inc.sh @@ -11,7 +11,18 @@ do_clean() { # clean: note build/ will be left, but build// should be gone local target=$1 builder_start_action clean:$target || return 0 + rm -rf "$MESON_PATH" + + # Removes ICU cached components so it will be re-downloaded and built. Note: + # we could use `git clean`, but this clarifies exactly what is deleted, and + # but we try not to use git commands in build scripts, to maintain clear + # responsibility + rm -rf \ + "$THIS_SCRIPT_PATH/subprojects/icu" \ + "$THIS_SCRIPT_PATH/subprojects/*.tgz" \ + "$THIS_SCRIPT_PATH/subprojects/*.zip" + builder_finish_action success clean:$target } diff --git a/core/doc/hotdoc.json b/core/doc/hotdoc.json index 4ece50d0f52..946c62beac0 100644 --- a/core/doc/hotdoc.json +++ b/core/doc/hotdoc.json @@ -4,7 +4,7 @@ "sitemap": "@doc_dir@/sitemap.txt", "index": "@doc_dir@/markdown_files/index.md", "c_sources": [ - "@include_dir@/keyman/keyboardprocessor.h" + "@include_dir@/keyman/keyman_core_api.h" ], "c_include_directories": [ "@include_dir@", diff --git a/core/doc/introspection.schema b/core/doc/introspection.schema index ff10c7c9695..3b7684e0e9d 100644 --- a/core/doc/introspection.schema +++ b/core/doc/introspection.schema @@ -47,7 +47,7 @@ } }, "properties": { - "$schema": { "const": "keyman/keyboardprocessor/doc/introspection.schema" }, + "$schema": { "const": "keyman/core/doc/introspection.schema" }, "keyboard": { "$ref": "#/definitions/keyboard" }, "options": { "type": "object", diff --git a/core/doc/markdown_files/index.md b/core/doc/markdown_files/index.md index 98870c356dc..d389857c5f6 100644 --- a/core/doc/markdown_files/index.md +++ b/core/doc/markdown_files/index.md @@ -46,7 +46,7 @@ A virtual key board event and modifier map recevied from the Platform layer to b processed with the state object for this Client application. - __Virtual Key:__ A code based on the US English layout, with values matching the Windows -virtual key codes. See `keyboardprocessor_vkeys.h` for definitions. +virtual key codes. See `keyman_core_api_vkeys.h` for definitions. - __Modifier Key:__ The set of Control, Shift, Alt, Caps Lock keys. On some platforms these may have other names (e.g. Alt is called Option on macOS); other platform-specific @@ -58,4 +58,4 @@ Caps Lock. ### Namespace -All calls, types and enums are prefixed with the namespace identifier `km_kbp_` +All calls, types and enums are prefixed with the namespace identifier `km_core_` diff --git a/core/doc/meson.build b/core/doc/meson.build index 01fcb5c98ad..6039e2e2dda 100644 --- a/core/doc/meson.build +++ b/core/doc/meson.build @@ -18,7 +18,7 @@ if hotdoc.found() output: 'hotdoc.json', configuration: cfg) deps = files( - '../include/keyman/keyboardprocessor.h', + '../include/keyman/keyman_core_api.h', '../src/jsonpp.hpp', '../src/utfcodec.hpp' ) diff --git a/core/include/keyman/keyboardprocessor_consts.h b/core/include/keyman/keyboardprocessor_consts.h deleted file mode 100644 index 1d0936610b3..00000000000 --- a/core/include/keyman/keyboardprocessor_consts.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -// Defined environment options for KMX processor -#define KM_KBP_KMX_ENV_PLATFORM u"platform" -#define KM_KBP_KMX_ENV_BASELAYOUT u"baseLayout" -#define KM_KBP_KMX_ENV_BASELAYOUTALT u"baseLayoutAlt" -#define KM_KBP_KMX_ENV_SIMULATEALTGR u"simulateAltgr" -#define KM_KBP_KMX_ENV_CAPSLOCK u"capsLock" -#define KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT u"baseLayoutGivesCtrlRAltForRAlt" diff --git a/core/include/keyman/keyboardprocessor_version.h.in b/core/include/keyman/keyboardprocessor_version.h.in deleted file mode 100644 index d434ae4e485..00000000000 --- a/core/include/keyman/keyboardprocessor_version.h.in +++ /dev/null @@ -1,15 +0,0 @@ -#define km_kbp_version_stringify(x) km_kbp_version_to_string(x) -#define km_kbp_version_to_string(x) #x - -// Product versioning - -#define KM_KBP_VERSION_MAJOR @majorver@ -#define KM_KBP_VERSION_MINOR @minorver@ -#define KM_KBP_VERSION_PATCH @patchver@ -#define KM_KBP_VERSION_STRING km_kbp_version_stringify(@majorver@ ## . ## @minorver@ ## . ## @patchver@ ## .0) - -// API versioning - -#define KM_KBP_LIB_CURRENT @lib_curr@ -#define KM_KBP_LIB_AGE @lib_age@ -#define KM_KBP_LIB_REVISION @lib_rev@ diff --git a/core/include/keyman/keyboardprocessor_vkeys.h b/core/include/keyman/keyboardprocessor_vkeys.h deleted file mode 100644 index e8d8122bda2..00000000000 --- a/core/include/keyman/keyboardprocessor_vkeys.h +++ /dev/null @@ -1,312 +0,0 @@ -/* - Copyright: © 2018 SIL International. - Description: API declarations for modifier keys, handy access masks and - Keyman VKEY names. These follow the same keytop->code - associations as the Windows API. This is a separate header to - maintain readability of the primary API header. - Create Date: 17 Oct 2018 - Authors: Tim Eves (TSE) - History: 17 Oct 2018 - TSE - Moved & refactored km_kbp_modifier_state - from keyboardprocessor.h. - - Added VKey and mask definitions. - 6 Oct 2018 - TSE - Move into keyman folder. - -*/ - -#pragma once - -enum km_kbp_modifier_state { - KM_KBP_MODIFIER_LCTRL = 1 << 0, - KM_KBP_MODIFIER_RCTRL = 1 << 1, - KM_KBP_MODIFIER_LALT = 1 << 2, - KM_KBP_MODIFIER_RALT = 1 << 3, - KM_KBP_MODIFIER_SHIFT = 1 << 4, - KM_KBP_MODIFIER_CTRL = 1 << 5, - KM_KBP_MODIFIER_ALT = 1 << 6, - /* - KM_KBP_MODIFIER_META = 1 << 7, // Either Meta-key flag (tentative). Not usable by keyboards currently - // Used internally (currently, only by KMW) to ensure Meta-key - // shortcuts safely bypass rules - // Meta key = Command key on macOS, Windows key on Windows - */ - KM_KBP_MODIFIER_CAPS = 1 << 8, - KM_KBP_MODIFIER_NOCAPS = 1 << 9, - /* - KM_KBP_MODIFIER_NUMLOCK = 1 << 10, - KM_KBP_MODIFIER_NONUMLOCK = 1 << 11, - KM_KBP_MODIFIER_SCROLLOCK = 1 << 12, - KM_KBP_MODIFIER_NOSCROLLOCK = 1 << 13, - KM_KBP_MODIFIER_VIRTUALKEY = 1 << 14, - */ -}; - -enum km_kbp_modifier_mask { - KM_KBP_MODIFIER_MASK_ALL = 0x7f, - KM_KBP_MODIFIER_MASK_ALT_GR_SIM = KM_KBP_MODIFIER_LCTRL|KM_KBP_MODIFIER_LALT, - KM_KBP_MODIFIER_MASK_CHIRAL = 0x1f, - KM_KBP_MODIFIER_MASK_IS_CHIRAL = 0x0f, - KM_KBP_MODIFIER_MASK_NON_CHIRAL = 0x7f, - KM_KBP_MODIFIER_MASK_CAPS = 0x0300, -/*KM_KBP_MODIFIER_MASK_NUMLOCK = 0x0C00, - KM_KBP_MODIFIER_MASK_SCROLLLOCK = 0x3000,*/ -}; - -// These are Windows API VKEYs, using Keyman VKEY names. -enum km_kpb_virtual_key { - KM_KBP_VKEY__00, - KM_KBP_VKEY_LBUTTON, - KM_KBP_VKEY_RBUTTON, - KM_KBP_VKEY_CANCEL, - KM_KBP_VKEY_MBUTTON, - KM_KBP_VKEY__05, - KM_KBP_VKEY__06, - KM_KBP_VKEY__07, - KM_KBP_VKEY_BKSP, - KM_KBP_VKEY_TAB, - KM_KBP_VKEY__0A, - KM_KBP_VKEY__0B, - KM_KBP_VKEY_KP5, - KM_KBP_VKEY_ENTER, - KM_KBP_VKEY__0E, - KM_KBP_VKEY__0F, - KM_KBP_VKEY_SHIFT, - KM_KBP_VKEY_CONTROL, - KM_KBP_VKEY_ALT, - KM_KBP_VKEY_PAUSE, - KM_KBP_VKEY_CAPS, - KM_KBP_VKEY__15, - KM_KBP_VKEY__16, - KM_KBP_VKEY__17, - KM_KBP_VKEY__18, - KM_KBP_VKEY__19, - KM_KBP_VKEY__1A, - KM_KBP_VKEY_ESC, - KM_KBP_VKEY__1C, - KM_KBP_VKEY__1D, - KM_KBP_VKEY__1E, - KM_KBP_VKEY__1F, - KM_KBP_VKEY_SPACE, - KM_KBP_VKEY_PGUP, - KM_KBP_VKEY_PGDN, - KM_KBP_VKEY_END, - KM_KBP_VKEY_HOME, - KM_KBP_VKEY_LEFT, - KM_KBP_VKEY_UP, - KM_KBP_VKEY_RIGHT, - KM_KBP_VKEY_DOWN, - KM_KBP_VKEY_SEL, - KM_KBP_VKEY_PRINT, - KM_KBP_VKEY_EXEC, - KM_KBP_VKEY_PRTSCN, - KM_KBP_VKEY_INS, - KM_KBP_VKEY_DEL, - KM_KBP_VKEY_HELP, - KM_KBP_VKEY_0, - KM_KBP_VKEY_1, - KM_KBP_VKEY_2, - KM_KBP_VKEY_3, - KM_KBP_VKEY_4, - KM_KBP_VKEY_5, - KM_KBP_VKEY_6, - KM_KBP_VKEY_7, - KM_KBP_VKEY_8, - KM_KBP_VKEY_9, - KM_KBP_VKEY__3A, - KM_KBP_VKEY__3B, - KM_KBP_VKEY__3C, - KM_KBP_VKEY__3D, - KM_KBP_VKEY__3E, - KM_KBP_VKEY__3F, - KM_KBP_VKEY__40, - KM_KBP_VKEY_A, - KM_KBP_VKEY_B, - KM_KBP_VKEY_C, - KM_KBP_VKEY_D, - KM_KBP_VKEY_E, - KM_KBP_VKEY_F, - KM_KBP_VKEY_G, - KM_KBP_VKEY_H, - KM_KBP_VKEY_I, - KM_KBP_VKEY_J, - KM_KBP_VKEY_K, - KM_KBP_VKEY_L, - KM_KBP_VKEY_M, - KM_KBP_VKEY_N, - KM_KBP_VKEY_O, - KM_KBP_VKEY_P, - KM_KBP_VKEY_Q, - KM_KBP_VKEY_R, - KM_KBP_VKEY_S, - KM_KBP_VKEY_T, - KM_KBP_VKEY_U, - KM_KBP_VKEY_V, - KM_KBP_VKEY_W, - KM_KBP_VKEY_X, - KM_KBP_VKEY_Y, - KM_KBP_VKEY_Z, - KM_KBP_VKEY__5B, - KM_KBP_VKEY__5C, - KM_KBP_VKEY__5D, - KM_KBP_VKEY__5E, - KM_KBP_VKEY__5F, - KM_KBP_VKEY_NP0, - KM_KBP_VKEY_NP1, - KM_KBP_VKEY_NP2, - KM_KBP_VKEY_NP3, - KM_KBP_VKEY_NP4, - KM_KBP_VKEY_NP5, - KM_KBP_VKEY_NP6, - KM_KBP_VKEY_NP7, - KM_KBP_VKEY_NP8, - KM_KBP_VKEY_NP9, - KM_KBP_VKEY_NPSTAR, - KM_KBP_VKEY_NPPLUS, - KM_KBP_VKEY_SEPARATOR, - KM_KBP_VKEY_NPMINUS, - KM_KBP_VKEY_NPDOT, - KM_KBP_VKEY_NPSLASH, - KM_KBP_VKEY_F1, - KM_KBP_VKEY_F2, - KM_KBP_VKEY_F3, - KM_KBP_VKEY_F4, - KM_KBP_VKEY_F5, - KM_KBP_VKEY_F6, - KM_KBP_VKEY_F7, - KM_KBP_VKEY_F8, - KM_KBP_VKEY_F9, - KM_KBP_VKEY_F10, - KM_KBP_VKEY_F11, - KM_KBP_VKEY_F12, - KM_KBP_VKEY_F13, - KM_KBP_VKEY_F14, - KM_KBP_VKEY_F15, - KM_KBP_VKEY_F16, - KM_KBP_VKEY_F17, - KM_KBP_VKEY_F18, - KM_KBP_VKEY_F19, - KM_KBP_VKEY_F20, - KM_KBP_VKEY_F21, - KM_KBP_VKEY_F22, - KM_KBP_VKEY_F23, - KM_KBP_VKEY_F24, - KM_KBP_VKEY__88, - KM_KBP_VKEY__89, - KM_KBP_VKEY__8A, - KM_KBP_VKEY__8B, - KM_KBP_VKEY__8C, - KM_KBP_VKEY__8D, - KM_KBP_VKEY__8E, - KM_KBP_VKEY__8F, - KM_KBP_VKEY_NUMLOCK, - KM_KBP_VKEY_SCROLL, - KM_KBP_VKEY__92, - KM_KBP_VKEY__93, - KM_KBP_VKEY__94, - KM_KBP_VKEY__95, - KM_KBP_VKEY__96, - KM_KBP_VKEY__97, - KM_KBP_VKEY__98, - KM_KBP_VKEY__99, - KM_KBP_VKEY__9A, - KM_KBP_VKEY__9B, - KM_KBP_VKEY__9C, - KM_KBP_VKEY__9D, - KM_KBP_VKEY__9E, - KM_KBP_VKEY__9F, - KM_KBP_VKEY__A0, - KM_KBP_VKEY__A1, - KM_KBP_VKEY__A2, - KM_KBP_VKEY__A3, - KM_KBP_VKEY__A4, - KM_KBP_VKEY__A5, - KM_KBP_VKEY__A6, - KM_KBP_VKEY__A7, - KM_KBP_VKEY__A8, - KM_KBP_VKEY__A9, - KM_KBP_VKEY__AA, - KM_KBP_VKEY__AB, - KM_KBP_VKEY__AC, - KM_KBP_VKEY__AD, - KM_KBP_VKEY__AE, - KM_KBP_VKEY__AF, - KM_KBP_VKEY__B0, - KM_KBP_VKEY__B1, - KM_KBP_VKEY__B2, - KM_KBP_VKEY__B3, - KM_KBP_VKEY__B4, - KM_KBP_VKEY__B5, - KM_KBP_VKEY__B6, - KM_KBP_VKEY__B7, - KM_KBP_VKEY__B8, - KM_KBP_VKEY__B9, - KM_KBP_VKEY_COLON, - KM_KBP_VKEY_EQUAL, - KM_KBP_VKEY_COMMA, - KM_KBP_VKEY_HYPHEN, - KM_KBP_VKEY_PERIOD, - KM_KBP_VKEY_SLASH, - KM_KBP_VKEY_BKQUOTE, - KM_KBP_VKEY__C1, - KM_KBP_VKEY__C2, - KM_KBP_VKEY__C3, - KM_KBP_VKEY__C4, - KM_KBP_VKEY__C5, - KM_KBP_VKEY__C6, - KM_KBP_VKEY__C7, - KM_KBP_VKEY__C8, - KM_KBP_VKEY__C9, - KM_KBP_VKEY__CA, - KM_KBP_VKEY__CB, - KM_KBP_VKEY__CC, - KM_KBP_VKEY__CD, - KM_KBP_VKEY__CE, - KM_KBP_VKEY__CF, - KM_KBP_VKEY__D0, - KM_KBP_VKEY__D1, - KM_KBP_VKEY__D2, - KM_KBP_VKEY__D3, - KM_KBP_VKEY__D4, - KM_KBP_VKEY__D5, - KM_KBP_VKEY__D6, - KM_KBP_VKEY__D7, - KM_KBP_VKEY__D8, - KM_KBP_VKEY__D9, - KM_KBP_VKEY__DA, - KM_KBP_VKEY_LBRKT, - KM_KBP_VKEY_BKSLASH, - KM_KBP_VKEY_RBRKT, - KM_KBP_VKEY_QUOTE, - KM_KBP_VKEY_oDF, - KM_KBP_VKEY_oE0, - KM_KBP_VKEY_oE1, - KM_KBP_VKEY_oE2, // 102nd key on European layouts - KM_KBP_VKEY_oE3, - KM_KBP_VKEY_oE4, - KM_KBP_VKEY__E5, - KM_KBP_VKEY_oE6, - KM_KBP_VKEY__E7, - KM_KBP_VKEY__E8, - KM_KBP_VKEY_oE9, - KM_KBP_VKEY_oEA, - KM_KBP_VKEY_oEB, - KM_KBP_VKEY_oEC, - KM_KBP_VKEY_oED, - KM_KBP_VKEY_oEE, - KM_KBP_VKEY_oEF, - KM_KBP_VKEY_oF0, - KM_KBP_VKEY_oF1, - KM_KBP_VKEY_oF2, - KM_KBP_VKEY_oF3, - KM_KBP_VKEY_oF4, - KM_KBP_VKEY_oF5, - KM_KBP_VKEY__F6, - KM_KBP_VKEY__F7, - KM_KBP_VKEY__F8, - KM_KBP_VKEY__F9, - KM_KBP_VKEY__FA, - KM_KBP_VKEY__FB, - KM_KBP_VKEY__FC, - KM_KBP_VKEY__FD, - KM_KBP_VKEY__FE, - KM_KBP_VKEY__FF, -}; diff --git a/core/include/keyman/keyboardprocessor.h b/core/include/keyman/keyman_core_api.h similarity index 58% rename from core/include/keyman/keyboardprocessor.h rename to core/include/keyman/keyman_core_api.h index 429a8ae6cbf..86358edeebd 100644 --- a/core/include/keyman/keyboardprocessor.h +++ b/core/include/keyman/keyman_core_api.h @@ -57,7 +57,7 @@ A virtual key event and modifier map received from the Platform layer to be processed with the state object for this Client application. - __Virtual Key:__ A code based on the US English layout, with values matching the Windows -virtual key codes. See `keyboardprocessor_vkeys.h` for definitions. +virtual key codes. See `keyman_core_api_vkeys.h` for definitions. - __Modifier Key:__ The set of Control, Shift, Alt, Caps Lock keys. On some platforms these may have other names (e.g. Alt is called Option on macOS); other platform-specific @@ -67,25 +67,25 @@ Caps Lock. ## API ### Namespace -All calls, types and enums are prefixed with the namespace identifier `km_kbp_` +All calls, types and enums are prefixed with the namespace identifier `km_core_` ### API idioms Almost all calls marshalling variable length aggregate data in or out of an API object take the form: -> km_kbp_status *fn_name*(object_ref, buffer_ptr, size_ptr) +> km_core_status *fn_name*(object_ref, buffer_ptr, size_ptr) where the buffer is nullable and all other arguments are required (will result -in an `KM_KBP_STATUS_INVALID_ARGUMENT` status being returned if nulled). When +in an `KM_CORE_STATUS_INVALID_ARGUMENT` status being returned if nulled). When `buffer` is `nullptr` or `0` the function will place the size of the required buffer in the variable pointed to by `size_ptr`. Calls which result in the allocation of resources, regardless of resulting ownership, are of the form: -> km_kbp_status *fn_name*(object_ref, out_ptr) +> km_core_status *fn_name*(object_ref, out_ptr) where `out_ptr` is a valid pointer to a caller allocated variable to hold the resulting ouput. This is often a reference to a created object. All arguments -are required (will result in an `KM_KBP_STATUS_INVALID_ARGUMENT` status being +are required (will result in an `KM_CORE_STATUS_INVALID_ARGUMENT` status being returned if nulled). For accessors to fixed size attributes of an object these will take the form: @@ -100,9 +100,9 @@ nothing in that event. */ #include #include -#include -#include -#include +#include +#include +#include #if defined(__cplusplus) extern "C" @@ -110,24 +110,24 @@ extern "C" #endif // Basic types // -typedef uint16_t km_kbp_virtual_key; // A virtual key code. -typedef uint32_t km_kbp_status; // Status return code. +typedef uint16_t km_core_virtual_key; // A virtual key code. +typedef uint32_t km_core_status; // Status return code. // Opaque object types. // -typedef struct km_kbp_context km_kbp_context; -typedef struct km_kbp_keyboard km_kbp_keyboard; -typedef struct km_kbp_state km_kbp_state; -typedef struct km_kbp_options km_kbp_options; +typedef struct km_core_context km_core_context; +typedef struct km_core_keyboard km_core_keyboard; +typedef struct km_core_state km_core_state; +typedef struct km_core_options km_core_options; // Forward declarations // -typedef struct km_kbp_option_item km_kbp_option_item; +typedef struct km_core_option_item km_core_option_item; // Callback function used to to access Input Method eXtension library functions // from Keyman Core // -typedef uint8_t (*km_kbp_keyboard_imx_platform)(km_kbp_state*, uint32_t, void*); +typedef uint8_t (*km_core_keyboard_imx_platform)(km_core_state*, uint32_t, void*); /*``` ### Error Handling @@ -137,21 +137,21 @@ value is an error). Any functions that can fail will always return a status value and all results are returned via outparams passed to the function. ```c */ -enum km_kbp_status_codes { - KM_KBP_STATUS_OK = 0, - KM_KBP_STATUS_NO_MEM = 1, - KM_KBP_STATUS_IO_ERROR = 2, - KM_KBP_STATUS_INVALID_ARGUMENT = 3, - KM_KBP_STATUS_KEY_ERROR = 4, - KM_KBP_STATUS_INSUFFICENT_BUFFER = 5, - KM_KBP_STATUS_INVALID_UTF = 6, - KM_KBP_STATUS_INVALID_KEYBOARD = 7, - KM_KBP_STATUS_OS_ERROR = 0x80000000 +enum km_core_status_codes { + KM_CORE_STATUS_OK = 0, + KM_CORE_STATUS_NO_MEM = 1, + KM_CORE_STATUS_IO_ERROR = 2, + KM_CORE_STATUS_INVALID_ARGUMENT = 3, + KM_CORE_STATUS_KEY_ERROR = 4, + KM_CORE_STATUS_INSUFFICENT_BUFFER = 5, + KM_CORE_STATUS_INVALID_UTF = 6, + KM_CORE_STATUS_INVALID_KEYBOARD = 7, + KM_CORE_STATUS_OS_ERROR = 0x80000000 }; /* ``` -The final status code KM_KBP_STATUS_OS_ERROR is intended to allow encapsulating +The final status code KM_CORE_STATUS_OS_ERROR is intended to allow encapsulating a platform error code; the remaining 31 low bits are the error code returned by the OS for cases where the failure mode is platform specific. For HRESULT codes this only permits failure codes to be passed. @@ -176,79 +176,79 @@ Contexts are always owned by their state. They may be set to a list of context_items or interrogated for their current list of context items. ```c */ -enum km_kbp_context_type { - KM_KBP_CT_END, - KM_KBP_CT_CHAR, - KM_KBP_CT_MARKER +enum km_core_context_type { + KM_CORE_CT_END, + KM_CORE_CT_CHAR, + KM_CORE_CT_MARKER }; typedef struct { uint8_t type; uint8_t _reserved[3]; union { - km_kbp_usv character; + km_core_usv character; uint32_t marker; }; -} km_kbp_context_item; +} km_core_context_item; -#define KM_KBP_CONTEXT_ITEM_END {KM_KBP_CT_END, {0,}, {0,}} +#define KM_CORE_CONTEXT_ITEM_END {KM_CORE_CT_END, {0,}, {0,}} /* ``` -### `km_kbp_context_items_from_utf16` +### `km_core_context_items_from_utf16` ##### Description: -Convert a UTF16 encoded Unicode string into an array of `km_kbp_context_item` +Convert a UTF16 encoded Unicode string into an array of `km_core_context_item` structures. Allocates memory as needed. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_NO_MEM`: In the event not enough memory can be allocated for the +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be allocated for the output buffer. -- `KM_KBP_STATUS_INVALID_UTF`: In the event the UTF16 string cannot be decoded +- `KM_CORE_STATUS_INVALID_UTF`: In the event the UTF16 string cannot be decoded because it contains unpaired surrogate codeunits. ##### Parameters: - __text__: a pointer to a null terminated array of utf16 encoded data. - __out_ptr__: a pointer to the result variable: - A pointer to the start of the `km_kbp_context_item` array containing the + A pointer to the start of the `km_core_context_item` array containing the representation of the input string. - Terminated with a type of `KM_KBP_CT_END`. Must be disposed of with - `km_kbp_context_items_dispose`. + Terminated with a type of `KM_CORE_CT_END`. Must be disposed of with + `km_core_context_items_dispose`. ```c */ KMN_API -km_kbp_status -km_kbp_context_items_from_utf16(km_kbp_cp const *text, - km_kbp_context_item **out_ptr); +km_core_status +km_core_context_items_from_utf16(km_core_cp const *text, + km_core_context_item **out_ptr); /* ``` -### `km_kbp_context_items_from_utf8` +### `km_core_context_items_from_utf8` ##### Description: -Convert an UTF8 encoded Unicode string into an array of `km_kbp_context_item` +Convert an UTF8 encoded Unicode string into an array of `km_core_context_item` structures. Allocates memory as needed. ##### Status: -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_NO_MEM`: In the event it cannot allocate enough memory for the +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_NO_MEM`: In the event it cannot allocate enough memory for the output buffer. -- `KM_KBP_STATUS_INVALID_UTF`: In the event the UTF8 string cannot be +- `KM_CORE_STATUS_INVALID_UTF`: In the event the UTF8 string cannot be decoded. ##### Parameters: - __text__: a pointer to a null terminated array of utf8 encoded data. - __out_ptr__: a pointer to the result variable: - A pointer to the start of the `km_kbp_context_item` array containing the + A pointer to the start of the `km_core_context_item` array containing the representation of the input string. - Terminated with a type of `KM_KBP_CT_END`. + Terminated with a type of `KM_CORE_CT_END`. ```c */ KMN_API -km_kbp_status -km_kbp_context_items_from_utf8(char const *text, - km_kbp_context_item **out_ptr); +km_core_status +km_core_context_items_from_utf8(char const *text, + km_core_context_item **out_ptr); /* ``` -### `km_kbp_context_items_to_utf16` +### `km_core_context_items_to_utf16` ##### Description: Convert a context item array into a UTF-16 encoded string placing it into the supplied buffer of specified size, and return the number of code units @@ -256,14 +256,14 @@ actually used in the conversion. If null is passed as the buffer the number codeunits required is returned. This will strip markers from the context during the conversion. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_INSUFFICENT_BUFFER`: If the buffer is not large enough. +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_INSUFFICENT_BUFFER`: If the buffer is not large enough. `buf_size` will contain the space required. The contents of the buffer are undefined. ##### Parameters: -- __context_items__: A pointer to the start of an array `km_kbp_context_item`. - Must be terminated with a type of `KM_KBP_CT_END`. +- __context_items__: A pointer to the start of an array `km_core_context_item`. + Must be terminated with a type of `KM_CORE_CT_END`. - __buf__: A pointer to the buffer to place the UTF-16 string into. May be null to request size calculation. - __buf_size__: a pointer to the result variable: @@ -273,14 +273,14 @@ context during the conversion. ```c */ KMN_API -km_kbp_status -km_kbp_context_items_to_utf16(km_kbp_context_item const *item, - km_kbp_cp *buf, +km_core_status +km_core_context_items_to_utf16(km_core_context_item const *item, + km_core_cp *buf, size_t *buf_size); /* ``` -### `km_kbp_context_items_to_utf8` +### `km_core_context_items_to_utf8` ##### Description: Convert a context item array into a UTF-8 encoded string placing it into the supplied buffer of specified size, and return the number of code units @@ -288,14 +288,14 @@ actually used in the conversion. If null is passed as the buffer the number codeunits required is returned. This will strip markers from the context during the conversion. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_INSUFFICENT_BUFFER`: If the buffer is not large enough. +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_INSUFFICENT_BUFFER`: If the buffer is not large enough. `buf_size` will contain the space required. The contents of the buffer are undefined. ##### Parameters: -- __context_items__: A pointer to the start of an array `km_kbp_context_item`. - Must be terminated with a type of `KM_KBP_CT_END`. +- __context_items__: A pointer to the start of an array `km_core_context_item`. + Must be terminated with a type of `KM_CORE_CT_END`. - __buf__: A pointer to the buffer to place the UTF-8 string into. May be null to request size calculation. - __buf_size__: a pointer to the result variable: @@ -305,79 +305,79 @@ context during the conversion. ```c */ KMN_API -km_kbp_status -km_kbp_context_items_to_utf8(km_kbp_context_item const *item, +km_core_status +km_core_context_items_to_utf8(km_core_context_item const *item, char *buf, size_t *buf_size); /* ``` -### `km_kbp_context_items_dispose` +### `km_core_context_items_dispose` ##### Description: -Free the allocated memory belonging to a `km_kbp_context_item` array previously -returned by `km_kbp_context_items_from_utf16` or `km_kbp_context_get` +Free the allocated memory belonging to a `km_core_context_item` array previously +returned by `km_core_context_items_from_utf16` or `km_core_context_get` ##### Parameters: -- __context_items__: A pointer to the start of the `km_kbp_context_item` array +- __context_items__: A pointer to the start of the `km_core_context_item` array to be disposed of. ```c */ KMN_API void -km_kbp_context_items_dispose(km_kbp_context_item *context_items); +km_core_context_items_dispose(km_core_context_item *context_items); /* ``` -### `km_kbp_context_set` +### `km_core_context_set` ##### Description: Replace the contents of the current context with a new sequence of -`km_kbp_context_item` entries. +`km_core_context_item` entries. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_NO_MEM`: In the event not enough memory can be allocated to +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be allocated to grow the context buffer internally. ##### Parameters: - __context__: A pointer to an opaque context object -- __context_items__: A pointer to the start of the `km_kbp_context_item` +- __context_items__: A pointer to the start of the `km_core_context_item` array containing the new context. It must be terminated with an item - of type `KM_KBP_CT_END`. + of type `KM_CORE_CT_END`. ```c */ KMN_API -km_kbp_status -km_kbp_context_set(km_kbp_context *context, - km_kbp_context_item const *context_items); +km_core_status +km_core_context_set(km_core_context *context, + km_core_context_item const *context_items); /* ``` -### `km_kbp_context_get` +### `km_core_context_get` ##### Description: Copies all items in the context into a new array and returns the new array. -This must be disposed of by caller using `km_kbp_context_items_dispose`. +This must be disposed of by caller using `km_core_context_items_dispose`. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_NO_MEM`: In the event not enough memory can be allocated for the +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be allocated for the output buffer. ##### Parameters: -- __context_items__: A pointer to the start of an array `km_kbp_context_item`. +- __context_items__: A pointer to the start of an array `km_core_context_item`. - __out__: a pointer to the result variable: - A pointer to the start of the `km_kbp_context_item` array containing a - copy of the context. Terminated with a type of `KM_KBP_CT_END`. Must be - disposed of with `km_kbp_context_items_dispose`. + A pointer to the start of the `km_core_context_item` array containing a + copy of the context. Terminated with a type of `KM_CORE_CT_END`. Must be + disposed of with `km_core_context_items_dispose`. ```c */ KMN_API -km_kbp_status -km_kbp_context_get(km_kbp_context const *context_items, - km_kbp_context_item **out); +km_core_status +km_core_context_get(km_core_context const *context_items, + km_core_context_item **out); /* ``` -### `km_kbp_context_clear` +### `km_core_context_clear` ##### Description: Removes all context_items from the internal array. If `context` is null, has no effect. @@ -388,11 +388,11 @@ null, has no effect. */ KMN_API void -km_kbp_context_clear(km_kbp_context *); +km_core_context_clear(km_core_context *); /* ``` -### `km_kbp_context_length` +### `km_core_context_length` ##### Description: Return the number of items in the context. ##### Return: @@ -405,75 +405,75 @@ pointer. */ KMN_API size_t -km_kbp_context_length(km_kbp_context *); +km_core_context_length(km_core_context *); /* ``` -### `km_kbp_context_append` +### `km_core_context_append` ##### Description: Add more items to the end (insertion point) of the context. If these exceed the maximum context length the same number of items will be dropped from the beginning of the context. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_NO_MEM`: In the event not enough memory can be allocated to +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be allocated to grow the context buffer internally. ##### Parameters: - __context__: A pointer to an opaque context object. -- __context_items__: A pointer to the start of the `KM_KBP_CT_END` terminated - array of `km_kbp_context_item` to append. +- __context_items__: A pointer to the start of the `KM_CORE_CT_END` terminated + array of `km_core_context_item` to append. ```c */ KMN_API -km_kbp_status -km_kbp_context_append(km_kbp_context *context, - km_kbp_context_item const *context_items); +km_core_status +km_core_context_append(km_core_context *context, + km_core_context_item const *context_items); /* ``` -### `km_kbp_context_shrink` +### `km_core_context_shrink` ##### Description: Remove a specified number of items from the end of the context, optionally add up to the same number of the supplied items to the front of the context. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_NO_MEM`: in the event it cannot allocated enough memory to grow +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_NO_MEM`: in the event it cannot allocated enough memory to grow the context internally. ##### Parameters: - __context__: A pointer to an opaque context object. - __num__: The number of items to remove from the end of context. -- __context_items__: Pointer to the start of the `KM_KBP_CT_END` terminated - array of `km_kbp_context_item` to add to the front. Up to `num` items will +- __context_items__: Pointer to the start of the `KM_CORE_CT_END` terminated + array of `km_core_context_item` to add to the front. Up to `num` items will be prepended. This may be null if not required. ```c */ KMN_API -km_kbp_status -km_kbp_context_shrink(km_kbp_context *context, +km_core_status +km_core_context_shrink(km_core_context *context, size_t num, - km_kbp_context_item const *prefix); + km_core_context_item const *prefix); /* ``` -### `km_kbp_context_item_list_size` +### `km_core_context_item_list_size` ##### Description: -Return the length of a terminated `km_kbp_context_item` array. +Return the length of a terminated `km_core_context_item` array. ##### Return: The number of items in the list, not including terminating item, or 0 if `context_items` is null. ##### Parameters: -- __context_items__: A pointer to a `KM_KBP_CT_END` terminated array of - `km_kbp_context_item` values. +- __context_items__: A pointer to a `KM_CORE_CT_END` terminated array of + `km_core_context_item` values. ```c */ KMN_API size_t -km_kbp_context_item_list_size(km_kbp_context_item const *context_items); +km_core_context_item_list_size(km_core_context_item const *context_items); /* ``` @@ -486,15 +486,15 @@ other actions. */ typedef struct { - uint8_t expected_type; // km_kbp_backspace_type + uint8_t expected_type; // km_core_backspace_type uintptr_t expected_value; // used mainly in unit tests -} km_kbp_backspace_item; +} km_core_backspace_item; -enum km_kbp_backspace_type { - KM_KBP_BT_UNKNOWN = 0, // Used at beginning of context; user-initiated backspace - KM_KBP_BT_CHAR = 1, // Deleting a character prior to insertion point - KM_KBP_BT_MARKER = 2, // Deleting a marker prior to insertion point - KM_KBP_BT_MAX_TYPE_ID +enum km_core_backspace_type { + KM_CORE_BT_UNKNOWN = 0, // Used at beginning of context; user-initiated backspace + KM_CORE_BT_CHAR = 1, // Deleting a character prior to insertion point + KM_CORE_BT_MARKER = 2, // Deleting a marker prior to insertion point + KM_CORE_BT_MAX_TYPE_ID }; typedef struct { @@ -502,28 +502,28 @@ typedef struct { uint8_t _reserved[sizeof(void*)-sizeof(uint8_t)]; union { uintptr_t marker; // MARKER type - km_kbp_option_item const * option; // OPT types - km_kbp_usv character; // CHAR type + km_core_option_item const * option; // OPT types + km_core_usv character; // CHAR type uint8_t capsLock; // CAPSLOCK type, 1 to turn on, 0 to turn off - km_kbp_backspace_item backspace; // BACKSPACE type + km_core_backspace_item backspace; // BACKSPACE type }; -} km_kbp_action_item; - -enum km_kbp_action_type { - KM_KBP_IT_END = 0, // Marks end of action items list. - KM_KBP_IT_CHAR = 1, // A Unicode character has been generated. - KM_KBP_IT_MARKER = 2, // Correlates to kmn's "deadkey" markers. - KM_KBP_IT_ALERT = 3, // The keyboard has triggered a alert/beep/bell. - KM_KBP_IT_BACK = 4, // Delete the codepoint preceding the insertion point. - KM_KBP_IT_PERSIST_OPT = 5, // The indicated option needs to be stored. - KM_KBP_IT_EMIT_KEYSTROKE = 6, // Emit the current keystroke to the application - KM_KBP_IT_INVALIDATE_CONTEXT = 7, +} km_core_action_item; + +enum km_core_action_type { + KM_CORE_IT_END = 0, // Marks end of action items list. + KM_CORE_IT_CHAR = 1, // A Unicode character has been generated. + KM_CORE_IT_MARKER = 2, // Correlates to kmn's "deadkey" markers. + KM_CORE_IT_ALERT = 3, // The keyboard has triggered a alert/beep/bell. + KM_CORE_IT_BACK = 4, // Delete the codepoint preceding the insertion point. + KM_CORE_IT_PERSIST_OPT = 5, // The indicated option needs to be stored. + KM_CORE_IT_EMIT_KEYSTROKE = 6, // Emit the current keystroke to the application + KM_CORE_IT_INVALIDATE_CONTEXT = 7, // The processor requests that the context buffer be cleared; // for applications where context is cached, this clears the context; // for applications where context is read from the focused text store, // the context is just re-read and markers flushed. - KM_KBP_IT_CAPSLOCK = 8, // Enable or disable capsLock - KM_KBP_IT_MAX_TYPE_ID + KM_CORE_IT_CAPSLOCK = 8, // Enable or disable capsLock + KM_CORE_IT_MAX_TYPE_ID }; @@ -533,9 +533,9 @@ enum km_kbp_action_type { A state’s default options are set from the keyboard at creation time and the environment. The Platform layer is then is expected to apply any persisted options it is maintaining. Options are passed into and out of API functions as -simple C arrays of `km_kbp_option_item` terminated with a `KM_KBP_OPTIONS_END` +simple C arrays of `km_core_option_item` terminated with a `KM_CORE_OPTIONS_END` sentinel value. A state's options are exposed and manipulatable via the -`km_kbp_options` API. All option values are of type C string. +`km_core_options` API. All option values are of type C string. During processing when the Platform layer finds a PERSIST action type it should store the updated option in the appropriate place, based on its scope. @@ -545,55 +545,55 @@ value. ```c */ -enum km_kbp_option_scope { - KM_KBP_OPT_UNKNOWN = 0, - KM_KBP_OPT_KEYBOARD = 1, - KM_KBP_OPT_ENVIRONMENT = 2, - KM_KBP_OPT_MAX_SCOPES +enum km_core_option_scope { + KM_CORE_OPT_UNKNOWN = 0, + KM_CORE_OPT_KEYBOARD = 1, + KM_CORE_OPT_ENVIRONMENT = 2, + KM_CORE_OPT_MAX_SCOPES }; -struct km_kbp_option_item { - km_kbp_cp const * key; - km_kbp_cp const * value; +struct km_core_option_item { + km_core_cp const * key; + km_core_cp const * value; uint8_t scope; // Scope which an option belongs to. }; -#define KM_KBP_OPTIONS_END { 0, 0, 0 } +#define KM_CORE_OPTIONS_END { 0, 0, 0 } /* ``` -### `km_kbp_options_list_size` +### `km_core_options_list_size` ##### Description: -Return the length of a terminated `km_kbp_option_item` array (options +Return the length of a terminated `km_core_option_item` array (options list). ##### Return: The number of items in the list, not including terminating item, or 0 if `opts` is null. ##### Parameters: -- __opts__: A pointer to a `KM_KBP_OPTIONS_END` terminated array of - `km_kbp_option_item` values. +- __opts__: A pointer to a `KM_CORE_OPTIONS_END` terminated array of + `km_core_option_item` values. ```c */ KMN_API size_t -km_kbp_options_list_size(km_kbp_option_item const *opts); +km_core_options_list_size(km_core_option_item const *opts); /* ``` -### `km_kbp_state_option_lookup` +### `km_core_state_option_lookup` ##### Description: Lookup an option based on its key, in an options list. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null, or +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null, or if the scope is invalid. -- `KM_KBP_STATUS_KEY_ERROR`: The key cannot be found. +- `KM_CORE_STATUS_KEY_ERROR`: The key cannot be found. ##### Parameters: - __state__: An opaque pointer to a state object. - __scope__: Which key-value store to interrogate. -- __key__: A UTF-16 string that matches the key in the target `km_kbp_option_item`. +- __key__: A UTF-16 string that matches the key in the target `km_core_option_item`. - __value__: A pointer to the result variable: A pointer to a UTF-16 string value owned by the state or keyboard object at the time of the call. This pointer is only valid *until* the next call to any @@ -601,47 +601,47 @@ Lookup an option based on its key, in an options list. ```c */ KMN_API -km_kbp_status -km_kbp_state_option_lookup(km_kbp_state const *state, +km_core_status +km_core_state_option_lookup(km_core_state const *state, uint8_t scope, - km_kbp_cp const *key, - km_kbp_cp const **value); + km_core_cp const *key, + km_core_cp const **value); /* ``` -### `km_kbp_state_options_update` +### `km_core_state_options_update` ##### Description: -Adds or updates one or more options from a list of `km_kbp_option_item`s. +Adds or updates one or more options from a list of `km_core_option_item`s. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_NO_MEM`: In the event an internal memory allocation fails. -- `KM_KBP_STATUS_KEY_ERROR`: The key cannot be found. +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_NO_MEM`: In the event an internal memory allocation fails. +- `KM_CORE_STATUS_KEY_ERROR`: The key cannot be found. ##### Parameters: - __state__: An opaque pointer to a state object. -- __new_opts__: An array of `km_kbp_option_item` objects to update or add. Must be - terminated with `KM_KBP_OPTIONS_END`. +- __new_opts__: An array of `km_core_option_item` objects to update or add. Must be + terminated with `KM_CORE_OPTIONS_END`. ```c */ KMN_API -km_kbp_status -km_kbp_state_options_update(km_kbp_state *state, - km_kbp_option_item const *new_opts); +km_core_status +km_core_state_options_update(km_core_state *state, + km_core_option_item const *new_opts); /* ``` -### `km_kbp_state_options_to_json` +### `km_core_state_options_to_json` ##### Description: -Export the contents of a `km_kbp_options` array to a JSON formatted document and +Export the contents of a `km_core_options` array to a JSON formatted document and place it in the supplied buffer, reporting how much space was used. If null is passed as the buffer the number of bytes required is returned in `space`. If there is insufficent space to hold the document the contents of the buffer is undefined. The returned buffer uses UTF-8 encoding. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. -- `KM_KBP_STATUS_NO_MEM`: In the event an internal memory allocation fails. +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_NO_MEM`: In the event an internal memory allocation fails. ##### Parameters: - __state__: An opaque pointer to a state object. - __buf__: A pointer to the buffer to place the C string containing the JSON @@ -653,8 +653,8 @@ null. On return it will hold how many bytes were used. ```c */ KMN_API -km_kbp_status -km_kbp_state_options_to_json(km_kbp_state const *state, +km_core_status +km_core_state_options_to_json(km_core_state const *state, char *buf, size_t *space); @@ -669,63 +669,63 @@ of state objects. ```c */ typedef struct { - km_kbp_cp const * version_string; // Processor specific version string. - km_kbp_cp const * id; // Keyman keyboard ID string. - km_kbp_path_name folder_path; // Path to the unpacked folder containing + km_core_cp const * version_string; // Processor specific version string. + km_core_cp const * id; // Keyman keyboard ID string. + km_core_path_name folder_path; // Path to the unpacked folder containing // the keyboard and associated resources. - km_kbp_option_item const * default_options; -} km_kbp_keyboard_attrs; + km_core_option_item const * default_options; +} km_core_keyboard_attrs; typedef struct { - km_kbp_virtual_key key; + km_core_virtual_key key; uint32_t modifier_flag; -} km_kbp_keyboard_key; +} km_core_keyboard_key; -#define KM_KBP_KEYBOARD_KEY_LIST_END { 0, 0 } +#define KM_CORE_KEYBOARD_KEY_LIST_END { 0, 0 } typedef struct { - km_kbp_cp const * library_name; - km_kbp_cp const * function_name; + km_core_cp const * library_name; + km_core_cp const * function_name; uint32_t imx_id; // unique identifier used to call this function -} km_kbp_keyboard_imx; +} km_core_keyboard_imx; -#define KM_KBP_KEYBOARD_IMX_END { 0, 0, 0 } +#define KM_CORE_KEYBOARD_IMX_END { 0, 0, 0 } /* ``` -### `km_kbp_keyboard_load` +### `km_core_keyboard_load` ##### Description: Parse and load keyboard from the supplied path and a pointer to the loaded keyboard into the out paramter. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_NO_MEM`: In the event an internal memory allocation fails. -- `KM_KBP_STATUS_IO_ERROR`: +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_NO_MEM`: In the event an internal memory allocation fails. +- `KM_CORE_STATUS_IO_ERROR`: In the event the keyboard file is unparseable for any reason -- `KM_KBP_STATUS_INVALID_ARGUMENT`: +- `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the file doesn't exist or is inaccesible or `keyboard` is null. -- `KM_KBP_STATUS_OS_ERROR`: Bit 31 (high bit) set, bits 0-30 are an OS-specific +- `KM_CORE_STATUS_OS_ERROR`: Bit 31 (high bit) set, bits 0-30 are an OS-specific error code. ##### Parameters: - __kb_path__: On Windows, a UTF-16 string; on other platforms, a C string: contains a valid path to the keyboard file. - __keyboard__: A pointer to result variable: A pointer to the opaque keyboard object returned by the Processor. This - memory must be freed with a call to `km_kbp_keyboard_dispose`. + memory must be freed with a call to `km_core_keyboard_dispose`. ```c */ KMN_API -km_kbp_status -km_kbp_keyboard_load(km_kbp_path_name kb_path, - km_kbp_keyboard **keyboard); +km_core_status +km_core_keyboard_load(km_core_path_name kb_path, + km_core_keyboard **keyboard); /* ``` -### `km_kbp_keyboard_dispose` +### `km_core_keyboard_dispose` ##### Description: Free the allocated memory belonging to an opaque keyboard object previously -returned by `km_kbp_keyboard_load`. +returned by `km_core_keyboard_load`. ##### Parameters: - __keyboard__: A pointer to the opaque keyboard object to be disposed of. @@ -734,57 +734,57 @@ returned by `km_kbp_keyboard_load`. */ KMN_API void -km_kbp_keyboard_dispose(km_kbp_keyboard *keyboard); +km_core_keyboard_dispose(km_core_keyboard *keyboard); /* ``` -### `km_kbp_keyboard_get_attrs` +### `km_core_keyboard_get_attrs` ##### Description: Returns the const internal attributes of the keyboard. This structure is valid for the lifetime of the opaque keyboard object. Do not modify the returned data. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. ##### Parameters: - __keyboard__: A pointer to the opaque keyboard object to be queried. - __out__: A pointer to the result: - A pointer to a `km_kbp_keyboard_attrs` structure. + A pointer to a `km_core_keyboard_attrs` structure. ```c */ KMN_API -km_kbp_status -km_kbp_keyboard_get_attrs(km_kbp_keyboard const *keyboard, - km_kbp_keyboard_attrs const **out); +km_core_status +km_core_keyboard_get_attrs(km_core_keyboard const *keyboard, + km_core_keyboard_attrs const **out); /* ``` -### `km_kbp_keyboard_get_key_list` +### `km_core_keyboard_get_key_list` ##### Description: Returns the unordered full set of modifier+virtual keys that are handled by the keyboard. The matching dispose call needs to be called to free the memory. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are null. ##### Parameters: - __keyboard__: A pointer to the opaque keyboard object to be queried. -- __out__: A pointer to an array of `km_kbp_keyboard_key` structures, - terminated by `KM_KBP_KEYBOARD_KEY_LIST_END`. +- __out__: A pointer to an array of `km_core_keyboard_key` structures, + terminated by `KM_CORE_KEYBOARD_KEY_LIST_END`. ```c */ KMN_API -km_kbp_status -km_kbp_keyboard_get_key_list(km_kbp_keyboard const *keyboard, - km_kbp_keyboard_key **out); +km_core_status +km_core_keyboard_get_key_list(km_core_keyboard const *keyboard, + km_core_keyboard_key **out); /** ``` -### `km_kbp_keyboard_key_list_dispose` +### `km_core_keyboard_key_list_dispose` ##### Description: Free the allocated memory belonging to a keyboard key list previously -returned by `km_kbp_keyboard_get_key_list`. +returned by `km_core_keyboard_get_key_list`. ##### Parameters: - __key_list__: A pointer to the keyboard key list to be disposed of. @@ -792,46 +792,46 @@ returned by `km_kbp_keyboard_get_key_list`. ```c */ KMN_API -void km_kbp_keyboard_key_list_dispose(km_kbp_keyboard_key *key_list); +void km_core_keyboard_key_list_dispose(km_core_keyboard_key *key_list); /** - * km_kbp_keyboard_get_imx_list: + * km_core_keyboard_get_imx_list: * * Returns: the list of IMX libraries and function names that are referenced by * the keyboard.The matching dispose call needs to be called to free the memory. */ KMN_API -km_kbp_status km_kbp_keyboard_get_imx_list(km_kbp_keyboard const *keyboard, km_kbp_keyboard_imx **imx_list); +km_core_status km_core_keyboard_get_imx_list(km_core_keyboard const *keyboard, km_core_keyboard_imx **imx_list); /** - * km_kbp_keyboard_imx_list_dispose: + * km_core_keyboard_imx_list_dispose: * * Disposes of the IMX list * * Returns: -- */ KMN_API -void km_kbp_keyboard_imx_list_dispose(km_kbp_keyboard_imx *imx_list); +void km_core_keyboard_imx_list_dispose(km_core_keyboard_imx *imx_list); /** - * km_kbp_state_imx_register_callback: + * km_core_state_imx_register_callback: * * Register the IMX callback endpoint for the client. * * Returns: -- */ KMN_API -void km_kbp_state_imx_register_callback(km_kbp_state *state, km_kbp_keyboard_imx_platform imx_callback, void *callback_object); +void km_core_state_imx_register_callback(km_core_state *state, km_core_keyboard_imx_platform imx_callback, void *callback_object); /** - * km_kbp_state_imx_deregister_callback: + * km_core_state_imx_deregister_callback: * * De-register IMX callback endpoint for the client. * * Returns: -- */ KMN_API -void km_kbp_state_imx_deregister_callback(km_kbp_state *state); +void km_core_state_imx_deregister_callback(km_core_state *state); /* ``` @@ -844,45 +844,45 @@ and dynamic options ("option stores" in kmn format). /* ``` -### `km_kbp_state_create` +### `km_core_state_create` ##### Description: Create a keyboard processor state object, maintaining state for the keyboard in the environment passed. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_NO_MEM`: +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_NO_MEM`: In the event memory is unavailable to allocate a state object. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: +- `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the `keyboard` or `out` pointer are null. ##### Parameters: - __keyboard__: A pointer to the opaque keyboard object this object will hold state for. - __env__: -The array of `km_kbp_option_item` key/value pairs used to initialise the -environment, terminated by `KM_KBP_OPTIONS_END`. +The array of `km_core_option_item` key/value pairs used to initialise the +environment, terminated by `KM_CORE_OPTIONS_END`. - __out__: A pointer to result variable: A pointer to the opaque state object returned by the Processor, initalised to maintain state for `keyboard`. -This must be disposed of by a call to `km_kbp_state_dispose`. +This must be disposed of by a call to `km_core_state_dispose`. ```c */ KMN_API -km_kbp_status -km_kbp_state_create(km_kbp_keyboard *keyboard, - km_kbp_option_item const *env, - km_kbp_state **out); +km_core_status +km_core_state_create(km_core_keyboard *keyboard, + km_core_option_item const *env, + km_core_state **out); /* ``` -### `km_kbp_state_clone` +### `km_core_state_clone` ##### Description: Clone an existing opaque state object. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_NO_MEM`: +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_NO_MEM`: In the event memory is unavailable to allocate a state object. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: +- `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the `state` or `out` pointer are null. ##### Parameters: - __state__: @@ -890,22 +890,22 @@ A pointer to the opaque statea object to be cloned. - __out__: A pointer to result variable: A pointer to the opaque state object returned by the Processor, cloned from the existing object `state`. This -must be disposed of by a call to `km_kbp_state_dispose`. +must be disposed of by a call to `km_core_state_dispose`. ```c */ KMN_API -km_kbp_status -km_kbp_state_clone(km_kbp_state const *state, - km_kbp_state **out); +km_core_status +km_core_state_clone(km_core_state const *state, + km_core_state **out); /* ``` -### `km_kbp_state_dispose` +### `km_core_state_dispose` ##### Description: -Free the allocated resources belonging to a `km_kbp_state` object previously -returned by `km_kbp_state_create` or `km_kbp_state_clone`. After this all -pointers previously returned by any km_kbp_state family of calls will become +Free the allocated resources belonging to a `km_core_state` object previously +returned by `km_core_state_create` or `km_core_state_clone`. After this all +pointers previously returned by any km_core_state family of calls will become invalid. ##### Parameters: - __state__: A pointer to the opaque state object to be disposed. @@ -914,11 +914,11 @@ invalid. */ KMN_API void -km_kbp_state_dispose(km_kbp_state *state); +km_core_state_dispose(km_core_state *state); /* ``` -### `km_kbp_state_context` +### `km_core_state_context` ##### Description: Get access to the state object's context. ##### Return: @@ -930,8 +930,8 @@ of the state object. If null is passed in, then null is returned. ```c */ KMN_API -km_kbp_context * -km_kbp_state_context(km_kbp_state *state); +km_core_context * +km_core_state_context(km_core_state *state); /* @@ -942,68 +942,68 @@ Get access to the state object's keyboard processor's intermediate context. This is used during an IMX callback, part way through processing a keystroke. ##### Return: A pointer to an context item array. Must be disposed of by a call -to `km_kbp_context_items_dispose`. +to `km_core_context_items_dispose`. ##### Parameters: - __state__: A pointer to the opaque state object to be queried. ```c */ KMN_API -km_kbp_status -kbp_state_get_intermediate_context(km_kbp_state *state, km_kbp_context_item ** context_items); +km_core_status +kbp_state_get_intermediate_context(km_core_state *state, km_core_context_item ** context_items); /* ``` -### `km_kbp_state_action_items` +### `km_core_state_action_items` ##### Description: Get the list of action items generated by the last call to -`km_kbp_process_event`. +`km_core_process_event`. ##### Return: -A pointer to a `km_kbp_action_item` list, of `*num_items` in length. This data +A pointer to a `km_core_action_item` list, of `*num_items` in length. This data becomes invalid when the state object is destroyed, or after a call to -`km_kbp_process_event`. Do not modify the contents of this data. The returned -array is terminated with a `KM_KBP_IT_END` entry. +`km_core_process_event`. Do not modify the contents of this data. The returned +array is terminated with a `KM_CORE_IT_END` entry. ##### Parameters: -- __state__: A pointer to the opaque `km_kbp_state` object to be queried. +- __state__: A pointer to the opaque `km_core_state` object to be queried. - __num_items__: A pointer to a result variable: The number of items in the action item list -including the `KM_KBP_IT_END` terminator. May be null if not that +including the `KM_CORE_IT_END` terminator. May be null if not that information is required. ```c */ KMN_API -km_kbp_action_item const * -km_kbp_state_action_items(km_kbp_state const *state, +km_core_action_item const * +km_core_state_action_items(km_core_state const *state, size_t *num_items); /* ``` -### `km_kbp_state_queue_action_items` +### `km_core_state_queue_action_items` ##### Description: Queue actions for the current keyboard processor state; normally -used in IMX callbacks called during `km_kbp_process_event`. +used in IMX callbacks called during `km_core_process_event`. ##### Return: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the `state` or `action_items` pointer are null. ##### Parameters: -- __state__: A pointer to the opaque `km_kbp_state` object to be queried. -- __action_items__: The action items to be added to the keyboardprocessor - queue. Must be terminated with a `KM_KBP_IT_END` entry. +- __state__: A pointer to the opaque `km_core_state` object to be queried. +- __action_items__: The action items to be added to the core + queue. Must be terminated with a `KM_CORE_IT_END` entry. ```c */ KMN_API -km_kbp_status -km_kbp_state_queue_action_items(km_kbp_state *state, - km_kbp_action_item const *action_items); +km_core_status +km_core_state_queue_action_items(km_core_state *state, + km_core_action_item const *action_items); /* ``` ### `km_kpb_state_to_json` ##### Description: -Export the internal state of a `km_kbp_state` object to a JSON format document +Export the internal state of a `km_core_state` object to a JSON format document and place it in the supplied buffer, reporting how much space was used. If null is passed as the buffer the number of bytes required is returned. If there is insufficent space to hold the document, the contents of the buffer is undefined. @@ -1014,8 +1014,8 @@ versioned is not part of this API and is intended solely for use in diagnostics or by development and debugging tools which are aware of processor implementation details. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_NO_MEM`: In the event an internal memory allocation fails. +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_NO_MEM`: In the event an internal memory allocation fails. ##### Parameters: - __state__: An pointer to an opaque state object. - __buf__: A pointer to the buffer to place the C string containing the JSON @@ -1027,8 +1027,8 @@ null. On return it will hold how many bytes were used. ```c */ KMN_API -km_kbp_status -km_kbp_state_to_json(km_kbp_state const *state, +km_core_status +km_core_state_to_json(km_core_state const *state, char *buf, size_t *space); @@ -1045,44 +1045,44 @@ typedef struct { uint16_t technology; // A bit field specifiying which Keyboard // technologies the engine supports. char const *vendor; // Implementor of the processor. -} km_kbp_attr; +} km_core_attr; -enum km_kbp_tech_value { - KM_KBP_TECH_UNSPECIFIED = 0, - KM_KBP_TECH_MOCK = 1 << 0, - KM_KBP_TECH_KMX = 1 << 1, - KM_KBP_TECH_LDML = 1 << 2 +enum km_core_tech_value { + KM_CORE_TECH_UNSPECIFIED = 0, + KM_CORE_TECH_MOCK = 1 << 0, + KM_CORE_TECH_KMX = 1 << 1, + KM_CORE_TECH_LDML = 1 << 2 }; /** - * km_kbp_event_flags: + * km_core_event_flags: * - * Bit flags to be used with the event_flags parameter of km_kbp_process_event + * Bit flags to be used with the event_flags parameter of km_core_process_event */ -enum km_kbp_event_flags { - KM_KBP_EVENT_FLAG_DEFAULT = 0, // default value: hardware - KM_KBP_EVENT_FLAG_TOUCH = 1, // set if the event is touch, otherwise hardware +enum km_core_event_flags { + KM_CORE_EVENT_FLAG_DEFAULT = 0, // default value: hardware + KM_CORE_EVENT_FLAG_TOUCH = 1, // set if the event is touch, otherwise hardware }; /* ``` -### `km_kbp_get_engine_attrs` +### `km_core_get_engine_attrs` ##### Description: Get access processors attributes describing version and technology implemented. ##### Return: -A pointer to a `km_kbp_attr` structure. Do not modify the contents of this +A pointer to a `km_core_attr` structure. Do not modify the contents of this structure. ##### Parameters: -- __state__: An opaque pointer to an `km_kbp_state`. +- __state__: An opaque pointer to an `km_core_state`. ```c */ KMN_API -km_kbp_attr const * -km_kbp_get_engine_attrs(km_kbp_state const *state); +km_core_attr const * +km_core_get_engine_attrs(km_core_state const *state); /* ``` -### `km_kbp_process_event` +### `km_core_process_event` ##### Description: Run the keyboard on an opaque state object with the provided virtual key and modifer key state. Updates the state object as appropriate and fills out its action list. @@ -1090,10 +1090,10 @@ key state. Updates the state object as appropriate and fills out its action list The action list will be cleared at the start of this call; options and context in the state may also be modified. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_NO_MEM`: +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_NO_MEM`: In the event memory is unavailable to allocate internal buffers. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: +- `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the `state` pointer is null or an invalid virtual key or modifier state is passed. @@ -1102,35 +1102,35 @@ state is passed. - __vk__: A virtual key to be processed. - __modifier_state__: The combinations of modifier keys set at the time key `vk` was pressed, bitmask -from the `km_kbp_modifier_state` enum. -- __event_flags__: Event level flags, see km_kbp_event_flags +from the `km_core_modifier_state` enum. +- __event_flags__: Event level flags, see km_core_event_flags ```c */ KMN_API -km_kbp_status -km_kbp_process_event(km_kbp_state *state, - km_kbp_virtual_key vk, +km_core_status +km_core_process_event(km_core_state *state, + km_core_virtual_key vk, uint16_t modifier_state, uint8_t is_key_down, uint16_t event_flags); /* ``` -### `km_kbp_process_queued_actions` +### `km_core_process_queued_actions` ##### Description: Process the keyboard processors queued actions for the opaque state object. Updates the state object as appropriate and fills out its action list. -The client can add actions externally via the `km_kbp_state_queue_action_items` and +The client can add actions externally via the `km_core_state_queue_action_items` and then request the processing of the actions with this method. The state action list will be cleared at the start of this call; options and context in the state may also be modified. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_NO_MEM`: +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_NO_MEM`: In the event memory is unavailable to allocate internal buffers. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: +- `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the `state` pointer is null ##### Parameters: @@ -1139,20 +1139,20 @@ In the event the `state` pointer is null ```c */ KMN_API -km_kbp_status -km_kbp_process_queued_actions(km_kbp_state *state); +km_core_status +km_core_process_queued_actions(km_core_state *state); /* ``` -### `km_kbp_event` +### `km_core_event` ##### Description: Tell the keyboard processor that an external event has occurred, such as a keyboard being activated through the language switching UI. ##### Return status: -- `KM_KBP_STATUS_OK`: On success. -- `KM_KBP_STATUS_NO_MEM`: +- `KM_CORE_STATUS_OK`: On success. +- `KM_CORE_STATUS_NO_MEM`: In the event memory is unavailable to allocate internal buffers. -- `KM_KBP_STATUS_INVALID_ARGUMENT`: +- `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the `state` pointer is null or an invalid event or data is passed. The keyboard processor may generate actions which should be processed by the @@ -1163,24 +1163,24 @@ the state may also be modified. ##### Parameters: - __state__: A pointer to the opaque state object. -- __event__: The event to be processed, from km_kbp_event_code enumeration +- __event__: The event to be processed, from km_core_event_code enumeration - __data__: Additional event-specific data. Currently unused, must be nullptr. ```c */ KMN_API -km_kbp_status -km_kbp_event( - km_kbp_state *state, +km_core_status +km_core_event( + km_core_state *state, uint32_t event, void* data ); -enum km_kbp_event_code { +enum km_core_event_code { // A keyboard has been activated by the user. The processor may use this // event, for example, to switch caps lock state or provide other UX. - KM_KBP_EVENT_KEYBOARD_ACTIVATED = 1, - //future: KM_KBP_EVENT_KEYBOARD_DEACTIVATED = 2, + KM_CORE_EVENT_KEYBOARD_ACTIVATED = 1, + //future: KM_CORE_EVENT_KEYBOARD_DEACTIVATED = 2, }; #if defined(__cplusplus) diff --git a/core/include/keyman/keyboardprocessor_bits.h b/core/include/keyman/keyman_core_api_bits.h similarity index 96% rename from core/include/keyman/keyboardprocessor_bits.h rename to core/include/keyman/keyman_core_api_bits.h index 03892a62afb..be2886d0583 100644 --- a/core/include/keyman/keyboardprocessor_bits.h +++ b/core/include/keyman/keyman_core_api_bits.h @@ -27,7 +27,7 @@ #endif #if defined _WIN32 || defined __CYGWIN__ - typedef wchar_t const * km_kbp_path_name; + typedef wchar_t const * km_core_path_name; #define _KM_KBP_PATH_SEPARATOR (L'\\') #define _KM_KBP_EXT_SEPARATOR (L'.') #if defined __GNUC__ // These three will be redefined for Windows @@ -43,7 +43,7 @@ #define _kmn_import_flag dllimport #define _kmn_static_flag #else - typedef char const * km_kbp_path_name; + typedef char const * km_core_path_name; #define _KM_KBP_PATH_SEPARATOR ('/') #define _KM_KBP_EXT_SEPARATOR ('.') #endif diff --git a/core/include/keyman/keyman_core_api_consts.h b/core/include/keyman/keyman_core_api_consts.h new file mode 100644 index 00000000000..67d72edb3d1 --- /dev/null +++ b/core/include/keyman/keyman_core_api_consts.h @@ -0,0 +1,9 @@ +#pragma once + +// Defined environment options for KMX processor +#define KM_CORE_KMX_ENV_PLATFORM u"platform" +#define KM_CORE_KMX_ENV_BASELAYOUT u"baseLayout" +#define KM_CORE_KMX_ENV_BASELAYOUTALT u"baseLayoutAlt" +#define KM_CORE_KMX_ENV_SIMULATEALTGR u"simulateAltgr" +#define KM_CORE_KMX_ENV_CAPSLOCK u"capsLock" +#define KM_CORE_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT u"baseLayoutGivesCtrlRAltForRAlt" diff --git a/core/include/keyman/keyboardprocessor_debug.h b/core/include/keyman/keyman_core_api_debug.h similarity index 60% rename from core/include/keyman/keyboardprocessor_debug.h rename to core/include/keyman/keyman_core_api_debug.h index 380b8ee3012..8f80481d2c5 100644 --- a/core/include/keyman/keyboardprocessor_debug.h +++ b/core/include/keyman/keyman_core_api_debug.h @@ -15,8 +15,8 @@ #include #include -#include -#include +#include +#include #if defined(__cplusplus) extern "C" @@ -24,7 +24,7 @@ extern "C" #endif /** - * The maximum size of context in km_kbp_cp units for a single debug + * The maximum size of context in km_core_cp units for a single debug * event. This is taken from MAXCONTEXT in keyman32 (Windows) and is purely * a convenience value. We can increase it if there is a demonstrated need. */ @@ -42,31 +42,31 @@ extern "C" * These modifier flags are used internally in the kmx engine, so will be * exposed only in debugging modifier states. */ -#define KM_KBP_MODIFIER_VIRTUALKEY 0x4000 -#define KM_KBP_MODIFIER_VIRTUALCHARKEY 0x8000 +#define KM_CORE_MODIFIER_VIRTUALKEY 0x4000 +#define KM_CORE_MODIFIER_VIRTUALCHARKEY 0x8000 /** * Input key event data. The `character` member is derived from * a US English key event for vk + modifier_state, and is 0 if * the vk + modifier_state do not generate a character. * - * Used only in event type KM_KBP_DEBUG_BEGIN. + * Used only in event type KM_CORE_DEBUG_BEGIN. */ typedef struct { uint16_t vk; uint16_t modifier_state; char16_t character; -} km_kbp_state_debug_key_info; +} km_core_state_debug_key_info; /** * Option event data. * - * Used only in event type KM_KBP_DEBUG_SET_OPTION. + * Used only in event type KM_CORE_DEBUG_SET_OPTION. */ typedef struct { void *store; // LPSTORE - km_kbp_cp value[DEBUG_MAX_CONTEXT]; // value to be saved into the store -} km_kbp_state_debug_kmx_option_info; + km_core_cp value[DEBUG_MAX_CONTEXT]; // value to be saved into the store +} km_core_state_debug_kmx_option_info; /** * KMX processor data for each event. kmx_base.h defines the types that are @@ -76,11 +76,11 @@ typedef struct { * The context value here will be an intermediate value, and may differ * from event to event as the context can be rewritten for each rule match. * - * Used in all event types except KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_END. + * Used in all event types except KM_CORE_DEBUG_BEGIN, KM_CORE_DEBUG_END. */ typedef struct { - km_kbp_cp context[DEBUG_MAX_CONTEXT]; // The context matched by the rule (? may not need this?) // TODO: rename to context_matched + km_core_cp context[DEBUG_MAX_CONTEXT]; // The context matched by the rule (? may not need this?) // TODO: rename to context_matched void *group; // LPGROUP void *rule; // LPKEY uint16_t store_offsets[DEBUG_STORE_OFFSETS_SIZE]; // pairs--store, char position, terminated by 0xFFFF // TODO use a better structure here @@ -89,8 +89,8 @@ typedef struct { /// the debugger; the debugger uses this to determine when to /// execute the actions when single-stepping. uint16_t first_action; - km_kbp_state_debug_kmx_option_info option; -} km_kbp_state_debug_kmx_info; + km_core_state_debug_kmx_option_info option; +} km_core_state_debug_kmx_info; /** * A single debug event. @@ -98,38 +98,38 @@ typedef struct { typedef struct { uint32_t type; // 32 bits is better optimized than 8 bits uint32_t flags; - km_kbp_state_debug_key_info key_info; - km_kbp_state_debug_kmx_info kmx_info; -} km_kbp_state_debug_item; + km_core_state_debug_key_info key_info; + km_core_state_debug_kmx_info kmx_info; +} km_core_state_debug_item; /** * A single debug event. */ -enum km_kbp_debug_type { - KM_KBP_DEBUG_BEGIN = 0, - //KM_KBP_DEBUG_BEGIN_ANSI = 1, // not supported; instead rewrite ansi keyboards to Unicode with mcompile - KM_KBP_DEBUG_GROUP_ENTER = 2, - KM_KBP_DEBUG_GROUP_EXIT = 3, - KM_KBP_DEBUG_RULE_ENTER = 4, - KM_KBP_DEBUG_RULE_EXIT = 5, - KM_KBP_DEBUG_MATCH_ENTER = 6, - KM_KBP_DEBUG_MATCH_EXIT = 7, - KM_KBP_DEBUG_NOMATCH_ENTER = 8, - KM_KBP_DEBUG_NOMATCH_EXIT = 9, - KM_KBP_DEBUG_END = 10, - KM_KBP_DEBUG_SET_OPTION = 11, +enum km_core_debug_type { + KM_CORE_DEBUG_BEGIN = 0, + //KM_CORE_DEBUG_BEGIN_ANSI = 1, // not supported; instead rewrite ansi keyboards to Unicode with mcompile + KM_CORE_DEBUG_GROUP_ENTER = 2, + KM_CORE_DEBUG_GROUP_EXIT = 3, + KM_CORE_DEBUG_RULE_ENTER = 4, + KM_CORE_DEBUG_RULE_EXIT = 5, + KM_CORE_DEBUG_MATCH_ENTER = 6, + KM_CORE_DEBUG_MATCH_EXIT = 7, + KM_CORE_DEBUG_NOMATCH_ENTER = 8, + KM_CORE_DEBUG_NOMATCH_EXIT = 9, + KM_CORE_DEBUG_END = 10, + KM_CORE_DEBUG_SET_OPTION = 11, }; -// Flags for KM_KBP_DEBUG_GROUP_EXIT -#define KM_KBP_DEBUG_FLAG_RECURSIVE_OVERFLOW 0x0001 -#define KM_KBP_DEBUG_FLAG_NOMATCH 0x0002 +// Flags for KM_CORE_DEBUG_GROUP_EXIT +#define KM_CORE_DEBUG_FLAG_RECURSIVE_OVERFLOW 0x0001 +#define KM_CORE_DEBUG_FLAG_NOMATCH 0x0002 -// Flags for KM_KBP_DEBUG_BEGIN +// Flags for KM_CORE_DEBUG_BEGIN // TODO: do we need this at all? -#define KM_KBP_DEBUG_FLAG_UNICODE 0x0001 // Always set +#define KM_CORE_DEBUG_FLAG_UNICODE 0x0001 // Always set -// Flags for KM_KBP_DEBUG_END -#define KM_KBP_DEBUG_FLAG_OUTPUTKEYSTROKE 0x0001 +// Flags for KM_CORE_DEBUG_END +#define KM_CORE_DEBUG_FLAG_OUTPUTKEYSTROKE 0x0001 /** * Enable or disable debug tracing @@ -137,11 +137,11 @@ enum km_kbp_debug_type { * @param state Pointer to initialized state * @param value Set to 1 to enable debugging, 0 to disable * - * @returns KM_KBP_STATUS_OK on success + * @returns KM_CORE_STATUS_OK on success */ KMN_API -km_kbp_status -km_kbp_state_debug_set(km_kbp_state *state, int value); +km_core_status +km_core_state_debug_set(km_core_state *state, int value); /** * Get current debug tracing status @@ -152,7 +152,7 @@ km_kbp_state_debug_set(km_kbp_state *state, int value); */ KMN_API uint8_t -km_kbp_state_debug_get(km_kbp_state const *state); +km_core_state_debug_get(km_core_state const *state); /** * Read current debug trace log @@ -162,11 +162,11 @@ km_kbp_state_debug_get(km_kbp_state const *state); * nullptr if not required. * * @returns pointer to read only array of debug item events, - * with last entry guaranteed to be KM_KBP_DEBUG_END. + * with last entry guaranteed to be KM_CORE_DEBUG_END. */ KMN_API -km_kbp_state_debug_item const * -km_kbp_state_debug_items(km_kbp_state const *state, size_t *num_items); +km_core_state_debug_item const * +km_core_state_debug_items(km_core_state const *state, size_t *num_items); #if defined(__cplusplus) } // extern "C" diff --git a/core/include/keyman/keyman_core_api_version.h.in b/core/include/keyman/keyman_core_api_version.h.in new file mode 100644 index 00000000000..064a1391547 --- /dev/null +++ b/core/include/keyman/keyman_core_api_version.h.in @@ -0,0 +1,15 @@ +#define km_core_version_stringify(x) km_core_version_to_string(x) +#define km_core_version_to_string(x) #x + +// Product versioning + +#define KM_CORE_VERSION_MAJOR @majorver@ +#define KM_CORE_VERSION_MINOR @minorver@ +#define KM_CORE_VERSION_PATCH @patchver@ +#define KM_CORE_VERSION_STRING km_core_version_stringify(@majorver@ ## . ## @minorver@ ## . ## @patchver@ ## .0) + +// API versioning + +#define KM_CORE_LIB_CURRENT @lib_curr@ +#define KM_CORE_LIB_AGE @lib_age@ +#define KM_CORE_LIB_REVISION @lib_rev@ diff --git a/core/include/keyman/keyman_core_api_vkeys.h b/core/include/keyman/keyman_core_api_vkeys.h new file mode 100644 index 00000000000..7e4a6d181aa --- /dev/null +++ b/core/include/keyman/keyman_core_api_vkeys.h @@ -0,0 +1,312 @@ +/* + Copyright: © 2018 SIL International. + Description: API declarations for modifier keys, handy access masks and + Keyman VKEY names. These follow the same keytop->code + associations as the Windows API. This is a separate header to + maintain readability of the primary API header. + Create Date: 17 Oct 2018 + Authors: Tim Eves (TSE) + History: 17 Oct 2018 - TSE - Moved & refactored km_core_modifier_state + from keyman_core_api.h. + - Added VKey and mask definitions. + 6 Oct 2018 - TSE - Move into keyman folder. + +*/ + +#pragma once + +enum km_core_modifier_state { + KM_CORE_MODIFIER_LCTRL = 1 << 0, + KM_CORE_MODIFIER_RCTRL = 1 << 1, + KM_CORE_MODIFIER_LALT = 1 << 2, + KM_CORE_MODIFIER_RALT = 1 << 3, + KM_CORE_MODIFIER_SHIFT = 1 << 4, + KM_CORE_MODIFIER_CTRL = 1 << 5, + KM_CORE_MODIFIER_ALT = 1 << 6, + /* + KM_CORE_MODIFIER_META = 1 << 7, // Either Meta-key flag (tentative). Not usable by keyboards currently + // Used internally (currently, only by KMW) to ensure Meta-key + // shortcuts safely bypass rules + // Meta key = Command key on macOS, Windows key on Windows + */ + KM_CORE_MODIFIER_CAPS = 1 << 8, + KM_CORE_MODIFIER_NOCAPS = 1 << 9, + /* + KM_CORE_MODIFIER_NUMLOCK = 1 << 10, + KM_CORE_MODIFIER_NONUMLOCK = 1 << 11, + KM_CORE_MODIFIER_SCROLLOCK = 1 << 12, + KM_CORE_MODIFIER_NOSCROLLOCK = 1 << 13, + KM_CORE_MODIFIER_VIRTUALKEY = 1 << 14, + */ +}; + +enum km_core_modifier_mask { + KM_CORE_MODIFIER_MASK_ALL = 0x7f, + KM_CORE_MODIFIER_MASK_ALT_GR_SIM = KM_CORE_MODIFIER_LCTRL|KM_CORE_MODIFIER_LALT, + KM_CORE_MODIFIER_MASK_CHIRAL = 0x1f, + KM_CORE_MODIFIER_MASK_IS_CHIRAL = 0x0f, + KM_CORE_MODIFIER_MASK_NON_CHIRAL = 0x7f, + KM_CORE_MODIFIER_MASK_CAPS = 0x0300, +/*KM_CORE_MODIFIER_MASK_NUMLOCK = 0x0C00, + KM_CORE_MODIFIER_MASK_SCROLLLOCK = 0x3000,*/ +}; + +// These are Windows API VKEYs, using Keyman VKEY names. +enum km_kpb_virtual_key { + KM_CORE_VKEY__00, + KM_CORE_VKEY_LBUTTON, + KM_CORE_VKEY_RBUTTON, + KM_CORE_VKEY_CANCEL, + KM_CORE_VKEY_MBUTTON, + KM_CORE_VKEY__05, + KM_CORE_VKEY__06, + KM_CORE_VKEY__07, + KM_CORE_VKEY_BKSP, + KM_CORE_VKEY_TAB, + KM_CORE_VKEY__0A, + KM_CORE_VKEY__0B, + KM_CORE_VKEY_KP5, + KM_CORE_VKEY_ENTER, + KM_CORE_VKEY__0E, + KM_CORE_VKEY__0F, + KM_CORE_VKEY_SHIFT, + KM_CORE_VKEY_CONTROL, + KM_CORE_VKEY_ALT, + KM_CORE_VKEY_PAUSE, + KM_CORE_VKEY_CAPS, + KM_CORE_VKEY__15, + KM_CORE_VKEY__16, + KM_CORE_VKEY__17, + KM_CORE_VKEY__18, + KM_CORE_VKEY__19, + KM_CORE_VKEY__1A, + KM_CORE_VKEY_ESC, + KM_CORE_VKEY__1C, + KM_CORE_VKEY__1D, + KM_CORE_VKEY__1E, + KM_CORE_VKEY__1F, + KM_CORE_VKEY_SPACE, + KM_CORE_VKEY_PGUP, + KM_CORE_VKEY_PGDN, + KM_CORE_VKEY_END, + KM_CORE_VKEY_HOME, + KM_CORE_VKEY_LEFT, + KM_CORE_VKEY_UP, + KM_CORE_VKEY_RIGHT, + KM_CORE_VKEY_DOWN, + KM_CORE_VKEY_SEL, + KM_CORE_VKEY_PRINT, + KM_CORE_VKEY_EXEC, + KM_CORE_VKEY_PRTSCN, + KM_CORE_VKEY_INS, + KM_CORE_VKEY_DEL, + KM_CORE_VKEY_HELP, + KM_CORE_VKEY_0, + KM_CORE_VKEY_1, + KM_CORE_VKEY_2, + KM_CORE_VKEY_3, + KM_CORE_VKEY_4, + KM_CORE_VKEY_5, + KM_CORE_VKEY_6, + KM_CORE_VKEY_7, + KM_CORE_VKEY_8, + KM_CORE_VKEY_9, + KM_CORE_VKEY__3A, + KM_CORE_VKEY__3B, + KM_CORE_VKEY__3C, + KM_CORE_VKEY__3D, + KM_CORE_VKEY__3E, + KM_CORE_VKEY__3F, + KM_CORE_VKEY__40, + KM_CORE_VKEY_A, + KM_CORE_VKEY_B, + KM_CORE_VKEY_C, + KM_CORE_VKEY_D, + KM_CORE_VKEY_E, + KM_CORE_VKEY_F, + KM_CORE_VKEY_G, + KM_CORE_VKEY_H, + KM_CORE_VKEY_I, + KM_CORE_VKEY_J, + KM_CORE_VKEY_K, + KM_CORE_VKEY_L, + KM_CORE_VKEY_M, + KM_CORE_VKEY_N, + KM_CORE_VKEY_O, + KM_CORE_VKEY_P, + KM_CORE_VKEY_Q, + KM_CORE_VKEY_R, + KM_CORE_VKEY_S, + KM_CORE_VKEY_T, + KM_CORE_VKEY_U, + KM_CORE_VKEY_V, + KM_CORE_VKEY_W, + KM_CORE_VKEY_X, + KM_CORE_VKEY_Y, + KM_CORE_VKEY_Z, + KM_CORE_VKEY__5B, + KM_CORE_VKEY__5C, + KM_CORE_VKEY__5D, + KM_CORE_VKEY__5E, + KM_CORE_VKEY__5F, + KM_CORE_VKEY_NP0, + KM_CORE_VKEY_NP1, + KM_CORE_VKEY_NP2, + KM_CORE_VKEY_NP3, + KM_CORE_VKEY_NP4, + KM_CORE_VKEY_NP5, + KM_CORE_VKEY_NP6, + KM_CORE_VKEY_NP7, + KM_CORE_VKEY_NP8, + KM_CORE_VKEY_NP9, + KM_CORE_VKEY_NPSTAR, + KM_CORE_VKEY_NPPLUS, + KM_CORE_VKEY_SEPARATOR, + KM_CORE_VKEY_NPMINUS, + KM_CORE_VKEY_NPDOT, + KM_CORE_VKEY_NPSLASH, + KM_CORE_VKEY_F1, + KM_CORE_VKEY_F2, + KM_CORE_VKEY_F3, + KM_CORE_VKEY_F4, + KM_CORE_VKEY_F5, + KM_CORE_VKEY_F6, + KM_CORE_VKEY_F7, + KM_CORE_VKEY_F8, + KM_CORE_VKEY_F9, + KM_CORE_VKEY_F10, + KM_CORE_VKEY_F11, + KM_CORE_VKEY_F12, + KM_CORE_VKEY_F13, + KM_CORE_VKEY_F14, + KM_CORE_VKEY_F15, + KM_CORE_VKEY_F16, + KM_CORE_VKEY_F17, + KM_CORE_VKEY_F18, + KM_CORE_VKEY_F19, + KM_CORE_VKEY_F20, + KM_CORE_VKEY_F21, + KM_CORE_VKEY_F22, + KM_CORE_VKEY_F23, + KM_CORE_VKEY_F24, + KM_CORE_VKEY__88, + KM_CORE_VKEY__89, + KM_CORE_VKEY__8A, + KM_CORE_VKEY__8B, + KM_CORE_VKEY__8C, + KM_CORE_VKEY__8D, + KM_CORE_VKEY__8E, + KM_CORE_VKEY__8F, + KM_CORE_VKEY_NUMLOCK, + KM_CORE_VKEY_SCROLL, + KM_CORE_VKEY__92, + KM_CORE_VKEY__93, + KM_CORE_VKEY__94, + KM_CORE_VKEY__95, + KM_CORE_VKEY__96, + KM_CORE_VKEY__97, + KM_CORE_VKEY__98, + KM_CORE_VKEY__99, + KM_CORE_VKEY__9A, + KM_CORE_VKEY__9B, + KM_CORE_VKEY__9C, + KM_CORE_VKEY__9D, + KM_CORE_VKEY__9E, + KM_CORE_VKEY__9F, + KM_CORE_VKEY__A0, + KM_CORE_VKEY__A1, + KM_CORE_VKEY__A2, + KM_CORE_VKEY__A3, + KM_CORE_VKEY__A4, + KM_CORE_VKEY__A5, + KM_CORE_VKEY__A6, + KM_CORE_VKEY__A7, + KM_CORE_VKEY__A8, + KM_CORE_VKEY__A9, + KM_CORE_VKEY__AA, + KM_CORE_VKEY__AB, + KM_CORE_VKEY__AC, + KM_CORE_VKEY__AD, + KM_CORE_VKEY__AE, + KM_CORE_VKEY__AF, + KM_CORE_VKEY__B0, + KM_CORE_VKEY__B1, + KM_CORE_VKEY__B2, + KM_CORE_VKEY__B3, + KM_CORE_VKEY__B4, + KM_CORE_VKEY__B5, + KM_CORE_VKEY__B6, + KM_CORE_VKEY__B7, + KM_CORE_VKEY__B8, + KM_CORE_VKEY__B9, + KM_CORE_VKEY_COLON, + KM_CORE_VKEY_EQUAL, + KM_CORE_VKEY_COMMA, + KM_CORE_VKEY_HYPHEN, + KM_CORE_VKEY_PERIOD, + KM_CORE_VKEY_SLASH, + KM_CORE_VKEY_BKQUOTE, + KM_CORE_VKEY__C1, + KM_CORE_VKEY__C2, + KM_CORE_VKEY__C3, + KM_CORE_VKEY__C4, + KM_CORE_VKEY__C5, + KM_CORE_VKEY__C6, + KM_CORE_VKEY__C7, + KM_CORE_VKEY__C8, + KM_CORE_VKEY__C9, + KM_CORE_VKEY__CA, + KM_CORE_VKEY__CB, + KM_CORE_VKEY__CC, + KM_CORE_VKEY__CD, + KM_CORE_VKEY__CE, + KM_CORE_VKEY__CF, + KM_CORE_VKEY__D0, + KM_CORE_VKEY__D1, + KM_CORE_VKEY__D2, + KM_CORE_VKEY__D3, + KM_CORE_VKEY__D4, + KM_CORE_VKEY__D5, + KM_CORE_VKEY__D6, + KM_CORE_VKEY__D7, + KM_CORE_VKEY__D8, + KM_CORE_VKEY__D9, + KM_CORE_VKEY__DA, + KM_CORE_VKEY_LBRKT, + KM_CORE_VKEY_BKSLASH, + KM_CORE_VKEY_RBRKT, + KM_CORE_VKEY_QUOTE, + KM_CORE_VKEY_oDF, + KM_CORE_VKEY_oE0, + KM_CORE_VKEY_oE1, + KM_CORE_VKEY_oE2, // 102nd key on European layouts + KM_CORE_VKEY_oE3, + KM_CORE_VKEY_oE4, + KM_CORE_VKEY__E5, + KM_CORE_VKEY_oE6, + KM_CORE_VKEY__E7, + KM_CORE_VKEY__E8, + KM_CORE_VKEY_oE9, + KM_CORE_VKEY_oEA, + KM_CORE_VKEY_oEB, + KM_CORE_VKEY_oEC, + KM_CORE_VKEY_oED, + KM_CORE_VKEY_oEE, + KM_CORE_VKEY_oEF, + KM_CORE_VKEY_oF0, + KM_CORE_VKEY_oF1, + KM_CORE_VKEY_oF2, + KM_CORE_VKEY_oF3, + KM_CORE_VKEY_oF4, + KM_CORE_VKEY_oF5, + KM_CORE_VKEY__F6, + KM_CORE_VKEY__F7, + KM_CORE_VKEY__F8, + KM_CORE_VKEY__F9, + KM_CORE_VKEY__FA, + KM_CORE_VKEY__FB, + KM_CORE_VKEY__FC, + KM_CORE_VKEY__FD, + KM_CORE_VKEY__FE, + KM_CORE_VKEY__FF, +}; diff --git a/core/include/keyman/meson.build b/core/include/keyman/meson.build index 7da255502de..8ef7d1a9f26 100644 --- a/core/include/keyman/meson.build +++ b/core/include/keyman/meson.build @@ -19,16 +19,16 @@ cfg.set('patchver', project_ver[2]) configure_file( configuration: cfg, - input: 'keyboardprocessor_version.h.in', - output: 'keyboardprocessor_version.h', + input: 'keyman_core_api_version.h.in', + output: 'keyman_core_api_version.h', ) -install_headers('keyboardprocessor.h', - 'keyboardprocessor_bits.h', - 'keyboardprocessor_consts.h', - 'keyboardprocessor_debug.h', - 'keyboardprocessor_vkeys.h', - join_paths(meson.current_build_dir(), 'keyboardprocessor_version.h'), +install_headers('keyman_core_api.h', + 'keyman_core_api_bits.h', + 'keyman_core_api_consts.h', + 'keyman_core_api_debug.h', + 'keyman_core_api_vkeys.h', + join_paths(meson.current_build_dir(), 'keyman_core_api_version.h'), '../../../common/include/km_types.h', '../../../common/include/kmx_file.h', subdir: 'keyman') diff --git a/core/include/ldml/keyboardprocessor_ldml.h b/core/include/ldml/keyboardprocessor_ldml.h index ae244ffbe75..45837b63855 100644 --- a/core/include/ldml/keyboardprocessor_ldml.h +++ b/core/include/ldml/keyboardprocessor_ldml.h @@ -16,6 +16,7 @@ #pragma once #define LDML_BKSP_FLAGS_ERROR 0x1 +#define LDML_CLDR_IMPLIED_FORMS_IMPORT "techpreview/scanCodes-implied.xml" #define LDML_CLDR_IMPLIED_KEYS_IMPORT "techpreview/keys-Latn-implied.xml" #define LDML_CLDR_IMPORT_BASE "cldr" #define LDML_CLDR_VERSION_LATEST "techpreview" @@ -45,11 +46,7 @@ #define LDML_KEYS_MOD_CTRLR 0x2 #define LDML_KEYS_MOD_NONE 0x0 #define LDML_KEYS_MOD_SHIFT 0x10 -#define LDML_LAYR_LIST_HARDWARE_ABNT2 0x1 -#define LDML_LAYR_LIST_HARDWARE_ISO 0x2 -#define LDML_LAYR_LIST_HARDWARE_JIS 0x3 -#define LDML_LAYR_LIST_HARDWARE_TOUCH 0x0 -#define LDML_LAYR_LIST_HARDWARE_US 0x4 +#define LDML_LAYR_LIST_HARDWARE_TOUCH "touch" #define LDML_LENGTH_BKSP 0xC #define LDML_LENGTH_BKSP_ITEM 0x10 #define LDML_LENGTH_DISP 0x10 @@ -91,8 +88,6 @@ #define LDML_LENGTH_USET_USET 0xC #define LDML_LENGTH_VARS 0x10 #define LDML_LENGTH_VARS_ITEM 0x10 -#define LDML_LENGTH_VKEY 0xC -#define LDML_LENGTH_VKEY_ITEM 0x8 #define LDML_MARKER_ANY_INDEX 0xD7FF #define LDML_MARKER_CODE 0x8 #define LDML_MARKER_MAX_COUNT 0xD7FE @@ -129,8 +124,6 @@ #define LDML_SECTIONNAME_USET "uset" #define LDML_SECTIONID_VARS 0x73726176 /* "vars" */ #define LDML_SECTIONNAME_VARS "vars" -#define LDML_SECTIONID_VKEY 0x79656B76 /* "vkey" */ -#define LDML_SECTIONNAME_VKEY "vkey" #define LDML_TRAN_FLAGS_ERROR 0x1 #define LDML_TRAN_GROUP_TYPE_REORDER 0x1 #define LDML_TRAN_GROUP_TYPE_TRANSFORM 0x0 diff --git a/core/include/ldml/keyboardprocessor_ldml.ts b/core/include/ldml/keyboardprocessor_ldml.ts index ed9ad899ed3..4e9aaedbb13 100644 --- a/core/include/ldml/keyboardprocessor_ldml.ts +++ b/core/include/ldml/keyboardprocessor_ldml.ts @@ -37,8 +37,7 @@ export type SectionIdent = 'strs' | 'tran' | 'uset' | - 'vars' | - 'vkey'; + 'vars'; type SectionMap = { @@ -74,6 +73,10 @@ class Constants { * implied keys file */ readonly cldr_implied_keys_import = `${this.cldr_version_techpreview}/keys-Latn-implied.xml`; + /** + * implied scancodes file + */ + readonly cldr_implied_forms_import = `${this.cldr_version_techpreview}/scanCodes-implied.xml`; /** * Length of a raw section header, in bytes */ @@ -350,35 +353,7 @@ class Constants { /** * for the 'hardware' field indicating a touch keyboard, non-hardware */ - readonly layr_list_hardware_touch = 0; - /** - * for the 'hardware' field indicating an abnt2 layout - */ - readonly layr_list_hardware_abnt2 = 1; - /** - * for the 'hardware' field indicating an iso layout - */ - readonly layr_list_hardware_iso = 2; - /** - * for the 'hardware' field indicating a jis layout - */ - readonly layr_list_hardware_jis = 3; - /** - * for the 'hardware' field indicating a us layout - */ - readonly layr_list_hardware_us = 4; - /** - * Convenience map of layr_list_hardware field values - */ - readonly layr_list_hardware_map: Map = new Map( - [ - ["touch", this.layr_list_hardware_touch], - ["abnt2", this.layr_list_hardware_abnt2], - ["iso", this.layr_list_hardware_iso], - ["jis", this.layr_list_hardware_jis], - ["us", this.layr_list_hardware_us], - ] - ); + readonly layr_list_hardware_touch = 'touch'; /** * Length of each layer entry in the 'layr' section variable part */ @@ -504,19 +479,6 @@ class Constants { */ readonly tran_group_type_reorder = 1; - /* ------------------------------------------------------------------ - * vkey section - ------------------------------------------------------------------ */ - - /** - * Minimum length of the 'vkey' section not including variable parts - */ - readonly length_vkey = 12; - /** - * Length of each item in the 'vkey' section variable part - */ - readonly length_vkey_item = 8; - /* ------------------------------------------------------------------ * vars section * ------------------------------------------------------------------ */ @@ -581,7 +543,6 @@ class Constants { tran: 'tran', uset: 'uset', vars: 'vars', - vkey: 'vkey', }; /** diff --git a/core/include/ldml/tsconfig.build.json b/core/include/ldml/tsconfig.build.json index 17c809a857a..fd0f003272c 100644 --- a/core/include/ldml/tsconfig.build.json +++ b/core/include/ldml/tsconfig.build.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.esm-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "composite": true, "declaration": true, diff --git a/core/include/ldml/tsconfig.json b/core/include/ldml/tsconfig.json index b89c96a0181..fa4135b0212 100644 --- a/core/include/ldml/tsconfig.json +++ b/core/include/ldml/tsconfig.json @@ -1,10 +1,8 @@ { - "extends": "../../../tsconfig-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "composite": true, "declaration": true, - "module": "es2020", - "moduleResolution": "node", "rootDir": ".", "outDir": "build/", }, diff --git a/core/src/context.hpp b/core/src/context.hpp index b344e0657cd..08edc861634 100644 --- a/core/src/context.hpp +++ b/core/src/context.hpp @@ -3,13 +3,13 @@ Description: Internal context class and adaptor class for the API. Create Date: 2 Oct 2018 Authors: Tim Eves (TSE) - History: 2 Oct 2018 - TSE - Refactored out of km_kbp_context_api.cpp + History: 2 Oct 2018 - TSE - Refactored out of km_core_context_api.cpp */ #pragma once #include #include -#include +#include // Forward declarations class json; @@ -20,32 +20,32 @@ namespace kbp // This will likely be replaced with a class implementing a more space // efficient data structure such as a ring buffer or bounded queue. -class context: public std::list +class context: public std::list { public: - void push_character(km_kbp_usv); + void push_character(km_core_usv); void push_marker(uint32_t); }; inline -void context::push_character(km_kbp_usv usv) { - emplace_back(km_kbp_context_item { KM_KBP_CT_CHAR, {0,}, {usv} }); +void context::push_character(km_core_usv usv) { + emplace_back(km_core_context_item { KM_CORE_CT_CHAR, {0,}, {usv} }); } inline void context::push_marker(uint32_t marker) { - emplace_back(km_kbp_context_item { KM_KBP_CT_MARKER, {0,}, {marker} }); + emplace_back(km_core_context_item { KM_CORE_CT_MARKER, {0,}, {marker} }); } } // namespace kbp } // namespace km json & operator << (json &, km::kbp::context const &); -json & operator << (json &, km_kbp_context_item const &); +json & operator << (json &, km_core_context_item const &); -struct km_kbp_context : public km::kbp::context +struct km_core_context : public km::kbp::context { }; diff --git a/core/src/debug.hpp b/core/src/debug.hpp index 8069cfbc532..935fad155ca 100644 --- a/core/src/debug.hpp +++ b/core/src/debug.hpp @@ -9,20 +9,20 @@ #include #include -#include -#include +#include +#include namespace km { namespace kbp { -class debug_items : public std::vector +class debug_items : public std::vector { private: bool _is_enabled; public: template debug_items(Args&&... args); - void push_begin(km_kbp_state_debug_key_info *key_info, uint32_t flags); + void push_begin(km_core_state_debug_key_info *key_info, uint32_t flags); void push_end(uint16_t first_action, uint32_t flags); void assert_push_entry(); bool is_enabled() const noexcept; @@ -31,29 +31,29 @@ class debug_items : public std::vector template debug_items::debug_items(Args&&... args) -: std::vector(std::forward(args)...) +: std::vector(std::forward(args)...) { // Ensure the debug_items list is terminated in case the client calls - // km_kbp_state_debug_items before they call process_event. + // km_core_state_debug_items before they call process_event. _is_enabled = false; push_end(0, 0); } inline void debug_items::assert_push_entry() { - assert(empty() || (!empty() && back().type != KM_KBP_DEBUG_END)); + assert(empty() || (!empty() && back().type != KM_CORE_DEBUG_END)); } inline -void debug_items::push_begin(km_kbp_state_debug_key_info *key_info, uint32_t flags) { +void debug_items::push_begin(km_core_state_debug_key_info *key_info, uint32_t flags) { assert_push_entry(); - emplace_back(km_kbp_state_debug_item{ KM_KBP_DEBUG_BEGIN, flags, {*key_info, }, { }}); + emplace_back(km_core_state_debug_item{ KM_CORE_DEBUG_BEGIN, flags, {*key_info, }, { }}); } inline void debug_items::push_end(uint16_t first_action, uint32_t flags) { assert_push_entry(); - emplace_back(km_kbp_state_debug_item{ KM_KBP_DEBUG_END, flags, { }, { u"", nullptr, nullptr, { }, first_action, {} } }); + emplace_back(km_core_state_debug_item{ KM_CORE_DEBUG_END, flags, { }, { u"", nullptr, nullptr, { }, first_action, {} } }); } inline diff --git a/core/src/debuglog.h b/core/src/debuglog.h index 16fba464285..1ecbaca6124 100644 --- a/core/src/debuglog.h +++ b/core/src/debuglog.h @@ -1,6 +1,6 @@ /* Debugging */ -#include +#include namespace km { namespace kbp { diff --git a/core/src/keyboard.cpp b/core/src/keyboard.cpp index 977da597d31..47693b9b664 100644 --- a/core/src/keyboard.cpp +++ b/core/src/keyboard.cpp @@ -3,7 +3,7 @@ Description: Internal keyboard class and adaptor class for the API. Create Date: 2 Oct 2018 Authors: Tim Eves (TSE) - History: 7 Oct 2018 - TSE - Refactored out of km_kbp_keyboard_api.cpp + History: 7 Oct 2018 - TSE - Refactored out of km_core_keyboard_api.cpp */ #include "keyboard.hpp" #include "jsonpp.hpp" diff --git a/core/src/keyboard.hpp b/core/src/keyboard.hpp index 57f8128c781..97329b7e761 100644 --- a/core/src/keyboard.hpp +++ b/core/src/keyboard.hpp @@ -3,7 +3,7 @@ Description: Internal keyboard class and adaptor class for the API. Create Date: 2 Oct 2018 Authors: Tim Eves (TSE) - History: 2 Oct 2018 - TSE - Refactored out of km_kbp_keyboard_api.cpp + History: 2 Oct 2018 - TSE - Refactored out of km_core_keyboard_api.cpp */ #pragma once @@ -11,7 +11,7 @@ #include #include -#include +#include #include "option.hpp" #include "path.hpp" @@ -22,7 +22,7 @@ class json; namespace km { namespace kbp { - class keyboard_attributes : public km_kbp_keyboard_attrs + class keyboard_attributes : public km_core_keyboard_attrs { std::u16string _keyboard_id; std::u16string _version_string; @@ -36,7 +36,7 @@ namespace kbp using path_type = decltype(_folder_path); keyboard_attributes() - : km_kbp_keyboard_attrs {nullptr, nullptr, nullptr, nullptr} {} + : km_core_keyboard_attrs {nullptr, nullptr, nullptr, nullptr} {} keyboard_attributes(keyboard_attributes const &) = delete; keyboard_attributes(keyboard_attributes &&); diff --git a/core/src/km_kbp_context_api.cpp b/core/src/km_core_context_api.cpp similarity index 54% rename from core/src/km_kbp_context_api.cpp rename to core/src/km_core_context_api.cpp index a9111f66c45..3655af4e964 100644 --- a/core/src/km_kbp_context_api.cpp +++ b/core/src/km_core_context_api.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include "context.hpp" #include "jsonpp.hpp" @@ -20,44 +20,44 @@ namespace { template - km_kbp_status + km_core_status _context_items_from(typename U::codeunit_t const *text, - km_kbp_context_item **out_ptr) + km_core_context_item **out_ptr) { assert(text); assert(out_ptr); - if (!text || !out_ptr) return KM_KBP_STATUS_INVALID_ARGUMENT; + if (!text || !out_ptr) return KM_CORE_STATUS_INVALID_ARGUMENT; *out_ptr = nullptr; try { - std::vector res; + std::vector res; for (auto i = typename U::const_iterator(text); *i; ++i) { - if(i.error()) return KM_KBP_STATUS_INVALID_UTF; - res.emplace_back(km_kbp_context_item {KM_KBP_CT_CHAR, {0,}, {*i}}); + if(i.error()) return KM_CORE_STATUS_INVALID_UTF; + res.emplace_back(km_core_context_item {KM_CORE_CT_CHAR, {0,}, {*i}}); } // Terminate the context_items array. - res.emplace_back(km_kbp_context_item KM_KBP_CONTEXT_ITEM_END); + res.emplace_back(km_core_context_item KM_CORE_CONTEXT_ITEM_END); - *out_ptr = new km_kbp_context_item[res.size()]; + *out_ptr = new km_core_context_item[res.size()]; std::move(res.begin(), res.end(), *out_ptr); } catch (std::bad_alloc &) { - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } template - km_kbp_status _context_items_to(km_kbp_context_item const *ci, + km_core_status _context_items_to(km_core_context_item const *ci, typename U::codeunit_t *buf, size_t * sz_ptr) { assert(ci); assert(sz_ptr); - if (!ci || !sz_ptr) return KM_KBP_STATUS_INVALID_ARGUMENT; + if (!ci || !sz_ptr) return KM_CORE_STATUS_INVALID_ARGUMENT; auto const buf_size = *sz_ptr; if (buf && buf_size > 0) @@ -65,9 +65,9 @@ namespace { auto i = typename U::iterator(buf); auto const e = decltype(i)(buf + buf_size - 1); - for (;i != e && ci->type != KM_KBP_CT_END && !i.error(); ++ci) + for (;i != e && ci->type != KM_CORE_CT_END && !i.error(); ++ci) { - if (ci->type == KM_KBP_CT_CHAR) + if (ci->type == KM_CORE_CT_CHAR) { *i = ci->character; ++i; } @@ -77,13 +77,13 @@ namespace { *sz_ptr = buf_size - (e - i); // Skip over any final markers - they are execluded from context - while(ci->type == KM_KBP_CT_MARKER) { + while(ci->type == KM_CORE_CT_MARKER) { ci++; } - return ci->type == KM_KBP_CT_END - ? KM_KBP_STATUS_OK - : KM_KBP_STATUS_INSUFFICENT_BUFFER; + return ci->type == KM_CORE_CT_END + ? KM_CORE_STATUS_OK + : KM_CORE_STATUS_INSUFFICENT_BUFFER; } else { @@ -92,38 +92,38 @@ namespace { do { - if (ci->type == KM_KBP_CT_CHAR) + if (ci->type == KM_CORE_CT_CHAR) { int8_t l = 4; U::codec::put(cps, ci->character, l); n += l; } } - while(ci++->type != KM_KBP_CT_END); + while(ci++->type != KM_CORE_CT_END); *sz_ptr = n+1; - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } } } -km_kbp_status -km_kbp_context_items_from_utf16(km_kbp_cp const *text, - km_kbp_context_item **out_ptr) +km_core_status +km_core_context_items_from_utf16(km_core_cp const *text, + km_core_context_item **out_ptr) { return _context_items_from(reinterpret_cast(text), out_ptr); } -km_kbp_status -km_kbp_context_items_from_utf8(char const *text, - km_kbp_context_item **out_ptr) +km_core_status +km_core_context_items_from_utf8(char const *text, + km_core_context_item **out_ptr) { return _context_items_from(reinterpret_cast(text), out_ptr); } -km_kbp_status km_kbp_context_items_to_utf8(km_kbp_context_item const *ci, +km_core_status km_core_context_items_to_utf8(km_core_context_item const *ci, char *buf, size_t * sz_ptr) { return _context_items_to(ci, @@ -132,8 +132,8 @@ km_kbp_status km_kbp_context_items_to_utf8(km_kbp_context_item const *ci, } -km_kbp_status km_kbp_context_items_to_utf16(km_kbp_context_item const *ci, - km_kbp_cp *buf, size_t * sz_ptr) +km_core_status km_core_context_items_to_utf16(km_core_context_item const *ci, + km_core_cp *buf, size_t * sz_ptr) { return _context_items_to(ci, reinterpret_cast(buf), @@ -141,41 +141,41 @@ km_kbp_status km_kbp_context_items_to_utf16(km_kbp_context_item const *ci, } -void km_kbp_context_items_dispose(km_kbp_context_item *ci) +void km_core_context_items_dispose(km_core_context_item *ci) { delete [] ci; } -km_kbp_status km_kbp_context_set(km_kbp_context *ctxt, km_kbp_context_item const *ci) +km_core_status km_core_context_set(km_core_context *ctxt, km_core_context_item const *ci) { - km_kbp_context_clear(ctxt); - return km_kbp_context_append(ctxt, ci); + km_core_context_clear(ctxt); + return km_core_context_append(ctxt, ci); } -km_kbp_status km_kbp_context_get(km_kbp_context const *ctxt, - km_kbp_context_item **out_ptr) +km_core_status km_core_context_get(km_core_context const *ctxt, + km_core_context_item **out_ptr) { assert(ctxt); assert(out_ptr); - if (!ctxt || !out_ptr) return KM_KBP_STATUS_INVALID_ARGUMENT; + if (!ctxt || !out_ptr) return KM_CORE_STATUS_INVALID_ARGUMENT; try { - *out_ptr = new km_kbp_context_item[ctxt->size() + 1]; + *out_ptr = new km_core_context_item[ctxt->size() + 1]; } catch (std::bad_alloc &) { - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } std::copy(ctxt->begin(), ctxt->end(), *out_ptr); - (*out_ptr)[ctxt->size()].type = KM_KBP_CT_END; + (*out_ptr)[ctxt->size()].type = KM_CORE_CT_END; - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -void km_kbp_context_clear(km_kbp_context *ctxt) +void km_core_context_clear(km_core_context *ctxt) { assert(ctxt); if (ctxt) @@ -185,38 +185,38 @@ void km_kbp_context_clear(km_kbp_context *ctxt) } -size_t km_kbp_context_length(km_kbp_context *ctxt) +size_t km_core_context_length(km_core_context *ctxt) { assert(ctxt); return ctxt ? ctxt->size() : 0; } -km_kbp_status km_kbp_context_append(km_kbp_context *ctxt, - km_kbp_context_item const *ci) +km_core_status km_core_context_append(km_core_context *ctxt, + km_core_context_item const *ci) { assert(ctxt); assert(ci); - if (!ctxt || !ci) return KM_KBP_STATUS_INVALID_ARGUMENT; + if (!ctxt || !ci) return KM_CORE_STATUS_INVALID_ARGUMENT; try { - for (;ci->type != KM_KBP_CT_END; ++ci) + for (;ci->type != KM_CORE_CT_END; ++ci) { ctxt->emplace_back(*ci); } } catch (std::bad_alloc &) { - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -km_kbp_status km_kbp_context_shrink(km_kbp_context *ctxt, size_t num, - km_kbp_context_item const * ci) +km_core_status km_core_context_shrink(km_core_context *ctxt, size_t num, + km_core_context_item const * ci) { assert(ctxt); - if (!ctxt) return KM_KBP_STATUS_INVALID_ARGUMENT; + if (!ctxt) return KM_CORE_STATUS_INVALID_ARGUMENT; try { @@ -225,21 +225,21 @@ km_kbp_status km_kbp_context_shrink(km_kbp_context *ctxt, size_t num, if (ci) { auto const ip = ctxt->begin(); - while(num-- && ci->type != KM_KBP_CT_END) + while(num-- && ci->type != KM_CORE_CT_END) { ctxt->emplace(ip, *ci); ci++; } } } catch (std::bad_alloc &) { - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } size_t -km_kbp_context_item_list_size(km_kbp_context_item const *context_items) +km_core_context_item_list_size(km_core_context_item const *context_items) { assert(context_items); if (!context_items) return 0; @@ -258,18 +258,18 @@ json & operator << (json & j, km::kbp::context const & ctxt) { return j << json::close; } -json & operator << (json & j, km_kbp_context_item const & i) +json & operator << (json & j, km_core_context_item const & i) { utf8::codeunit_t cps[7] = {0,}; // 6 bytes for maximal UTF-8 char (e.g. U+10FFFF) + nul terminator int8_t l = 4; switch (i.type) { - case KM_KBP_CT_CHAR: + case KM_CORE_CT_CHAR: utf8::codec::put(cps, i.character, l); j << json::string(&cps[0]); break; - case KM_KBP_CT_MARKER: + case KM_CORE_CT_MARKER: j << json::integer_u(i.marker); break; default: diff --git a/core/src/km_kbp_debug_api.cpp b/core/src/km_core_debug_api.cpp similarity index 69% rename from core/src/km_kbp_debug_api.cpp rename to core/src/km_core_debug_api.cpp index 0871df17ae5..df324c222e6 100644 --- a/core/src/km_kbp_debug_api.cpp +++ b/core/src/km_core_debug_api.cpp @@ -8,29 +8,29 @@ #include #include -#include +#include #include "processor.hpp" #include "state.hpp" using namespace km::kbp; -km_kbp_status -km_kbp_state_debug_set( - km_kbp_state *state, +km_core_status +km_core_state_debug_set( + km_core_state *state, int value ) { assert(state); if(!state) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } state->debug_items().set_enabled(value ? true : false); - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } uint8_t -km_kbp_state_debug_get( - km_kbp_state const *state +km_core_state_debug_get( + km_core_state const *state ) { assert(state); if(!state) { @@ -39,9 +39,9 @@ km_kbp_state_debug_get( return state->debug_items().is_enabled() ? 1 : 0; } -km_kbp_state_debug_item const * -km_kbp_state_debug_items( - km_kbp_state const *state, +km_core_state_debug_item const * +km_core_state_debug_items( + km_core_state const *state, size_t *num_items ) { assert(state && state->debug_items().size() > 0); @@ -58,6 +58,6 @@ km_kbp_state_debug_items( // Process events will ensure that the debug vector is always well // terminated - assert(state->debug_items().back().type == KM_KBP_DEBUG_END); + assert(state->debug_items().back().type == KM_CORE_DEBUG_END); return state->debug_items().data(); } diff --git a/core/src/km_kbp_keyboard_api.cpp b/core/src/km_core_keyboard_api.cpp similarity index 63% rename from core/src/km_kbp_keyboard_api.cpp rename to core/src/km_core_keyboard_api.cpp index 13f3cafc45c..632a2beb28d 100644 --- a/core/src/km_kbp_keyboard_api.cpp +++ b/core/src/km_core_keyboard_api.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include "keyboard.hpp" #include "processor.hpp" #include "kmx/kmx_processor.hpp" @@ -43,85 +43,85 @@ namespace } -km_kbp_status -km_kbp_keyboard_load(km_kbp_path_name kb_path, km_kbp_keyboard **keyboard) +km_core_status +km_core_keyboard_load(km_core_path_name kb_path, km_core_keyboard **keyboard) { assert(keyboard); if (!keyboard) - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; try { abstract_processor *kp = processor_factory(kb_path); - km_kbp_status status = kp->validate(); - if (status != KM_KBP_STATUS_OK) { + km_core_status status = kp->validate(); + if (status != KM_CORE_STATUS_OK) { delete kp; return status; } - *keyboard = static_cast(kp); + *keyboard = static_cast(kp); } catch (std::bad_alloc &) { - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } void -km_kbp_keyboard_dispose(km_kbp_keyboard *keyboard) +km_core_keyboard_dispose(km_core_keyboard *keyboard) { delete keyboard; } -km_kbp_status -km_kbp_keyboard_get_attrs(km_kbp_keyboard const *keyboard, - km_kbp_keyboard_attrs const **out) +km_core_status +km_core_keyboard_get_attrs(km_core_keyboard const *keyboard, + km_core_keyboard_attrs const **out) { assert(keyboard); assert(out); if (!keyboard || !out) - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; *out = &keyboard->keyboard(); - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -km_kbp_status -km_kbp_keyboard_get_key_list(km_kbp_keyboard const *keyboard, - km_kbp_keyboard_key **out) +km_core_status +km_core_keyboard_get_key_list(km_core_keyboard const *keyboard, + km_core_keyboard_key **out) { assert(keyboard); assert(out); if (!keyboard || !out) - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; *out = keyboard->get_key_list(); - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -void km_kbp_keyboard_key_list_dispose(km_kbp_keyboard_key *key_list) +void km_core_keyboard_key_list_dispose(km_core_keyboard_key *key_list) { delete[] key_list; } -km_kbp_status km_kbp_keyboard_get_imx_list( - km_kbp_keyboard const *keyboard, - km_kbp_keyboard_imx** imx_list +km_core_status km_core_keyboard_get_imx_list( + km_core_keyboard const *keyboard, + km_core_keyboard_imx** imx_list ) { assert(keyboard); assert(imx_list); if (!keyboard || !imx_list) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } *imx_list = keyboard->get_imx_list(); - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -void km_kbp_keyboard_imx_list_dispose(km_kbp_keyboard_imx *imx_list) +void km_core_keyboard_imx_list_dispose(km_core_keyboard_imx *imx_list) { if(!imx_list) { return; } - km_kbp_keyboard_imx *imx_rule_it = imx_list; + km_core_keyboard_imx *imx_rule_it = imx_list; for (; imx_rule_it->library_name; ++imx_rule_it) { delete [] imx_rule_it->library_name; // from u16dup delete [] imx_rule_it->function_name; // from u16dup diff --git a/core/src/km_kbp_options_api.cpp b/core/src/km_core_options_api.cpp similarity index 56% rename from core/src/km_kbp_options_api.cpp rename to core/src/km_core_options_api.cpp index 7dc48790987..3cb0745fa90 100644 --- a/core/src/km_kbp_options_api.cpp +++ b/core/src/km_core_options_api.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include #include "processor.hpp" #include "jsonpp.hpp" @@ -19,7 +19,7 @@ size_t -km_kbp_options_list_size(km_kbp_option_item const *opts) +km_core_options_list_size(km_core_option_item const *opts) { assert(opts); if (!opts) return 0; @@ -33,31 +33,31 @@ km_kbp_options_list_size(km_kbp_option_item const *opts) } -km_kbp_status -km_kbp_state_option_lookup(km_kbp_state const *state, - uint8_t scope, km_kbp_cp const *key, - km_kbp_cp const **value_out) +km_core_status +km_core_state_option_lookup(km_core_state const *state, + uint8_t scope, km_core_cp const *key, + km_core_cp const **value_out) { assert(state); assert(key); assert(value_out); - if (!state || !key || !value_out) return KM_KBP_STATUS_INVALID_ARGUMENT; + if (!state || !key || !value_out) return KM_CORE_STATUS_INVALID_ARGUMENT; - if (scope == KM_KBP_OPT_UNKNOWN || scope > KM_KBP_OPT_MAX_SCOPES) - return KM_KBP_STATUS_INVALID_ARGUMENT; + if (scope == KM_CORE_OPT_UNKNOWN || scope > KM_CORE_OPT_MAX_SCOPES) + return KM_CORE_STATUS_INVALID_ARGUMENT; auto & processor = state->processor(); - *value_out = processor.lookup_option(km_kbp_option_scope(scope), key); - if (!*value_out) return KM_KBP_STATUS_KEY_ERROR; + *value_out = processor.lookup_option(km_core_option_scope(scope), key); + if (!*value_out) return KM_CORE_STATUS_KEY_ERROR; - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -km_kbp_status -km_kbp_state_options_update(km_kbp_state *state, km_kbp_option_item const *opt) +km_core_status +km_core_state_options_update(km_core_state *state, km_core_option_item const *opt) { assert(state); assert(opt); - if (!state|| !opt) return KM_KBP_STATUS_INVALID_ARGUMENT; + if (!state|| !opt) return KM_CORE_STATUS_INVALID_ARGUMENT; auto & processor = state->processor(); @@ -65,32 +65,32 @@ km_kbp_state_options_update(km_kbp_state *state, km_kbp_option_item const *opt) { for (;opt->key; ++opt) { - if (opt->scope == KM_KBP_OPT_UNKNOWN || opt->scope > KM_KBP_OPT_MAX_SCOPES) - return KM_KBP_STATUS_INVALID_ARGUMENT; + if (opt->scope == KM_CORE_OPT_UNKNOWN || opt->scope > KM_CORE_OPT_MAX_SCOPES) + return KM_CORE_STATUS_INVALID_ARGUMENT; if (processor.update_option( - km_kbp_option_scope(opt->scope), + km_core_option_scope(opt->scope), opt->key, opt->value).empty()) - return KM_KBP_STATUS_KEY_ERROR; + return KM_CORE_STATUS_KEY_ERROR; } } catch (std::bad_alloc &) { - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } // This function doesn't need to use the json pretty printer for such a simple // list of key:value pairs but it's a good introduction to it. -km_kbp_status -km_kbp_state_options_to_json(km_kbp_state const *state, char *buf, size_t *space) +km_core_status +km_core_state_options_to_json(km_core_state const *state, char *buf, size_t *space) { assert(state); assert(space); if (!state || !space) - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; std::stringstream _buf; json jo(_buf); @@ -103,7 +103,7 @@ km_kbp_state_options_to_json(km_kbp_state const *state, char *buf, size_t *space catch (std::bad_alloc &) { *space = 0; - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } // Fetch the finished doc and copy it to the buffer if there enough space. @@ -116,5 +116,5 @@ km_kbp_state_options_to_json(km_kbp_state const *state, char *buf, size_t *space // Return space needed/used. *space = doc.size()+1; - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } diff --git a/core/src/km_kbp_processevent_api.cpp b/core/src/km_core_processevent_api.cpp similarity index 62% rename from core/src/km_kbp_processevent_api.cpp rename to core/src/km_core_processevent_api.cpp index 69eba06a41c..5295d39af7b 100644 --- a/core/src/km_kbp_processevent_api.cpp +++ b/core/src/km_core_processevent_api.cpp @@ -8,63 +8,63 @@ History: 17 Oct 2018 - TSE - Initial implementation. */ -#include +#include #include "processor.hpp" #include "state.hpp" -km_kbp_status -km_kbp_event( - km_kbp_state *state, +km_core_status +km_core_event( + km_core_state *state, uint32_t event, void* data ) { assert(state != nullptr); if(state == nullptr) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } - // event: KM_KBP_EVENT_KEYBOARD_ACTIVATED; data should be nullptr - // future event: KM_KBP_EVENT_KEYBOARD_DEACTIVATED + // event: KM_CORE_EVENT_KEYBOARD_ACTIVATED; data should be nullptr + // future event: KM_CORE_EVENT_KEYBOARD_DEACTIVATED switch(event) { - case KM_KBP_EVENT_KEYBOARD_ACTIVATED: + case KM_CORE_EVENT_KEYBOARD_ACTIVATED: assert(data == nullptr); if(data != nullptr) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } break; default: - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } return state->processor().external_event(state, event, data); } -km_kbp_status -km_kbp_process_event(km_kbp_state *state, - km_kbp_virtual_key vk, +km_core_status +km_core_process_event(km_core_state *state, + km_core_virtual_key vk, uint16_t modifier_state, uint8_t is_key_down, uint16_t event_flags) { assert(state != nullptr); if(state == nullptr) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } return state->processor().process_event(state, vk, modifier_state, is_key_down, event_flags); } -km_kbp_status -km_kbp_process_queued_actions( - km_kbp_state *state +km_core_status +km_core_process_queued_actions( + km_core_state *state ) { assert(state != nullptr); if(state == nullptr) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } return state->processor().process_queued_actions(state); } -km_kbp_attr const * -km_kbp_get_engine_attrs(km_kbp_state const *state) +km_core_attr const * +km_core_get_engine_attrs(km_core_state const *state) { assert(state != nullptr); if(state == nullptr) { diff --git a/core/src/km_kbp_state_api.cpp b/core/src/km_core_state_api.cpp similarity index 59% rename from core/src/km_kbp_state_api.cpp rename to core/src/km_core_state_api.cpp index b966688950f..fdafd9a5b72 100644 --- a/core/src/km_kbp_state_api.cpp +++ b/core/src/km_core_state_api.cpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include "jsonpp.hpp" #include "processor.hpp" @@ -23,68 +23,68 @@ using namespace km::kbp; // Forward declarations class context; -km_kbp_status km_kbp_state_create(km_kbp_keyboard * keyboard, - km_kbp_option_item const *env, - km_kbp_state ** out) +km_core_status km_core_state_create(km_core_keyboard * keyboard, + km_core_option_item const *env, + km_core_state ** out) { assert(keyboard); assert(env); assert(out); if (!keyboard || !env || !out) - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; try { - *out = new km_kbp_state(static_cast(*keyboard), env); + *out = new km_core_state(static_cast(*keyboard), env); } catch (std::bad_alloc &) { - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -km_kbp_status km_kbp_state_clone(km_kbp_state const *state, - km_kbp_state ** out) +km_core_status km_core_state_clone(km_core_state const *state, + km_core_state ** out) { assert(state); assert(out); if (!state || !out) - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; - *out = new km_kbp_state(*state); - return KM_KBP_STATUS_OK; + *out = new km_core_state(*state); + return KM_CORE_STATUS_OK; } -void km_kbp_state_dispose(km_kbp_state *state) +void km_core_state_dispose(km_core_state *state) { delete state; } -km_kbp_context *km_kbp_state_context(km_kbp_state *state) +km_core_context *km_core_state_context(km_core_state *state) { assert(state); if (!state) return nullptr; - return static_cast(&state->context()); + return static_cast(&state->context()); } -km_kbp_status kbp_state_get_intermediate_context( - km_kbp_state *state, - km_kbp_context_item ** context_items +km_core_status kbp_state_get_intermediate_context( + km_core_state *state, + km_core_context_item ** context_items ) { assert(state); assert(context_items); if (!state || !context_items) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } auto & processor = state->processor(); *context_items = processor.get_intermediate_context(); - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -km_kbp_action_item const * km_kbp_state_action_items(km_kbp_state const *state, +km_core_action_item const * km_core_state_action_items(km_core_state const *state, size_t *num_items) { assert(state && state->actions().size() > 0); @@ -95,33 +95,33 @@ km_kbp_action_item const * km_kbp_state_action_items(km_kbp_state const *state, // Process events will ensure that the actions vector is always well // teminated - assert(state->actions().back().type == KM_KBP_IT_END); + assert(state->actions().back().type == KM_CORE_IT_END); return state->actions().data(); } -km_kbp_status km_kbp_state_queue_action_items( - km_kbp_state *state, - km_kbp_action_item const *action_items +km_core_status km_core_state_queue_action_items( + km_core_state *state, + km_core_action_item const *action_items ) { assert(state); assert(action_items); if (!state|| !action_items) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; } auto & processor = state->processor(); - for (; action_items->type != KM_KBP_IT_END; ++action_items) { - if (action_items->type >= KM_KBP_IT_MAX_TYPE_ID) { - return KM_KBP_STATUS_INVALID_ARGUMENT; + for (; action_items->type != KM_CORE_IT_END; ++action_items) { + if (action_items->type >= KM_CORE_IT_MAX_TYPE_ID) { + return KM_CORE_STATUS_INVALID_ARGUMENT; } if (!processor.queue_action(state, action_items)) { - return KM_KBP_STATUS_KEY_ERROR; + return KM_CORE_STATUS_KEY_ERROR; } } - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } namespace { char const * action_item_name_lut[] = { @@ -146,10 +146,10 @@ namespace { } -json & operator << (json & j, km_kbp_action_item const &act) +json & operator << (json & j, km_core_action_item const &act) { j << json::flat << json::object; - if (act.type >= KM_KBP_IT_MAX_TYPE_ID) + if (act.type >= KM_CORE_IT_MAX_TYPE_ID) { j << "invalid" << json::null << json::close; return j; @@ -158,16 +158,16 @@ json & operator << (json & j, km_kbp_action_item const &act) j << action_item_name_lut[act.type]; switch (act.type) { - case KM_KBP_IT_END: - case KM_KBP_IT_ALERT: - case KM_KBP_IT_BACK: + case KM_CORE_IT_END: + case KM_CORE_IT_ALERT: + case KM_CORE_IT_BACK: j << json::null; break; - case KM_KBP_IT_CHAR: - case KM_KBP_IT_MARKER: - j << km_kbp_context_item {act.type, {0,}, {act.character}}; // TODO: is act.type correct here? it may map okay but this is bad practice to mix constants across types. Similarly using act.character instead of act.type + case KM_CORE_IT_CHAR: + case KM_CORE_IT_MARKER: + j << km_core_context_item {act.type, {0,}, {act.character}}; // TODO: is act.type correct here? it may map okay but this is bad practice to mix constants across types. Similarly using act.character instead of act.type break; - case KM_KBP_IT_PERSIST_OPT: + case KM_CORE_IT_PERSIST_OPT: j << json::object << scope_names_lut[act.option->scope] << json::flat << json::object @@ -187,7 +187,7 @@ json & operator << (json & j, actions const & acts) j << json::array; for (auto & act: acts) { - if (act.type != KM_KBP_IT_END) + if (act.type != KM_CORE_IT_END) { j << act; } @@ -197,13 +197,13 @@ json & operator << (json & j, actions const & acts) } -km_kbp_status km_kbp_state_to_json(km_kbp_state const *state, +km_core_status km_core_state_to_json(km_core_state const *state, char *buf, size_t *space) { assert(state); if (!state) - return KM_KBP_STATUS_INVALID_ARGUMENT; + return KM_CORE_STATUS_INVALID_ARGUMENT; std::stringstream _buf; json jo(_buf); @@ -212,7 +212,7 @@ km_kbp_status km_kbp_state_to_json(km_kbp_state const *state, { // Pretty print the document. jo << json::object - << "$schema" << "keyman/keyboardprocessor/doc/introspection.schema" + << "$schema" << "keyman/core/doc/introspection.schema" << "keyboard" << state->processor().keyboard() // << "options" << state->options() TODO: Fix << "context" << state->context() @@ -222,7 +222,7 @@ km_kbp_status km_kbp_state_to_json(km_kbp_state const *state, catch (std::bad_alloc &) { *space = 0; - return KM_KBP_STATUS_NO_MEM; + return KM_CORE_STATUS_NO_MEM; } // Fetch the finished doc and copy it to the buffer if there enough space. @@ -235,13 +235,13 @@ km_kbp_status km_kbp_state_to_json(km_kbp_state const *state, // Return space needed/used. *space = doc.size()+1; - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } -void km_kbp_state_imx_register_callback( - km_kbp_state *state, - km_kbp_keyboard_imx_platform imx_callback, +void km_core_state_imx_register_callback( + km_core_state *state, + km_core_keyboard_imx_platform imx_callback, void *callback_object ) { assert(state); @@ -251,7 +251,7 @@ void km_kbp_state_imx_register_callback( state->imx_register_callback(imx_callback, callback_object); } -void km_kbp_state_imx_deregister_callback(km_kbp_state *state) +void km_core_state_imx_deregister_callback(km_core_state *state) { assert(state); if (!state) { diff --git a/core/src/kmx/kmx_base.h b/core/src/kmx/kmx_base.h index 7fc335cfc46..77cf53c209b 100644 --- a/core/src/kmx/kmx_base.h +++ b/core/src/kmx/kmx_base.h @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include #if defined(_WIN32) || defined(_WIN64) #define snprintf _snprintf diff --git a/core/src/kmx/kmx_capslock.cpp b/core/src/kmx/kmx_capslock.cpp index e125ccd4cf1..f14745bf326 100644 --- a/core/src/kmx/kmx_capslock.cpp +++ b/core/src/kmx/kmx_capslock.cpp @@ -2,7 +2,7 @@ Copyright: Copyright (C) 2003-2018 SIL International. Authors: mcdurdin */ -#include +#include #include using namespace km::kbp; diff --git a/core/src/kmx/kmx_consts.cpp b/core/src/kmx/kmx_consts.cpp index 26457469498..a0e1ff660ab 100644 --- a/core/src/kmx/kmx_consts.cpp +++ b/core/src/kmx/kmx_consts.cpp @@ -6,22 +6,22 @@ namespace kbp { namespace kmx { const struct char_to_vkey s_char_to_vkey[] = { - {KM_KBP_VKEY_SPACE, 0, 0}, // + {KM_CORE_VKEY_SPACE, 0, 0}, // {'1', 1, 0}, // ! - {KM_KBP_VKEY_QUOTE, 1, 0}, // " + {KM_CORE_VKEY_QUOTE, 1, 0}, // " {'3', 1, 0}, // # {'4', 1, 0}, // $ {'5', 1, 0}, // % {'7', 1, 0}, // & - {KM_KBP_VKEY_QUOTE, 0, 0}, // ' + {KM_CORE_VKEY_QUOTE, 0, 0}, // ' {'9', 1, 0}, // ( {'0', 1, 0}, // ) {'8', 1, 0}, // * - {KM_KBP_VKEY_EQUAL, 1, 0}, // + - {KM_KBP_VKEY_COMMA, 0, 0}, // , - {KM_KBP_VKEY_HYPHEN, 0, 0}, // - - {KM_KBP_VKEY_PERIOD, 0, 0}, // . - {KM_KBP_VKEY_SLASH, 0, 0}, // / + {KM_CORE_VKEY_EQUAL, 1, 0}, // + + {KM_CORE_VKEY_COMMA, 0, 0}, // , + {KM_CORE_VKEY_HYPHEN, 0, 0}, // - + {KM_CORE_VKEY_PERIOD, 0, 0}, // . + {KM_CORE_VKEY_SLASH, 0, 0}, // / {'0', 0, 0}, {'1', 0, 0}, {'2', 0, 0}, @@ -32,12 +32,12 @@ const struct char_to_vkey s_char_to_vkey[] = { {'7', 0, 0}, {'8', 0, 0}, {'9', 0, 0}, - {KM_KBP_VKEY_COLON, 1, 0}, // : - {KM_KBP_VKEY_COLON, 0, 0}, // ; - {KM_KBP_VKEY_COMMA, 1, 0}, // < - {KM_KBP_VKEY_EQUAL, 0, 0}, // = - {KM_KBP_VKEY_PERIOD, 1, 0}, // > - {KM_KBP_VKEY_SLASH, 1, 0}, // ? + {KM_CORE_VKEY_COLON, 1, 0}, // : + {KM_CORE_VKEY_COLON, 0, 0}, // ; + {KM_CORE_VKEY_COMMA, 1, 0}, // < + {KM_CORE_VKEY_EQUAL, 0, 0}, // = + {KM_CORE_VKEY_PERIOD, 1, 0}, // > + {KM_CORE_VKEY_SLASH, 1, 0}, // ? {'2', 1, 0}, // @ {'A', 1, 1}, {'B', 1, 1}, @@ -65,12 +65,12 @@ const struct char_to_vkey s_char_to_vkey[] = { {'X', 1, 1}, {'Y', 1, 1}, {'Z', 1, 1}, - {KM_KBP_VKEY_LBRKT, 0, 0}, - {KM_KBP_VKEY_BKSLASH, 0, 0}, - {KM_KBP_VKEY_RBRKT, 0, 0}, + {KM_CORE_VKEY_LBRKT, 0, 0}, + {KM_CORE_VKEY_BKSLASH, 0, 0}, + {KM_CORE_VKEY_RBRKT, 0, 0}, {'6', 1, 0}, - {KM_KBP_VKEY_HYPHEN, 1, 0}, - {KM_KBP_VKEY_BKQUOTE, 0, 0}, + {KM_CORE_VKEY_HYPHEN, 1, 0}, + {KM_CORE_VKEY_BKQUOTE, 0, 0}, {'A', 0, 1}, {'B', 0, 1}, {'C', 0, 1}, @@ -97,10 +97,10 @@ const struct char_to_vkey s_char_to_vkey[] = { {'X', 0, 1}, {'Y', 0, 1}, {'Z', 0, 1}, - {KM_KBP_VKEY_LBRKT, 1, 0}, - {KM_KBP_VKEY_BKSLASH, 1, 0}, - {KM_KBP_VKEY_RBRKT, 1, 0}, - {KM_KBP_VKEY_BKQUOTE, 1, 0}, + {KM_CORE_VKEY_LBRKT, 1, 0}, + {KM_CORE_VKEY_BKSLASH, 1, 0}, + {KM_CORE_VKEY_RBRKT, 1, 0}, + {KM_CORE_VKEY_BKQUOTE, 1, 0}, {0, 0, 0} }; diff --git a/core/src/kmx/kmx_debugger.cpp b/core/src/kmx/kmx_debugger.cpp index c217086acdb..84280280deb 100644 --- a/core/src/kmx/kmx_debugger.cpp +++ b/core/src/kmx/kmx_debugger.cpp @@ -21,7 +21,7 @@ void KMX_DebugItems::push_item( PKMX_WORD index_stack ) { _items->assert_push_entry(); - km_kbp_state_debug_item item = {type, flags, {}, {}}; + km_core_state_debug_item item = {type, flags, {}, {}}; item.kmx_info.rule = key; if(item.kmx_info.rule && index_stack) { this->fill_store_offsets(&item.kmx_info, index_stack); @@ -43,7 +43,7 @@ void KMX_DebugItems::push_set_option( KMX_WCHAR const * value ) { _items->assert_push_entry(); - km_kbp_state_debug_item item = {KM_KBP_DEBUG_SET_OPTION, 0, {}, {}}; + km_core_state_debug_item item = {KM_CORE_DEBUG_SET_OPTION, 0, {}, {}}; item.kmx_info.first_action = first_action; item.kmx_info.rule = nullptr; item.kmx_info.group = nullptr; @@ -57,11 +57,11 @@ void KMX_DebugItems::push_set_option( _items->emplace_back(item); } -void KMX_DebugItems::fill_store_offsets(km_kbp_state_debug_kmx_info *info, PKMX_WORD index_stack) { +void KMX_DebugItems::fill_store_offsets(km_core_state_debug_kmx_info *info, PKMX_WORD index_stack) { int i, n; - km_kbp_cp *p; + km_core_cp *p; // TODO turn this into a struct rather than interwoven values for(i = n = 0, p = static_cast(info->rule)->dpContext; p && *p; p = incxstr(p), i++) { diff --git a/core/src/kmx/kmx_debugger.h b/core/src/kmx/kmx_debugger.h index 20006e291c7..45b9b8d3110 100644 --- a/core/src/kmx/kmx_debugger.h +++ b/core/src/kmx/kmx_debugger.h @@ -31,12 +31,12 @@ class KMX_DebugItems PKMX_WORD index_stack = nullptr ); void fill_store_offsets( - km_kbp_state_debug_kmx_info *info, + km_core_state_debug_kmx_info *info, PKMX_WORD index_stack ); public: KMX_DebugItems(debug_items *items); - void push_begin(km_kbp_state_debug_key_info *key_info, uint32_t flags); + void push_begin(km_core_state_debug_key_info *key_info, uint32_t flags); void push_end(uint16_t first_action, uint32_t flags); void push_group_enter(uint16_t first_action, LPGROUP group); void push_group_exit(uint16_t first_action, uint32_t flags, LPGROUP group); @@ -73,10 +73,10 @@ KMX_DebugItems::KMX_DebugItems(debug_items *items) { inline void KMX_DebugItems::push_begin( - km_kbp_state_debug_key_info *key_info, + km_core_state_debug_key_info *key_info, uint32_t flags ) { - // As the vector always starts with a single KM_KBP_DEBUG_END entry, + // As the vector always starts with a single KM_CORE_DEBUG_END entry, // we clear that and any other potential events first before starting a new event sequence _items->clear(); _items->push_begin(key_info, flags); @@ -92,32 +92,32 @@ KMX_DebugItems::push_end( inline void KMX_DebugItems::push_group_enter(uint16_t first_action, LPGROUP group) { - push_item(KM_KBP_DEBUG_GROUP_ENTER, first_action, 0, group); + push_item(KM_CORE_DEBUG_GROUP_ENTER, first_action, 0, group); } inline void KMX_DebugItems::push_group_exit(uint16_t first_action, uint32_t flags, LPGROUP group) { - push_item(KM_KBP_DEBUG_GROUP_EXIT, first_action, flags, group); + push_item(KM_CORE_DEBUG_GROUP_EXIT, first_action, flags, group); } inline void KMX_DebugItems::push_nomatch_enter(uint16_t first_action, LPGROUP group) { - push_item(KM_KBP_DEBUG_NOMATCH_ENTER, first_action, 0, group); + push_item(KM_CORE_DEBUG_NOMATCH_ENTER, first_action, 0, group); } inline void KMX_DebugItems::push_nomatch_exit(uint16_t first_action, LPGROUP group) { - push_item(KM_KBP_DEBUG_NOMATCH_EXIT, first_action, 0, group); + push_item(KM_CORE_DEBUG_NOMATCH_EXIT, first_action, 0, group); } inline void KMX_DebugItems::push_match_enter(uint16_t first_action, LPGROUP group) { - push_item(KM_KBP_DEBUG_MATCH_ENTER, first_action, 0, group); + push_item(KM_CORE_DEBUG_MATCH_ENTER, first_action, 0, group); } inline void KMX_DebugItems::push_match_exit(uint16_t first_action, LPGROUP group) { - push_item(KM_KBP_DEBUG_MATCH_EXIT, first_action, 0, group); + push_item(KM_CORE_DEBUG_MATCH_EXIT, first_action, 0, group); } inline void @@ -128,7 +128,7 @@ KMX_DebugItems::push_rule_enter( PKMX_WCHAR context, PKMX_WORD index_stack ) { - push_item(KM_KBP_DEBUG_RULE_ENTER, first_action, 0, group, key, context, index_stack); + push_item(KM_CORE_DEBUG_RULE_ENTER, first_action, 0, group, key, context, index_stack); } inline void @@ -139,7 +139,7 @@ KMX_DebugItems::push_rule_exit( PKMX_WCHAR context, PKMX_WORD index_stack ) { - push_item(KM_KBP_DEBUG_RULE_EXIT, first_action, 0, group, key, context, index_stack); + push_item(KM_CORE_DEBUG_RULE_EXIT, first_action, 0, group, key, context, index_stack); } } // namespace kmx diff --git a/core/src/kmx/kmx_environment.cpp b/core/src/kmx/kmx_environment.cpp index 4d3d3c54903..5d6e367e141 100644 --- a/core/src/kmx/kmx_environment.cpp +++ b/core/src/kmx/kmx_environment.cpp @@ -3,7 +3,7 @@ Authors: mcdurdin */ #include -#include +#include #include #include @@ -11,7 +11,7 @@ using namespace km::kbp; using namespace kmx; namespace { - km_kbp_cp const + km_core_cp const *DEFAULT_PLATFORM = u"windows hardware desktop native", *DEFAULT_BASELAYOUT = u"kbdus.dll", *DEFAULT_BASELAYOUTALT = u"en-US", @@ -20,11 +20,11 @@ namespace { } KMX_Environment::KMX_Environment() { - Set(KM_KBP_KMX_ENV_PLATFORM, DEFAULT_PLATFORM); - Set(KM_KBP_KMX_ENV_BASELAYOUT, DEFAULT_BASELAYOUT); - Set(KM_KBP_KMX_ENV_BASELAYOUTALT, DEFAULT_BASELAYOUTALT); - Set(KM_KBP_KMX_ENV_SIMULATEALTGR, DEFAULT_SIMULATEALTGR); - Set(KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT, DEFAULT_BASELAYOUTGIVESCTRLRALTFORRALT); + Set(KM_CORE_KMX_ENV_PLATFORM, DEFAULT_PLATFORM); + Set(KM_CORE_KMX_ENV_BASELAYOUT, DEFAULT_BASELAYOUT); + Set(KM_CORE_KMX_ENV_BASELAYOUTALT, DEFAULT_BASELAYOUTALT); + Set(KM_CORE_KMX_ENV_SIMULATEALTGR, DEFAULT_SIMULATEALTGR); + Set(KM_CORE_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT, DEFAULT_BASELAYOUTGIVESCTRLRALTFORRALT); } @@ -32,19 +32,19 @@ char16_t const * KMX_Environment::LookUp(std::u16string const & key) const { assert(!key.empty()); if (!key.empty()) return nullptr; - if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_PLATFORM)) { + if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_PLATFORM)) { return _platform.c_str(); } - else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUT)) { + else if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_BASELAYOUT)) { return _baseLayout.c_str(); } - else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUTALT)) { + else if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_BASELAYOUTALT)) { return _baseLayoutAlt.c_str(); } - else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_SIMULATEALTGR)) { + else if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_SIMULATEALTGR)) { return _simulateAltGr ? u"1" : u"0"; } - else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT)) { + else if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT)) { return _baseLayoutGivesCtrlRAltForRAlt ? u"1" : u"0"; } else { @@ -57,19 +57,19 @@ char16_t const * KMX_Environment::LookUp(std::u16string const & key) const { void KMX_Environment::Set(std::u16string const & key, std::u16string const & value) { assert(!key.empty()); - if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_PLATFORM)) { + if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_PLATFORM)) { _platform = value; } - else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUT)) { + else if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_BASELAYOUT)) { _baseLayout = value; } - else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUTALT)) { + else if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_BASELAYOUTALT)) { _baseLayoutAlt = value; } - else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_SIMULATEALTGR)) { + else if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_SIMULATEALTGR)) { _simulateAltGr = value == u"1"; } - else if (!u16icmp(key.c_str(), KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT)) { + else if (!u16icmp(key.c_str(), KM_CORE_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT)) { _baseLayoutGivesCtrlRAltForRAlt = value == u"1"; } else { diff --git a/core/src/kmx/kmx_environment.h b/core/src/kmx/kmx_environment.h index 4d934e0d104..d15b3c587bc 100644 --- a/core/src/kmx/kmx_environment.h +++ b/core/src/kmx/kmx_environment.h @@ -15,8 +15,8 @@ class KMX_Environment { std::u16string _platform; void InitOption( std::vector + + + diff --git a/core/tests/unit/ldml/keyboards/meson.build b/core/tests/unit/ldml/keyboards/meson.build index 4bce343bd30..b83c74d1414 100644 --- a/core/tests/unit/ldml/keyboards/meson.build +++ b/core/tests/unit/ldml/keyboards/meson.build @@ -51,7 +51,7 @@ kmc_root = join_paths(meson.source_root(),'..','developer','src','kmc') ldml_root = join_paths(meson.source_root(),'..','resources','standards-data','ldml-keyboards','techpreview') ldml_data = join_paths(ldml_root, '3.0') ldml_testdata = join_paths(ldml_root, 'test') -kmc_cmd = [node, kmc_root] +kmc_cmd = [node, '--enable-source-maps', kmc_root] # Build all keyboards in output folder diff --git a/core/tests/unit/ldml/ldml.cpp b/core/tests/unit/ldml/ldml.cpp index bf78d009365..31a4cded731 100644 --- a/core/tests/unit/ldml/ldml.cpp +++ b/core/tests/unit/ldml/ldml.cpp @@ -32,9 +32,9 @@ namespace { bool g_beep_found = false; -km_kbp_option_item test_env_opts[] = +km_core_option_item test_env_opts[] = { - KM_KBP_OPTIONS_END + KM_CORE_OPTIONS_END }; std::string @@ -56,22 +56,22 @@ string_to_hex(const std::u16string &input) { void apply_action( - km_kbp_state const *, - km_kbp_action_item const &act, + km_core_state const *, + km_core_action_item const &act, std::u16string &text_store, - std::vector &context, + std::vector &context, km::tests::LdmlTestSource &test_source) { switch (act.type) { - case KM_KBP_IT_END: + case KM_CORE_IT_END: assert(false); break; - case KM_KBP_IT_ALERT: + case KM_CORE_IT_ALERT: g_beep_found = true; // std::cout << "beep" << std::endl; break; - case KM_KBP_IT_CHAR: - context.push_back(km_kbp_context_item{ - KM_KBP_CT_CHAR, + case KM_CORE_IT_CHAR: + context.push_back(km_core_context_item{ + KM_CORE_CT_CHAR, { 0, }, @@ -85,29 +85,29 @@ apply_action( } // std::cout << "char(" << act.character << ") size=" << cp->size() << std::endl; break; - case KM_KBP_IT_MARKER: + case KM_CORE_IT_MARKER: // std::cout << "deadkey(" << act.marker << ")" << std::endl; - context.push_back(km_kbp_context_item{ - KM_KBP_CT_MARKER, + context.push_back(km_core_context_item{ + KM_CORE_CT_MARKER, { 0, }, {(uint32_t)act.marker}}); break; - case KM_KBP_IT_BACK: + case KM_CORE_IT_BACK: // It is valid for a backspace to be received with an empty text store // as the user can press backspace with no text in the store and Keyman // will pass that back to the client, as the client may do additional // processing at start of a text store, e.g. delete from a previous cell // in a table. Or, if Keyman has a cached context, then there may be // additional text in the text store that Keyman can't see. - if (act.backspace.expected_type == KM_KBP_BT_MARKER) { + if (act.backspace.expected_type == KM_CORE_BT_MARKER) { assert(!context.empty()); - assert(context.back().type == KM_KBP_CT_MARKER); + assert(context.back().type == KM_CORE_CT_MARKER); context.pop_back(); } else if (text_store.length() > 0) { assert(!context.empty() && !text_store.empty()); - km_kbp_usv ch = text_store.back(); + km_core_usv ch = text_store.back(); text_store.pop_back(); if (text_store.length() > 0 && Uni_IsSurrogate2(ch)) { auto ch1 = text_store.back(); @@ -120,20 +120,20 @@ apply_action( } assert(ch == act.backspace.expected_value); - assert(context.back().type == KM_KBP_CT_CHAR); + assert(context.back().type == KM_CORE_CT_CHAR); assert(context.back().character == ch); context.pop_back(); } break; - case KM_KBP_IT_PERSIST_OPT: + case KM_CORE_IT_PERSIST_OPT: break; - case KM_KBP_IT_INVALIDATE_CONTEXT: + case KM_CORE_IT_INVALIDATE_CONTEXT: std::cout << "action: context invalidated (markers cleared)" << std::endl; break; - case KM_KBP_IT_EMIT_KEYSTROKE: + case KM_CORE_IT_EMIT_KEYSTROKE: std::cout << "action: emit keystroke" << std::endl; break; - case KM_KBP_IT_CAPSLOCK: + case KM_CORE_IT_CAPSLOCK: std::cout << "action: capsLock " << act.capsLock << std::endl; test_source.set_caps_lock_on(act.capsLock); break; @@ -147,25 +147,25 @@ apply_action( * verify the current context */ void -verify_context(std::u16string& text_store, km_kbp_state* &test_state, std::vector &test_context) { +verify_context(std::u16string& text_store, km_core_state* &test_state, std::vector &test_context) { // Compare context and text store at each step - should be identical size_t n = 0; - km_kbp_context_item* citems = nullptr; - try_status(km_kbp_context_get(km_kbp_state_context(test_state), &citems)); - try_status(km_kbp_context_items_to_utf16(citems, nullptr, &n)); - km_kbp_cp *buf = new km_kbp_cp[n]; - try_status(km_kbp_context_items_to_utf16(citems, buf, &n)); + km_core_context_item* citems = nullptr; + try_status(km_core_context_get(km_core_state_context(test_state), &citems)); + try_status(km_core_context_items_to_utf16(citems, nullptr, &n)); + km_core_cp *buf = new km_core_cp[n]; + try_status(km_core_context_items_to_utf16(citems, buf, &n)); std::cout << "context : " << string_to_hex(buf) << " [" << buf << "]" << std::endl; // Verify that both our local test_context and the core's test_state.context have // not diverged auto ci = citems; - for (auto test_ci = test_context.begin(); ci->type != KM_KBP_CT_END || test_ci != test_context.end(); ci++, test_ci++) { - assert(ci->type != KM_KBP_CT_END && test_ci != test_context.end()); // Verify that both lists are same length + for (auto test_ci = test_context.begin(); ci->type != KM_CORE_CT_END || test_ci != test_context.end(); ci++, test_ci++) { + assert(ci->type != KM_CORE_CT_END && test_ci != test_context.end()); // Verify that both lists are same length assert(test_ci->type == ci->type && test_ci->marker == ci->marker); } - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); if (text_store != buf) { std::cerr << "text store has diverged from buf" << std::endl; std::cerr << "text store: " << string_to_hex(text_store) << " [" << text_store << "]" << std::endl; @@ -177,31 +177,31 @@ verify_context(std::u16string& text_store, km_kbp_state* &test_state, std::vecto int run_test(const km::kbp::path &source, const km::kbp::path &compiled, km::tests::LdmlTestSource& test_source) { - km_kbp_keyboard * test_kb = nullptr; - km_kbp_state * test_state = nullptr; + km_core_keyboard * test_kb = nullptr; + km_core_state * test_state = nullptr; - const km_kbp_status expect_load_status = test_source.get_expected_load_status(); - assert_equal(km_kbp_keyboard_load(compiled.c_str(), &test_kb), expect_load_status); + const km_core_status expect_load_status = test_source.get_expected_load_status(); + assert_equal(km_core_keyboard_load(compiled.c_str(), &test_kb), expect_load_status); - if (expect_load_status != KM_KBP_STATUS_OK) { + if (expect_load_status != KM_CORE_STATUS_OK) { std::cout << "Keyboard was expected to be invalid, so exiting " << std::endl; return 0; } // Setup state, environment - try_status(km_kbp_state_create(test_kb, test_env_opts, &test_state)); + try_status(km_core_state_create(test_kb, test_env_opts, &test_state)); // Setup context - km_kbp_context_item *citems = nullptr; - try_status(km_kbp_context_items_from_utf16(test_source.get_context().c_str(), &citems)); - try_status(km_kbp_context_set(km_kbp_state_context(test_state), citems)); + km_core_context_item *citems = nullptr; + try_status(km_core_context_items_from_utf16(test_source.get_context().c_str(), &citems)); + try_status(km_core_context_set(km_core_state_context(test_state), citems)); // Make a copy of the setup context for the test - std::vector test_context; - for(km_kbp_context_item *ci = citems; ci->type != KM_KBP_CT_END; ci++) { + std::vector test_context; + for(km_core_context_item *ci = citems; ci->type != KM_CORE_CT_END; ci++) { test_context.emplace_back(*ci); } - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); // Setup baseline text store std::u16string text_store = test_source.get_context(); @@ -220,15 +220,15 @@ run_test(const km::kbp::path &source, const km::kbp::path &compiled, km::tests:: // we mimic that in the tests. We assume caps lock state is // updated on key_down before the processor receives the // event. - if (p.vk == KM_KBP_VKEY_CAPS) { + if (p.vk == KM_CORE_VKEY_CAPS) { test_source.toggle_caps_lock_state(); } for (auto key_down = 1; key_down >= 0; key_down--) { // expected error only applies to key down - try_status(km_kbp_process_event(test_state, p.vk, p.modifier_state | test_source.caps_lock_state(), key_down, KM_KBP_EVENT_FLAG_DEFAULT)); // TODO-LDML: for now. Should send touch and hardware events. + try_status(km_core_process_event(test_state, p.vk, p.modifier_state | test_source.caps_lock_state(), key_down, KM_CORE_EVENT_FLAG_DEFAULT)); // TODO-LDML: for now. Should send touch and hardware events. - for (auto act = km_kbp_state_action_items(test_state, nullptr); act->type != KM_KBP_IT_END; act++) { + for (auto act = km_core_state_action_items(test_state, nullptr); act->type != KM_CORE_IT_END; act++) { apply_action(test_state, *act, text_store, test_context, test_source); } } @@ -238,14 +238,14 @@ run_test(const km::kbp::path &source, const km::kbp::path &compiled, km::tests:: std::cerr << "TODO-LDML: note, LDML_ACTION_EMIT_STRING is NOT going through keyboard, transforms etc." << std::endl; text_store.append(action.string); // TODO-LDML: not going through keyboard // Now, update context? - km_kbp_context_item *nitems = nullptr; - try_status(km_kbp_context_items_from_utf16(action.string.c_str(), &nitems)); - try_status(km_kbp_context_append(km_kbp_state_context(test_state), nitems)); + km_core_context_item *nitems = nullptr; + try_status(km_core_context_items_from_utf16(action.string.c_str(), &nitems)); + try_status(km_core_context_append(km_core_state_context(test_state), nitems)); // update the test_context also. - for (km_kbp_context_item *ci = nitems; ci->type != KM_KBP_CT_END; ci++) { + for (km_core_context_item *ci = nitems; ci->type != KM_CORE_CT_END; ci++) { test_context.emplace_back(*ci); } - km_kbp_context_items_dispose(nitems); + km_core_context_items_dispose(nitems); verify_context(text_store, test_state, test_context); } else if (action.type == km::tests::LDML_ACTION_CHECK_EXPECTED) { @@ -275,18 +275,18 @@ run_test(const km::kbp::path &source, const km::kbp::path &compiled, km::tests:: // Verify that both our local test_context and the core's test_state.context have // not diverged - try_status(km_kbp_context_get(km_kbp_state_context(test_state), &citems)); + try_status(km_core_context_get(km_core_state_context(test_state), &citems)); auto ci = citems; - for(auto test_ci = test_context.begin(); ci->type != KM_KBP_CT_END || test_ci != test_context.end(); ci++, test_ci++) { - assert(ci->type != KM_KBP_CT_END && test_ci != test_context.end()); // Verify that both lists are same length + for(auto test_ci = test_context.begin(); ci->type != KM_CORE_CT_END || test_ci != test_context.end(); ci++, test_ci++) { + assert(ci->type != KM_CORE_CT_END && test_ci != test_context.end()); // Verify that both lists are same length assert(test_ci->type == ci->type && test_ci->marker == ci->marker); } - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); // Destroy them - km_kbp_state_dispose(test_state); - km_kbp_keyboard_dispose(test_kb); + km_core_state_dispose(test_state); + km_core_keyboard_dispose(test_kb); return 0; } diff --git a/core/tests/unit/ldml/ldml_test_source.cpp b/core/tests/unit/ldml/ldml_test_source.cpp index 33a7e1a3d86..1a5905d1db3 100644 --- a/core/tests/unit/ldml/ldml_test_source.cpp +++ b/core/tests/unit/ldml/ldml_test_source.cpp @@ -66,8 +66,8 @@ LdmlTestSource::~LdmlTestSource() { } -km_kbp_status LdmlTestSource::get_expected_load_status() { - return KM_KBP_STATUS_OK; +km_core_status LdmlTestSource::get_expected_load_status() { + return KM_CORE_STATUS_OK; } bool LdmlTestSource::get_expected_beep() const { @@ -108,7 +108,7 @@ LdmlTestSource::parse_source_string(std::string const &s) { for (auto p = s.begin(); p != s.end(); p++) { if (*p == '\\') { p++; - km_kbp_usv v; + km_core_usv v; bool had_open_curly = false; assert(p != s.end()); if (*p == 'u' || *p == 'U') { @@ -126,10 +126,10 @@ LdmlTestSource::parse_source_string(std::string const &s) { assert(v >= 0x0001 && v <= 0x10FFFF); p += n - 1; if (v < 0x10000) { - t += km_kbp_cp(v); + t += km_core_cp(v); } else { - t += km_kbp_cp(Uni_UTF32ToSurrogate1(v)); - t += km_kbp_cp(Uni_UTF32ToSurrogate2(v)); + t += km_core_cp(Uni_UTF32ToSurrogate1(v)); + t += km_core_cp(Uni_UTF32ToSurrogate2(v)); } if (had_open_curly) { p++; @@ -157,7 +157,7 @@ LdmlTestSource::parse_u8_source_string(std::string const &u8s) { for (auto p = s.begin(); p != s.end(); p++) { if (*p == '\\') { p++; - km_kbp_usv v; + km_core_usv v; bool had_open_curly = false; assert(p != s.end()); if (*p == 'u' || *p == 'U') { @@ -177,10 +177,10 @@ LdmlTestSource::parse_u8_source_string(std::string const &u8s) { assert(v >= 0x0001 && v <= 0x10FFFF); p += n - 1; if (v < 0x10000) { - t += km_kbp_cp(v); + t += km_core_cp(v); } else { - t += km_kbp_cp(Uni_UTF32ToSurrogate1(v)); - t += km_kbp_cp(Uni_UTF32ToSurrogate2(v)); + t += km_core_cp(Uni_UTF32ToSurrogate1(v)); + t += km_core_cp(Uni_UTF32ToSurrogate2(v)); } if (had_open_curly) { p++; @@ -257,9 +257,9 @@ LdmlEmbeddedTestSource::load_source( const km::kbp::path &path ) { return 0; } -km_kbp_status +km_core_status LdmlEmbeddedTestSource::get_expected_load_status() { - return expected_error ? KM_KBP_STATUS_INVALID_KEYBOARD : KM_KBP_STATUS_OK; + return expected_error ? KM_CORE_STATUS_INVALID_KEYBOARD : KM_CORE_STATUS_OK; } const std::u16string& @@ -273,7 +273,7 @@ bool LdmlEmbeddedTestSource::get_expected_beep() const { int LdmlTestSource::caps_lock_state() { - return _caps_lock_on ? KM_KBP_MODIFIER_CAPS : 0; + return _caps_lock_on ? KM_CORE_MODIFIER_CAPS : 0; } void @@ -291,7 +291,7 @@ LdmlTestSource::char_to_event(char ch) { assert(ch >= 32); return { km::kbp::kmx::s_char_to_vkey[(int)ch - 32].vk, - (uint16_t)(km::kbp::kmx::s_char_to_vkey[(int)ch - 32].shifted ? KM_KBP_MODIFIER_SHIFT : 0)}; + (uint16_t)(km::kbp::kmx::s_char_to_vkey[(int)ch - 32].shifted ? KM_CORE_MODIFIER_SHIFT : 0)}; } uint16_t @@ -312,7 +312,7 @@ LdmlEmbeddedTestSource::vkey_to_event(std::string const &vk_event) { std::stringstream f(vk_event); std::string s; uint16_t modifier_state = 0; - km_kbp_virtual_key vk = 0; + km_core_virtual_key vk = 0; while (std::getline(f, s, ' ')) { uint16_t modifier = get_modifier(s); if (modifier != 0) { @@ -442,7 +442,7 @@ void LdmlJsonTestSource::set_key_from_id(key_event& k, const std::u16string& id) auto *kmap = kmxplus->key2Helper.getKmap(kmapIndex); assert(kmap != nullptr); if (kmap->key == keyIndex) { - k = {(km_kbp_virtual_key)kmap->vkey, (uint16_t)kmap->mod}; + k = {(km_core_virtual_key)kmap->vkey, (uint16_t)kmap->mod}; return; } } @@ -561,7 +561,7 @@ LdmlJsonRepertoireTestSource::next_action(ldml_action &fillin) { } // we have already excluded strings, so just get the codepoint - const km_kbp_usv ch = iterator->getCodepoint(); + const km_core_usv ch = iterator->getCodepoint(); // as string for debugging. // const icu::UnicodeString& str = iterator->getString(); @@ -606,7 +606,7 @@ LdmlJsonRepertoireTestSource::next_action(ldml_action &fillin) { auto *kmap = kmxplus->key2Helper.getKmap(kmapIndex); assert(kmap != nullptr); if (kmap->key == keyIndex) { - fillin.k = {(km_kbp_virtual_key)kmap->vkey, (uint16_t)kmap->mod}; + fillin.k = {(km_core_virtual_key)kmap->vkey, (uint16_t)kmap->mod}; std::cout << "found vkey " << fillin.k.vk << ":" << fillin.k.modifier_state << std::endl; fillin.type = LDML_ACTION_KEY_EVENT; return; diff --git a/core/tests/unit/ldml/ldml_test_source.hpp b/core/tests/unit/ldml/ldml_test_source.hpp index 340f0bd0e90..f0770d96548 100644 --- a/core/tests/unit/ldml/ldml_test_source.hpp +++ b/core/tests/unit/ldml/ldml_test_source.hpp @@ -12,7 +12,7 @@ namespace km { namespace tests { struct key_event { - km_kbp_virtual_key vk; + km_core_virtual_key vk; uint16_t modifier_state; }; @@ -58,7 +58,7 @@ class LdmlTestSource { virtual int caps_lock_state(); virtual void toggle_caps_lock_state(); virtual void set_caps_lock_on(bool caps_lock_on); - virtual km_kbp_status get_expected_load_status(); + virtual km_core_status get_expected_load_status(); virtual const std::u16string &get_context() const = 0; virtual bool get_expected_beep() const; @@ -104,7 +104,7 @@ class LdmlEmbeddedTestSource : public LdmlTestSource { */ int load_source(const km::kbp::path &path); - virtual km_kbp_status get_expected_load_status(); + virtual km_core_status get_expected_load_status(); virtual const std::u16string &get_context() const; virtual bool get_expected_beep() const; diff --git a/core/tests/unit/ldml/ldml_test_utils.cpp b/core/tests/unit/ldml/ldml_test_utils.cpp index 57c71dce375..f12017f183b 100644 --- a/core/tests/unit/ldml/ldml_test_utils.cpp +++ b/core/tests/unit/ldml/ldml_test_utils.cpp @@ -13,7 +13,7 @@ namespace km { namespace tests { -km_kbp_virtual_key +km_core_virtual_key get_vk(std::string const &vk) { for (int i = 1; i < 256; i++) { if (vk == km::kbp::kmx::s_key_names[i]) { diff --git a/core/tests/unit/ldml/ldml_test_utils.hpp b/core/tests/unit/ldml/ldml_test_utils.hpp index 8b19edf8d33..1d876365bbb 100644 --- a/core/tests/unit/ldml/ldml_test_utils.hpp +++ b/core/tests/unit/ldml/ldml_test_utils.hpp @@ -13,12 +13,12 @@ #include // for char to vk mapping tables #include // for surrogate pair macros #include -#include +#include namespace km { namespace tests { -km_kbp_virtual_key get_vk(std::string const &vk); +km_core_virtual_key get_vk(std::string const &vk); } // namespace tests } // namespace km diff --git a/developer/src/Makefile b/developer/src/Makefile index 0c6c81ece6b..6a1cf398e51 100644 --- a/developer/src/Makefile +++ b/developer/src/Makefile @@ -153,6 +153,8 @@ do-build-release: $(MAKE) build-release-dependencies $(MAKE) "SIGNCODE_BUILD=SIGNCODE_BUILD" build test $(MAKE) signcode + cd $(DEVELOPER_ROOT)\src\tools\verify_signatures + $(MAKE) test cd $(DEVELOPER_ROOT)\src\inst $(MAKE) diff --git a/developer/src/common/web/test-helpers/tsconfig.json b/developer/src/common/web/test-helpers/tsconfig.json index 47646be3a61..d7089c703f2 100644 --- a/developer/src/common/web/test-helpers/tsconfig.json +++ b/developer/src/common/web/test-helpers/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../../../tsconfig.esm-base.json", + "extends": "../../../../../tsconfig.base.json", "compilerOptions": { "rootDir": ".", diff --git a/developer/src/inst/download.in.mak b/developer/src/inst/download.in.mak index eeadd67ac0a..871f4b012c0 100644 --- a/developer/src/inst/download.in.mak +++ b/developer/src/inst/download.in.mak @@ -26,6 +26,9 @@ copykmdev: makeinstaller make-kmcomp-install-zip -mkdir $(DEVELOPER_ROOT)\release\$Version copy /Y $(DEVELOPER_ROOT)\src\inst\keymandeveloper.msi $(DEVELOPER_ROOT)\release\$Version\keymandeveloper.msi copy /Y $(DEVELOPER_ROOT)\src\inst\keymandeveloper-$Version.exe $(DEVELOPER_ROOT)\release\$Version\keymandeveloper-$Version.exe + $(SIGCHECK) $(DEVELOPER_ROOT)\release\$Version\* > sig1 + $(VERIFY_SIGNATURES) < sig1 + -del sig1 test-releaseexists: if exist $(DEVELOPER_ROOT)\release\$Version\keymandeveloper*.msi echo. & echo Release $Version already exists. Delete it or update VERSION.md and try again & exit 1 diff --git a/developer/src/kmc-analyze/tsconfig.json b/developer/src/kmc-analyze/tsconfig.json index 3a9149e1213..987abd3cc3c 100644 --- a/developer/src/kmc-analyze/tsconfig.json +++ b/developer/src/kmc-analyze/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.esm-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "build/src/", diff --git a/developer/src/kmc-keyboard-info/test/tsconfig.json b/developer/src/kmc-keyboard-info/test/tsconfig.json index bf96b7b1509..6d48ad864d2 100644 --- a/developer/src/kmc-keyboard-info/test/tsconfig.json +++ b/developer/src/kmc-keyboard-info/test/tsconfig.json @@ -6,7 +6,6 @@ "rootDirs": ["./", "../src/"], "outDir": "../build/test", "esModuleInterop": true, - "moduleResolution": "node16", "allowSyntheticDefaultImports": true, "baseUrl": ".", "paths": { diff --git a/developer/src/kmc-kmn/test/fixtures/features/version_160.kmn b/developer/src/kmc-kmn/test/fixtures/features/version_160.kmn new file mode 100644 index 00000000000..43ba17e6af7 --- /dev/null +++ b/developer/src/kmc-kmn/test/fixtures/features/version_160.kmn @@ -0,0 +1,8 @@ +c Description: Verifies that kmcmplib can compile a v16.0 keyboard + +store(&NAME) 'version_160' +store(&VERSION) '16.0' + +begin unicode > use(main) + +group(main) using keys diff --git a/developer/src/kmc-kmn/test/fixtures/features/version_170.kmn b/developer/src/kmc-kmn/test/fixtures/features/version_170.kmn new file mode 100644 index 00000000000..b9779d0734b --- /dev/null +++ b/developer/src/kmc-kmn/test/fixtures/features/version_170.kmn @@ -0,0 +1,8 @@ +c Description: Verifies that kmcmplib can compile a v17.0 keyboard + +store(&NAME) 'version_170' +store(&VERSION) '17.0' + +begin unicode > use(main) + +group(main) using keys diff --git a/developer/src/kmc-kmn/test/test-features.ts b/developer/src/kmc-kmn/test/test-features.ts new file mode 100644 index 00000000000..aa3b050a9fd --- /dev/null +++ b/developer/src/kmc-kmn/test/test-features.ts @@ -0,0 +1,44 @@ +import 'mocha'; +import { assert } from 'chai'; +import { KmnCompiler } from '../src/main.js'; +import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; +import { makePathToFixture } from './helpers/index.js'; +import { KMX, KmxFileReader } from '@keymanapp/common-types'; + +describe('Keyboard compiler features', async function() { + let compiler: KmnCompiler = null; + let callbacks: TestCompilerCallbacks = null; + + this.beforeAll(async function() { + compiler = new KmnCompiler(); + callbacks = new TestCompilerCallbacks(); + assert(await compiler.init(callbacks)); + assert(compiler.verifyInitialized()); + }); + + beforeEach(function() { + callbacks.clear(); + }); + + // Test each Keyman file version target + + const versions = [ + // TODO(lowpri): we should add a test for each version + also test automatic feature detection + ['16.0', '160', KMX.KMXFile.VERSION_160], + ['17.0', '170', KMX.KMXFile.VERSION_170], + ]; + + for(const v of versions) { + it(`should build a version ${v[0]} keyboard`, function() { + const fixtureName = makePathToFixture('features', `version_${v[1]}.kmn`); + + const result = compiler.runCompiler(fixtureName, `version_${v[1]}.kmx`, {saveDebug: true}); + if(result === null) callbacks.printMessages(); + assert.isNotNull(result); + + const reader = new KmxFileReader(); + const keyboard = reader.read(result.kmx.data); + assert.equal(keyboard.fileVersion, v[2]); + }); + } +}); diff --git a/developer/src/kmc-kmn/tsconfig.json b/developer/src/kmc-kmn/tsconfig.json index 04683902eae..4210b750af0 100644 --- a/developer/src/kmc-kmn/tsconfig.json +++ b/developer/src/kmc-kmn/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.esm-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "build/src/", diff --git a/developer/src/kmc-ldml/src/compiler/compiler.ts b/developer/src/kmc-ldml/src/compiler/compiler.ts index ad0340ed820..c29aa9fa938 100644 --- a/developer/src/kmc-ldml/src/compiler/compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/compiler.ts @@ -8,7 +8,6 @@ import { LayrCompiler } from './layr.js'; import { LocaCompiler } from './loca.js'; import { MetaCompiler } from './meta.js'; import { NameCompiler } from './name.js'; -import { VkeyCompiler } from './vkey.js'; import { VarsCompiler } from './vars.js'; import { StrsCompiler, ElemCompiler, ListCompiler, UsetCompiler } from './empty-compiler.js'; @@ -38,7 +37,6 @@ export const SECTION_COMPILERS = [ MetaCompiler, NameCompiler, TranCompiler, - VkeyCompiler, ]; export class LdmlKeyboardCompiler { diff --git a/developer/src/kmc-ldml/src/compiler/disp.ts b/developer/src/kmc-ldml/src/compiler/disp.ts index 77c9609876a..ade215b1fa7 100644 --- a/developer/src/kmc-ldml/src/compiler/disp.ts +++ b/developer/src/kmc-ldml/src/compiler/disp.ts @@ -57,15 +57,20 @@ export class DispCompiler extends SectionCompiler { let result = new Disp(); // displayOptions - result.baseCharacter = sections.strs.allocAndUnescapeString(this.keyboard3.displays?.displayOptions?.baseCharacter); - - // TODO-LDML: substitute variables! + result.baseCharacter = sections.strs.allocString(this.keyboard3.displays?.displayOptions?.baseCharacter, {unescape: true}); // displays result.disps = this.keyboard3.displays?.display.map(display => ({ - to: sections.strs.allocAndUnescapeString(sections.vars.substituteMarkerString(display.to)), + to: sections.strs.allocString(display.to, { + stringVariables: true, + markers: true, + unescape: true, + }, sections), id: sections.strs.allocString(display.id), // not escaped, not substituted - display: sections.strs.allocAndUnescapeString(display.display), + display: sections.strs.allocString(display.display, { + stringVariables: true, + unescape: true, + }, sections), })) || []; // TODO-LDML: need coverage for the [] result.disps.sort((a: DispItem, b: DispItem) => { diff --git a/developer/src/kmc-ldml/src/compiler/keys.ts b/developer/src/kmc-ldml/src/compiler/keys.ts index 652b584d0ff..a09ebbf2b23 100644 --- a/developer/src/kmc-ldml/src/compiler/keys.ts +++ b/developer/src/kmc-ldml/src/compiler/keys.ts @@ -36,6 +36,15 @@ export class KeysCompiler extends SectionCompiler { public validate() { let valid = true; + // There's no 'form' compiler. + // We validate this here so that someone checks it. + this.keyboard3.forms?.form?.forEach((form) => { + if (!LDMLKeyboard.ImportStatus.isImpliedImport(form)) { + // If it's not an implied import, give a warning. + this.callbacks.reportMessage(CompilerMessages.Warn_CustomForm({ id: form.id })); + } + }); + // general key-level validation here, only of used keys const usedKeys = allUsedKeyIdsInLayers(this.keyboard3?.layers); const uniqueKeys = calculateUniqueKeys([...this.keyboard3.keys?.key]); @@ -121,18 +130,21 @@ export class KeysCompiler extends SectionCompiler { for (let lkflick of lkflicks.flick) { let flags = 0; - const to = sections.strs.allocAndUnescapeString(lkflick.to, true); + const to = sections.strs.allocString(lkflick.to, { + stringVariables: true, markers: true, unescape: true, singleOk: true + }, sections); if (!to.isOneChar) { flags |= constants.keys_flick_flags_extend; } let directions: ListItem = sections.list.allocListFromSpaces( - sections.strs, - lkflick.directions - ); + lkflick.directions, + { + stringVariables: true, markers: true, unescape: true + }, + sections); flicks.flicks.push({ directions, flags, - // TODO-LDML: markers,variables to, }); } @@ -159,25 +171,44 @@ export class KeysCompiler extends SectionCompiler { flags |= constants.keys_key_flags_notransform; } const id = sections.strs.allocString(key.id); - const longPress: ListItem = sections.list.allocListFromEscapedSpaces( - sections.strs, - // TODO-LDML: markers,variables - key.longPress - ); - const longPressDefault = sections.strs.allocAndUnescapeString( - // TODO-LDML: variables - sections.vars.substituteMarkerString(key.longPressDefault), - ); - const multiTap: ListItem = sections.list.allocListFromEscapedSpaces( - sections.strs, - // TODO-LDML: markers,variables - key.multiTap - ); + const longPress: ListItem = sections.list.allocListFromSpaces( + key.longPress, { + stringVariables: true, + markers: true, + unescape: true, + }, + sections); + + const longPressDefault = sections.strs.allocString(key.longPressDefault, + { + stringVariables: true, + markers: true, + unescape: true, + }, + sections); + + const multiTap: ListItem = sections.list.allocListFromSpaces( + key.multiTap, + { + stringVariables: true, + markers: true, + unescape: true, + }, + sections); const keySwitch = sections.strs.allocString(key.switch); // 'switch' is a reserved word + const toRaw = key.to; - // TODO-LDML: variables - let toCooked = sections.vars.substituteMarkerString(toRaw); - const to = sections.strs.allocAndUnescapeString(toCooked, true); + + let toCooked = sections.vars.substituteStrings(toRaw, sections); + toCooked = sections.vars.substituteMarkerString(toCooked); + const to = sections.strs.allocString(key.to, + { + stringVariables: true, + markers: true, + unescape: true, + singleOk: true + }, + sections); if (!to.isOneChar) { flags |= constants.keys_key_flags_extend; } @@ -196,6 +227,26 @@ export class KeysCompiler extends SectionCompiler { } } + private getKeymapFromForm(hardware : string, badScans?: Set) : Constants.KeyMap { + return KeysCompiler.getKeymapFromForms(this.keyboard3?.forms.form, hardware, badScans); + } + + public static getKeymapFromForms(forms: LDMLKeyboard.LKForm[], hardware: string, badScans?: Set): Constants.KeyMap { + // seach in reverse form because of overrides + const ldmlForm = [...forms].reverse().find((f) => f.id === hardware); + if (!ldmlForm) { + return undefined; + } + return KeysCompiler.getKeymapFromScancodes(ldmlForm, badScans); + } + + public static getKeymapFromScancodes(ldmlForm: LDMLKeyboard.LKForm, badScans?: Set) { + const { scanCodes } = ldmlForm; + const ldmlScan = scanCodes.map(o => o.codes.split(" ").map(n => Number.parseInt(n, 16))); + const ldmlVkey = Constants.CLDRScanToKeyMap(ldmlScan, badScans); + return ldmlVkey; + } + /** * TODO-LDML: from old 'keys' * Validate for purpose of kmap @@ -217,14 +268,21 @@ export class KeysCompiler extends SectionCompiler { valid = false; } - const keymap = Constants.HardwareToKeymap.get(hardware); - /* c8 ignore next 5 */ + const badScans = new Set(); + const keymap = this.getKeymapFromForm(hardware, badScans); if (!keymap) { - // not reached due to XML validation this.callbacks.reportMessage( CompilerMessages.Error_InvalidHardware({ form: hardware }) ); valid = false; + return valid; + } else if (badScans.size !== 0) { + const codes = Array.from(badScans.values()).map(n => Number(n).toString(16)).sort(); + this.callbacks.reportMessage( + CompilerMessages.Error_InvalidScanCode({ form: hardware, codes }) + ); + valid = false; + return valid; } const uniqueKeys = calculateUniqueKeys([...this.keyboard3.keys?.key]); @@ -287,7 +345,7 @@ export class KeysCompiler extends SectionCompiler { hardware: string ): Keys { const mod = translateLayerAttrToModifier(layer); - const keymap = Constants.HardwareToKeymap.get(hardware); + const keymap = this.getKeymapFromForm(hardware); let y = -1; for (let row of layer.row) { diff --git a/developer/src/kmc-ldml/src/compiler/layr.ts b/developer/src/kmc-ldml/src/compiler/layr.ts index 281ca8d5db9..0559c57f6df 100644 --- a/developer/src/kmc-ldml/src/compiler/layr.ts +++ b/developer/src/kmc-ldml/src/compiler/layr.ts @@ -35,11 +35,6 @@ export class LayrCompiler extends SectionCompiler { if (hardwareLayers > 1) { valid = false; this.callbacks.reportMessage(CompilerMessages.Error_ExcessHardware({form})); - } else if (!constants.layr_list_hardware_map.get(form)) { - /* c8 ignore next 4 */ - // not reached due to XML validation - valid = false; - this.callbacks.reportMessage(CompilerMessages.Error_InvalidHardware({form})); } } layers.layer.forEach((layer) => { @@ -63,7 +58,7 @@ export class LayrCompiler extends SectionCompiler { const sect = new Layr(); sect.lists = this.keyboard3.layers.map((layers) => { - const hardware = constants.layr_list_hardware_map.get(layers.form); + const hardware = sections.strs.allocString(layers.form); // Already validated in validate const list: LayrList = { hardware, diff --git a/developer/src/kmc-ldml/src/compiler/messages.ts b/developer/src/kmc-ldml/src/compiler/messages.ts index 804ec1d02dd..e22a9f62812 100644 --- a/developer/src/kmc-ldml/src/compiler/messages.ts +++ b/developer/src/kmc-ldml/src/compiler/messages.ts @@ -1,8 +1,8 @@ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m } from "@keymanapp/common-types"; -const SevInfo = CompilerErrorSeverity.Info | CompilerErrorNamespace.LdmlKeyboardCompiler; +// const SevInfo = CompilerErrorSeverity.Info | CompilerErrorNamespace.LdmlKeyboardCompiler; const SevHint = CompilerErrorSeverity.Hint | CompilerErrorNamespace.LdmlKeyboardCompiler; -// const SevWarn = CompilerErrorSeverity.Warn | CompilerErrorNamespace.LdmlKeyboardCompiler; +const SevWarn = CompilerErrorSeverity.Warn | CompilerErrorNamespace.LdmlKeyboardCompiler; const SevError = CompilerErrorSeverity.Error | CompilerErrorNamespace.LdmlKeyboardCompiler; const SevFatal = CompilerErrorSeverity.Fatal | CompilerErrorNamespace.LdmlKeyboardCompiler; @@ -35,21 +35,16 @@ export class CompilerMessages { m(this.HINT_LocaleIsNotMinimalAndClean, `Locale '${o.sourceLocale}' is not minimal or correctly formatted and should be '${o.locale}'`); static HINT_LocaleIsNotMinimalAndClean = SevHint | 0x0008; - static Hint_VkeyIsNotValid = (o:{vkey: string}) => - m(this.HINT_VkeyIsNotValid, `Virtual key '${o.vkey}' is not found in the CLDR VKey Enum table.`); - static HINT_VkeyIsNotValid = SevHint | 0x0009; + static Error_InvalidScanCode = (o:{form?: string, codes?: string[]}) => + m(this.ERROR_InvalidScanCode, `Form '${o.form}' has invalid/unknown scancodes '${o.codes?.join(' ')}'`); + static ERROR_InvalidScanCode = SevError | 0x0009; - static Hint_VkeyIsRedundant = (o:{vkey: string}) => - m(this.HINT_VkeyIsRedundant, `Virtual key '${o.vkey}' is mapped to itself, which is redundant.`); - static HINT_VkeyIsRedundant = SevHint | 0x000A; + static Warn_CustomForm = (o:{id: string}) => + m(this.WARN_CustomForm, `Custom
element. Key layout may not be as expected.`); + static WARN_CustomForm = SevWarn | 0x000A; - static Error_VkeyIsRepeated = (o:{vkey: string}) => - m(this.ERROR_VkeyIsRepeated, `Virtual key '${o.vkey}' has more than one vkey entry.`); - static ERROR_VkeyIsRepeated = SevError | 0x000B; - - static Info_MultipleVkeysHaveSameTarget = (o:{vkey: string}) => - m(this.INFO_MultipleVkeysHaveSameTarget, `Target virtual key '${o.vkey}' has multiple source mappings, which may be an error.`); - static INFO_MultipleVkeysHaveSameTarget = SevInfo | 0x000C; + // 0x000B - available + // 0x000C - available static Error_InvalidVersion = (o:{version: string}) => m(this.ERROR_InvalidVersion, `Version number '${o.version}' must be a semantic version format string.`); @@ -148,6 +143,6 @@ export class CompilerMessages { static Error_DisplayNeedsToOrId = (o:{to?: string, id?: string}) => m(this.ERROR_DisplayNeedsToOrId, `display ${CompilerMessages.toOrId(o)} needs to= or id=, but not both`); static ERROR_DisplayNeedsToOrId = SevError | 0x0022; - } + diff --git a/developer/src/kmc-ldml/src/compiler/tran.ts b/developer/src/kmc-ldml/src/compiler/tran.ts index 9f39e302ef3..89a9d61f1cf 100644 --- a/developer/src/kmc-ldml/src/compiler/tran.ts +++ b/developer/src/kmc-ldml/src/compiler/tran.ts @@ -121,12 +121,11 @@ export class TransformCompiler m !== MarkerParser.ANY_MARKER_ID).sort(); - result.markers = sections.list.allocList(sections.strs, allMarkers); + result.markers = sections.list.allocList(allMarkers, {}, sections); return result.valid() ? result : null; } diff --git a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts index c45326ff984..1ad0a4ea1c5 100644 --- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts @@ -1,4 +1,5 @@ -import { Constants, VisualKeyboard, LDMLKeyboard } from "@keymanapp/common-types"; +import { VisualKeyboard, LDMLKeyboard } from "@keymanapp/common-types"; +import { KeysCompiler } from "./keys.js"; export class LdmlKeyboardVisualKeyboardCompiler { public compile(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile): VisualKeyboard.VisualKeyboard { @@ -14,8 +15,9 @@ export class LdmlKeyboardVisualKeyboardCompiler { result.header.unicodeFont = {...VisualKeyboard.DEFAULT_KVK_FONT}; for(let layers of source.keyboard3.layers) { + const hardware = layers.form; for(let layer of layers.layer) { - this.compileHardwareLayer(source, result, layer); + this.compileHardwareLayer(source, result, layer, hardware); } } return result; @@ -24,9 +26,16 @@ export class LdmlKeyboardVisualKeyboardCompiler { private compileHardwareLayer( source: LDMLKeyboard.LDMLKeyboardXMLSourceFile, vk: VisualKeyboard.VisualKeyboard, - layer: LDMLKeyboard.LKLayer + layer: LDMLKeyboard.LKLayer, + hardware: string, ) { - // TODO-LDML: consider consolidation with keys.ts? + if (hardware === 'touch') { + hardware = 'us'; // TODO-LDML: US Only. Do something different here? + } + const keymap = KeysCompiler.getKeymapFromForms(source.keyboard3?.forms?.form, hardware); + if (!keymap) { + throw Error(`Internal error: could not find keymap for form ${hardware}`); + } const shift = this.translateLayerIdToVisualKeyboardShift(layer.id); let y = -1; @@ -48,7 +57,7 @@ export class LdmlKeyboardVisualKeyboardCompiler { flags: VisualKeyboard.VisualKeyboardKeyFlags.kvkkUnicode, shift: shift, text: keydef.to, // TODO-LDML: displays - vkey: Constants.USVirtualKeyMap[y][x] // TODO-LDML: #7965 US-only + vkey: keymap[y][x], }); } } diff --git a/developer/src/kmc-ldml/src/compiler/vkey.ts b/developer/src/kmc-ldml/src/compiler/vkey.ts deleted file mode 100644 index 1c4c69403be..00000000000 --- a/developer/src/kmc-ldml/src/compiler/vkey.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { constants } from "@keymanapp/ldml-keyboard-constants"; -import { KMXPlus, Constants } from '@keymanapp/common-types'; -import { CompilerMessages } from "./messages.js"; -import { SectionCompiler } from "./section-compiler.js"; - -import Vkey = KMXPlus.Vkey; -import LdmlVkeyNames = Constants.LdmlVkeyNames; - -export class VkeyCompiler extends SectionCompiler { - - public get id() { - return constants.section.vkey; - } - - public validate(): boolean { - let valid = true; - if(this.keyboard3.vkeys) { - let from: string[] = [], to: string[] = []; - - this.keyboard3.vkeys.vkey.forEach(vk => { - if(LdmlVkeyNames[vk.from] === undefined) { - // TODO-LDML: When we do #7135 this may need to change back to an error. - this.callbacks.reportMessage(CompilerMessages.Hint_VkeyIsNotValid({vkey: vk.from})); - return; - } - - if(LdmlVkeyNames[vk.to] === undefined) { - // TODO-LDML: When we do #7135 this may need to change back to an error. - this.callbacks.reportMessage(CompilerMessages.Hint_VkeyIsNotValid({vkey: vk.to})); - return; - } - - if(vk.from == vk.to) { - this.callbacks.reportMessage(CompilerMessages.Hint_VkeyIsRedundant({vkey: vk.from})); - } - - if(from.find(svk => svk == vk.from)) { - this.callbacks.reportMessage(CompilerMessages.Error_VkeyIsRepeated({vkey: vk.from})); - valid = false; - } - from.push(vk.from); - - if(to.find(svk => svk == vk.to)) { - this.callbacks.reportMessage(CompilerMessages.Info_MultipleVkeysHaveSameTarget({vkey: vk.to})); - } - to.push(vk.to); - }); - } - return valid; - } - - public compile(): Vkey { - let result = new Vkey(); - if(!this.keyboard3.vkeys) { - /* c8 ignore next 2 */ - return result; // not hit due to boxing - } - - result.vkeys = this.keyboard3.vkeys?.vkey.map(vk => { - return { - vkey: LdmlVkeyNames[vk.from], - target: LdmlVkeyNames[vk.to] - }; - }); - // Sort according to vkey binary order, per C7043 - result.vkeys.sort((a,b) => a.vkey - b.vkey); - return result; - } -} diff --git a/developer/src/kmc-ldml/test/fixtures/basic.txt b/developer/src/kmc-ldml/test/fixtures/basic.txt index 74280b3ecf8..0cd2fa77c17 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic.txt +++ b/developer/src/kmc-ldml/test/fixtures/basic.txt @@ -137,9 +137,6 @@ block(sectitems) 76 61 72 73 diff(sect,vars) - 76 6b 65 79 - diff(sect,vkey) - block(endsect) # ---------------------------------------------------------------------------------------------------- @@ -305,7 +302,7 @@ block(layr) # struct COMP_KMXPLUS_LAYR { 01 00 00 00 # KMX_DWORD rowCount 02 00 00 00 # KMX_DWORD keyCount # list 0 - 04 00 00 00 # KMX_DWORD hardware = 'us' + index(strNull,strUs,2) # KMXPLUS_STR hardware = 'us' 00 00 00 00 # KMX_DWORD layer; 01 00 00 00 # count 7B 00 00 00 # KMX_DWORD minDeviceWidth; // 123 @@ -426,6 +423,7 @@ block(strs) # struct COMP_KMXPLUS_STRS { diff(strs,strAuthor) sizeof(strAuthor,2) diff(strs,strConformsTo) sizeof(strConformsTo,2) diff(strs,strThat) sizeof(strThat,2) + diff(strs,strUs) sizeof(strUs,2) diff(strs,strVse) sizeof(strVse,2) diff(strs,strVst) sizeof(strVst,2) diff(strs,strVus) sizeof(strVus,2) @@ -463,6 +461,7 @@ block(strs) # struct COMP_KMXPLUS_STRS { block(strConformsTo) 74 00 65 00 63 00 68 00 70 00 72 00 65 00 76 00 69 00 65 00 77 00 block(x) 00 00 # 'techpreview' block(strThat) 74 00 68 00 61 00 74 00 block(x) 00 00 # 'that' + block(strUs) 75 00 73 00 block(x) 00 00 # 'us' (layout) block(strVse) 76 00 73 00 65 00 block(x) 00 00 # 'vse' block(strVst) 76 00 73 00 74 00 block(x) 00 00 # 'vst' block(strVus) 76 00 75 00 73 00 block(x) 00 00 # 'vus' @@ -579,13 +578,4 @@ block(vars) # struct COMP_KMXPLUS_VARS { 00 00 00 00 # KMXPLUS_ELEM elem block(varsEnd) -block(vkey) # struct COMP_KMXPLUS_VKEY { - 76 6b 65 79 # KMX_DWORD header.ident; // 0000 Section name - vkey - sizeof(vkey) # KMX_DWORD header.size; // 0004 Section length - 02 00 00 00 # KMX_DWORD count; // 0008 Number of vkey maps - - 41 00 00 00 51 00 00 00 # KMX_DWORD vkey; KMX_DWORD target; // K_A => K_Q - 51 00 00 00 41 00 00 00 # KMX_DWORD vkey; KMX_DWORD target; // K_Q => K_A - # }; - block(eof) # end of file diff --git a/developer/src/kmc-ldml/test/fixtures/basic.xml b/developer/src/kmc-ldml/test/fixtures/basic.xml index 9c45f5e07fc..144bcb49247 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic.xml +++ b/developer/src/kmc-ldml/test/fixtures/basic.xml @@ -14,11 +14,6 @@ - - - - - diff --git a/developer/src/kmc-ldml/test/fixtures/sections/disp/maximal.xml b/developer/src/kmc-ldml/test/fixtures/sections/disp/maximal.xml index 1a698edddbb..862c9310043 100644 --- a/developer/src/kmc-ldml/test/fixtures/sections/disp/maximal.xml +++ b/developer/src/kmc-ldml/test/fixtures/sections/disp/maximal.xml @@ -9,7 +9,11 @@ - + + + + + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/keys/maximal.xml b/developer/src/kmc-ldml/test/fixtures/sections/keys/maximal.xml index 6c9b983fbd6..40f0be95ba1 100644 --- a/developer/src/kmc-ldml/test/fixtures/sections/keys/maximal.xml +++ b/developer/src/kmc-ldml/test/fixtures/sections/keys/maximal.xml @@ -12,13 +12,12 @@ - + - + - @@ -34,4 +33,9 @@ + + + + + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-custom-us-form.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-custom-us-form.xml new file mode 100644 index 00000000000..2c92c0d8608 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-custom-us-form.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-custom-zzz-form.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-custom-zzz-form.xml new file mode 100644 index 00000000000..0ab10f3d032 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-custom-zzz-form.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/warn-custom-us-form.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/warn-custom-us-form.xml new file mode 100644 index 00000000000..d3a0573b21d --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/warn-custom-us-form.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/warn-custom-zzz-form.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/warn-custom-zzz-form.xml new file mode 100644 index 00000000000..502b254135b --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/warn-custom-zzz-form.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + +
+ + +
+ + + + + +
diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-from-vkey.xml b/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-from-vkey.xml deleted file mode 100644 index 9ed1d1b63f1..00000000000 --- a/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-from-vkey.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-repeated-vkey.xml b/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-repeated-vkey.xml deleted file mode 100644 index 36deceb4d86..00000000000 --- a/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-repeated-vkey.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-to-vkey.xml b/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-to-vkey.xml deleted file mode 100644 index 58b573adc24..00000000000 --- a/developer/src/kmc-ldml/test/fixtures/sections/vkey/invalid-to-vkey.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vkey/minimal.xml b/developer/src/kmc-ldml/test/fixtures/sections/vkey/minimal.xml deleted file mode 100644 index 4af6dd30320..00000000000 --- a/developer/src/kmc-ldml/test/fixtures/sections/vkey/minimal.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vkey/redundant.xml b/developer/src/kmc-ldml/test/fixtures/sections/vkey/redundant.xml deleted file mode 100644 index 612d12c0146..00000000000 --- a/developer/src/kmc-ldml/test/fixtures/sections/vkey/redundant.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vkey/same-target.xml b/developer/src/kmc-ldml/test/fixtures/sections/vkey/same-target.xml deleted file mode 100644 index 9dd34420eb3..00000000000 --- a/developer/src/kmc-ldml/test/fixtures/sections/vkey/same-target.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/developer/src/kmc-ldml/test/test-compiler-e2e.ts b/developer/src/kmc-ldml/test/test-compiler-e2e.ts index 41acd7c81d3..343f6cc7ac6 100644 --- a/developer/src/kmc-ldml/test/test-compiler-e2e.ts +++ b/developer/src/kmc-ldml/test/test-compiler-e2e.ts @@ -1,12 +1,10 @@ import 'mocha'; import {assert} from 'chai'; -import x_hextobin from '@keymanapp/hextobin'; +import hextobin from '@keymanapp/hextobin'; import { KMXBuilder } from '@keymanapp/common-types'; import {checkMessages, compileKeyboard, compilerTestCallbacks, compilerTestOptions, makePathToFixture} from './helpers/index.js'; import { LdmlKeyboardCompiler } from '../src/compiler/compiler.js'; -const hextobin = (x_hextobin as any).default; - describe('compiler-tests', function() { this.slow(500); // 0.5 sec -- json schema validation takes a while diff --git a/developer/src/kmc-ldml/test/test-keys.ts b/developer/src/kmc-ldml/test/test-keys.ts index 9429b339791..5a085a0d0fb 100644 --- a/developer/src/kmc-ldml/test/test-keys.ts +++ b/developer/src/kmc-ldml/test/test-keys.ts @@ -38,6 +38,10 @@ describe('keys', function () { assert.equal(compilerTestCallbacks.messages.length, 0); assert.equal(keys.keys.length, 4); + const [w] = keys.keys.filter(({ id }) => id.value === 'w'); + assert.ok(w); + assert.equal(w.to.value, 'w', 'substituted key value'); + const [q] = keys.keys.filter(({ id }) => id.value === 'q'); assert.ok(q); assert.isFalse(!!(q.flags & constants.keys_key_flags_gap)); @@ -57,7 +61,7 @@ describe('keys', function () { const [flick0_ne_sw] = flick0.flicks.filter(({ directions }) => directions && directions.isEqual('ne sw'.split(' '))); assert.ok(flick0_ne_sw); - assert.equal(flick0_ne_sw.to?.value, 'ê'); + assert.equal(flick0_ne_sw.to?.value, 'ê'); // via variable }, }, { @@ -129,11 +133,11 @@ describe('keys', function () { const MARKER_1 = MarkerParser.markerOutput(1); assert.equal(ww.to.value, MARKER_1); assert.equal(ww.longPressDefault.value, MARKER_1); - // TODO-LDML: assert.equal(ww.longPress[0].value.value, MARKER_1); - // TODO-LDML: assert.equal(ww.multiTap[0].value.value, MARKER_1); + assert.equal(ww.longPress[0].value.value, MARKER_1); + assert.equal(ww.multiTap[0].value.value, MARKER_1); const [flickw] = keys.flicks?.filter(({id}) => id.value === 'flickw'); assert.ok(flickw); - // TODO-LDML: assert.equal(flickw.flicks[0].to.value, MARKER_1); + assert.equal(flickw.flicks[0].to.value, MARKER_1); }, }, ]); @@ -241,6 +245,90 @@ describe('keys.kmap', function () { CompilerMessages.Error_MissingFlicks({flicks:'an-undefined-flick-id',id:'Q'}), ] }, + { + subpath: 'sections/layr/invalid-invalid-form.xml', + errors: [CompilerMessages.Error_InvalidHardware({ + form: 'holographic', + }),], + }, + { + // warning on custom form + subpath: 'sections/layr/warn-custom-us-form.xml', + warnings: [ + CompilerMessages.Warn_CustomForm({id: "us"}), + ], + callback: (sect, subpath, callbacks) => { + const keys = sect as Keys; + assert.isNotNull(keys); + assert.equal(compilerTestCallbacks.messages.length, 0); + assert.equal(keys.keys.length, 3); + assert.sameDeepMembers(keys.kmap, [ + { + vkey: K.K_K, + key: 'one', + mod: constants.keys_mod_none, + }, + { + vkey: K.K_E, + key: 'two', + mod: constants.keys_mod_none, + }, + { + vkey: K.K_Y, + key: 'three', + mod: constants.keys_mod_none, + }, + ]); + }, + }, + { + // warning on a custom unknown form - but no error! + subpath: 'sections/layr/warn-custom-zzz-form.xml', + warnings: [ + CompilerMessages.Warn_CustomForm({id: "zzz"}), + ], + callback: (sect, subpath, callbacks) => { + const keys = sect as Keys; + assert.isNotNull(keys); + assert.equal(compilerTestCallbacks.messages.length, 0); + assert.equal(keys.keys.length, 3); + assert.sameDeepMembers(keys.kmap, [ + { + vkey: K.K_K, + key: 'one', + mod: constants.keys_mod_none, + }, + { + vkey: K.K_E, + key: 'two', + mod: constants.keys_mod_none, + }, + { + vkey: K.K_Y, + key: 'three', + mod: constants.keys_mod_none, + }, + ]); + }, + }, + { + subpath: 'sections/layr/error-custom-us-form.xml', + warnings: [ + CompilerMessages.Warn_CustomForm({id: "us"}), + ], + errors: [ + CompilerMessages.Error_InvalidScanCode({ form: "us", codes: ['ff'] }), + ], + }, + { + subpath: 'sections/layr/error-custom-zzz-form.xml', + warnings: [ + CompilerMessages.Warn_CustomForm({id: "zzz"}), + ], + errors: [ + CompilerMessages.Error_InvalidScanCode({ form: "zzz", codes: ['ff'] }), + ], + }, ]); it('should reject layouts with too many hardware rows', async function() { diff --git a/developer/src/kmc-ldml/test/test-layr.ts b/developer/src/kmc-ldml/test/test-layr.ts index 86c7e2729bd..126935c33b5 100644 --- a/developer/src/kmc-ldml/test/test-layr.ts +++ b/developer/src/kmc-ldml/test/test-layr.ts @@ -2,7 +2,7 @@ import 'mocha'; import { assert } from 'chai'; import { LayrCompiler } from '../src/compiler/layr.js'; import { CompilerMessages } from '../src/compiler/messages.js'; -import { compilerTestCallbacks, loadSectionFixture, testCompilationCases } from './helpers/index.js'; +import { compilerTestCallbacks, testCompilationCases } from './helpers/index.js'; import { KMXPlus } from '@keymanapp/common-types'; import { constants } from '@keymanapp/ldml-keyboard-constants'; @@ -20,37 +20,38 @@ function allKeysOk(row : LayrRow, str : string, msg? : string) { describe('layr', function () { this.slow(500); // 0.5 sec -- json schema validation takes a while - // reuse the keys minimal file - it('should compile minimal keys data', async function () { - let layr = await loadSectionFixture(LayrCompiler, 'sections/keys/minimal.xml', compilerTestCallbacks) as Layr; - assert.ok(layr); - assert.equal(compilerTestCallbacks.messages.length, 0); - - assert.equal(layr.lists?.length, 1); - const list0 = layr.lists[0]; - assert.ok(list0); - assert.equal(list0.layers.length, 1); - assert.equal(list0.hardware, constants.layr_list_hardware_us); - const layer0 = list0.layers[0]; - assert.ok(layer0); - assert.equal(layer0.rows.length, 1); - const row0 = layer0.rows[0]; - assert.ok(row0); - assert.equal(row0.keys.length, 2); + testCompilationCases(LayrCompiler, [ + { + subpath: 'sections/keys/minimal.xml', + callback(sect) { + const layr = sect; + assert.ok(layr); + assert.equal(compilerTestCallbacks.messages.length, 0); - assert.equal(layer0.id.value, 'base'); - assert.equal(layer0.mod, constants.keys_mod_none); - assert.equal(row0.keys[0]?.value, 'grave'); - }); + assert.equal(layr.lists?.length, 1); + const list0 = layr.lists[0]; + assert.ok(list0); + assert.equal(list0.layers.length, 1); + assert.equal(list0.hardware.value, 'us'); + const layer0 = list0.layers[0]; + assert.ok(layer0); + assert.equal(layer0.rows.length, 1); + const row0 = layer0.rows[0]; + assert.ok(row0); + assert.equal(row0.keys.length, 2); - testCompilationCases(LayrCompiler, [ + assert.equal(layer0.id.value, 'base'); + assert.equal(layer0.mod, constants.keys_mod_none); + assert.equal(row0.keys[0]?.value, 'grave'); + }, + }, { subpath: 'sections/keys/maximal.xml', callback(sect) { const layr = sect; assert.equal(layr.lists?.length, 2); - const listHardware = layr.lists.find(v => v.hardware === constants.layr_list_hardware_iso); + const listHardware = layr.lists.find(v => v.hardware.value === 'iso'); assert.ok(listHardware); assert.equal(listHardware.minDeviceWidth, 0); assert.equal(listHardware.layers.length, 2); @@ -72,7 +73,7 @@ describe('layr', function () { assert.equal(hardware1row0.keys.length, 2); allKeysOk(hardware1row0,'q w', 'hardware1row0'); - const listTouch = layr.lists.find(v => v.hardware === constants.layr_list_hardware_touch); + const listTouch = layr.lists.find(v => v.hardware.value === constants.layr_list_hardware_touch); assert.ok(listTouch); assert.equal(listTouch.minDeviceWidth, 300); assert.equal(listTouch.layers.length, 1); @@ -104,23 +105,10 @@ describe('layr', function () { subpath: 'sections/layr/invalid-multi-hardware.xml', errors: [CompilerMessages.Error_ExcessHardware({ form: 'iso' })], }, - { - subpath: 'sections/layr/invalid-invalid-form.xml', - errors: [CompilerMessages.Error_InvalidHardware({ - form: 'holographic', - }),], - }, { // missing layer element subpath: 'sections/layr/invalid-missing-layer.xml', errors: [CompilerMessages.Error_MustBeAtLeastOneLayerElement()], }, - { - // missing layers element completely - subpath: 'sections/layr/invalid-missing-layer.xml', - errors: [ - CompilerMessages.Error_MustBeAtLeastOneLayerElement(), - ], - } ]); }); diff --git a/developer/src/kmc-ldml/test/test-vars.ts b/developer/src/kmc-ldml/test/test-vars.ts index 5bdd5e65f01..4b053c30d23 100644 --- a/developer/src/kmc-ldml/test/test-vars.ts +++ b/developer/src/kmc-ldml/test/test-vars.ts @@ -203,8 +203,9 @@ describe('vars', function () { callback(sect) { const vars = sect; assert.ok(vars.markers); - assert.sameDeepOrderedMembers(vars.markers.toStringArray(), - ['m','x']); + // assert.sameDeepOrderedMembers(vars.markers.toStringArray(), + // ['m','x']); + assert.equal(vars.markers.toString(), 'm x'); }, }, { diff --git a/developer/src/kmc-ldml/test/test-virtual-key-constants.ts b/developer/src/kmc-ldml/test/test-virtual-key-constants.ts deleted file mode 100644 index 3ad5d3662cc..00000000000 --- a/developer/src/kmc-ldml/test/test-virtual-key-constants.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { expect } from 'chai'; -import { Constants } from '@keymanapp/common-types'; - -import LdmlVkeyNames = Constants.LdmlVkeyNames; - -describe('virtual key constants', function () { - - it('should map the CLDR VKey Enum values to the right constants', function () { - - // These are copied-and-pasted from the table in TR35 - // We want to check that our constants match the ones in that table! - const CLDRVKeyEnumValues: Record = { - 'SPACE': 0x20, - '0': 0x30, - '1': 0x31, - '2': 0x32, - '3': 0x33, - '4': 0x34, - '5': 0x35, - '6': 0x36, - '7': 0x37, - '8': 0x38, - '9': 0x39, - 'A': 0x41, - 'B': 0x42, - 'C': 0x43, - 'D': 0x44, - 'E': 0x45, - 'F': 0x46, - 'G': 0x47, - 'H': 0x48, - 'I': 0x49, - 'J': 0x4A, - 'K': 0x4B, - 'L': 0x4C, - 'M': 0x4D, - 'N': 0x4E, - 'O': 0x4F, - 'P': 0x50, - 'Q': 0x51, - 'R': 0x52, - 'S': 0x53, - 'T': 0x54, - 'U': 0x55, - 'V': 0x56, - 'W': 0x57, - 'X': 0x58, - 'Y': 0x59, - 'Z': 0x5A, - 'SEMICOLON': 0xBA, - 'EQUAL': 0xBB, - 'COMMA': 0xBC, - 'HYPHEN': 0xBD, - 'PERIOD': 0xBE, - 'SLASH': 0xBF, - 'GRAVE': 0xC0, - 'LBRACKET': 0xDB, - 'BACKSLASH': 0xDC, - 'RBRACKET': 0xDD, - 'QUOTE': 0xDE, - 'LESS-THAN': 0xE2, - 'ABNT2': 0xC1 - }; - - const keys = Object.keys(CLDRVKeyEnumValues); - for (let key of keys) { - expect(CLDRVKeyEnumValues[key]).to.be.equal(LdmlVkeyNames[key]); - } - }); -}); diff --git a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler-e2e.ts b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler-e2e.ts index 87d4d914c9e..133f4286c85 100644 --- a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler-e2e.ts +++ b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler-e2e.ts @@ -1,11 +1,9 @@ import 'mocha'; import {assert} from 'chai'; -import x_hextobin from '@keymanapp/hextobin'; +import hextobin from '@keymanapp/hextobin'; import { KvkFileWriter } from '@keymanapp/common-types'; import {checkMessages, compilerTestOptions, compileVisualKeyboard, makePathToFixture} from './helpers/index.js'; -const hextobin = (x_hextobin as any).default; - describe('visual-keyboard-compiler', function() { this.slow(500); // 0.5 sec -- json schema validation takes a while diff --git a/developer/src/kmc-ldml/test/test-vkey.ts b/developer/src/kmc-ldml/test/test-vkey.ts deleted file mode 100644 index dec24125e2a..00000000000 --- a/developer/src/kmc-ldml/test/test-vkey.ts +++ /dev/null @@ -1,62 +0,0 @@ -import 'mocha'; -import { assert } from 'chai'; -import { VkeyCompiler } from '../src/compiler/vkey.js'; -import { compilerTestCallbacks, loadSectionFixture } from './helpers/index.js'; -import { KMXPlus, Constants } from '@keymanapp/common-types'; -import { CompilerMessages } from '../src/compiler/messages.js'; - -import Vkey = KMXPlus.Vkey; -import USVirtualKeyCodes = Constants.USVirtualKeyCodes; - -describe('vkey compiler', function () { - this.slow(500); // 0.5 sec -- json schema validation takes a while - - it('should compile minimal vkey data', async function() { - let vkey = await loadSectionFixture(VkeyCompiler, 'sections/vkey/minimal.xml', compilerTestCallbacks) as Vkey; - assert.equal(compilerTestCallbacks.messages.length, 0); - - assert.equal(vkey.vkeys.length, 4); - // Note, final order is sorted by `vkey` member - assert.deepEqual(vkey.vkeys[0], {vkey: USVirtualKeyCodes.K_A, target: USVirtualKeyCodes.K_Q}); - assert.deepEqual(vkey.vkeys[1], {vkey: USVirtualKeyCodes.K_Q, target: USVirtualKeyCodes.K_A}); - assert.deepEqual(vkey.vkeys[2], {vkey: USVirtualKeyCodes.K_W, target: USVirtualKeyCodes.K_Z}); - assert.deepEqual(vkey.vkeys[3], {vkey: USVirtualKeyCodes.K_Z, target: USVirtualKeyCodes.K_W}); - }); - - it('should hint on redundant data', async function() { - let vkey = await loadSectionFixture(VkeyCompiler, 'sections/vkey/redundant.xml', compilerTestCallbacks) as Vkey; - assert.isNotNull(vkey); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], CompilerMessages.Hint_VkeyIsRedundant({vkey: 'A'})); - }); - - it('should report an info message if same target found', async function() { - let vkey = await loadSectionFixture(VkeyCompiler, 'sections/vkey/same-target.xml', compilerTestCallbacks) as Vkey; - assert.isNotNull(vkey); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], CompilerMessages.Info_MultipleVkeysHaveSameTarget({vkey: 'Q'})); - }); - - it('should hint on invalid "from" vkey', async function() { - let vkey = await loadSectionFixture(VkeyCompiler, 'sections/vkey/invalid-from-vkey.xml', compilerTestCallbacks) as Vkey; - assert.isNotNull(vkey); - assert.equal(compilerTestCallbacks.messages.length, 2); - assert.deepEqual(compilerTestCallbacks.messages[0], CompilerMessages.Hint_VkeyIsNotValid({vkey: 'q'})); - assert.deepEqual(compilerTestCallbacks.messages[1], CompilerMessages.Hint_VkeyIsNotValid({vkey: 'HYFEN'})); - }); - - it('should hint on invalid "to" vkey', async function() { - let vkey = await loadSectionFixture(VkeyCompiler, 'sections/vkey/invalid-to-vkey.xml', compilerTestCallbacks) as Vkey; - assert.isNotNull(vkey); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], CompilerMessages.Hint_VkeyIsNotValid({vkey: 'A-ACUTE'})); - }); - - it('should error on repeated vkeys', async function() { - let vkey = await loadSectionFixture(VkeyCompiler, 'sections/vkey/invalid-repeated-vkey.xml', compilerTestCallbacks) as Vkey; - assert.isNull(vkey); - assert.equal(compilerTestCallbacks.messages.length, 1); - assert.deepEqual(compilerTestCallbacks.messages[0], CompilerMessages.Error_VkeyIsRepeated({vkey: 'A'})); - }); -}); - diff --git a/developer/src/kmc-ldml/tsconfig.json b/developer/src/kmc-ldml/tsconfig.json index c9ec649b40f..fdcf5fd82bb 100644 --- a/developer/src/kmc-ldml/tsconfig.json +++ b/developer/src/kmc-ldml/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../../tsconfig.esm-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { "outDir": "build/src/", diff --git a/developer/src/kmc-model-info/test/tsconfig.json b/developer/src/kmc-model-info/test/tsconfig.json index bf96b7b1509..6d48ad864d2 100644 --- a/developer/src/kmc-model-info/test/tsconfig.json +++ b/developer/src/kmc-model-info/test/tsconfig.json @@ -6,7 +6,6 @@ "rootDirs": ["./", "../src/"], "outDir": "../build/test", "esModuleInterop": true, - "moduleResolution": "node16", "allowSyntheticDefaultImports": true, "baseUrl": ".", "paths": { diff --git a/developer/src/kmc-model/src/build-trie.ts b/developer/src/kmc-model/src/build-trie.ts index 5f5ae99f85d..7a9b8873f4f 100644 --- a/developer/src/kmc-model/src/build-trie.ts +++ b/developer/src/kmc-model/src/build-trie.ts @@ -112,8 +112,10 @@ function _parseWordList(wordlist: WordList, source: WordListSource): void { wordform = wordform.normalize('NFC'); if (original !== wordform) { - // Mixed normalization forms are yucky! Warn about it. - callbacks.reportMessage(ModelCompilerMessages.Warn_MixedNormalizationForms({wordform: wordform})); + // Mixed normalization forms are yucky! Hint about it, because it may + // result in unexpected counts where multiple normalization forms for one + // word + callbacks.reportMessage(ModelCompilerMessages.Hint_MixedNormalizationForms({wordform: wordform})); } wordform = wordform.trim() @@ -129,9 +131,9 @@ function _parseWordList(wordlist: WordList, source: WordListSource): void { } if (wordsSeenInThisFile.has(wordform)) { - // The same word seen across multiple files is fine, - // but a word seen multiple times in one file is a problem! - callbacks.reportMessage(ModelCompilerMessages.Warn_DuplicateWordInSameFile({wordform: wordform})); + // The same word seen across multiple files is fine, but a word seen + // multiple times in one file may be a problem + callbacks.reportMessage(ModelCompilerMessages.Hint_DuplicateWordInSameFile({wordform: wordform})); } wordsSeenInThisFile.add(wordform); diff --git a/developer/src/kmc-model/src/model-compiler-errors.ts b/developer/src/kmc-model/src/model-compiler-errors.ts index beb3398caac..5d112eb96b6 100644 --- a/developer/src/kmc-model/src/model-compiler-errors.ts +++ b/developer/src/kmc-model/src/model-compiler-errors.ts @@ -2,8 +2,8 @@ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerEvent, CompilerM const Namespace = CompilerErrorNamespace.ModelCompiler; // const SevInfo = CompilerErrorSeverity.Info | Namespace; -// const SevHint = CompilerErrorSeverity.Hint | Namespace; -const SevWarn = CompilerErrorSeverity.Warn | Namespace; +const SevHint = CompilerErrorSeverity.Hint | Namespace; +// const SevWarn = CompilerErrorSeverity.Warn | Namespace; const SevError = CompilerErrorSeverity.Error | Namespace; const SevFatal = CompilerErrorSeverity.Fatal | Namespace; @@ -24,13 +24,13 @@ export class ModelCompilerMessages { static Fatal_UnexpectedException = (o:{e: any}) => m(this.FATAL_UnexpectedException, null, o.e ?? 'unknown error'); static FATAL_UnexpectedException = SevFatal | 0x0001; - static Warn_MixedNormalizationForms = (o:{wordform: string}) => m(this.WARN_MixedNormalizationForms, + static Hint_MixedNormalizationForms = (o:{wordform: string}) => m(this.HINT_MixedNormalizationForms, `“${o.wordform}” is not in Unicode NFC. Automatically converting to NFC.`); - static WARN_MixedNormalizationForms = SevWarn | 0x0002; + static HINT_MixedNormalizationForms = SevHint | 0x0002; - static Warn_DuplicateWordInSameFile = (o:{wordform: string}) => m(this.WARN_DuplicateWordInSameFile, + static Hint_DuplicateWordInSameFile = (o:{wordform: string}) => m(this.HINT_DuplicateWordInSameFile, `duplicate word “${o.wordform}” found in same file; summing counts`); - static WARN_DuplicateWordInSameFile = SevWarn | 0x0003; + static HINT_DuplicateWordInSameFile = SevHint | 0x0003; static Error_UnimplementedModelFormat = (o:{format: string}) => m(this.ERROR_UnimplementedModelFormat, `Unimplemented model format: ${o.format}`); diff --git a/developer/src/kmc-model/test/test-join-word-breaker.ts b/developer/src/kmc-model/test/test-join-word-breaker.ts index d06bc7a6efd..b08411cb561 100644 --- a/developer/src/kmc-model/test/test-join-word-breaker.ts +++ b/developer/src/kmc-model/test/test-join-word-breaker.ts @@ -1,5 +1,5 @@ import { assert } from "chai"; -import defaultWordBreaker from './wordbreakers/default-wordbreaker-esm.js'; +import defaultWordBreaker from '@keymanapp/models-wordbreakers'; import {decorateWithJoin} from '../src/join-word-breaker-decorator.js'; describe('The join word breaker decorator', function () { diff --git a/developer/src/kmc-model/test/test-override-script-defaults.ts b/developer/src/kmc-model/test/test-override-script-defaults.ts index 909f52c2981..a0500320fd9 100644 --- a/developer/src/kmc-model/test/test-override-script-defaults.ts +++ b/developer/src/kmc-model/test/test-override-script-defaults.ts @@ -1,5 +1,5 @@ import { assert } from "chai"; -import defaultWordBreaker from './wordbreakers/default-wordbreaker-esm.js'; +import defaultWordBreaker from '@keymanapp/models-wordbreakers'; import {decorateWithScriptOverrides} from '../src/script-overrides-decorator.js'; const THIN_SPACE = "\u2009"; diff --git a/developer/src/kmc-model/test/test-parse-wordlist.ts b/developer/src/kmc-model/test/test-parse-wordlist.ts index ab610f5e802..93269e243d1 100644 --- a/developer/src/kmc-model/test/test-parse-wordlist.ts +++ b/developer/src/kmc-model/test/test-parse-wordlist.ts @@ -108,9 +108,9 @@ describe('parsing a word list', function () { assert.lengthOf(testCallbacks.messages, 4); // hello has been seen multiple times: - assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.WARN_DuplicateWordInSameFile)); + assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile)); // helló and hello + U+0301 have both been seen: - assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.WARN_MixedNormalizationForms)); + assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms)); // Let's parse another file: @@ -119,9 +119,9 @@ describe('parsing a word list', function () { parseWordListFromContents(repeatedWords, "hello\u0301\t5\n"); assert.lengthOf(testCallbacks.messages, 1); // hello + U+0301 (NFD) has been seen, but... - assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.WARN_MixedNormalizationForms)); + assert.isTrue(testCallbacks.hasMessage(ModelCompilerMessages.HINT_MixedNormalizationForms)); // BUT! We have not seen a duplicate **within the same file** - assert.isFalse(testCallbacks.hasMessage(ModelCompilerMessages.WARN_DuplicateWordInSameFile)); + assert.isFalse(testCallbacks.hasMessage(ModelCompilerMessages.HINT_DuplicateWordInSameFile)); assert.deepEqual(repeatedWords, { hello: expected['hello'], diff --git a/developer/src/kmc-model/test/tsconfig.json b/developer/src/kmc-model/test/tsconfig.json index 3902bed57f0..0917ea186ae 100644 --- a/developer/src/kmc-model/test/tsconfig.json +++ b/developer/src/kmc-model/test/tsconfig.json @@ -6,7 +6,6 @@ "rootDirs": ["./", "../src/"], "outDir": "../build/test", "esModuleInterop": true, - "moduleResolution": "node16", "allowSyntheticDefaultImports": true, "baseUrl": ".", "paths": { diff --git a/developer/src/kmc-model/test/wordbreakers/README.md b/developer/src/kmc-model/test/wordbreakers/README.md deleted file mode 100644 index d204b51c6a3..00000000000 --- a/developer/src/kmc-model/test/wordbreakers/README.md +++ /dev/null @@ -1,3 +0,0 @@ -Wordbreakers ES Module format - -TODO: once we move common/models/wordbreakers to ESM, eliminate this. diff --git a/developer/src/kmc-model/test/wordbreakers/data.ts b/developer/src/kmc-model/test/wordbreakers/data.ts deleted file mode 100644 index 5622bf5c037..00000000000 --- a/developer/src/kmc-model/test/wordbreakers/data.ts +++ /dev/null @@ -1,1776 +0,0 @@ -// TEMP: esm version of /common/models/wordbreakers/default/data.ts -// Hand updated version of automatically generated file. -/** - * Valid values for a word break property. - */ -export enum WordBreakProperty { - Other, - LF, - Newline, - CR, - WSegSpace, - Double_Quote, - Single_Quote, - MidNum, - MidNumLet, - Numeric, - MidLetter, - ALetter, - ExtendNumLet, - Format, - Extend, - Hebrew_Letter, - ZWJ, - Katakana, - Regional_Indicator, - sot, - eot -}; - -/** - * Constants for indexing values in WORD_BREAK_PROPERTY. - */ -export enum I { - Start = 0, - Value = 1 -} - -export const WORD_BREAK_PROPERTY: [number, WordBreakProperty][] = [ - [/*start*/ 0x0, WordBreakProperty.Other], - [/*start*/ 0xA, WordBreakProperty.LF], - [/*start*/ 0xB, WordBreakProperty.Newline], - [/*start*/ 0xD, WordBreakProperty.CR], - [/*start*/ 0xE, WordBreakProperty.Other], - [/*start*/ 0x20, WordBreakProperty.WSegSpace], - [/*start*/ 0x21, WordBreakProperty.Other], - [/*start*/ 0x22, WordBreakProperty.Double_Quote], - [/*start*/ 0x23, WordBreakProperty.Other], - [/*start*/ 0x27, WordBreakProperty.Single_Quote], - [/*start*/ 0x28, WordBreakProperty.Other], - [/*start*/ 0x2C, WordBreakProperty.MidNum], - [/*start*/ 0x2D, WordBreakProperty.Other], - [/*start*/ 0x2E, WordBreakProperty.MidNumLet], - [/*start*/ 0x2F, WordBreakProperty.Other], - [/*start*/ 0x30, WordBreakProperty.Numeric], - [/*start*/ 0x3A, WordBreakProperty.MidLetter], - [/*start*/ 0x3B, WordBreakProperty.MidNum], - [/*start*/ 0x3C, WordBreakProperty.Other], - [/*start*/ 0x41, WordBreakProperty.ALetter], - [/*start*/ 0x5B, WordBreakProperty.Other], - [/*start*/ 0x5F, WordBreakProperty.ExtendNumLet], - [/*start*/ 0x60, WordBreakProperty.Other], - [/*start*/ 0x61, WordBreakProperty.ALetter], - [/*start*/ 0x7B, WordBreakProperty.Other], - [/*start*/ 0x85, WordBreakProperty.Newline], - [/*start*/ 0x86, WordBreakProperty.Other], - [/*start*/ 0xAA, WordBreakProperty.ALetter], - [/*start*/ 0xAB, WordBreakProperty.Other], - [/*start*/ 0xAD, WordBreakProperty.Format], - [/*start*/ 0xAE, WordBreakProperty.Other], - [/*start*/ 0xB5, WordBreakProperty.ALetter], - [/*start*/ 0xB6, WordBreakProperty.Other], - [/*start*/ 0xB7, WordBreakProperty.MidLetter], - [/*start*/ 0xB8, WordBreakProperty.Other], - [/*start*/ 0xBA, WordBreakProperty.ALetter], - [/*start*/ 0xBB, WordBreakProperty.Other], - [/*start*/ 0xC0, WordBreakProperty.ALetter], - [/*start*/ 0xD7, WordBreakProperty.Other], - [/*start*/ 0xD8, WordBreakProperty.ALetter], - [/*start*/ 0xF7, WordBreakProperty.Other], - [/*start*/ 0xF8, WordBreakProperty.ALetter], - [/*start*/ 0x2D8, WordBreakProperty.Other], - [/*start*/ 0x2DE, WordBreakProperty.ALetter], - [/*start*/ 0x300, WordBreakProperty.Extend], - [/*start*/ 0x370, WordBreakProperty.ALetter], - [/*start*/ 0x375, WordBreakProperty.Other], - [/*start*/ 0x376, WordBreakProperty.ALetter], - [/*start*/ 0x378, WordBreakProperty.Other], - [/*start*/ 0x37A, WordBreakProperty.ALetter], - [/*start*/ 0x37E, WordBreakProperty.MidNum], - [/*start*/ 0x37F, WordBreakProperty.ALetter], - [/*start*/ 0x380, WordBreakProperty.Other], - [/*start*/ 0x386, WordBreakProperty.ALetter], - [/*start*/ 0x387, WordBreakProperty.MidLetter], - [/*start*/ 0x388, WordBreakProperty.ALetter], - [/*start*/ 0x38B, WordBreakProperty.Other], - [/*start*/ 0x38C, WordBreakProperty.ALetter], - [/*start*/ 0x38D, WordBreakProperty.Other], - [/*start*/ 0x38E, WordBreakProperty.ALetter], - [/*start*/ 0x3A2, WordBreakProperty.Other], - [/*start*/ 0x3A3, WordBreakProperty.ALetter], - [/*start*/ 0x3F6, WordBreakProperty.Other], - [/*start*/ 0x3F7, WordBreakProperty.ALetter], - [/*start*/ 0x482, WordBreakProperty.Other], - [/*start*/ 0x483, WordBreakProperty.Extend], - [/*start*/ 0x48A, WordBreakProperty.ALetter], - [/*start*/ 0x530, WordBreakProperty.Other], - [/*start*/ 0x531, WordBreakProperty.ALetter], - [/*start*/ 0x557, WordBreakProperty.Other], - [/*start*/ 0x559, WordBreakProperty.ALetter], - [/*start*/ 0x55D, WordBreakProperty.Other], - [/*start*/ 0x55E, WordBreakProperty.ALetter], - [/*start*/ 0x55F, WordBreakProperty.MidLetter], - [/*start*/ 0x560, WordBreakProperty.ALetter], - [/*start*/ 0x589, WordBreakProperty.MidNum], - [/*start*/ 0x58A, WordBreakProperty.ALetter], - [/*start*/ 0x58B, WordBreakProperty.Other], - [/*start*/ 0x591, WordBreakProperty.Extend], - [/*start*/ 0x5BE, WordBreakProperty.Other], - [/*start*/ 0x5BF, WordBreakProperty.Extend], - [/*start*/ 0x5C0, WordBreakProperty.Other], - [/*start*/ 0x5C1, WordBreakProperty.Extend], - [/*start*/ 0x5C3, WordBreakProperty.Other], - [/*start*/ 0x5C4, WordBreakProperty.Extend], - [/*start*/ 0x5C6, WordBreakProperty.Other], - [/*start*/ 0x5C7, WordBreakProperty.Extend], - [/*start*/ 0x5C8, WordBreakProperty.Other], - [/*start*/ 0x5D0, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0x5EB, WordBreakProperty.Other], - [/*start*/ 0x5EF, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0x5F3, WordBreakProperty.ALetter], - [/*start*/ 0x5F4, WordBreakProperty.MidLetter], - [/*start*/ 0x5F5, WordBreakProperty.Other], - [/*start*/ 0x600, WordBreakProperty.Format], - [/*start*/ 0x606, WordBreakProperty.Other], - [/*start*/ 0x60C, WordBreakProperty.MidNum], - [/*start*/ 0x60E, WordBreakProperty.Other], - [/*start*/ 0x610, WordBreakProperty.Extend], - [/*start*/ 0x61B, WordBreakProperty.Other], - [/*start*/ 0x61C, WordBreakProperty.Format], - [/*start*/ 0x61D, WordBreakProperty.Other], - [/*start*/ 0x620, WordBreakProperty.ALetter], - [/*start*/ 0x64B, WordBreakProperty.Extend], - [/*start*/ 0x660, WordBreakProperty.Numeric], - [/*start*/ 0x66A, WordBreakProperty.Other], - [/*start*/ 0x66B, WordBreakProperty.Numeric], - [/*start*/ 0x66C, WordBreakProperty.MidNum], - [/*start*/ 0x66D, WordBreakProperty.Other], - [/*start*/ 0x66E, WordBreakProperty.ALetter], - [/*start*/ 0x670, WordBreakProperty.Extend], - [/*start*/ 0x671, WordBreakProperty.ALetter], - [/*start*/ 0x6D4, WordBreakProperty.Other], - [/*start*/ 0x6D5, WordBreakProperty.ALetter], - [/*start*/ 0x6D6, WordBreakProperty.Extend], - [/*start*/ 0x6DD, WordBreakProperty.Format], - [/*start*/ 0x6DE, WordBreakProperty.Other], - [/*start*/ 0x6DF, WordBreakProperty.Extend], - [/*start*/ 0x6E5, WordBreakProperty.ALetter], - [/*start*/ 0x6E7, WordBreakProperty.Extend], - [/*start*/ 0x6E9, WordBreakProperty.Other], - [/*start*/ 0x6EA, WordBreakProperty.Extend], - [/*start*/ 0x6EE, WordBreakProperty.ALetter], - [/*start*/ 0x6F0, WordBreakProperty.Numeric], - [/*start*/ 0x6FA, WordBreakProperty.ALetter], - [/*start*/ 0x6FD, WordBreakProperty.Other], - [/*start*/ 0x6FF, WordBreakProperty.ALetter], - [/*start*/ 0x700, WordBreakProperty.Other], - [/*start*/ 0x70F, WordBreakProperty.Format], - [/*start*/ 0x710, WordBreakProperty.ALetter], - [/*start*/ 0x711, WordBreakProperty.Extend], - [/*start*/ 0x712, WordBreakProperty.ALetter], - [/*start*/ 0x730, WordBreakProperty.Extend], - [/*start*/ 0x74B, WordBreakProperty.Other], - [/*start*/ 0x74D, WordBreakProperty.ALetter], - [/*start*/ 0x7A6, WordBreakProperty.Extend], - [/*start*/ 0x7B1, WordBreakProperty.ALetter], - [/*start*/ 0x7B2, WordBreakProperty.Other], - [/*start*/ 0x7C0, WordBreakProperty.Numeric], - [/*start*/ 0x7CA, WordBreakProperty.ALetter], - [/*start*/ 0x7EB, WordBreakProperty.Extend], - [/*start*/ 0x7F4, WordBreakProperty.ALetter], - [/*start*/ 0x7F6, WordBreakProperty.Other], - [/*start*/ 0x7F8, WordBreakProperty.MidNum], - [/*start*/ 0x7F9, WordBreakProperty.Other], - [/*start*/ 0x7FA, WordBreakProperty.ALetter], - [/*start*/ 0x7FB, WordBreakProperty.Other], - [/*start*/ 0x7FD, WordBreakProperty.Extend], - [/*start*/ 0x7FE, WordBreakProperty.Other], - [/*start*/ 0x800, WordBreakProperty.ALetter], - [/*start*/ 0x816, WordBreakProperty.Extend], - [/*start*/ 0x81A, WordBreakProperty.ALetter], - [/*start*/ 0x81B, WordBreakProperty.Extend], - [/*start*/ 0x824, WordBreakProperty.ALetter], - [/*start*/ 0x825, WordBreakProperty.Extend], - [/*start*/ 0x828, WordBreakProperty.ALetter], - [/*start*/ 0x829, WordBreakProperty.Extend], - [/*start*/ 0x82E, WordBreakProperty.Other], - [/*start*/ 0x840, WordBreakProperty.ALetter], - [/*start*/ 0x859, WordBreakProperty.Extend], - [/*start*/ 0x85C, WordBreakProperty.Other], - [/*start*/ 0x860, WordBreakProperty.ALetter], - [/*start*/ 0x86B, WordBreakProperty.Other], - [/*start*/ 0x8A0, WordBreakProperty.ALetter], - [/*start*/ 0x8B5, WordBreakProperty.Other], - [/*start*/ 0x8B6, WordBreakProperty.ALetter], - [/*start*/ 0x8C8, WordBreakProperty.Other], - [/*start*/ 0x8D3, WordBreakProperty.Extend], - [/*start*/ 0x8E2, WordBreakProperty.Format], - [/*start*/ 0x8E3, WordBreakProperty.Extend], - [/*start*/ 0x904, WordBreakProperty.ALetter], - [/*start*/ 0x93A, WordBreakProperty.Extend], - [/*start*/ 0x93D, WordBreakProperty.ALetter], - [/*start*/ 0x93E, WordBreakProperty.Extend], - [/*start*/ 0x950, WordBreakProperty.ALetter], - [/*start*/ 0x951, WordBreakProperty.Extend], - [/*start*/ 0x958, WordBreakProperty.ALetter], - [/*start*/ 0x962, WordBreakProperty.Extend], - [/*start*/ 0x964, WordBreakProperty.Other], - [/*start*/ 0x966, WordBreakProperty.Numeric], - [/*start*/ 0x970, WordBreakProperty.Other], - [/*start*/ 0x971, WordBreakProperty.ALetter], - [/*start*/ 0x981, WordBreakProperty.Extend], - [/*start*/ 0x984, WordBreakProperty.Other], - [/*start*/ 0x985, WordBreakProperty.ALetter], - [/*start*/ 0x98D, WordBreakProperty.Other], - [/*start*/ 0x98F, WordBreakProperty.ALetter], - [/*start*/ 0x991, WordBreakProperty.Other], - [/*start*/ 0x993, WordBreakProperty.ALetter], - [/*start*/ 0x9A9, WordBreakProperty.Other], - [/*start*/ 0x9AA, WordBreakProperty.ALetter], - [/*start*/ 0x9B1, WordBreakProperty.Other], - [/*start*/ 0x9B2, WordBreakProperty.ALetter], - [/*start*/ 0x9B3, WordBreakProperty.Other], - [/*start*/ 0x9B6, WordBreakProperty.ALetter], - [/*start*/ 0x9BA, WordBreakProperty.Other], - [/*start*/ 0x9BC, WordBreakProperty.Extend], - [/*start*/ 0x9BD, WordBreakProperty.ALetter], - [/*start*/ 0x9BE, WordBreakProperty.Extend], - [/*start*/ 0x9C5, WordBreakProperty.Other], - [/*start*/ 0x9C7, WordBreakProperty.Extend], - [/*start*/ 0x9C9, WordBreakProperty.Other], - [/*start*/ 0x9CB, WordBreakProperty.Extend], - [/*start*/ 0x9CE, WordBreakProperty.ALetter], - [/*start*/ 0x9CF, WordBreakProperty.Other], - [/*start*/ 0x9D7, WordBreakProperty.Extend], - [/*start*/ 0x9D8, WordBreakProperty.Other], - [/*start*/ 0x9DC, WordBreakProperty.ALetter], - [/*start*/ 0x9DE, WordBreakProperty.Other], - [/*start*/ 0x9DF, WordBreakProperty.ALetter], - [/*start*/ 0x9E2, WordBreakProperty.Extend], - [/*start*/ 0x9E4, WordBreakProperty.Other], - [/*start*/ 0x9E6, WordBreakProperty.Numeric], - [/*start*/ 0x9F0, WordBreakProperty.ALetter], - [/*start*/ 0x9F2, WordBreakProperty.Other], - [/*start*/ 0x9FC, WordBreakProperty.ALetter], - [/*start*/ 0x9FD, WordBreakProperty.Other], - [/*start*/ 0x9FE, WordBreakProperty.Extend], - [/*start*/ 0x9FF, WordBreakProperty.Other], - [/*start*/ 0xA01, WordBreakProperty.Extend], - [/*start*/ 0xA04, WordBreakProperty.Other], - [/*start*/ 0xA05, WordBreakProperty.ALetter], - [/*start*/ 0xA0B, WordBreakProperty.Other], - [/*start*/ 0xA0F, WordBreakProperty.ALetter], - [/*start*/ 0xA11, WordBreakProperty.Other], - [/*start*/ 0xA13, WordBreakProperty.ALetter], - [/*start*/ 0xA29, WordBreakProperty.Other], - [/*start*/ 0xA2A, WordBreakProperty.ALetter], - [/*start*/ 0xA31, WordBreakProperty.Other], - [/*start*/ 0xA32, WordBreakProperty.ALetter], - [/*start*/ 0xA34, WordBreakProperty.Other], - [/*start*/ 0xA35, WordBreakProperty.ALetter], - [/*start*/ 0xA37, WordBreakProperty.Other], - [/*start*/ 0xA38, WordBreakProperty.ALetter], - [/*start*/ 0xA3A, WordBreakProperty.Other], - [/*start*/ 0xA3C, WordBreakProperty.Extend], - [/*start*/ 0xA3D, WordBreakProperty.Other], - [/*start*/ 0xA3E, WordBreakProperty.Extend], - [/*start*/ 0xA43, WordBreakProperty.Other], - [/*start*/ 0xA47, WordBreakProperty.Extend], - [/*start*/ 0xA49, WordBreakProperty.Other], - [/*start*/ 0xA4B, WordBreakProperty.Extend], - [/*start*/ 0xA4E, WordBreakProperty.Other], - [/*start*/ 0xA51, WordBreakProperty.Extend], - [/*start*/ 0xA52, WordBreakProperty.Other], - [/*start*/ 0xA59, WordBreakProperty.ALetter], - [/*start*/ 0xA5D, WordBreakProperty.Other], - [/*start*/ 0xA5E, WordBreakProperty.ALetter], - [/*start*/ 0xA5F, WordBreakProperty.Other], - [/*start*/ 0xA66, WordBreakProperty.Numeric], - [/*start*/ 0xA70, WordBreakProperty.Extend], - [/*start*/ 0xA72, WordBreakProperty.ALetter], - [/*start*/ 0xA75, WordBreakProperty.Extend], - [/*start*/ 0xA76, WordBreakProperty.Other], - [/*start*/ 0xA81, WordBreakProperty.Extend], - [/*start*/ 0xA84, WordBreakProperty.Other], - [/*start*/ 0xA85, WordBreakProperty.ALetter], - [/*start*/ 0xA8E, WordBreakProperty.Other], - [/*start*/ 0xA8F, WordBreakProperty.ALetter], - [/*start*/ 0xA92, WordBreakProperty.Other], - [/*start*/ 0xA93, WordBreakProperty.ALetter], - [/*start*/ 0xAA9, WordBreakProperty.Other], - [/*start*/ 0xAAA, WordBreakProperty.ALetter], - [/*start*/ 0xAB1, WordBreakProperty.Other], - [/*start*/ 0xAB2, WordBreakProperty.ALetter], - [/*start*/ 0xAB4, WordBreakProperty.Other], - [/*start*/ 0xAB5, WordBreakProperty.ALetter], - [/*start*/ 0xABA, WordBreakProperty.Other], - [/*start*/ 0xABC, WordBreakProperty.Extend], - [/*start*/ 0xABD, WordBreakProperty.ALetter], - [/*start*/ 0xABE, WordBreakProperty.Extend], - [/*start*/ 0xAC6, WordBreakProperty.Other], - [/*start*/ 0xAC7, WordBreakProperty.Extend], - [/*start*/ 0xACA, WordBreakProperty.Other], - [/*start*/ 0xACB, WordBreakProperty.Extend], - [/*start*/ 0xACE, WordBreakProperty.Other], - [/*start*/ 0xAD0, WordBreakProperty.ALetter], - [/*start*/ 0xAD1, WordBreakProperty.Other], - [/*start*/ 0xAE0, WordBreakProperty.ALetter], - [/*start*/ 0xAE2, WordBreakProperty.Extend], - [/*start*/ 0xAE4, WordBreakProperty.Other], - [/*start*/ 0xAE6, WordBreakProperty.Numeric], - [/*start*/ 0xAF0, WordBreakProperty.Other], - [/*start*/ 0xAF9, WordBreakProperty.ALetter], - [/*start*/ 0xAFA, WordBreakProperty.Extend], - [/*start*/ 0xB00, WordBreakProperty.Other], - [/*start*/ 0xB01, WordBreakProperty.Extend], - [/*start*/ 0xB04, WordBreakProperty.Other], - [/*start*/ 0xB05, WordBreakProperty.ALetter], - [/*start*/ 0xB0D, WordBreakProperty.Other], - [/*start*/ 0xB0F, WordBreakProperty.ALetter], - [/*start*/ 0xB11, WordBreakProperty.Other], - [/*start*/ 0xB13, WordBreakProperty.ALetter], - [/*start*/ 0xB29, WordBreakProperty.Other], - [/*start*/ 0xB2A, WordBreakProperty.ALetter], - [/*start*/ 0xB31, WordBreakProperty.Other], - [/*start*/ 0xB32, WordBreakProperty.ALetter], - [/*start*/ 0xB34, WordBreakProperty.Other], - [/*start*/ 0xB35, WordBreakProperty.ALetter], - [/*start*/ 0xB3A, WordBreakProperty.Other], - [/*start*/ 0xB3C, WordBreakProperty.Extend], - [/*start*/ 0xB3D, WordBreakProperty.ALetter], - [/*start*/ 0xB3E, WordBreakProperty.Extend], - [/*start*/ 0xB45, WordBreakProperty.Other], - [/*start*/ 0xB47, WordBreakProperty.Extend], - [/*start*/ 0xB49, WordBreakProperty.Other], - [/*start*/ 0xB4B, WordBreakProperty.Extend], - [/*start*/ 0xB4E, WordBreakProperty.Other], - [/*start*/ 0xB55, WordBreakProperty.Extend], - [/*start*/ 0xB58, WordBreakProperty.Other], - [/*start*/ 0xB5C, WordBreakProperty.ALetter], - [/*start*/ 0xB5E, WordBreakProperty.Other], - [/*start*/ 0xB5F, WordBreakProperty.ALetter], - [/*start*/ 0xB62, WordBreakProperty.Extend], - [/*start*/ 0xB64, WordBreakProperty.Other], - [/*start*/ 0xB66, WordBreakProperty.Numeric], - [/*start*/ 0xB70, WordBreakProperty.Other], - [/*start*/ 0xB71, WordBreakProperty.ALetter], - [/*start*/ 0xB72, WordBreakProperty.Other], - [/*start*/ 0xB82, WordBreakProperty.Extend], - [/*start*/ 0xB83, WordBreakProperty.ALetter], - [/*start*/ 0xB84, WordBreakProperty.Other], - [/*start*/ 0xB85, WordBreakProperty.ALetter], - [/*start*/ 0xB8B, WordBreakProperty.Other], - [/*start*/ 0xB8E, WordBreakProperty.ALetter], - [/*start*/ 0xB91, WordBreakProperty.Other], - [/*start*/ 0xB92, WordBreakProperty.ALetter], - [/*start*/ 0xB96, WordBreakProperty.Other], - [/*start*/ 0xB99, WordBreakProperty.ALetter], - [/*start*/ 0xB9B, WordBreakProperty.Other], - [/*start*/ 0xB9C, WordBreakProperty.ALetter], - [/*start*/ 0xB9D, WordBreakProperty.Other], - [/*start*/ 0xB9E, WordBreakProperty.ALetter], - [/*start*/ 0xBA0, WordBreakProperty.Other], - [/*start*/ 0xBA3, WordBreakProperty.ALetter], - [/*start*/ 0xBA5, WordBreakProperty.Other], - [/*start*/ 0xBA8, WordBreakProperty.ALetter], - [/*start*/ 0xBAB, WordBreakProperty.Other], - [/*start*/ 0xBAE, WordBreakProperty.ALetter], - [/*start*/ 0xBBA, WordBreakProperty.Other], - [/*start*/ 0xBBE, WordBreakProperty.Extend], - [/*start*/ 0xBC3, WordBreakProperty.Other], - [/*start*/ 0xBC6, WordBreakProperty.Extend], - [/*start*/ 0xBC9, WordBreakProperty.Other], - [/*start*/ 0xBCA, WordBreakProperty.Extend], - [/*start*/ 0xBCE, WordBreakProperty.Other], - [/*start*/ 0xBD0, WordBreakProperty.ALetter], - [/*start*/ 0xBD1, WordBreakProperty.Other], - [/*start*/ 0xBD7, WordBreakProperty.Extend], - [/*start*/ 0xBD8, WordBreakProperty.Other], - [/*start*/ 0xBE6, WordBreakProperty.Numeric], - [/*start*/ 0xBF0, WordBreakProperty.Other], - [/*start*/ 0xC00, WordBreakProperty.Extend], - [/*start*/ 0xC05, WordBreakProperty.ALetter], - [/*start*/ 0xC0D, WordBreakProperty.Other], - [/*start*/ 0xC0E, WordBreakProperty.ALetter], - [/*start*/ 0xC11, WordBreakProperty.Other], - [/*start*/ 0xC12, WordBreakProperty.ALetter], - [/*start*/ 0xC29, WordBreakProperty.Other], - [/*start*/ 0xC2A, WordBreakProperty.ALetter], - [/*start*/ 0xC3A, WordBreakProperty.Other], - [/*start*/ 0xC3D, WordBreakProperty.ALetter], - [/*start*/ 0xC3E, WordBreakProperty.Extend], - [/*start*/ 0xC45, WordBreakProperty.Other], - [/*start*/ 0xC46, WordBreakProperty.Extend], - [/*start*/ 0xC49, WordBreakProperty.Other], - [/*start*/ 0xC4A, WordBreakProperty.Extend], - [/*start*/ 0xC4E, WordBreakProperty.Other], - [/*start*/ 0xC55, WordBreakProperty.Extend], - [/*start*/ 0xC57, WordBreakProperty.Other], - [/*start*/ 0xC58, WordBreakProperty.ALetter], - [/*start*/ 0xC5B, WordBreakProperty.Other], - [/*start*/ 0xC60, WordBreakProperty.ALetter], - [/*start*/ 0xC62, WordBreakProperty.Extend], - [/*start*/ 0xC64, WordBreakProperty.Other], - [/*start*/ 0xC66, WordBreakProperty.Numeric], - [/*start*/ 0xC70, WordBreakProperty.Other], - [/*start*/ 0xC80, WordBreakProperty.ALetter], - [/*start*/ 0xC81, WordBreakProperty.Extend], - [/*start*/ 0xC84, WordBreakProperty.Other], - [/*start*/ 0xC85, WordBreakProperty.ALetter], - [/*start*/ 0xC8D, WordBreakProperty.Other], - [/*start*/ 0xC8E, WordBreakProperty.ALetter], - [/*start*/ 0xC91, WordBreakProperty.Other], - [/*start*/ 0xC92, WordBreakProperty.ALetter], - [/*start*/ 0xCA9, WordBreakProperty.Other], - [/*start*/ 0xCAA, WordBreakProperty.ALetter], - [/*start*/ 0xCB4, WordBreakProperty.Other], - [/*start*/ 0xCB5, WordBreakProperty.ALetter], - [/*start*/ 0xCBA, WordBreakProperty.Other], - [/*start*/ 0xCBC, WordBreakProperty.Extend], - [/*start*/ 0xCBD, WordBreakProperty.ALetter], - [/*start*/ 0xCBE, WordBreakProperty.Extend], - [/*start*/ 0xCC5, WordBreakProperty.Other], - [/*start*/ 0xCC6, WordBreakProperty.Extend], - [/*start*/ 0xCC9, WordBreakProperty.Other], - [/*start*/ 0xCCA, WordBreakProperty.Extend], - [/*start*/ 0xCCE, WordBreakProperty.Other], - [/*start*/ 0xCD5, WordBreakProperty.Extend], - [/*start*/ 0xCD7, WordBreakProperty.Other], - [/*start*/ 0xCDE, WordBreakProperty.ALetter], - [/*start*/ 0xCDF, WordBreakProperty.Other], - [/*start*/ 0xCE0, WordBreakProperty.ALetter], - [/*start*/ 0xCE2, WordBreakProperty.Extend], - [/*start*/ 0xCE4, WordBreakProperty.Other], - [/*start*/ 0xCE6, WordBreakProperty.Numeric], - [/*start*/ 0xCF0, WordBreakProperty.Other], - [/*start*/ 0xCF1, WordBreakProperty.ALetter], - [/*start*/ 0xCF3, WordBreakProperty.Other], - [/*start*/ 0xD00, WordBreakProperty.Extend], - [/*start*/ 0xD04, WordBreakProperty.ALetter], - [/*start*/ 0xD0D, WordBreakProperty.Other], - [/*start*/ 0xD0E, WordBreakProperty.ALetter], - [/*start*/ 0xD11, WordBreakProperty.Other], - [/*start*/ 0xD12, WordBreakProperty.ALetter], - [/*start*/ 0xD3B, WordBreakProperty.Extend], - [/*start*/ 0xD3D, WordBreakProperty.ALetter], - [/*start*/ 0xD3E, WordBreakProperty.Extend], - [/*start*/ 0xD45, WordBreakProperty.Other], - [/*start*/ 0xD46, WordBreakProperty.Extend], - [/*start*/ 0xD49, WordBreakProperty.Other], - [/*start*/ 0xD4A, WordBreakProperty.Extend], - [/*start*/ 0xD4E, WordBreakProperty.ALetter], - [/*start*/ 0xD4F, WordBreakProperty.Other], - [/*start*/ 0xD54, WordBreakProperty.ALetter], - [/*start*/ 0xD57, WordBreakProperty.Extend], - [/*start*/ 0xD58, WordBreakProperty.Other], - [/*start*/ 0xD5F, WordBreakProperty.ALetter], - [/*start*/ 0xD62, WordBreakProperty.Extend], - [/*start*/ 0xD64, WordBreakProperty.Other], - [/*start*/ 0xD66, WordBreakProperty.Numeric], - [/*start*/ 0xD70, WordBreakProperty.Other], - [/*start*/ 0xD7A, WordBreakProperty.ALetter], - [/*start*/ 0xD80, WordBreakProperty.Other], - [/*start*/ 0xD81, WordBreakProperty.Extend], - [/*start*/ 0xD84, WordBreakProperty.Other], - [/*start*/ 0xD85, WordBreakProperty.ALetter], - [/*start*/ 0xD97, WordBreakProperty.Other], - [/*start*/ 0xD9A, WordBreakProperty.ALetter], - [/*start*/ 0xDB2, WordBreakProperty.Other], - [/*start*/ 0xDB3, WordBreakProperty.ALetter], - [/*start*/ 0xDBC, WordBreakProperty.Other], - [/*start*/ 0xDBD, WordBreakProperty.ALetter], - [/*start*/ 0xDBE, WordBreakProperty.Other], - [/*start*/ 0xDC0, WordBreakProperty.ALetter], - [/*start*/ 0xDC7, WordBreakProperty.Other], - [/*start*/ 0xDCA, WordBreakProperty.Extend], - [/*start*/ 0xDCB, WordBreakProperty.Other], - [/*start*/ 0xDCF, WordBreakProperty.Extend], - [/*start*/ 0xDD5, WordBreakProperty.Other], - [/*start*/ 0xDD6, WordBreakProperty.Extend], - [/*start*/ 0xDD7, WordBreakProperty.Other], - [/*start*/ 0xDD8, WordBreakProperty.Extend], - [/*start*/ 0xDE0, WordBreakProperty.Other], - [/*start*/ 0xDE6, WordBreakProperty.Numeric], - [/*start*/ 0xDF0, WordBreakProperty.Other], - [/*start*/ 0xDF2, WordBreakProperty.Extend], - [/*start*/ 0xDF4, WordBreakProperty.Other], - [/*start*/ 0xE31, WordBreakProperty.Extend], - [/*start*/ 0xE32, WordBreakProperty.Other], - [/*start*/ 0xE34, WordBreakProperty.Extend], - [/*start*/ 0xE3B, WordBreakProperty.Other], - [/*start*/ 0xE47, WordBreakProperty.Extend], - [/*start*/ 0xE4F, WordBreakProperty.Other], - [/*start*/ 0xE50, WordBreakProperty.Numeric], - [/*start*/ 0xE5A, WordBreakProperty.Other], - [/*start*/ 0xEB1, WordBreakProperty.Extend], - [/*start*/ 0xEB2, WordBreakProperty.Other], - [/*start*/ 0xEB4, WordBreakProperty.Extend], - [/*start*/ 0xEBD, WordBreakProperty.Other], - [/*start*/ 0xEC8, WordBreakProperty.Extend], - [/*start*/ 0xECE, WordBreakProperty.Other], - [/*start*/ 0xED0, WordBreakProperty.Numeric], - [/*start*/ 0xEDA, WordBreakProperty.Other], - [/*start*/ 0xF00, WordBreakProperty.ALetter], - [/*start*/ 0xF01, WordBreakProperty.Other], - [/*start*/ 0xF18, WordBreakProperty.Extend], - [/*start*/ 0xF1A, WordBreakProperty.Other], - [/*start*/ 0xF20, WordBreakProperty.Numeric], - [/*start*/ 0xF2A, WordBreakProperty.Other], - [/*start*/ 0xF35, WordBreakProperty.Extend], - [/*start*/ 0xF36, WordBreakProperty.Other], - [/*start*/ 0xF37, WordBreakProperty.Extend], - [/*start*/ 0xF38, WordBreakProperty.Other], - [/*start*/ 0xF39, WordBreakProperty.Extend], - [/*start*/ 0xF3A, WordBreakProperty.Other], - [/*start*/ 0xF3E, WordBreakProperty.Extend], - [/*start*/ 0xF40, WordBreakProperty.ALetter], - [/*start*/ 0xF48, WordBreakProperty.Other], - [/*start*/ 0xF49, WordBreakProperty.ALetter], - [/*start*/ 0xF6D, WordBreakProperty.Other], - [/*start*/ 0xF71, WordBreakProperty.Extend], - [/*start*/ 0xF85, WordBreakProperty.Other], - [/*start*/ 0xF86, WordBreakProperty.Extend], - [/*start*/ 0xF88, WordBreakProperty.ALetter], - [/*start*/ 0xF8D, WordBreakProperty.Extend], - [/*start*/ 0xF98, WordBreakProperty.Other], - [/*start*/ 0xF99, WordBreakProperty.Extend], - [/*start*/ 0xFBD, WordBreakProperty.Other], - [/*start*/ 0xFC6, WordBreakProperty.Extend], - [/*start*/ 0xFC7, WordBreakProperty.Other], - [/*start*/ 0x102B, WordBreakProperty.Extend], - [/*start*/ 0x103F, WordBreakProperty.Other], - [/*start*/ 0x1040, WordBreakProperty.Numeric], - [/*start*/ 0x104A, WordBreakProperty.Other], - [/*start*/ 0x1056, WordBreakProperty.Extend], - [/*start*/ 0x105A, WordBreakProperty.Other], - [/*start*/ 0x105E, WordBreakProperty.Extend], - [/*start*/ 0x1061, WordBreakProperty.Other], - [/*start*/ 0x1062, WordBreakProperty.Extend], - [/*start*/ 0x1065, WordBreakProperty.Other], - [/*start*/ 0x1067, WordBreakProperty.Extend], - [/*start*/ 0x106E, WordBreakProperty.Other], - [/*start*/ 0x1071, WordBreakProperty.Extend], - [/*start*/ 0x1075, WordBreakProperty.Other], - [/*start*/ 0x1082, WordBreakProperty.Extend], - [/*start*/ 0x108E, WordBreakProperty.Other], - [/*start*/ 0x108F, WordBreakProperty.Extend], - [/*start*/ 0x1090, WordBreakProperty.Numeric], - [/*start*/ 0x109A, WordBreakProperty.Extend], - [/*start*/ 0x109E, WordBreakProperty.Other], - [/*start*/ 0x10A0, WordBreakProperty.ALetter], - [/*start*/ 0x10C6, WordBreakProperty.Other], - [/*start*/ 0x10C7, WordBreakProperty.ALetter], - [/*start*/ 0x10C8, WordBreakProperty.Other], - [/*start*/ 0x10CD, WordBreakProperty.ALetter], - [/*start*/ 0x10CE, WordBreakProperty.Other], - [/*start*/ 0x10D0, WordBreakProperty.ALetter], - [/*start*/ 0x10FB, WordBreakProperty.Other], - [/*start*/ 0x10FC, WordBreakProperty.ALetter], - [/*start*/ 0x1249, WordBreakProperty.Other], - [/*start*/ 0x124A, WordBreakProperty.ALetter], - [/*start*/ 0x124E, WordBreakProperty.Other], - [/*start*/ 0x1250, WordBreakProperty.ALetter], - [/*start*/ 0x1257, WordBreakProperty.Other], - [/*start*/ 0x1258, WordBreakProperty.ALetter], - [/*start*/ 0x1259, WordBreakProperty.Other], - [/*start*/ 0x125A, WordBreakProperty.ALetter], - [/*start*/ 0x125E, WordBreakProperty.Other], - [/*start*/ 0x1260, WordBreakProperty.ALetter], - [/*start*/ 0x1289, WordBreakProperty.Other], - [/*start*/ 0x128A, WordBreakProperty.ALetter], - [/*start*/ 0x128E, WordBreakProperty.Other], - [/*start*/ 0x1290, WordBreakProperty.ALetter], - [/*start*/ 0x12B1, WordBreakProperty.Other], - [/*start*/ 0x12B2, WordBreakProperty.ALetter], - [/*start*/ 0x12B6, WordBreakProperty.Other], - [/*start*/ 0x12B8, WordBreakProperty.ALetter], - [/*start*/ 0x12BF, WordBreakProperty.Other], - [/*start*/ 0x12C0, WordBreakProperty.ALetter], - [/*start*/ 0x12C1, WordBreakProperty.Other], - [/*start*/ 0x12C2, WordBreakProperty.ALetter], - [/*start*/ 0x12C6, WordBreakProperty.Other], - [/*start*/ 0x12C8, WordBreakProperty.ALetter], - [/*start*/ 0x12D7, WordBreakProperty.Other], - [/*start*/ 0x12D8, WordBreakProperty.ALetter], - [/*start*/ 0x1311, WordBreakProperty.Other], - [/*start*/ 0x1312, WordBreakProperty.ALetter], - [/*start*/ 0x1316, WordBreakProperty.Other], - [/*start*/ 0x1318, WordBreakProperty.ALetter], - [/*start*/ 0x135B, WordBreakProperty.Other], - [/*start*/ 0x135D, WordBreakProperty.Extend], - [/*start*/ 0x1360, WordBreakProperty.Other], - [/*start*/ 0x1380, WordBreakProperty.ALetter], - [/*start*/ 0x1390, WordBreakProperty.Other], - [/*start*/ 0x13A0, WordBreakProperty.ALetter], - [/*start*/ 0x13F6, WordBreakProperty.Other], - [/*start*/ 0x13F8, WordBreakProperty.ALetter], - [/*start*/ 0x13FE, WordBreakProperty.Other], - [/*start*/ 0x1401, WordBreakProperty.ALetter], - [/*start*/ 0x166D, WordBreakProperty.Other], - [/*start*/ 0x166F, WordBreakProperty.ALetter], - [/*start*/ 0x1680, WordBreakProperty.WSegSpace], - [/*start*/ 0x1681, WordBreakProperty.ALetter], - [/*start*/ 0x169B, WordBreakProperty.Other], - [/*start*/ 0x16A0, WordBreakProperty.ALetter], - [/*start*/ 0x16EB, WordBreakProperty.Other], - [/*start*/ 0x16EE, WordBreakProperty.ALetter], - [/*start*/ 0x16F9, WordBreakProperty.Other], - [/*start*/ 0x1700, WordBreakProperty.ALetter], - [/*start*/ 0x170D, WordBreakProperty.Other], - [/*start*/ 0x170E, WordBreakProperty.ALetter], - [/*start*/ 0x1712, WordBreakProperty.Extend], - [/*start*/ 0x1715, WordBreakProperty.Other], - [/*start*/ 0x1720, WordBreakProperty.ALetter], - [/*start*/ 0x1732, WordBreakProperty.Extend], - [/*start*/ 0x1735, WordBreakProperty.Other], - [/*start*/ 0x1740, WordBreakProperty.ALetter], - [/*start*/ 0x1752, WordBreakProperty.Extend], - [/*start*/ 0x1754, WordBreakProperty.Other], - [/*start*/ 0x1760, WordBreakProperty.ALetter], - [/*start*/ 0x176D, WordBreakProperty.Other], - [/*start*/ 0x176E, WordBreakProperty.ALetter], - [/*start*/ 0x1771, WordBreakProperty.Other], - [/*start*/ 0x1772, WordBreakProperty.Extend], - [/*start*/ 0x1774, WordBreakProperty.Other], - [/*start*/ 0x17B4, WordBreakProperty.Extend], - [/*start*/ 0x17D4, WordBreakProperty.Other], - [/*start*/ 0x17DD, WordBreakProperty.Extend], - [/*start*/ 0x17DE, WordBreakProperty.Other], - [/*start*/ 0x17E0, WordBreakProperty.Numeric], - [/*start*/ 0x17EA, WordBreakProperty.Other], - [/*start*/ 0x180B, WordBreakProperty.Extend], - [/*start*/ 0x180E, WordBreakProperty.Format], - [/*start*/ 0x180F, WordBreakProperty.Other], - [/*start*/ 0x1810, WordBreakProperty.Numeric], - [/*start*/ 0x181A, WordBreakProperty.Other], - [/*start*/ 0x1820, WordBreakProperty.ALetter], - [/*start*/ 0x1879, WordBreakProperty.Other], - [/*start*/ 0x1880, WordBreakProperty.ALetter], - [/*start*/ 0x1885, WordBreakProperty.Extend], - [/*start*/ 0x1887, WordBreakProperty.ALetter], - [/*start*/ 0x18A9, WordBreakProperty.Extend], - [/*start*/ 0x18AA, WordBreakProperty.ALetter], - [/*start*/ 0x18AB, WordBreakProperty.Other], - [/*start*/ 0x18B0, WordBreakProperty.ALetter], - [/*start*/ 0x18F6, WordBreakProperty.Other], - [/*start*/ 0x1900, WordBreakProperty.ALetter], - [/*start*/ 0x191F, WordBreakProperty.Other], - [/*start*/ 0x1920, WordBreakProperty.Extend], - [/*start*/ 0x192C, WordBreakProperty.Other], - [/*start*/ 0x1930, WordBreakProperty.Extend], - [/*start*/ 0x193C, WordBreakProperty.Other], - [/*start*/ 0x1946, WordBreakProperty.Numeric], - [/*start*/ 0x1950, WordBreakProperty.Other], - [/*start*/ 0x19D0, WordBreakProperty.Numeric], - [/*start*/ 0x19DA, WordBreakProperty.Other], - [/*start*/ 0x1A00, WordBreakProperty.ALetter], - [/*start*/ 0x1A17, WordBreakProperty.Extend], - [/*start*/ 0x1A1C, WordBreakProperty.Other], - [/*start*/ 0x1A55, WordBreakProperty.Extend], - [/*start*/ 0x1A5F, WordBreakProperty.Other], - [/*start*/ 0x1A60, WordBreakProperty.Extend], - [/*start*/ 0x1A7D, WordBreakProperty.Other], - [/*start*/ 0x1A7F, WordBreakProperty.Extend], - [/*start*/ 0x1A80, WordBreakProperty.Numeric], - [/*start*/ 0x1A8A, WordBreakProperty.Other], - [/*start*/ 0x1A90, WordBreakProperty.Numeric], - [/*start*/ 0x1A9A, WordBreakProperty.Other], - [/*start*/ 0x1AB0, WordBreakProperty.Extend], - [/*start*/ 0x1AC1, WordBreakProperty.Other], - [/*start*/ 0x1B00, WordBreakProperty.Extend], - [/*start*/ 0x1B05, WordBreakProperty.ALetter], - [/*start*/ 0x1B34, WordBreakProperty.Extend], - [/*start*/ 0x1B45, WordBreakProperty.ALetter], - [/*start*/ 0x1B4C, WordBreakProperty.Other], - [/*start*/ 0x1B50, WordBreakProperty.Numeric], - [/*start*/ 0x1B5A, WordBreakProperty.Other], - [/*start*/ 0x1B6B, WordBreakProperty.Extend], - [/*start*/ 0x1B74, WordBreakProperty.Other], - [/*start*/ 0x1B80, WordBreakProperty.Extend], - [/*start*/ 0x1B83, WordBreakProperty.ALetter], - [/*start*/ 0x1BA1, WordBreakProperty.Extend], - [/*start*/ 0x1BAE, WordBreakProperty.ALetter], - [/*start*/ 0x1BB0, WordBreakProperty.Numeric], - [/*start*/ 0x1BBA, WordBreakProperty.ALetter], - [/*start*/ 0x1BE6, WordBreakProperty.Extend], - [/*start*/ 0x1BF4, WordBreakProperty.Other], - [/*start*/ 0x1C00, WordBreakProperty.ALetter], - [/*start*/ 0x1C24, WordBreakProperty.Extend], - [/*start*/ 0x1C38, WordBreakProperty.Other], - [/*start*/ 0x1C40, WordBreakProperty.Numeric], - [/*start*/ 0x1C4A, WordBreakProperty.Other], - [/*start*/ 0x1C4D, WordBreakProperty.ALetter], - [/*start*/ 0x1C50, WordBreakProperty.Numeric], - [/*start*/ 0x1C5A, WordBreakProperty.ALetter], - [/*start*/ 0x1C7E, WordBreakProperty.Other], - [/*start*/ 0x1C80, WordBreakProperty.ALetter], - [/*start*/ 0x1C89, WordBreakProperty.Other], - [/*start*/ 0x1C90, WordBreakProperty.ALetter], - [/*start*/ 0x1CBB, WordBreakProperty.Other], - [/*start*/ 0x1CBD, WordBreakProperty.ALetter], - [/*start*/ 0x1CC0, WordBreakProperty.Other], - [/*start*/ 0x1CD0, WordBreakProperty.Extend], - [/*start*/ 0x1CD3, WordBreakProperty.Other], - [/*start*/ 0x1CD4, WordBreakProperty.Extend], - [/*start*/ 0x1CE9, WordBreakProperty.ALetter], - [/*start*/ 0x1CED, WordBreakProperty.Extend], - [/*start*/ 0x1CEE, WordBreakProperty.ALetter], - [/*start*/ 0x1CF4, WordBreakProperty.Extend], - [/*start*/ 0x1CF5, WordBreakProperty.ALetter], - [/*start*/ 0x1CF7, WordBreakProperty.Extend], - [/*start*/ 0x1CFA, WordBreakProperty.ALetter], - [/*start*/ 0x1CFB, WordBreakProperty.Other], - [/*start*/ 0x1D00, WordBreakProperty.ALetter], - [/*start*/ 0x1DC0, WordBreakProperty.Extend], - [/*start*/ 0x1DFA, WordBreakProperty.Other], - [/*start*/ 0x1DFB, WordBreakProperty.Extend], - [/*start*/ 0x1E00, WordBreakProperty.ALetter], - [/*start*/ 0x1F16, WordBreakProperty.Other], - [/*start*/ 0x1F18, WordBreakProperty.ALetter], - [/*start*/ 0x1F1E, WordBreakProperty.Other], - [/*start*/ 0x1F20, WordBreakProperty.ALetter], - [/*start*/ 0x1F46, WordBreakProperty.Other], - [/*start*/ 0x1F48, WordBreakProperty.ALetter], - [/*start*/ 0x1F4E, WordBreakProperty.Other], - [/*start*/ 0x1F50, WordBreakProperty.ALetter], - [/*start*/ 0x1F58, WordBreakProperty.Other], - [/*start*/ 0x1F59, WordBreakProperty.ALetter], - [/*start*/ 0x1F5A, WordBreakProperty.Other], - [/*start*/ 0x1F5B, WordBreakProperty.ALetter], - [/*start*/ 0x1F5C, WordBreakProperty.Other], - [/*start*/ 0x1F5D, WordBreakProperty.ALetter], - [/*start*/ 0x1F5E, WordBreakProperty.Other], - [/*start*/ 0x1F5F, WordBreakProperty.ALetter], - [/*start*/ 0x1F7E, WordBreakProperty.Other], - [/*start*/ 0x1F80, WordBreakProperty.ALetter], - [/*start*/ 0x1FB5, WordBreakProperty.Other], - [/*start*/ 0x1FB6, WordBreakProperty.ALetter], - [/*start*/ 0x1FBD, WordBreakProperty.Other], - [/*start*/ 0x1FBE, WordBreakProperty.ALetter], - [/*start*/ 0x1FBF, WordBreakProperty.Other], - [/*start*/ 0x1FC2, WordBreakProperty.ALetter], - [/*start*/ 0x1FC5, WordBreakProperty.Other], - [/*start*/ 0x1FC6, WordBreakProperty.ALetter], - [/*start*/ 0x1FCD, WordBreakProperty.Other], - [/*start*/ 0x1FD0, WordBreakProperty.ALetter], - [/*start*/ 0x1FD4, WordBreakProperty.Other], - [/*start*/ 0x1FD6, WordBreakProperty.ALetter], - [/*start*/ 0x1FDC, WordBreakProperty.Other], - [/*start*/ 0x1FE0, WordBreakProperty.ALetter], - [/*start*/ 0x1FED, WordBreakProperty.Other], - [/*start*/ 0x1FF2, WordBreakProperty.ALetter], - [/*start*/ 0x1FF5, WordBreakProperty.Other], - [/*start*/ 0x1FF6, WordBreakProperty.ALetter], - [/*start*/ 0x1FFD, WordBreakProperty.Other], - [/*start*/ 0x2000, WordBreakProperty.WSegSpace], - [/*start*/ 0x2007, WordBreakProperty.Other], - [/*start*/ 0x2008, WordBreakProperty.WSegSpace], - [/*start*/ 0x200B, WordBreakProperty.Other], - [/*start*/ 0x200C, WordBreakProperty.Extend], - [/*start*/ 0x200D, WordBreakProperty.ZWJ], - [/*start*/ 0x200E, WordBreakProperty.Format], - [/*start*/ 0x2010, WordBreakProperty.Other], - [/*start*/ 0x2018, WordBreakProperty.MidNumLet], - [/*start*/ 0x201A, WordBreakProperty.Other], - [/*start*/ 0x2024, WordBreakProperty.MidNumLet], - [/*start*/ 0x2025, WordBreakProperty.Other], - [/*start*/ 0x2027, WordBreakProperty.MidLetter], - [/*start*/ 0x2028, WordBreakProperty.Newline], - [/*start*/ 0x202A, WordBreakProperty.Format], - [/*start*/ 0x202F, WordBreakProperty.ExtendNumLet], - [/*start*/ 0x2030, WordBreakProperty.Other], - [/*start*/ 0x203F, WordBreakProperty.ExtendNumLet], - [/*start*/ 0x2041, WordBreakProperty.Other], - [/*start*/ 0x2044, WordBreakProperty.MidNum], - [/*start*/ 0x2045, WordBreakProperty.Other], - [/*start*/ 0x2054, WordBreakProperty.ExtendNumLet], - [/*start*/ 0x2055, WordBreakProperty.Other], - [/*start*/ 0x205F, WordBreakProperty.WSegSpace], - [/*start*/ 0x2060, WordBreakProperty.Format], - [/*start*/ 0x2065, WordBreakProperty.Other], - [/*start*/ 0x2066, WordBreakProperty.Format], - [/*start*/ 0x2070, WordBreakProperty.Other], - [/*start*/ 0x2071, WordBreakProperty.ALetter], - [/*start*/ 0x2072, WordBreakProperty.Other], - [/*start*/ 0x207F, WordBreakProperty.ALetter], - [/*start*/ 0x2080, WordBreakProperty.Other], - [/*start*/ 0x2090, WordBreakProperty.ALetter], - [/*start*/ 0x209D, WordBreakProperty.Other], - [/*start*/ 0x20D0, WordBreakProperty.Extend], - [/*start*/ 0x20F1, WordBreakProperty.Other], - [/*start*/ 0x2102, WordBreakProperty.ALetter], - [/*start*/ 0x2103, WordBreakProperty.Other], - [/*start*/ 0x2107, WordBreakProperty.ALetter], - [/*start*/ 0x2108, WordBreakProperty.Other], - [/*start*/ 0x210A, WordBreakProperty.ALetter], - [/*start*/ 0x2114, WordBreakProperty.Other], - [/*start*/ 0x2115, WordBreakProperty.ALetter], - [/*start*/ 0x2116, WordBreakProperty.Other], - [/*start*/ 0x2119, WordBreakProperty.ALetter], - [/*start*/ 0x211E, WordBreakProperty.Other], - [/*start*/ 0x2124, WordBreakProperty.ALetter], - [/*start*/ 0x2125, WordBreakProperty.Other], - [/*start*/ 0x2126, WordBreakProperty.ALetter], - [/*start*/ 0x2127, WordBreakProperty.Other], - [/*start*/ 0x2128, WordBreakProperty.ALetter], - [/*start*/ 0x2129, WordBreakProperty.Other], - [/*start*/ 0x212A, WordBreakProperty.ALetter], - [/*start*/ 0x212E, WordBreakProperty.Other], - [/*start*/ 0x212F, WordBreakProperty.ALetter], - [/*start*/ 0x213A, WordBreakProperty.Other], - [/*start*/ 0x213C, WordBreakProperty.ALetter], - [/*start*/ 0x2140, WordBreakProperty.Other], - [/*start*/ 0x2145, WordBreakProperty.ALetter], - [/*start*/ 0x214A, WordBreakProperty.Other], - [/*start*/ 0x214E, WordBreakProperty.ALetter], - [/*start*/ 0x214F, WordBreakProperty.Other], - [/*start*/ 0x2160, WordBreakProperty.ALetter], - [/*start*/ 0x2189, WordBreakProperty.Other], - [/*start*/ 0x24B6, WordBreakProperty.ALetter], - [/*start*/ 0x24EA, WordBreakProperty.Other], - [/*start*/ 0x2C00, WordBreakProperty.ALetter], - [/*start*/ 0x2C2F, WordBreakProperty.Other], - [/*start*/ 0x2C30, WordBreakProperty.ALetter], - [/*start*/ 0x2C5F, WordBreakProperty.Other], - [/*start*/ 0x2C60, WordBreakProperty.ALetter], - [/*start*/ 0x2CE5, WordBreakProperty.Other], - [/*start*/ 0x2CEB, WordBreakProperty.ALetter], - [/*start*/ 0x2CEF, WordBreakProperty.Extend], - [/*start*/ 0x2CF2, WordBreakProperty.ALetter], - [/*start*/ 0x2CF4, WordBreakProperty.Other], - [/*start*/ 0x2D00, WordBreakProperty.ALetter], - [/*start*/ 0x2D26, WordBreakProperty.Other], - [/*start*/ 0x2D27, WordBreakProperty.ALetter], - [/*start*/ 0x2D28, WordBreakProperty.Other], - [/*start*/ 0x2D2D, WordBreakProperty.ALetter], - [/*start*/ 0x2D2E, WordBreakProperty.Other], - [/*start*/ 0x2D30, WordBreakProperty.ALetter], - [/*start*/ 0x2D68, WordBreakProperty.Other], - [/*start*/ 0x2D6F, WordBreakProperty.ALetter], - [/*start*/ 0x2D70, WordBreakProperty.Other], - [/*start*/ 0x2D7F, WordBreakProperty.Extend], - [/*start*/ 0x2D80, WordBreakProperty.ALetter], - [/*start*/ 0x2D97, WordBreakProperty.Other], - [/*start*/ 0x2DA0, WordBreakProperty.ALetter], - [/*start*/ 0x2DA7, WordBreakProperty.Other], - [/*start*/ 0x2DA8, WordBreakProperty.ALetter], - [/*start*/ 0x2DAF, WordBreakProperty.Other], - [/*start*/ 0x2DB0, WordBreakProperty.ALetter], - [/*start*/ 0x2DB7, WordBreakProperty.Other], - [/*start*/ 0x2DB8, WordBreakProperty.ALetter], - [/*start*/ 0x2DBF, WordBreakProperty.Other], - [/*start*/ 0x2DC0, WordBreakProperty.ALetter], - [/*start*/ 0x2DC7, WordBreakProperty.Other], - [/*start*/ 0x2DC8, WordBreakProperty.ALetter], - [/*start*/ 0x2DCF, WordBreakProperty.Other], - [/*start*/ 0x2DD0, WordBreakProperty.ALetter], - [/*start*/ 0x2DD7, WordBreakProperty.Other], - [/*start*/ 0x2DD8, WordBreakProperty.ALetter], - [/*start*/ 0x2DDF, WordBreakProperty.Other], - [/*start*/ 0x2DE0, WordBreakProperty.Extend], - [/*start*/ 0x2E00, WordBreakProperty.Other], - [/*start*/ 0x2E2F, WordBreakProperty.ALetter], - [/*start*/ 0x2E30, WordBreakProperty.Other], - [/*start*/ 0x3000, WordBreakProperty.WSegSpace], - [/*start*/ 0x3001, WordBreakProperty.Other], - [/*start*/ 0x3005, WordBreakProperty.ALetter], - [/*start*/ 0x3006, WordBreakProperty.Other], - [/*start*/ 0x302A, WordBreakProperty.Extend], - [/*start*/ 0x3030, WordBreakProperty.Other], - [/*start*/ 0x3031, WordBreakProperty.Katakana], - [/*start*/ 0x3036, WordBreakProperty.Other], - [/*start*/ 0x303B, WordBreakProperty.ALetter], - [/*start*/ 0x303D, WordBreakProperty.Other], - [/*start*/ 0x3099, WordBreakProperty.Extend], - [/*start*/ 0x309B, WordBreakProperty.Katakana], - [/*start*/ 0x309D, WordBreakProperty.Other], - [/*start*/ 0x30A0, WordBreakProperty.Katakana], - [/*start*/ 0x30FB, WordBreakProperty.Other], - [/*start*/ 0x30FC, WordBreakProperty.Katakana], - [/*start*/ 0x3100, WordBreakProperty.Other], - [/*start*/ 0x3105, WordBreakProperty.ALetter], - [/*start*/ 0x3130, WordBreakProperty.Other], - [/*start*/ 0x3131, WordBreakProperty.ALetter], - [/*start*/ 0x318F, WordBreakProperty.Other], - [/*start*/ 0x31A0, WordBreakProperty.ALetter], - [/*start*/ 0x31C0, WordBreakProperty.Other], - [/*start*/ 0x31F0, WordBreakProperty.Katakana], - [/*start*/ 0x3200, WordBreakProperty.Other], - [/*start*/ 0x32D0, WordBreakProperty.Katakana], - [/*start*/ 0x32FF, WordBreakProperty.Other], - [/*start*/ 0x3300, WordBreakProperty.Katakana], - [/*start*/ 0x3358, WordBreakProperty.Other], - [/*start*/ 0xA000, WordBreakProperty.ALetter], - [/*start*/ 0xA48D, WordBreakProperty.Other], - [/*start*/ 0xA4D0, WordBreakProperty.ALetter], - [/*start*/ 0xA4FE, WordBreakProperty.Other], - [/*start*/ 0xA500, WordBreakProperty.ALetter], - [/*start*/ 0xA60D, WordBreakProperty.Other], - [/*start*/ 0xA610, WordBreakProperty.ALetter], - [/*start*/ 0xA620, WordBreakProperty.Numeric], - [/*start*/ 0xA62A, WordBreakProperty.ALetter], - [/*start*/ 0xA62C, WordBreakProperty.Other], - [/*start*/ 0xA640, WordBreakProperty.ALetter], - [/*start*/ 0xA66F, WordBreakProperty.Extend], - [/*start*/ 0xA673, WordBreakProperty.Other], - [/*start*/ 0xA674, WordBreakProperty.Extend], - [/*start*/ 0xA67E, WordBreakProperty.Other], - [/*start*/ 0xA67F, WordBreakProperty.ALetter], - [/*start*/ 0xA69E, WordBreakProperty.Extend], - [/*start*/ 0xA6A0, WordBreakProperty.ALetter], - [/*start*/ 0xA6F0, WordBreakProperty.Extend], - [/*start*/ 0xA6F2, WordBreakProperty.Other], - [/*start*/ 0xA708, WordBreakProperty.ALetter], - [/*start*/ 0xA7C0, WordBreakProperty.Other], - [/*start*/ 0xA7C2, WordBreakProperty.ALetter], - [/*start*/ 0xA7CB, WordBreakProperty.Other], - [/*start*/ 0xA7F5, WordBreakProperty.ALetter], - [/*start*/ 0xA802, WordBreakProperty.Extend], - [/*start*/ 0xA803, WordBreakProperty.ALetter], - [/*start*/ 0xA806, WordBreakProperty.Extend], - [/*start*/ 0xA807, WordBreakProperty.ALetter], - [/*start*/ 0xA80B, WordBreakProperty.Extend], - [/*start*/ 0xA80C, WordBreakProperty.ALetter], - [/*start*/ 0xA823, WordBreakProperty.Extend], - [/*start*/ 0xA828, WordBreakProperty.Other], - [/*start*/ 0xA82C, WordBreakProperty.Extend], - [/*start*/ 0xA82D, WordBreakProperty.Other], - [/*start*/ 0xA840, WordBreakProperty.ALetter], - [/*start*/ 0xA874, WordBreakProperty.Other], - [/*start*/ 0xA880, WordBreakProperty.Extend], - [/*start*/ 0xA882, WordBreakProperty.ALetter], - [/*start*/ 0xA8B4, WordBreakProperty.Extend], - [/*start*/ 0xA8C6, WordBreakProperty.Other], - [/*start*/ 0xA8D0, WordBreakProperty.Numeric], - [/*start*/ 0xA8DA, WordBreakProperty.Other], - [/*start*/ 0xA8E0, WordBreakProperty.Extend], - [/*start*/ 0xA8F2, WordBreakProperty.ALetter], - [/*start*/ 0xA8F8, WordBreakProperty.Other], - [/*start*/ 0xA8FB, WordBreakProperty.ALetter], - [/*start*/ 0xA8FC, WordBreakProperty.Other], - [/*start*/ 0xA8FD, WordBreakProperty.ALetter], - [/*start*/ 0xA8FF, WordBreakProperty.Extend], - [/*start*/ 0xA900, WordBreakProperty.Numeric], - [/*start*/ 0xA90A, WordBreakProperty.ALetter], - [/*start*/ 0xA926, WordBreakProperty.Extend], - [/*start*/ 0xA92E, WordBreakProperty.Other], - [/*start*/ 0xA930, WordBreakProperty.ALetter], - [/*start*/ 0xA947, WordBreakProperty.Extend], - [/*start*/ 0xA954, WordBreakProperty.Other], - [/*start*/ 0xA960, WordBreakProperty.ALetter], - [/*start*/ 0xA97D, WordBreakProperty.Other], - [/*start*/ 0xA980, WordBreakProperty.Extend], - [/*start*/ 0xA984, WordBreakProperty.ALetter], - [/*start*/ 0xA9B3, WordBreakProperty.Extend], - [/*start*/ 0xA9C1, WordBreakProperty.Other], - [/*start*/ 0xA9CF, WordBreakProperty.ALetter], - [/*start*/ 0xA9D0, WordBreakProperty.Numeric], - [/*start*/ 0xA9DA, WordBreakProperty.Other], - [/*start*/ 0xA9E5, WordBreakProperty.Extend], - [/*start*/ 0xA9E6, WordBreakProperty.Other], - [/*start*/ 0xA9F0, WordBreakProperty.Numeric], - [/*start*/ 0xA9FA, WordBreakProperty.Other], - [/*start*/ 0xAA00, WordBreakProperty.ALetter], - [/*start*/ 0xAA29, WordBreakProperty.Extend], - [/*start*/ 0xAA37, WordBreakProperty.Other], - [/*start*/ 0xAA40, WordBreakProperty.ALetter], - [/*start*/ 0xAA43, WordBreakProperty.Extend], - [/*start*/ 0xAA44, WordBreakProperty.ALetter], - [/*start*/ 0xAA4C, WordBreakProperty.Extend], - [/*start*/ 0xAA4E, WordBreakProperty.Other], - [/*start*/ 0xAA50, WordBreakProperty.Numeric], - [/*start*/ 0xAA5A, WordBreakProperty.Other], - [/*start*/ 0xAA7B, WordBreakProperty.Extend], - [/*start*/ 0xAA7E, WordBreakProperty.Other], - [/*start*/ 0xAAB0, WordBreakProperty.Extend], - [/*start*/ 0xAAB1, WordBreakProperty.Other], - [/*start*/ 0xAAB2, WordBreakProperty.Extend], - [/*start*/ 0xAAB5, WordBreakProperty.Other], - [/*start*/ 0xAAB7, WordBreakProperty.Extend], - [/*start*/ 0xAAB9, WordBreakProperty.Other], - [/*start*/ 0xAABE, WordBreakProperty.Extend], - [/*start*/ 0xAAC0, WordBreakProperty.Other], - [/*start*/ 0xAAC1, WordBreakProperty.Extend], - [/*start*/ 0xAAC2, WordBreakProperty.Other], - [/*start*/ 0xAAE0, WordBreakProperty.ALetter], - [/*start*/ 0xAAEB, WordBreakProperty.Extend], - [/*start*/ 0xAAF0, WordBreakProperty.Other], - [/*start*/ 0xAAF2, WordBreakProperty.ALetter], - [/*start*/ 0xAAF5, WordBreakProperty.Extend], - [/*start*/ 0xAAF7, WordBreakProperty.Other], - [/*start*/ 0xAB01, WordBreakProperty.ALetter], - [/*start*/ 0xAB07, WordBreakProperty.Other], - [/*start*/ 0xAB09, WordBreakProperty.ALetter], - [/*start*/ 0xAB0F, WordBreakProperty.Other], - [/*start*/ 0xAB11, WordBreakProperty.ALetter], - [/*start*/ 0xAB17, WordBreakProperty.Other], - [/*start*/ 0xAB20, WordBreakProperty.ALetter], - [/*start*/ 0xAB27, WordBreakProperty.Other], - [/*start*/ 0xAB28, WordBreakProperty.ALetter], - [/*start*/ 0xAB2F, WordBreakProperty.Other], - [/*start*/ 0xAB30, WordBreakProperty.ALetter], - [/*start*/ 0xAB6A, WordBreakProperty.Other], - [/*start*/ 0xAB70, WordBreakProperty.ALetter], - [/*start*/ 0xABE3, WordBreakProperty.Extend], - [/*start*/ 0xABEB, WordBreakProperty.Other], - [/*start*/ 0xABEC, WordBreakProperty.Extend], - [/*start*/ 0xABEE, WordBreakProperty.Other], - [/*start*/ 0xABF0, WordBreakProperty.Numeric], - [/*start*/ 0xABFA, WordBreakProperty.Other], - [/*start*/ 0xAC00, WordBreakProperty.ALetter], - [/*start*/ 0xD7A4, WordBreakProperty.Other], - [/*start*/ 0xD7B0, WordBreakProperty.ALetter], - [/*start*/ 0xD7C7, WordBreakProperty.Other], - [/*start*/ 0xD7CB, WordBreakProperty.ALetter], - [/*start*/ 0xD7FC, WordBreakProperty.Other], - [/*start*/ 0xFB00, WordBreakProperty.ALetter], - [/*start*/ 0xFB07, WordBreakProperty.Other], - [/*start*/ 0xFB13, WordBreakProperty.ALetter], - [/*start*/ 0xFB18, WordBreakProperty.Other], - [/*start*/ 0xFB1D, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB1E, WordBreakProperty.Extend], - [/*start*/ 0xFB1F, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB29, WordBreakProperty.Other], - [/*start*/ 0xFB2A, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB37, WordBreakProperty.Other], - [/*start*/ 0xFB38, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB3D, WordBreakProperty.Other], - [/*start*/ 0xFB3E, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB3F, WordBreakProperty.Other], - [/*start*/ 0xFB40, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB42, WordBreakProperty.Other], - [/*start*/ 0xFB43, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB45, WordBreakProperty.Other], - [/*start*/ 0xFB46, WordBreakProperty.Hebrew_Letter], - [/*start*/ 0xFB50, WordBreakProperty.ALetter], - [/*start*/ 0xFBB2, WordBreakProperty.Other], - [/*start*/ 0xFBD3, WordBreakProperty.ALetter], - [/*start*/ 0xFD3E, WordBreakProperty.Other], - [/*start*/ 0xFD50, WordBreakProperty.ALetter], - [/*start*/ 0xFD90, WordBreakProperty.Other], - [/*start*/ 0xFD92, WordBreakProperty.ALetter], - [/*start*/ 0xFDC8, WordBreakProperty.Other], - [/*start*/ 0xFDF0, WordBreakProperty.ALetter], - [/*start*/ 0xFDFC, WordBreakProperty.Other], - [/*start*/ 0xFE00, WordBreakProperty.Extend], - [/*start*/ 0xFE10, WordBreakProperty.MidNum], - [/*start*/ 0xFE11, WordBreakProperty.Other], - [/*start*/ 0xFE13, WordBreakProperty.MidLetter], - [/*start*/ 0xFE14, WordBreakProperty.MidNum], - [/*start*/ 0xFE15, WordBreakProperty.Other], - [/*start*/ 0xFE20, WordBreakProperty.Extend], - [/*start*/ 0xFE30, WordBreakProperty.Other], - [/*start*/ 0xFE33, WordBreakProperty.ExtendNumLet], - [/*start*/ 0xFE35, WordBreakProperty.Other], - [/*start*/ 0xFE4D, WordBreakProperty.ExtendNumLet], - [/*start*/ 0xFE50, WordBreakProperty.MidNum], - [/*start*/ 0xFE51, WordBreakProperty.Other], - [/*start*/ 0xFE52, WordBreakProperty.MidNumLet], - [/*start*/ 0xFE53, WordBreakProperty.Other], - [/*start*/ 0xFE54, WordBreakProperty.MidNum], - [/*start*/ 0xFE55, WordBreakProperty.MidLetter], - [/*start*/ 0xFE56, WordBreakProperty.Other], - [/*start*/ 0xFE70, WordBreakProperty.ALetter], - [/*start*/ 0xFE75, WordBreakProperty.Other], - [/*start*/ 0xFE76, WordBreakProperty.ALetter], - [/*start*/ 0xFEFD, WordBreakProperty.Other], - [/*start*/ 0xFEFF, WordBreakProperty.Format], - [/*start*/ 0xFF00, WordBreakProperty.Other], - [/*start*/ 0xFF07, WordBreakProperty.MidNumLet], - [/*start*/ 0xFF08, WordBreakProperty.Other], - [/*start*/ 0xFF0C, WordBreakProperty.MidNum], - [/*start*/ 0xFF0D, WordBreakProperty.Other], - [/*start*/ 0xFF0E, WordBreakProperty.MidNumLet], - [/*start*/ 0xFF0F, WordBreakProperty.Other], - [/*start*/ 0xFF10, WordBreakProperty.Numeric], - [/*start*/ 0xFF1A, WordBreakProperty.MidLetter], - [/*start*/ 0xFF1B, WordBreakProperty.MidNum], - [/*start*/ 0xFF1C, WordBreakProperty.Other], - [/*start*/ 0xFF21, WordBreakProperty.ALetter], - [/*start*/ 0xFF3B, WordBreakProperty.Other], - [/*start*/ 0xFF3F, WordBreakProperty.ExtendNumLet], - [/*start*/ 0xFF40, WordBreakProperty.Other], - [/*start*/ 0xFF41, WordBreakProperty.ALetter], - [/*start*/ 0xFF5B, WordBreakProperty.Other], - [/*start*/ 0xFF66, WordBreakProperty.Katakana], - [/*start*/ 0xFF9E, WordBreakProperty.Extend], - [/*start*/ 0xFFA0, WordBreakProperty.ALetter], - [/*start*/ 0xFFBF, WordBreakProperty.Other], - [/*start*/ 0xFFC2, WordBreakProperty.ALetter], - [/*start*/ 0xFFC8, WordBreakProperty.Other], - [/*start*/ 0xFFCA, WordBreakProperty.ALetter], - [/*start*/ 0xFFD0, WordBreakProperty.Other], - [/*start*/ 0xFFD2, WordBreakProperty.ALetter], - [/*start*/ 0xFFD8, WordBreakProperty.Other], - [/*start*/ 0xFFDA, WordBreakProperty.ALetter], - [/*start*/ 0xFFDD, WordBreakProperty.Other], - [/*start*/ 0xFFF9, WordBreakProperty.Format], - [/*start*/ 0xFFFC, WordBreakProperty.Other], - [/*start*/ 0x10000, WordBreakProperty.ALetter], - [/*start*/ 0x1000C, WordBreakProperty.Other], - [/*start*/ 0x1000D, WordBreakProperty.ALetter], - [/*start*/ 0x10027, WordBreakProperty.Other], - [/*start*/ 0x10028, WordBreakProperty.ALetter], - [/*start*/ 0x1003B, WordBreakProperty.Other], - [/*start*/ 0x1003C, WordBreakProperty.ALetter], - [/*start*/ 0x1003E, WordBreakProperty.Other], - [/*start*/ 0x1003F, WordBreakProperty.ALetter], - [/*start*/ 0x1004E, WordBreakProperty.Other], - [/*start*/ 0x10050, WordBreakProperty.ALetter], - [/*start*/ 0x1005E, WordBreakProperty.Other], - [/*start*/ 0x10080, WordBreakProperty.ALetter], - [/*start*/ 0x100FB, WordBreakProperty.Other], - [/*start*/ 0x10140, WordBreakProperty.ALetter], - [/*start*/ 0x10175, WordBreakProperty.Other], - [/*start*/ 0x101FD, WordBreakProperty.Extend], - [/*start*/ 0x101FE, WordBreakProperty.Other], - [/*start*/ 0x10280, WordBreakProperty.ALetter], - [/*start*/ 0x1029D, WordBreakProperty.Other], - [/*start*/ 0x102A0, WordBreakProperty.ALetter], - [/*start*/ 0x102D1, WordBreakProperty.Other], - [/*start*/ 0x102E0, WordBreakProperty.Extend], - [/*start*/ 0x102E1, WordBreakProperty.Other], - [/*start*/ 0x10300, WordBreakProperty.ALetter], - [/*start*/ 0x10320, WordBreakProperty.Other], - [/*start*/ 0x1032D, WordBreakProperty.ALetter], - [/*start*/ 0x1034B, WordBreakProperty.Other], - [/*start*/ 0x10350, WordBreakProperty.ALetter], - [/*start*/ 0x10376, WordBreakProperty.Extend], - [/*start*/ 0x1037B, WordBreakProperty.Other], - [/*start*/ 0x10380, WordBreakProperty.ALetter], - [/*start*/ 0x1039E, WordBreakProperty.Other], - [/*start*/ 0x103A0, WordBreakProperty.ALetter], - [/*start*/ 0x103C4, WordBreakProperty.Other], - [/*start*/ 0x103C8, WordBreakProperty.ALetter], - [/*start*/ 0x103D0, WordBreakProperty.Other], - [/*start*/ 0x103D1, WordBreakProperty.ALetter], - [/*start*/ 0x103D6, WordBreakProperty.Other], - [/*start*/ 0x10400, WordBreakProperty.ALetter], - [/*start*/ 0x1049E, WordBreakProperty.Other], - [/*start*/ 0x104A0, WordBreakProperty.Numeric], - [/*start*/ 0x104AA, WordBreakProperty.Other], - [/*start*/ 0x104B0, WordBreakProperty.ALetter], - [/*start*/ 0x104D4, WordBreakProperty.Other], - [/*start*/ 0x104D8, WordBreakProperty.ALetter], - [/*start*/ 0x104FC, WordBreakProperty.Other], - [/*start*/ 0x10500, WordBreakProperty.ALetter], - [/*start*/ 0x10528, WordBreakProperty.Other], - [/*start*/ 0x10530, WordBreakProperty.ALetter], - [/*start*/ 0x10564, WordBreakProperty.Other], - [/*start*/ 0x10600, WordBreakProperty.ALetter], - [/*start*/ 0x10737, WordBreakProperty.Other], - [/*start*/ 0x10740, WordBreakProperty.ALetter], - [/*start*/ 0x10756, WordBreakProperty.Other], - [/*start*/ 0x10760, WordBreakProperty.ALetter], - [/*start*/ 0x10768, WordBreakProperty.Other], - [/*start*/ 0x10800, WordBreakProperty.ALetter], - [/*start*/ 0x10806, WordBreakProperty.Other], - [/*start*/ 0x10808, WordBreakProperty.ALetter], - [/*start*/ 0x10809, WordBreakProperty.Other], - [/*start*/ 0x1080A, WordBreakProperty.ALetter], - [/*start*/ 0x10836, WordBreakProperty.Other], - [/*start*/ 0x10837, WordBreakProperty.ALetter], - [/*start*/ 0x10839, WordBreakProperty.Other], - [/*start*/ 0x1083C, WordBreakProperty.ALetter], - [/*start*/ 0x1083D, WordBreakProperty.Other], - [/*start*/ 0x1083F, WordBreakProperty.ALetter], - [/*start*/ 0x10856, WordBreakProperty.Other], - [/*start*/ 0x10860, WordBreakProperty.ALetter], - [/*start*/ 0x10877, WordBreakProperty.Other], - [/*start*/ 0x10880, WordBreakProperty.ALetter], - [/*start*/ 0x1089F, WordBreakProperty.Other], - [/*start*/ 0x108E0, WordBreakProperty.ALetter], - [/*start*/ 0x108F3, WordBreakProperty.Other], - [/*start*/ 0x108F4, WordBreakProperty.ALetter], - [/*start*/ 0x108F6, WordBreakProperty.Other], - [/*start*/ 0x10900, WordBreakProperty.ALetter], - [/*start*/ 0x10916, WordBreakProperty.Other], - [/*start*/ 0x10920, WordBreakProperty.ALetter], - [/*start*/ 0x1093A, WordBreakProperty.Other], - [/*start*/ 0x10980, WordBreakProperty.ALetter], - [/*start*/ 0x109B8, WordBreakProperty.Other], - [/*start*/ 0x109BE, WordBreakProperty.ALetter], - [/*start*/ 0x109C0, WordBreakProperty.Other], - [/*start*/ 0x10A00, WordBreakProperty.ALetter], - [/*start*/ 0x10A01, WordBreakProperty.Extend], - [/*start*/ 0x10A04, WordBreakProperty.Other], - [/*start*/ 0x10A05, WordBreakProperty.Extend], - [/*start*/ 0x10A07, WordBreakProperty.Other], - [/*start*/ 0x10A0C, WordBreakProperty.Extend], - [/*start*/ 0x10A10, WordBreakProperty.ALetter], - [/*start*/ 0x10A14, WordBreakProperty.Other], - [/*start*/ 0x10A15, WordBreakProperty.ALetter], - [/*start*/ 0x10A18, WordBreakProperty.Other], - [/*start*/ 0x10A19, WordBreakProperty.ALetter], - [/*start*/ 0x10A36, WordBreakProperty.Other], - [/*start*/ 0x10A38, WordBreakProperty.Extend], - [/*start*/ 0x10A3B, WordBreakProperty.Other], - [/*start*/ 0x10A3F, WordBreakProperty.Extend], - [/*start*/ 0x10A40, WordBreakProperty.Other], - [/*start*/ 0x10A60, WordBreakProperty.ALetter], - [/*start*/ 0x10A7D, WordBreakProperty.Other], - [/*start*/ 0x10A80, WordBreakProperty.ALetter], - [/*start*/ 0x10A9D, WordBreakProperty.Other], - [/*start*/ 0x10AC0, WordBreakProperty.ALetter], - [/*start*/ 0x10AC8, WordBreakProperty.Other], - [/*start*/ 0x10AC9, WordBreakProperty.ALetter], - [/*start*/ 0x10AE5, WordBreakProperty.Extend], - [/*start*/ 0x10AE7, WordBreakProperty.Other], - [/*start*/ 0x10B00, WordBreakProperty.ALetter], - [/*start*/ 0x10B36, WordBreakProperty.Other], - [/*start*/ 0x10B40, WordBreakProperty.ALetter], - [/*start*/ 0x10B56, WordBreakProperty.Other], - [/*start*/ 0x10B60, WordBreakProperty.ALetter], - [/*start*/ 0x10B73, WordBreakProperty.Other], - [/*start*/ 0x10B80, WordBreakProperty.ALetter], - [/*start*/ 0x10B92, WordBreakProperty.Other], - [/*start*/ 0x10C00, WordBreakProperty.ALetter], - [/*start*/ 0x10C49, WordBreakProperty.Other], - [/*start*/ 0x10C80, WordBreakProperty.ALetter], - [/*start*/ 0x10CB3, WordBreakProperty.Other], - [/*start*/ 0x10CC0, WordBreakProperty.ALetter], - [/*start*/ 0x10CF3, WordBreakProperty.Other], - [/*start*/ 0x10D00, WordBreakProperty.ALetter], - [/*start*/ 0x10D24, WordBreakProperty.Extend], - [/*start*/ 0x10D28, WordBreakProperty.Other], - [/*start*/ 0x10D30, WordBreakProperty.Numeric], - [/*start*/ 0x10D3A, WordBreakProperty.Other], - [/*start*/ 0x10E80, WordBreakProperty.ALetter], - [/*start*/ 0x10EAA, WordBreakProperty.Other], - [/*start*/ 0x10EAB, WordBreakProperty.Extend], - [/*start*/ 0x10EAD, WordBreakProperty.Other], - [/*start*/ 0x10EB0, WordBreakProperty.ALetter], - [/*start*/ 0x10EB2, WordBreakProperty.Other], - [/*start*/ 0x10F00, WordBreakProperty.ALetter], - [/*start*/ 0x10F1D, WordBreakProperty.Other], - [/*start*/ 0x10F27, WordBreakProperty.ALetter], - [/*start*/ 0x10F28, WordBreakProperty.Other], - [/*start*/ 0x10F30, WordBreakProperty.ALetter], - [/*start*/ 0x10F46, WordBreakProperty.Extend], - [/*start*/ 0x10F51, WordBreakProperty.Other], - [/*start*/ 0x10FB0, WordBreakProperty.ALetter], - [/*start*/ 0x10FC5, WordBreakProperty.Other], - [/*start*/ 0x10FE0, WordBreakProperty.ALetter], - [/*start*/ 0x10FF7, WordBreakProperty.Other], - [/*start*/ 0x11000, WordBreakProperty.Extend], - [/*start*/ 0x11003, WordBreakProperty.ALetter], - [/*start*/ 0x11038, WordBreakProperty.Extend], - [/*start*/ 0x11047, WordBreakProperty.Other], - [/*start*/ 0x11066, WordBreakProperty.Numeric], - [/*start*/ 0x11070, WordBreakProperty.Other], - [/*start*/ 0x1107F, WordBreakProperty.Extend], - [/*start*/ 0x11083, WordBreakProperty.ALetter], - [/*start*/ 0x110B0, WordBreakProperty.Extend], - [/*start*/ 0x110BB, WordBreakProperty.Other], - [/*start*/ 0x110BD, WordBreakProperty.Format], - [/*start*/ 0x110BE, WordBreakProperty.Other], - [/*start*/ 0x110CD, WordBreakProperty.Format], - [/*start*/ 0x110CE, WordBreakProperty.Other], - [/*start*/ 0x110D0, WordBreakProperty.ALetter], - [/*start*/ 0x110E9, WordBreakProperty.Other], - [/*start*/ 0x110F0, WordBreakProperty.Numeric], - [/*start*/ 0x110FA, WordBreakProperty.Other], - [/*start*/ 0x11100, WordBreakProperty.Extend], - [/*start*/ 0x11103, WordBreakProperty.ALetter], - [/*start*/ 0x11127, WordBreakProperty.Extend], - [/*start*/ 0x11135, WordBreakProperty.Other], - [/*start*/ 0x11136, WordBreakProperty.Numeric], - [/*start*/ 0x11140, WordBreakProperty.Other], - [/*start*/ 0x11144, WordBreakProperty.ALetter], - [/*start*/ 0x11145, WordBreakProperty.Extend], - [/*start*/ 0x11147, WordBreakProperty.ALetter], - [/*start*/ 0x11148, WordBreakProperty.Other], - [/*start*/ 0x11150, WordBreakProperty.ALetter], - [/*start*/ 0x11173, WordBreakProperty.Extend], - [/*start*/ 0x11174, WordBreakProperty.Other], - [/*start*/ 0x11176, WordBreakProperty.ALetter], - [/*start*/ 0x11177, WordBreakProperty.Other], - [/*start*/ 0x11180, WordBreakProperty.Extend], - [/*start*/ 0x11183, WordBreakProperty.ALetter], - [/*start*/ 0x111B3, WordBreakProperty.Extend], - [/*start*/ 0x111C1, WordBreakProperty.ALetter], - [/*start*/ 0x111C5, WordBreakProperty.Other], - [/*start*/ 0x111C9, WordBreakProperty.Extend], - [/*start*/ 0x111CD, WordBreakProperty.Other], - [/*start*/ 0x111CE, WordBreakProperty.Extend], - [/*start*/ 0x111D0, WordBreakProperty.Numeric], - [/*start*/ 0x111DA, WordBreakProperty.ALetter], - [/*start*/ 0x111DB, WordBreakProperty.Other], - [/*start*/ 0x111DC, WordBreakProperty.ALetter], - [/*start*/ 0x111DD, WordBreakProperty.Other], - [/*start*/ 0x11200, WordBreakProperty.ALetter], - [/*start*/ 0x11212, WordBreakProperty.Other], - [/*start*/ 0x11213, WordBreakProperty.ALetter], - [/*start*/ 0x1122C, WordBreakProperty.Extend], - [/*start*/ 0x11238, WordBreakProperty.Other], - [/*start*/ 0x1123E, WordBreakProperty.Extend], - [/*start*/ 0x1123F, WordBreakProperty.Other], - [/*start*/ 0x11280, WordBreakProperty.ALetter], - [/*start*/ 0x11287, WordBreakProperty.Other], - [/*start*/ 0x11288, WordBreakProperty.ALetter], - [/*start*/ 0x11289, WordBreakProperty.Other], - [/*start*/ 0x1128A, WordBreakProperty.ALetter], - [/*start*/ 0x1128E, WordBreakProperty.Other], - [/*start*/ 0x1128F, WordBreakProperty.ALetter], - [/*start*/ 0x1129E, WordBreakProperty.Other], - [/*start*/ 0x1129F, WordBreakProperty.ALetter], - [/*start*/ 0x112A9, WordBreakProperty.Other], - [/*start*/ 0x112B0, WordBreakProperty.ALetter], - [/*start*/ 0x112DF, WordBreakProperty.Extend], - [/*start*/ 0x112EB, WordBreakProperty.Other], - [/*start*/ 0x112F0, WordBreakProperty.Numeric], - [/*start*/ 0x112FA, WordBreakProperty.Other], - [/*start*/ 0x11300, WordBreakProperty.Extend], - [/*start*/ 0x11304, WordBreakProperty.Other], - [/*start*/ 0x11305, WordBreakProperty.ALetter], - [/*start*/ 0x1130D, WordBreakProperty.Other], - [/*start*/ 0x1130F, WordBreakProperty.ALetter], - [/*start*/ 0x11311, WordBreakProperty.Other], - [/*start*/ 0x11313, WordBreakProperty.ALetter], - [/*start*/ 0x11329, WordBreakProperty.Other], - [/*start*/ 0x1132A, WordBreakProperty.ALetter], - [/*start*/ 0x11331, WordBreakProperty.Other], - [/*start*/ 0x11332, WordBreakProperty.ALetter], - [/*start*/ 0x11334, WordBreakProperty.Other], - [/*start*/ 0x11335, WordBreakProperty.ALetter], - [/*start*/ 0x1133A, WordBreakProperty.Other], - [/*start*/ 0x1133B, WordBreakProperty.Extend], - [/*start*/ 0x1133D, WordBreakProperty.ALetter], - [/*start*/ 0x1133E, WordBreakProperty.Extend], - [/*start*/ 0x11345, WordBreakProperty.Other], - [/*start*/ 0x11347, WordBreakProperty.Extend], - [/*start*/ 0x11349, WordBreakProperty.Other], - [/*start*/ 0x1134B, WordBreakProperty.Extend], - [/*start*/ 0x1134E, WordBreakProperty.Other], - [/*start*/ 0x11350, WordBreakProperty.ALetter], - [/*start*/ 0x11351, WordBreakProperty.Other], - [/*start*/ 0x11357, WordBreakProperty.Extend], - [/*start*/ 0x11358, WordBreakProperty.Other], - [/*start*/ 0x1135D, WordBreakProperty.ALetter], - [/*start*/ 0x11362, WordBreakProperty.Extend], - [/*start*/ 0x11364, WordBreakProperty.Other], - [/*start*/ 0x11366, WordBreakProperty.Extend], - [/*start*/ 0x1136D, WordBreakProperty.Other], - [/*start*/ 0x11370, WordBreakProperty.Extend], - [/*start*/ 0x11375, WordBreakProperty.Other], - [/*start*/ 0x11400, WordBreakProperty.ALetter], - [/*start*/ 0x11435, WordBreakProperty.Extend], - [/*start*/ 0x11447, WordBreakProperty.ALetter], - [/*start*/ 0x1144B, WordBreakProperty.Other], - [/*start*/ 0x11450, WordBreakProperty.Numeric], - [/*start*/ 0x1145A, WordBreakProperty.Other], - [/*start*/ 0x1145E, WordBreakProperty.Extend], - [/*start*/ 0x1145F, WordBreakProperty.ALetter], - [/*start*/ 0x11462, WordBreakProperty.Other], - [/*start*/ 0x11480, WordBreakProperty.ALetter], - [/*start*/ 0x114B0, WordBreakProperty.Extend], - [/*start*/ 0x114C4, WordBreakProperty.ALetter], - [/*start*/ 0x114C6, WordBreakProperty.Other], - [/*start*/ 0x114C7, WordBreakProperty.ALetter], - [/*start*/ 0x114C8, WordBreakProperty.Other], - [/*start*/ 0x114D0, WordBreakProperty.Numeric], - [/*start*/ 0x114DA, WordBreakProperty.Other], - [/*start*/ 0x11580, WordBreakProperty.ALetter], - [/*start*/ 0x115AF, WordBreakProperty.Extend], - [/*start*/ 0x115B6, WordBreakProperty.Other], - [/*start*/ 0x115B8, WordBreakProperty.Extend], - [/*start*/ 0x115C1, WordBreakProperty.Other], - [/*start*/ 0x115D8, WordBreakProperty.ALetter], - [/*start*/ 0x115DC, WordBreakProperty.Extend], - [/*start*/ 0x115DE, WordBreakProperty.Other], - [/*start*/ 0x11600, WordBreakProperty.ALetter], - [/*start*/ 0x11630, WordBreakProperty.Extend], - [/*start*/ 0x11641, WordBreakProperty.Other], - [/*start*/ 0x11644, WordBreakProperty.ALetter], - [/*start*/ 0x11645, WordBreakProperty.Other], - [/*start*/ 0x11650, WordBreakProperty.Numeric], - [/*start*/ 0x1165A, WordBreakProperty.Other], - [/*start*/ 0x11680, WordBreakProperty.ALetter], - [/*start*/ 0x116AB, WordBreakProperty.Extend], - [/*start*/ 0x116B8, WordBreakProperty.ALetter], - [/*start*/ 0x116B9, WordBreakProperty.Other], - [/*start*/ 0x116C0, WordBreakProperty.Numeric], - [/*start*/ 0x116CA, WordBreakProperty.Other], - [/*start*/ 0x1171D, WordBreakProperty.Extend], - [/*start*/ 0x1172C, WordBreakProperty.Other], - [/*start*/ 0x11730, WordBreakProperty.Numeric], - [/*start*/ 0x1173A, WordBreakProperty.Other], - [/*start*/ 0x11800, WordBreakProperty.ALetter], - [/*start*/ 0x1182C, WordBreakProperty.Extend], - [/*start*/ 0x1183B, WordBreakProperty.Other], - [/*start*/ 0x118A0, WordBreakProperty.ALetter], - [/*start*/ 0x118E0, WordBreakProperty.Numeric], - [/*start*/ 0x118EA, WordBreakProperty.Other], - [/*start*/ 0x118FF, WordBreakProperty.ALetter], - [/*start*/ 0x11907, WordBreakProperty.Other], - [/*start*/ 0x11909, WordBreakProperty.ALetter], - [/*start*/ 0x1190A, WordBreakProperty.Other], - [/*start*/ 0x1190C, WordBreakProperty.ALetter], - [/*start*/ 0x11914, WordBreakProperty.Other], - [/*start*/ 0x11915, WordBreakProperty.ALetter], - [/*start*/ 0x11917, WordBreakProperty.Other], - [/*start*/ 0x11918, WordBreakProperty.ALetter], - [/*start*/ 0x11930, WordBreakProperty.Extend], - [/*start*/ 0x11936, WordBreakProperty.Other], - [/*start*/ 0x11937, WordBreakProperty.Extend], - [/*start*/ 0x11939, WordBreakProperty.Other], - [/*start*/ 0x1193B, WordBreakProperty.Extend], - [/*start*/ 0x1193F, WordBreakProperty.ALetter], - [/*start*/ 0x11940, WordBreakProperty.Extend], - [/*start*/ 0x11941, WordBreakProperty.ALetter], - [/*start*/ 0x11942, WordBreakProperty.Extend], - [/*start*/ 0x11944, WordBreakProperty.Other], - [/*start*/ 0x11950, WordBreakProperty.Numeric], - [/*start*/ 0x1195A, WordBreakProperty.Other], - [/*start*/ 0x119A0, WordBreakProperty.ALetter], - [/*start*/ 0x119A8, WordBreakProperty.Other], - [/*start*/ 0x119AA, WordBreakProperty.ALetter], - [/*start*/ 0x119D1, WordBreakProperty.Extend], - [/*start*/ 0x119D8, WordBreakProperty.Other], - [/*start*/ 0x119DA, WordBreakProperty.Extend], - [/*start*/ 0x119E1, WordBreakProperty.ALetter], - [/*start*/ 0x119E2, WordBreakProperty.Other], - [/*start*/ 0x119E3, WordBreakProperty.ALetter], - [/*start*/ 0x119E4, WordBreakProperty.Extend], - [/*start*/ 0x119E5, WordBreakProperty.Other], - [/*start*/ 0x11A00, WordBreakProperty.ALetter], - [/*start*/ 0x11A01, WordBreakProperty.Extend], - [/*start*/ 0x11A0B, WordBreakProperty.ALetter], - [/*start*/ 0x11A33, WordBreakProperty.Extend], - [/*start*/ 0x11A3A, WordBreakProperty.ALetter], - [/*start*/ 0x11A3B, WordBreakProperty.Extend], - [/*start*/ 0x11A3F, WordBreakProperty.Other], - [/*start*/ 0x11A47, WordBreakProperty.Extend], - [/*start*/ 0x11A48, WordBreakProperty.Other], - [/*start*/ 0x11A50, WordBreakProperty.ALetter], - [/*start*/ 0x11A51, WordBreakProperty.Extend], - [/*start*/ 0x11A5C, WordBreakProperty.ALetter], - [/*start*/ 0x11A8A, WordBreakProperty.Extend], - [/*start*/ 0x11A9A, WordBreakProperty.Other], - [/*start*/ 0x11A9D, WordBreakProperty.ALetter], - [/*start*/ 0x11A9E, WordBreakProperty.Other], - [/*start*/ 0x11AC0, WordBreakProperty.ALetter], - [/*start*/ 0x11AF9, WordBreakProperty.Other], - [/*start*/ 0x11C00, WordBreakProperty.ALetter], - [/*start*/ 0x11C09, WordBreakProperty.Other], - [/*start*/ 0x11C0A, WordBreakProperty.ALetter], - [/*start*/ 0x11C2F, WordBreakProperty.Extend], - [/*start*/ 0x11C37, WordBreakProperty.Other], - [/*start*/ 0x11C38, WordBreakProperty.Extend], - [/*start*/ 0x11C40, WordBreakProperty.ALetter], - [/*start*/ 0x11C41, WordBreakProperty.Other], - [/*start*/ 0x11C50, WordBreakProperty.Numeric], - [/*start*/ 0x11C5A, WordBreakProperty.Other], - [/*start*/ 0x11C72, WordBreakProperty.ALetter], - [/*start*/ 0x11C90, WordBreakProperty.Other], - [/*start*/ 0x11C92, WordBreakProperty.Extend], - [/*start*/ 0x11CA8, WordBreakProperty.Other], - [/*start*/ 0x11CA9, WordBreakProperty.Extend], - [/*start*/ 0x11CB7, WordBreakProperty.Other], - [/*start*/ 0x11D00, WordBreakProperty.ALetter], - [/*start*/ 0x11D07, WordBreakProperty.Other], - [/*start*/ 0x11D08, WordBreakProperty.ALetter], - [/*start*/ 0x11D0A, WordBreakProperty.Other], - [/*start*/ 0x11D0B, WordBreakProperty.ALetter], - [/*start*/ 0x11D31, WordBreakProperty.Extend], - [/*start*/ 0x11D37, WordBreakProperty.Other], - [/*start*/ 0x11D3A, WordBreakProperty.Extend], - [/*start*/ 0x11D3B, WordBreakProperty.Other], - [/*start*/ 0x11D3C, WordBreakProperty.Extend], - [/*start*/ 0x11D3E, WordBreakProperty.Other], - [/*start*/ 0x11D3F, WordBreakProperty.Extend], - [/*start*/ 0x11D46, WordBreakProperty.ALetter], - [/*start*/ 0x11D47, WordBreakProperty.Extend], - [/*start*/ 0x11D48, WordBreakProperty.Other], - [/*start*/ 0x11D50, WordBreakProperty.Numeric], - [/*start*/ 0x11D5A, WordBreakProperty.Other], - [/*start*/ 0x11D60, WordBreakProperty.ALetter], - [/*start*/ 0x11D66, WordBreakProperty.Other], - [/*start*/ 0x11D67, WordBreakProperty.ALetter], - [/*start*/ 0x11D69, WordBreakProperty.Other], - [/*start*/ 0x11D6A, WordBreakProperty.ALetter], - [/*start*/ 0x11D8A, WordBreakProperty.Extend], - [/*start*/ 0x11D8F, WordBreakProperty.Other], - [/*start*/ 0x11D90, WordBreakProperty.Extend], - [/*start*/ 0x11D92, WordBreakProperty.Other], - [/*start*/ 0x11D93, WordBreakProperty.Extend], - [/*start*/ 0x11D98, WordBreakProperty.ALetter], - [/*start*/ 0x11D99, WordBreakProperty.Other], - [/*start*/ 0x11DA0, WordBreakProperty.Numeric], - [/*start*/ 0x11DAA, WordBreakProperty.Other], - [/*start*/ 0x11EE0, WordBreakProperty.ALetter], - [/*start*/ 0x11EF3, WordBreakProperty.Extend], - [/*start*/ 0x11EF7, WordBreakProperty.Other], - [/*start*/ 0x11FB0, WordBreakProperty.ALetter], - [/*start*/ 0x11FB1, WordBreakProperty.Other], - [/*start*/ 0x12000, WordBreakProperty.ALetter], - [/*start*/ 0x1239A, WordBreakProperty.Other], - [/*start*/ 0x12400, WordBreakProperty.ALetter], - [/*start*/ 0x1246F, WordBreakProperty.Other], - [/*start*/ 0x12480, WordBreakProperty.ALetter], - [/*start*/ 0x12544, WordBreakProperty.Other], - [/*start*/ 0x13000, WordBreakProperty.ALetter], - [/*start*/ 0x1342F, WordBreakProperty.Other], - [/*start*/ 0x13430, WordBreakProperty.Format], - [/*start*/ 0x13439, WordBreakProperty.Other], - [/*start*/ 0x14400, WordBreakProperty.ALetter], - [/*start*/ 0x14647, WordBreakProperty.Other], - [/*start*/ 0x16800, WordBreakProperty.ALetter], - [/*start*/ 0x16A39, WordBreakProperty.Other], - [/*start*/ 0x16A40, WordBreakProperty.ALetter], - [/*start*/ 0x16A5F, WordBreakProperty.Other], - [/*start*/ 0x16A60, WordBreakProperty.Numeric], - [/*start*/ 0x16A6A, WordBreakProperty.Other], - [/*start*/ 0x16AD0, WordBreakProperty.ALetter], - [/*start*/ 0x16AEE, WordBreakProperty.Other], - [/*start*/ 0x16AF0, WordBreakProperty.Extend], - [/*start*/ 0x16AF5, WordBreakProperty.Other], - [/*start*/ 0x16B00, WordBreakProperty.ALetter], - [/*start*/ 0x16B30, WordBreakProperty.Extend], - [/*start*/ 0x16B37, WordBreakProperty.Other], - [/*start*/ 0x16B40, WordBreakProperty.ALetter], - [/*start*/ 0x16B44, WordBreakProperty.Other], - [/*start*/ 0x16B50, WordBreakProperty.Numeric], - [/*start*/ 0x16B5A, WordBreakProperty.Other], - [/*start*/ 0x16B63, WordBreakProperty.ALetter], - [/*start*/ 0x16B78, WordBreakProperty.Other], - [/*start*/ 0x16B7D, WordBreakProperty.ALetter], - [/*start*/ 0x16B90, WordBreakProperty.Other], - [/*start*/ 0x16E40, WordBreakProperty.ALetter], - [/*start*/ 0x16E80, WordBreakProperty.Other], - [/*start*/ 0x16F00, WordBreakProperty.ALetter], - [/*start*/ 0x16F4B, WordBreakProperty.Other], - [/*start*/ 0x16F4F, WordBreakProperty.Extend], - [/*start*/ 0x16F50, WordBreakProperty.ALetter], - [/*start*/ 0x16F51, WordBreakProperty.Extend], - [/*start*/ 0x16F88, WordBreakProperty.Other], - [/*start*/ 0x16F8F, WordBreakProperty.Extend], - [/*start*/ 0x16F93, WordBreakProperty.ALetter], - [/*start*/ 0x16FA0, WordBreakProperty.Other], - [/*start*/ 0x16FE0, WordBreakProperty.ALetter], - [/*start*/ 0x16FE2, WordBreakProperty.Other], - [/*start*/ 0x16FE3, WordBreakProperty.ALetter], - [/*start*/ 0x16FE4, WordBreakProperty.Extend], - [/*start*/ 0x16FE5, WordBreakProperty.Other], - [/*start*/ 0x16FF0, WordBreakProperty.Extend], - [/*start*/ 0x16FF2, WordBreakProperty.Other], - [/*start*/ 0x1B000, WordBreakProperty.Katakana], - [/*start*/ 0x1B001, WordBreakProperty.Other], - [/*start*/ 0x1B164, WordBreakProperty.Katakana], - [/*start*/ 0x1B168, WordBreakProperty.Other], - [/*start*/ 0x1BC00, WordBreakProperty.ALetter], - [/*start*/ 0x1BC6B, WordBreakProperty.Other], - [/*start*/ 0x1BC70, WordBreakProperty.ALetter], - [/*start*/ 0x1BC7D, WordBreakProperty.Other], - [/*start*/ 0x1BC80, WordBreakProperty.ALetter], - [/*start*/ 0x1BC89, WordBreakProperty.Other], - [/*start*/ 0x1BC90, WordBreakProperty.ALetter], - [/*start*/ 0x1BC9A, WordBreakProperty.Other], - [/*start*/ 0x1BC9D, WordBreakProperty.Extend], - [/*start*/ 0x1BC9F, WordBreakProperty.Other], - [/*start*/ 0x1BCA0, WordBreakProperty.Format], - [/*start*/ 0x1BCA4, WordBreakProperty.Other], - [/*start*/ 0x1D165, WordBreakProperty.Extend], - [/*start*/ 0x1D16A, WordBreakProperty.Other], - [/*start*/ 0x1D16D, WordBreakProperty.Extend], - [/*start*/ 0x1D173, WordBreakProperty.Format], - [/*start*/ 0x1D17B, WordBreakProperty.Extend], - [/*start*/ 0x1D183, WordBreakProperty.Other], - [/*start*/ 0x1D185, WordBreakProperty.Extend], - [/*start*/ 0x1D18C, WordBreakProperty.Other], - [/*start*/ 0x1D1AA, WordBreakProperty.Extend], - [/*start*/ 0x1D1AE, WordBreakProperty.Other], - [/*start*/ 0x1D242, WordBreakProperty.Extend], - [/*start*/ 0x1D245, WordBreakProperty.Other], - [/*start*/ 0x1D400, WordBreakProperty.ALetter], - [/*start*/ 0x1D455, WordBreakProperty.Other], - [/*start*/ 0x1D456, WordBreakProperty.ALetter], - [/*start*/ 0x1D49D, WordBreakProperty.Other], - [/*start*/ 0x1D49E, WordBreakProperty.ALetter], - [/*start*/ 0x1D4A0, WordBreakProperty.Other], - [/*start*/ 0x1D4A2, WordBreakProperty.ALetter], - [/*start*/ 0x1D4A3, WordBreakProperty.Other], - [/*start*/ 0x1D4A5, WordBreakProperty.ALetter], - [/*start*/ 0x1D4A7, WordBreakProperty.Other], - [/*start*/ 0x1D4A9, WordBreakProperty.ALetter], - [/*start*/ 0x1D4AD, WordBreakProperty.Other], - [/*start*/ 0x1D4AE, WordBreakProperty.ALetter], - [/*start*/ 0x1D4BA, WordBreakProperty.Other], - [/*start*/ 0x1D4BB, WordBreakProperty.ALetter], - [/*start*/ 0x1D4BC, WordBreakProperty.Other], - [/*start*/ 0x1D4BD, WordBreakProperty.ALetter], - [/*start*/ 0x1D4C4, WordBreakProperty.Other], - [/*start*/ 0x1D4C5, WordBreakProperty.ALetter], - [/*start*/ 0x1D506, WordBreakProperty.Other], - [/*start*/ 0x1D507, WordBreakProperty.ALetter], - [/*start*/ 0x1D50B, WordBreakProperty.Other], - [/*start*/ 0x1D50D, WordBreakProperty.ALetter], - [/*start*/ 0x1D515, WordBreakProperty.Other], - [/*start*/ 0x1D516, WordBreakProperty.ALetter], - [/*start*/ 0x1D51D, WordBreakProperty.Other], - [/*start*/ 0x1D51E, WordBreakProperty.ALetter], - [/*start*/ 0x1D53A, WordBreakProperty.Other], - [/*start*/ 0x1D53B, WordBreakProperty.ALetter], - [/*start*/ 0x1D53F, WordBreakProperty.Other], - [/*start*/ 0x1D540, WordBreakProperty.ALetter], - [/*start*/ 0x1D545, WordBreakProperty.Other], - [/*start*/ 0x1D546, WordBreakProperty.ALetter], - [/*start*/ 0x1D547, WordBreakProperty.Other], - [/*start*/ 0x1D54A, WordBreakProperty.ALetter], - [/*start*/ 0x1D551, WordBreakProperty.Other], - [/*start*/ 0x1D552, WordBreakProperty.ALetter], - [/*start*/ 0x1D6A6, WordBreakProperty.Other], - [/*start*/ 0x1D6A8, WordBreakProperty.ALetter], - [/*start*/ 0x1D6C1, WordBreakProperty.Other], - [/*start*/ 0x1D6C2, WordBreakProperty.ALetter], - [/*start*/ 0x1D6DB, WordBreakProperty.Other], - [/*start*/ 0x1D6DC, WordBreakProperty.ALetter], - [/*start*/ 0x1D6FB, WordBreakProperty.Other], - [/*start*/ 0x1D6FC, WordBreakProperty.ALetter], - [/*start*/ 0x1D715, WordBreakProperty.Other], - [/*start*/ 0x1D716, WordBreakProperty.ALetter], - [/*start*/ 0x1D735, WordBreakProperty.Other], - [/*start*/ 0x1D736, WordBreakProperty.ALetter], - [/*start*/ 0x1D74F, WordBreakProperty.Other], - [/*start*/ 0x1D750, WordBreakProperty.ALetter], - [/*start*/ 0x1D76F, WordBreakProperty.Other], - [/*start*/ 0x1D770, WordBreakProperty.ALetter], - [/*start*/ 0x1D789, WordBreakProperty.Other], - [/*start*/ 0x1D78A, WordBreakProperty.ALetter], - [/*start*/ 0x1D7A9, WordBreakProperty.Other], - [/*start*/ 0x1D7AA, WordBreakProperty.ALetter], - [/*start*/ 0x1D7C3, WordBreakProperty.Other], - [/*start*/ 0x1D7C4, WordBreakProperty.ALetter], - [/*start*/ 0x1D7CC, WordBreakProperty.Other], - [/*start*/ 0x1D7CE, WordBreakProperty.Numeric], - [/*start*/ 0x1D800, WordBreakProperty.Other], - [/*start*/ 0x1DA00, WordBreakProperty.Extend], - [/*start*/ 0x1DA37, WordBreakProperty.Other], - [/*start*/ 0x1DA3B, WordBreakProperty.Extend], - [/*start*/ 0x1DA6D, WordBreakProperty.Other], - [/*start*/ 0x1DA75, WordBreakProperty.Extend], - [/*start*/ 0x1DA76, WordBreakProperty.Other], - [/*start*/ 0x1DA84, WordBreakProperty.Extend], - [/*start*/ 0x1DA85, WordBreakProperty.Other], - [/*start*/ 0x1DA9B, WordBreakProperty.Extend], - [/*start*/ 0x1DAA0, WordBreakProperty.Other], - [/*start*/ 0x1DAA1, WordBreakProperty.Extend], - [/*start*/ 0x1DAB0, WordBreakProperty.Other], - [/*start*/ 0x1E000, WordBreakProperty.Extend], - [/*start*/ 0x1E007, WordBreakProperty.Other], - [/*start*/ 0x1E008, WordBreakProperty.Extend], - [/*start*/ 0x1E019, WordBreakProperty.Other], - [/*start*/ 0x1E01B, WordBreakProperty.Extend], - [/*start*/ 0x1E022, WordBreakProperty.Other], - [/*start*/ 0x1E023, WordBreakProperty.Extend], - [/*start*/ 0x1E025, WordBreakProperty.Other], - [/*start*/ 0x1E026, WordBreakProperty.Extend], - [/*start*/ 0x1E02B, WordBreakProperty.Other], - [/*start*/ 0x1E100, WordBreakProperty.ALetter], - [/*start*/ 0x1E12D, WordBreakProperty.Other], - [/*start*/ 0x1E130, WordBreakProperty.Extend], - [/*start*/ 0x1E137, WordBreakProperty.ALetter], - [/*start*/ 0x1E13E, WordBreakProperty.Other], - [/*start*/ 0x1E140, WordBreakProperty.Numeric], - [/*start*/ 0x1E14A, WordBreakProperty.Other], - [/*start*/ 0x1E14E, WordBreakProperty.ALetter], - [/*start*/ 0x1E14F, WordBreakProperty.Other], - [/*start*/ 0x1E2C0, WordBreakProperty.ALetter], - [/*start*/ 0x1E2EC, WordBreakProperty.Extend], - [/*start*/ 0x1E2F0, WordBreakProperty.Numeric], - [/*start*/ 0x1E2FA, WordBreakProperty.Other], - [/*start*/ 0x1E800, WordBreakProperty.ALetter], - [/*start*/ 0x1E8C5, WordBreakProperty.Other], - [/*start*/ 0x1E8D0, WordBreakProperty.Extend], - [/*start*/ 0x1E8D7, WordBreakProperty.Other], - [/*start*/ 0x1E900, WordBreakProperty.ALetter], - [/*start*/ 0x1E944, WordBreakProperty.Extend], - [/*start*/ 0x1E94B, WordBreakProperty.ALetter], - [/*start*/ 0x1E94C, WordBreakProperty.Other], - [/*start*/ 0x1E950, WordBreakProperty.Numeric], - [/*start*/ 0x1E95A, WordBreakProperty.Other], - [/*start*/ 0x1EE00, WordBreakProperty.ALetter], - [/*start*/ 0x1EE04, WordBreakProperty.Other], - [/*start*/ 0x1EE05, WordBreakProperty.ALetter], - [/*start*/ 0x1EE20, WordBreakProperty.Other], - [/*start*/ 0x1EE21, WordBreakProperty.ALetter], - [/*start*/ 0x1EE23, WordBreakProperty.Other], - [/*start*/ 0x1EE24, WordBreakProperty.ALetter], - [/*start*/ 0x1EE25, WordBreakProperty.Other], - [/*start*/ 0x1EE27, WordBreakProperty.ALetter], - [/*start*/ 0x1EE28, WordBreakProperty.Other], - [/*start*/ 0x1EE29, WordBreakProperty.ALetter], - [/*start*/ 0x1EE33, WordBreakProperty.Other], - [/*start*/ 0x1EE34, WordBreakProperty.ALetter], - [/*start*/ 0x1EE38, WordBreakProperty.Other], - [/*start*/ 0x1EE39, WordBreakProperty.ALetter], - [/*start*/ 0x1EE3A, WordBreakProperty.Other], - [/*start*/ 0x1EE3B, WordBreakProperty.ALetter], - [/*start*/ 0x1EE3C, WordBreakProperty.Other], - [/*start*/ 0x1EE42, WordBreakProperty.ALetter], - [/*start*/ 0x1EE43, WordBreakProperty.Other], - [/*start*/ 0x1EE47, WordBreakProperty.ALetter], - [/*start*/ 0x1EE48, WordBreakProperty.Other], - [/*start*/ 0x1EE49, WordBreakProperty.ALetter], - [/*start*/ 0x1EE4A, WordBreakProperty.Other], - [/*start*/ 0x1EE4B, WordBreakProperty.ALetter], - [/*start*/ 0x1EE4C, WordBreakProperty.Other], - [/*start*/ 0x1EE4D, WordBreakProperty.ALetter], - [/*start*/ 0x1EE50, WordBreakProperty.Other], - [/*start*/ 0x1EE51, WordBreakProperty.ALetter], - [/*start*/ 0x1EE53, WordBreakProperty.Other], - [/*start*/ 0x1EE54, WordBreakProperty.ALetter], - [/*start*/ 0x1EE55, WordBreakProperty.Other], - [/*start*/ 0x1EE57, WordBreakProperty.ALetter], - [/*start*/ 0x1EE58, WordBreakProperty.Other], - [/*start*/ 0x1EE59, WordBreakProperty.ALetter], - [/*start*/ 0x1EE5A, WordBreakProperty.Other], - [/*start*/ 0x1EE5B, WordBreakProperty.ALetter], - [/*start*/ 0x1EE5C, WordBreakProperty.Other], - [/*start*/ 0x1EE5D, WordBreakProperty.ALetter], - [/*start*/ 0x1EE5E, WordBreakProperty.Other], - [/*start*/ 0x1EE5F, WordBreakProperty.ALetter], - [/*start*/ 0x1EE60, WordBreakProperty.Other], - [/*start*/ 0x1EE61, WordBreakProperty.ALetter], - [/*start*/ 0x1EE63, WordBreakProperty.Other], - [/*start*/ 0x1EE64, WordBreakProperty.ALetter], - [/*start*/ 0x1EE65, WordBreakProperty.Other], - [/*start*/ 0x1EE67, WordBreakProperty.ALetter], - [/*start*/ 0x1EE6B, WordBreakProperty.Other], - [/*start*/ 0x1EE6C, WordBreakProperty.ALetter], - [/*start*/ 0x1EE73, WordBreakProperty.Other], - [/*start*/ 0x1EE74, WordBreakProperty.ALetter], - [/*start*/ 0x1EE78, WordBreakProperty.Other], - [/*start*/ 0x1EE79, WordBreakProperty.ALetter], - [/*start*/ 0x1EE7D, WordBreakProperty.Other], - [/*start*/ 0x1EE7E, WordBreakProperty.ALetter], - [/*start*/ 0x1EE7F, WordBreakProperty.Other], - [/*start*/ 0x1EE80, WordBreakProperty.ALetter], - [/*start*/ 0x1EE8A, WordBreakProperty.Other], - [/*start*/ 0x1EE8B, WordBreakProperty.ALetter], - [/*start*/ 0x1EE9C, WordBreakProperty.Other], - [/*start*/ 0x1EEA1, WordBreakProperty.ALetter], - [/*start*/ 0x1EEA4, WordBreakProperty.Other], - [/*start*/ 0x1EEA5, WordBreakProperty.ALetter], - [/*start*/ 0x1EEAA, WordBreakProperty.Other], - [/*start*/ 0x1EEAB, WordBreakProperty.ALetter], - [/*start*/ 0x1EEBC, WordBreakProperty.Other], - [/*start*/ 0x1F130, WordBreakProperty.ALetter], - [/*start*/ 0x1F14A, WordBreakProperty.Other], - [/*start*/ 0x1F150, WordBreakProperty.ALetter], - [/*start*/ 0x1F16A, WordBreakProperty.Other], - [/*start*/ 0x1F170, WordBreakProperty.ALetter], - [/*start*/ 0x1F18A, WordBreakProperty.Other], - [/*start*/ 0x1F1E6, WordBreakProperty.Regional_Indicator], - [/*start*/ 0x1F200, WordBreakProperty.Other], - [/*start*/ 0x1F3FB, WordBreakProperty.Extend], - [/*start*/ 0x1F400, WordBreakProperty.Other], - [/*start*/ 0x1FBF0, WordBreakProperty.Numeric], - [/*start*/ 0x1FBFA, WordBreakProperty.Other], - [/*start*/ 0xE0001, WordBreakProperty.Format], - [/*start*/ 0xE0002, WordBreakProperty.Other], - [/*start*/ 0xE0020, WordBreakProperty.Extend], - [/*start*/ 0xE0080, WordBreakProperty.Other], - [/*start*/ 0xE0100, WordBreakProperty.Extend], - [/*start*/ 0xE01F0, WordBreakProperty.Other], -]; diff --git a/developer/src/kmc-model/test/wordbreakers/default-wordbreaker-esm.ts b/developer/src/kmc-model/test/wordbreakers/default-wordbreaker-esm.ts deleted file mode 100644 index 55c0e560da6..00000000000 --- a/developer/src/kmc-model/test/wordbreakers/default-wordbreaker-esm.ts +++ /dev/null @@ -1,383 +0,0 @@ -// TEMP: esm version of /common/models/wordbreakers/default/index.ts - - import { I, WORD_BREAK_PROPERTY, WordBreakProperty } from './data.js'; - - - /** - * Word breaker based on Unicode Standard Annex #29, Section 4.1: - * Default Word Boundary Specification. - * - * @see http://unicode.org/reports/tr29/#Word_Boundaries - * @see https://github.com/eddieantonio/unicode-default-word-boundary/tree/v12.0.0 - */ - export default function default_(text: string): Span[] { - let boundaries = findBoundaries(text); - if (boundaries.length == 0) { - return []; - } - - // All non-empty strings have at least TWO boundaries: at the start and at the end of - // the string. - let spans = []; - for (let i = 0; i < boundaries.length - 1; i++) { - let start = boundaries[i]; - let end = boundaries[i + 1]; - let span = new LazySpan(text, start, end); - - if (isNonSpace(span.text)) { - spans.push(span); - // Preserve a sequence-final space if it exists. Needed to signal "end of word". - } else if (i == boundaries.length - 2) { // if "we just checked the final boundary"... - // We don't want to return the whitespace itself; the correct token is simply ''. - span = new LazySpan(text, end, end); - spans.push(span); - } - } - return spans; - } - - // Utilities // - // type WordBreakProperty = data.WordBreakProperty; - // const WordBreakProperty = data.WordBreakProperty; - // type I = data.I; - // const I = data.I; - // const WORD_BREAK_PROPERTY = data.WORD_BREAK_PROPERTY; - - /** - * A span that does not cut out the substring until it absolutely has to! - */ - class LazySpan implements Span { - private _source: string; - readonly start: number; - readonly end: number; - constructor(source: string, start: number, end: number) { - this._source = source; - this.start = start; - this.end = end; - } - - get text(): string { - return this._source.substring(this.start, this.end); - } - - get length(): number { - return this.end - this.start; - } - } - - /** - * Returns true when the chunk does not solely consist of whitespace. - * - * @param chunk a chunk of text. Starts and ends at word boundaries. - */ - function isNonSpace(chunk: string): boolean { - return !Array.from(chunk).map(property).every(wb => ( - wb === WordBreakProperty.CR || - wb === WordBreakProperty.LF || - wb === WordBreakProperty.Newline || - wb === WordBreakProperty.WSegSpace - )); - } - - /** - * Yields a series of string indices where a word break should - * occur. That is, there should be a break BEFORE each string - * index yielded by this generator. - * - * @param text Text to find word boundaries in. - */ - function findBoundaries(text: string): number[] { - // WB1 and WB2: no boundaries if given an empty string. - if (text.length === 0) { - // There are no boundaries in an empty string! - return []; - } - - // This algorithm works by maintaining a sliding window of four SCALAR VALUES. - // - // - Scalar values? JavaScript strings are NOT actually a string of - // Unicode code points; some characters are made up of TWO - // JavaScript indices. e.g., - // "💩".length === 2; - // "💩"[0] === '\uD83D'; - // "💩"[1] === '\uDCA9'; - // - // These characters that are represented by TWO indices are - // called "surrogate pairs". Since we don't want to be in the - // "middle" of a character, make sure we're always advancing - // by scalar values, and NOT indices. That means, we sometimes - // need to advance by TWO indices, not just one. - // - Four values? Some rules look at what's to the left of - // left, and some look at what's to the right of right. So - // keep track of this! - - let boundaries = []; - - let rightPos: number; - let lookaheadPos = 0; // lookahead, one scalar value to the right of right. - // Before the start of the string is also the start of the string. - let lookbehind: WordBreakProperty; - let left = WordBreakProperty.sot; - let right = WordBreakProperty.sot; - let lookahead = wordbreakPropertyAt(0); - // Count RIs to make sure we're not splitting emoji flags: - let nConsecutiveRegionalIndicators = 0; - - do { - // Shift all positions, one scalar value to the right. - rightPos = lookaheadPos; - lookaheadPos = positionAfter(lookaheadPos); - // Shift all properties, one scalar value to the right. - [lookbehind, left, right, lookahead] = - [left, right, lookahead, wordbreakPropertyAt(lookaheadPos)]; - - // Break at the start and end of text, unless the text is empty. - // WB1: Break at start of text... - if (left === WordBreakProperty.sot) { - boundaries.push(rightPos); - continue; - } - // WB2: Break at the end of text... - if (right === WordBreakProperty.eot) { - boundaries.push(rightPos); - break; // Reached the end of the string. We're done! - } - // WB3: Do not break within CRLF: - if (left === WordBreakProperty.CR && right === WordBreakProperty.LF) - continue; - // WB3b: Otherwise, break after... - if (left === WordBreakProperty.Newline || - left === WordBreakProperty.CR || - left === WordBreakProperty.LF) { - boundaries.push(rightPos); - continue; - } - // WB3a: ...and before newlines - if (right === WordBreakProperty.Newline || - right === WordBreakProperty.CR || - right === WordBreakProperty.LF) { - boundaries.push(rightPos); - continue; - } - - // TODO: WB3c is not implemented, due to its complex, error-prone - // implementation, requiring a ginormous regexp, and the fact that - // the only thing it does is prevent big emoji sequences from being - // split up, like 🧚🏼‍♂️ - // https://www.unicode.org/Public/emoji/12.0/emoji-zwj-sequences.txt - - // WB3d: Keep horizontal whitespace together - if (left === WordBreakProperty.WSegSpace && right == WordBreakProperty.WSegSpace) - continue; - - // WB4: Ignore format and extend characters - // This is to keep grapheme clusters together! - // See: Section 6.2: https://unicode.org/reports/tr29/#Grapheme_Cluster_and_Format_Rules - // N.B.: The rule about "except after sot, CR, LF, and - // Newline" already been by WB1, WB2, WB3a, and WB3b above. - while (right === WordBreakProperty.Format || - right === WordBreakProperty.Extend || - right === WordBreakProperty.ZWJ) { - // Continue advancing in the string, as if these - // characters do not exist. DO NOT update left and - // lookbehind however! - [rightPos, lookaheadPos] = [lookaheadPos, positionAfter(lookaheadPos)]; - [right, lookahead] = [lookahead, wordbreakPropertyAt(lookaheadPos)]; - } - // In ignoring the characters in the previous loop, we could - // have fallen off the end of the string, so end the loop - // prematurely if that happens! - if (right === WordBreakProperty.eot) { - boundaries.push(rightPos); - break; - } - // WB4 (continued): Lookahead must ALSO ignore these format, - // extend, ZWJ characters! - while (lookahead === WordBreakProperty.Format || - lookahead === WordBreakProperty.Extend || - lookahead === WordBreakProperty.ZWJ) { - // Continue advancing in the string, as if these - // characters do not exist. DO NOT update left and right, - // however! - lookaheadPos = positionAfter(lookaheadPos); - lookahead = wordbreakPropertyAt(lookaheadPos); - } - - // WB5: Do not break between most letters. - if (isAHLetter(left) && isAHLetter(right)) - continue; - // Do not break across certain punctuation - // WB6: (Don't break before apostrophes in contractions) - if (isAHLetter(left) && isAHLetter(lookahead) && - (right === WordBreakProperty.MidLetter || isMidNumLetQ(right))) - continue; - // WB7: (Don't break after apostrophes in contractions) - if (isAHLetter(lookbehind) && isAHLetter(right) && - (left === WordBreakProperty.MidLetter || isMidNumLetQ(left))) - continue; - // WB7a - if (left === WordBreakProperty.Hebrew_Letter && right === WordBreakProperty.Single_Quote) - continue; - // WB7b - if (left === WordBreakProperty.Hebrew_Letter && right === WordBreakProperty.Double_Quote && - lookahead === WordBreakProperty.Hebrew_Letter) - continue; - // WB7c - if (lookbehind === WordBreakProperty.Hebrew_Letter && left === WordBreakProperty.Double_Quote && - right === WordBreakProperty.Hebrew_Letter) - continue; - // Do not break within sequences of digits, or digits adjacent to letters. - // e.g., "3a" or "A3" - // WB8 - if (left === WordBreakProperty.Numeric && right === WordBreakProperty.Numeric) - continue; - // WB9 - if (isAHLetter(left) && right === WordBreakProperty.Numeric) - continue; - // WB10 - if (left === WordBreakProperty.Numeric && isAHLetter(right)) - continue; - // Do not break within sequences, such as 3.2, 3,456.789 - // WB11 - if (lookbehind === WordBreakProperty.Numeric && right === WordBreakProperty.Numeric && - (left === WordBreakProperty.MidNum || isMidNumLetQ(left))) - continue; - // WB12 - if (left === WordBreakProperty.Numeric && lookahead === WordBreakProperty.Numeric && - (right === WordBreakProperty.MidNum || isMidNumLetQ(right))) - continue; - // WB13: Do not break between Katakana - if (left === WordBreakProperty.Katakana && right === WordBreakProperty.Katakana) - continue; - // Do not break from extenders (e.g., U+202F NARROW NO-BREAK SPACE) - // WB13a - if ((isAHLetter(left) || - left === WordBreakProperty.Numeric || - left === WordBreakProperty.Katakana || - left === WordBreakProperty.ExtendNumLet) && - right === WordBreakProperty.ExtendNumLet) - continue; - // WB13b - if ((isAHLetter(right) || - right === WordBreakProperty.Numeric || - right === WordBreakProperty.Katakana) && left === WordBreakProperty.ExtendNumLet) - continue; - - // WB15 & WB16: - // Do not break within emoji flag sequences. That is, do not break between - // regional indicator (RI) symbols if there is an odd number of RI - // characters before the break point. - if (right === WordBreakProperty.Regional_Indicator) { - // Emoji flags are actually composed of TWO scalar values, each being a - // "regional indicator". These indicators correspond to Latin letters. Put - // two of them together, and they spell out an ISO 3166-1-alpha-2 country - // code. Since these always come in pairs, NEVER split the pairs! So, if - // we happen to be inside the middle of an odd numbered of - // Regional_Indicators, DON'T SPLIT IT! - nConsecutiveRegionalIndicators += 1; - if ((nConsecutiveRegionalIndicators % 2) == 1) { - continue; - } - } else { - nConsecutiveRegionalIndicators = 0; - } - // WB999: Otherwise, break EVERYWHERE (including around ideographs) - boundaries.push(rightPos); - } while (rightPos < text.length); - - return boundaries; - - ///// Internal utility functions ///// - - /** - * Returns the position of the start of the next scalar value. This jumps - * over surrogate pairs. - * - * If asked for the character AFTER the end of the string, this always - * returns the length of the string. - */ - function positionAfter(pos: number): number { - if (pos >= text.length) { - return text.length; - } else if (isStartOfSurrogatePair(text[pos])) { - return pos + 2; - } - return pos + 1; - } - - /** - * Return the value of the Word_Break property at the given string index. - * @param pos position in the text. - */ - function wordbreakPropertyAt(pos: number) { - if (pos < 0) { - return WordBreakProperty.sot; // Always "start of string" before the string starts! - } else if (pos >= text.length) { - return WordBreakProperty.eot; // Always "end of string" after the string ends! - } else if (isStartOfSurrogatePair(text[pos])) { - // Surrogate pairs the next TWO items from the string! - return property(text[pos] + text[pos + 1]); - } - return property(text[pos]); - } - - // Word_Break rule macros - // See: https://unicode.org/reports/tr29/#WB_Rule_Macros - function isAHLetter(prop: WordBreakProperty): boolean { - return prop === WordBreakProperty.ALetter || - prop === WordBreakProperty.Hebrew_Letter; - } - - function isMidNumLetQ(prop: WordBreakProperty): boolean { - return prop === WordBreakProperty.MidNumLet || - prop === WordBreakProperty.Single_Quote; - } - } - - function isStartOfSurrogatePair(character: string) { - let codeUnit = character.charCodeAt(0); - return codeUnit >= 0xD800 && codeUnit <= 0xDBFF; - } - - /** - * Return the Word_Break property value for a character. - * Note that - * @param character a scalar value - */ - function property(character: string): WordBreakProperty { - // This MUST be a scalar value. - // TODO: remove dependence on character.codepointAt()? - let codepoint = character.codePointAt(0) as number; - return searchForProperty(codepoint, 0, WORD_BREAK_PROPERTY.length - 1); - } - - /** - * Binary search for the word break property of a given CODE POINT. - * - * The auto-generated data.ts master array defines a **character range** - * lookup table. If a character's codepoint is equal to or greater than - * the I.Start value for an entry and exclusively less than the next entry, - * it falls in the first entry's range bucket and is classified accordingly - * by this method. - */ - function searchForProperty(codePoint: number, left: number, right: number): WordBreakProperty { - // All items that are not found in the array are assigned the 'Other' property. - if (right < left) { - return WordBreakProperty.Other; - } - - let midpoint = left + ~~((right - left) / 2); - let candidate = WORD_BREAK_PROPERTY[midpoint]; - - let nextRange = WORD_BREAK_PROPERTY[midpoint + 1]; - let startOfNextRange = nextRange ? nextRange[I.Start] : Infinity; - - if (codePoint < candidate[I.Start]) { - return searchForProperty(codePoint, left, midpoint - 1); - } else if (codePoint >= startOfNextRange) { - return searchForProperty(codePoint, midpoint + 1, right); - } - - // We found it! - return candidate[I.Value]; - } diff --git a/developer/src/kmc-package/src/compiler/kmx-keyboard-metadata.ts b/developer/src/kmc-package/src/compiler/kmx-keyboard-metadata.ts index 1fbefd7e940..75ada3a8acc 100644 --- a/developer/src/kmc-package/src/compiler/kmx-keyboard-metadata.ts +++ b/developer/src/kmc-package/src/compiler/kmx-keyboard-metadata.ts @@ -8,7 +8,8 @@ export function getCompiledKmxKeyboardMetadata(kmx: KMX.KEYBOARD): WebKeyboardMe keyboardName: getStoreFromKmx(kmx, KMX.KMXFile.TSS_NAME), keyboardVersion: getStoreFromKmx(kmx, KMX.KMXFile.TSS_KEYBOARDVERSION), minKeymanVersion: ((kmx.fileVersion & 0xFF00) >> 8).toString() + '.' + (kmx.fileVersion & 0xFF).toString(), - targets: getStoreFromKmx(kmx, KMX.KMXFile.TSS_TARGETS) ?? 'windows' + targets: getStoreFromKmx(kmx, KMX.KMXFile.TSS_TARGETS) ?? 'windows', + hasTouchLayout: !!getStoreFromKmx(kmx, KMX.KMXFile.TSS_LAYOUTFILE) }; } diff --git a/developer/src/kmc-package/src/compiler/messages.ts b/developer/src/kmc-package/src/compiler/messages.ts index c230c697723..9358882ad4f 100644 --- a/developer/src/kmc-package/src/compiler/messages.ts +++ b/developer/src/kmc-package/src/compiler/messages.ts @@ -2,7 +2,7 @@ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m const Namespace = CompilerErrorNamespace.PackageCompiler; const SevInfo = CompilerErrorSeverity.Info | Namespace; -// const SevHint = CompilerErrorSeverity.Hint | Namespace; +const SevHint = CompilerErrorSeverity.Hint | Namespace; const SevWarn = CompilerErrorSeverity.Warn | Namespace; const SevError = CompilerErrorSeverity.Error | Namespace; const SevFatal = CompilerErrorSeverity.Fatal | Namespace; @@ -116,5 +116,12 @@ export class CompilerMessages { `The keyboard ${o.id} should have at least one language specified.`); static WARN_KeyboardShouldHaveAtLeastOneLanguage = SevWarn | 0x001B; + static Hint_JsKeyboardFileHasNoTouchTargets = (o:{id:string}) => m(this.HINT_JsKeyboardFileHasNoTouchTargets, + `The keyboard ${o.id} has been included for touch platforms, but does not include a touch layout.`); + static HINT_JsKeyboardFileHasNoTouchTargets = SevHint | 0x001C; + + static Hint_PackageContainsSourceFile = (o:{filename:string}) => m(this.HINT_PackageContainsSourceFile, + `The source file ${o.filename} should not be included in the package; instead include the compiled result.`); + static HINT_PackageContainsSourceFile = SevHint | 0x001D; } diff --git a/developer/src/kmc-package/src/compiler/package-keyboard-target-validator.ts b/developer/src/kmc-package/src/compiler/package-keyboard-target-validator.ts index a79ec8f00a7..96cb23686e9 100644 --- a/developer/src/kmc-package/src/compiler/package-keyboard-target-validator.ts +++ b/developer/src/kmc-package/src/compiler/package-keyboard-target-validator.ts @@ -8,9 +8,14 @@ export class PackageKeyboardTargetValidator { public verifyAllTargets(kmp: KmpJsonFile.KmpJsonFile, metadata: KeyboardMetadataCollection): void { for(let keyboard of Object.keys(metadata)) { + let hasJS = true; + if(metadata[keyboard].data.targets) { - // get the targets from the .kmx - this.verifyTargets(metadata[keyboard].keyboard, metadata[keyboard].data.targets, kmp); + // get the targets from the .kmx (only the .kmx has the targets data) + hasJS = this.verifyTargets(metadata[keyboard].keyboard, metadata[keyboard].data.targets, kmp); + } + if(hasJS && !metadata[keyboard].data.hasTouchLayout) { + this.callbacks.reportMessage(CompilerMessages.Hint_JsKeyboardFileHasNoTouchTargets({id: metadata[keyboard].keyboard.id})); } } } @@ -23,7 +28,7 @@ export class PackageKeyboardTargetValidator { keyboard: KmpJsonFile.KmpJsonFileKeyboard, targetsText: string, kmp: KmpJsonFile.KmpJsonFile - ): void { + ): boolean { // Note, if we have gotten this far, we've already located and loaded a // .kmx, so no need to verify that the package includes a .kmx @@ -34,7 +39,12 @@ export class PackageKeyboardTargetValidator { if(!kmp.files.find(file => this.callbacks.path.basename(file.name, '.js') == keyboard.id)) { // .js version of the keyboard is not found, warn this.callbacks.reportMessage(CompilerMessages.Warn_JsKeyboardFileIsMissing({id: keyboard.id})); + return false; } + // A js file is included and targeted + return true; } + // js is not targeted + return false; } } \ No newline at end of file diff --git a/developer/src/kmc-package/src/compiler/package-validation.ts b/developer/src/kmc-package/src/compiler/package-validation.ts index 94e180a465e..f0463e8f532 100644 --- a/developer/src/kmc-package/src/compiler/package-validation.ts +++ b/developer/src/kmc-package/src/compiler/package-validation.ts @@ -1,4 +1,4 @@ -import { KmpJsonFile, CompilerCallbacks, CompilerOptions } from '@keymanapp/common-types'; +import { KmpJsonFile, CompilerCallbacks, CompilerOptions, KeymanFileTypes } from '@keymanapp/common-types'; import { CompilerMessages } from './messages.js'; import { keymanEngineForWindowsFiles, keymanForWindowsInstallerFiles, keymanForWindowsRedistFiles } from './redist-files.js'; @@ -167,15 +167,35 @@ export class PackageValidation { } private checkIfContentFileIsDangerous(file: KmpJsonFile.KmpJsonFileContentFile): boolean { - let filename = this.callbacks.path.basename(file.name).toLowerCase(); + const filename = this.callbacks.path.basename(file.name).toLowerCase(); + + // # Test for inclusion of redistributable files + if(keymanForWindowsInstallerFiles.includes(filename) || keymanForWindowsRedistFiles.includes(filename) || keymanEngineForWindowsFiles.includes(filename)) { this.callbacks.reportMessage(CompilerMessages.Warn_RedistFileShouldNotBeInPackage({filename})); } + + // # Test for inclusion of .doc or .docx files + if(filename.match(/\.doc(x?)$/)) { this.callbacks.reportMessage(CompilerMessages.Warn_DocFileDangerous({filename})); } + + // # Test for inclusion of keyboard source files + // + // We treat this as a hint, because it's not a dangerous problem, just + // something that suggests that perhaps they are trying to distribute the + // wrong files. + // + // Note: we allow .xml in the package because there are other files + // which may be valid, not just LDML keyboards + const fileType = KeymanFileTypes.sourceTypeFromFilename(file.name); + if(fileType !== null && fileType !== KeymanFileTypes.Source.LdmlKeyboard) { + this.callbacks.reportMessage(CompilerMessages.Hint_PackageContainsSourceFile({filename: file.name})); + } + return true; } diff --git a/developer/src/kmc-package/src/compiler/web-keyboard-metadata.ts b/developer/src/kmc-package/src/compiler/web-keyboard-metadata.ts index 5800163ff95..eed412df1e2 100644 --- a/developer/src/kmc-package/src/compiler/web-keyboard-metadata.ts +++ b/developer/src/kmc-package/src/compiler/web-keyboard-metadata.ts @@ -6,6 +6,7 @@ export interface WebKeyboardMetadata { isRtl: boolean; isMnemonic: boolean; targets?: string; + hasTouchLayout: boolean; }; /** @@ -24,12 +25,14 @@ export function getCompiledWebKeyboardMetadata(js: string): WebKeyboardMetadata const minverRegex = /this.KMINVER\s*=\s*([''"])(.*?)\1/; const rtlRegex = /this.KRTL\s*=\s*(.*?)\s*;/; const mnemonicRegex = /this.KM\s*=\s*(.*?)\s*;/; + const touchLayoutRegex = /this.KVKL\s*=\s*{/; const name = nameRegex.exec(js); const kbver = kbverRegex.exec(js); const minver = minverRegex.exec(js); const rtl = rtlRegex.exec(js); const mnemonic = mnemonicRegex.exec(js); + const touchLayout = touchLayoutRegex.exec(js); const SKeymanVersion70 = '7.0'; @@ -38,6 +41,7 @@ export function getCompiledWebKeyboardMetadata(js: string): WebKeyboardMetadata keyboardVersion: kbver ? kbver[2] : null, minKeymanVersion: minver ? minver[2] : SKeymanVersion70, isRtl: !!(rtl && rtl[1].match(/^(1|true)$/)), - isMnemonic: !!(mnemonic && mnemonic[1].match(/^(1|true)$/)) + isMnemonic: !!(mnemonic && mnemonic[1].match(/^(1|true)$/)), + hasTouchLayout: !!touchLayout }; } diff --git a/developer/src/kmc-package/test/fixtures/invalid/error_package_must_contain_a_model_or_a_keyboard.kps b/developer/src/kmc-package/test/fixtures/invalid/error_package_must_contain_a_model_or_a_keyboard.kps index 335201a6e5b..51b3e3f363d 100644 --- a/developer/src/kmc-package/test/fixtures/invalid/error_package_must_contain_a_model_or_a_keyboard.kps +++ b/developer/src/kmc-package/test/fixtures/invalid/error_package_must_contain_a_model_or_a_keyboard.kps @@ -10,12 +10,11 @@ - - khmer_angkor.kmn - Keyboard Khmer Angkor + + example.txt + Example text file 0 - .kmn + .txt diff --git a/developer/src/kmc-package/test/fixtures/invalid/example.txt b/developer/src/kmc-package/test/fixtures/invalid/example.txt new file mode 100644 index 00000000000..0f8c58ac580 --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/invalid/example.txt @@ -0,0 +1 @@ +This is a sample text file \ No newline at end of file diff --git a/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.js b/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.js new file mode 100644 index 00000000000..5a6fff14f71 --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.js @@ -0,0 +1 @@ +KeymanWeb.KR(new Keyboard_hint_js_keyboard_file_has_no_touch_targets());function Keyboard_hint_js_keyboard_file_has_no_touch_targets(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_hint_js_keyboard_file_has_no_touch_targets";this.KN="hint_js_keyboard_file_has_no_touch_targets";this.KMINVER="9.0";this.KV=null;this.KDU=0;this.KH='';this.KM=0;this.KBVER="1.0";this.KMBM=0x0;this.KVER="17.0.184.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;return r;};} \ No newline at end of file diff --git a/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.kmn b/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.kmn new file mode 100644 index 00000000000..f5919a61c73 --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.kmn @@ -0,0 +1,7 @@ +store(&name) 'hint_js_keyboard_file_has_no_touch_targets' +store(&keyboardversion) '1.0' +store(&targets) 'web' + +begin unicode > use(main) + +group(main) using keys \ No newline at end of file diff --git a/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.kps b/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.kps new file mode 100644 index 00000000000..0a24a29deb4 --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/invalid/hint_js_keyboard_file_has_no_touch_targets.kps @@ -0,0 +1,40 @@ + + + + 15.0.266.0 + 7.0 + + + + + + + + + + Khmer Angkor + © 2015-2022 SIL International + Makara Sok + + https://keyman.com/keyboards/khmer_angkor + + + + hint_js_keyboard_file_has_no_touch_targets.js + Keyboard + 0 + .js + + + + + hint_js_keyboard_file_has_no_touch_targets + hint_js_keyboard_file_has_no_touch_targets + 1.0 + + Central Khmer (Khmer, Cambodia) + + + + + diff --git a/developer/src/kmc-package/test/fixtures/invalid/hint_source_file_should_not_be_in_package.kps b/developer/src/kmc-package/test/fixtures/invalid/hint_source_file_should_not_be_in_package.kps new file mode 100644 index 00000000000..8de72f2a829 --- /dev/null +++ b/developer/src/kmc-package/test/fixtures/invalid/hint_source_file_should_not_be_in_package.kps @@ -0,0 +1,38 @@ + + + + 15.0.266.0 + 7.0 + + + SENĆOŦEN (Saanich Dialect) Keyboard + © 2019 National Research Council Canada + Eddie Antonio Santos + 1.0 + + + + basic.kmx + Keyboard Basic + 0 + .kmx + + + + basic.kmn + Keyboard Source Basic + 0 + .kmn + + + + + Basic + basic + 1.0 + + Khmer + + + + diff --git a/developer/src/kmc-package/test/fixtures/invalid/my_file.PDF b/developer/src/kmc-package/test/fixtures/invalid/my_file.PDF new file mode 100644 index 00000000000..8f8a5ee09e0 Binary files /dev/null and b/developer/src/kmc-package/test/fixtures/invalid/my_file.PDF differ diff --git a/developer/src/kmc-package/test/test-messages.ts b/developer/src/kmc-package/test/test-messages.ts index e1d463dc4f2..019ee24852f 100644 --- a/developer/src/kmc-package/test/test-messages.ts +++ b/developer/src/kmc-package/test/test-messages.ts @@ -128,6 +128,13 @@ describe('CompilerMessages', function () { CompilerMessages.WARN_FileInPackageDoesNotFollowFilenameConventions, {checkFilenameConventions: true}); }); + // Test the inverse -- no warning generated if checkFilenameConventions is false + + it('should not generate WARN_FileInPackageDoesNotFollowFilenameConventions if content filename has wrong conventions but checkFilenameConventions is false', async function() { + testForMessage(this, ['invalid', 'warn_file_in_package_does_not_follow_filename_conventions.kps'], null, {checkFilenameConventions: false}); + testForMessage(this, ['invalid', 'warn_file_in_package_does_not_follow_filename_conventions_2.kps'], null, {checkFilenameConventions: false}); + }); + // ERROR_PackageNameCannotBeBlank it('should generate ERROR_PackageNameCannotBeBlank if package info has empty name', async function() { @@ -182,7 +189,7 @@ describe('CompilerMessages', function () { // ERROR_PackageMustContainAPackageOrAKeyboard - it('should generate ERROR_PackageMustContainAModelOrAKeyboard if package contains a .doc file', async function() { + it('should generate ERROR_PackageMustContainAModelOrAKeyboard if package contains no keyboard or model', async function() { testForMessage(this, ['invalid', 'error_package_must_contain_a_model_or_a_keyboard.kps'], CompilerMessages.ERROR_PackageMustContainAModelOrAKeyboard); }); @@ -201,4 +208,22 @@ describe('CompilerMessages', function () { CompilerMessages.WARN_KeyboardShouldHaveAtLeastOneLanguage); }); + // HINT_JsKeyboardFileHasNoTouchTargets + + it('should generate HINT_JsKeyboardFileHasNoTouchTargets if keyboard has no touch targets', async function() { + testForMessage(this, ['invalid', 'hint_js_keyboard_file_has_no_touch_targets.kps'], + CompilerMessages.HINT_JsKeyboardFileHasNoTouchTargets); + }); + + it('should not generate HINT_JsKeyboardFileHasNoTouchTargets if keyboard has a touch target', async function() { + testForMessage(this, ['khmer_angkor', 'source', 'khmer_angkor.kps'], null); + }); + + // HINT_PackageContainsSourceFile + + it('should generate HINT_PackageContainsSourceFile if package contains a source file', async function() { + testForMessage(this, ['invalid', 'hint_source_file_should_not_be_in_package.kps'], + CompilerMessages.HINT_PackageContainsSourceFile); + }); + }); diff --git a/developer/src/kmc/build.sh b/developer/src/kmc/build.sh index e7c809419ef..137098d6c42 100755 --- a/developer/src/kmc/build.sh +++ b/developer/src/kmc/build.sh @@ -74,9 +74,10 @@ fi if builder_start_action test; then eslint . tsc --build test/ - mocha - # TODO: enable c8 (disabled because no coverage at present) - # && c8 --reporter=lcov --reporter=text mocha + readonly C8_THRESHOLD=35 + c8 --reporter=lcov --reporter=text --lines $C8_THRESHOLD --statements $C8_THRESHOLD --branches $C8_THRESHOLD --functions $C8_THRESHOLD mocha + builder_echo warning "Coverage thresholds are currently $C8_THRESHOLD%, which is lower than ideal." + builder_echo warning "Please increase threshold in build.sh as test coverage improves." builder_finish_action success test fi diff --git a/developer/src/kmc/src/commands/build.ts b/developer/src/kmc/src/commands/build.ts index 1047dd8208c..62fbb95031c 100644 --- a/developer/src/kmc/src/commands/build.ts +++ b/developer/src/kmc/src/commands/build.ts @@ -129,6 +129,9 @@ async function build(filename: string, parentCallbacks: NodeCompilerCallbacks, o : InfrastructureMessages.Info_FileBuiltSuccessfully({filename:buildFilename}) ); } else { + if(!callbacks.hasFailureMessage(false)) { // false == check only for error+fatal messages + callbacks.reportMessage(InfrastructureMessages.Info_WarningsHaveFailedBuild()); + } callbacks.reportMessage(builder instanceof BuildProject ? InfrastructureMessages.Info_ProjectNotBuiltSuccessfully({filename:buildFilename}) : InfrastructureMessages.Info_FileNotBuiltSuccessfully({filename:buildFilename}) diff --git a/developer/src/kmc/src/messages/infrastructureMessages.ts b/developer/src/kmc/src/messages/infrastructureMessages.ts index ee828dae751..25032152a50 100644 --- a/developer/src/kmc/src/messages/infrastructureMessages.ts +++ b/developer/src/kmc/src/messages/infrastructureMessages.ts @@ -71,5 +71,9 @@ export class InfrastructureMessages { static Error_NotAProjectFile = (o:{filename:string}) => m(this.ERROR_NotAProjectFile, `File ${o.filename} must have a .kpj extension to be treated as a project.`); static ERROR_NotAProjectFile = SevError | 0x000F; + + static Info_WarningsHaveFailedBuild = () => m(this.INFO_WarningsHaveFailedBuild, + `The build failed because option "treat warnings as errors" is enabled and there are one or more warnings.`); + static INFO_WarningsHaveFailedBuild = SevInfo | 0x0010; } diff --git a/developer/src/kmc/test/test-infrastructureMessages.ts b/developer/src/kmc/test/test-infrastructureMessages.ts index a9b55d075df..fde352f3dd3 100644 --- a/developer/src/kmc/test/test-infrastructureMessages.ts +++ b/developer/src/kmc/test/test-infrastructureMessages.ts @@ -6,6 +6,7 @@ import { makePathToFixture } from './helpers/index.js'; import { NodeCompilerCallbacks } from '../src/util/NodeCompilerCallbacks.js'; import { CompilerErrorNamespace } from '@keymanapp/common-types'; import { unitTestEndpoints } from '../src/commands/build.js'; +import { KmnCompilerMessages } from '@keymanapp/kmc-kmn'; describe('InfrastructureMessages', function () { it('should have a valid InfrastructureMessages object', function() { @@ -65,4 +66,22 @@ describe('InfrastructureMessages', function () { assert.isTrue(ncb.hasMessage(InfrastructureMessages.HINT_FilenameHasDifferingCase), `HINT_FilenameHasDifferingCase not generated, instead got: `+JSON.stringify(ncb.messages,null,2)); }); + + // INFO_WarningsHaveFailedBuild + + it('should generate INFO_WarningsHaveFailedBuild if only warnings failed the build', async function() { + // NOTE: we can probably re-use this format for most other message tests in the future + const ncb = new NodeCompilerCallbacks({logLevel: 'silent'}); + const filename = makePathToFixture('compiler-warnings-as-errors', 'keyboard.kmn'); + const expectedMessages = [ + InfrastructureMessages.INFO_BuildingFile, + KmnCompilerMessages.WARN_HeaderStatementIsDeprecated, + InfrastructureMessages.INFO_WarningsHaveFailedBuild, + InfrastructureMessages.INFO_FileNotBuiltSuccessfully + ]; + await unitTestEndpoints.build(filename, ncb, {compilerWarningsAsErrors: true}); + assert.deepEqual(ncb.messages.map(m => m.code), expectedMessages, + `actual callbacks.messages:\n${JSON.stringify(ncb.messages,null,2)}\n\n`+ + `did not match expected:\n${JSON.stringify(expectedMessages,null,2)}\n\n`); + }); }); diff --git a/developer/src/kmc/tsconfig.kmc-base.json b/developer/src/kmc/tsconfig.kmc-base.json index f8cff50b3fa..6956b6e05db 100644 --- a/developer/src/kmc/tsconfig.kmc-base.json +++ b/developer/src/kmc/tsconfig.kmc-base.json @@ -1,3 +1,3 @@ { - "extends": "../../../tsconfig.esm-base.json", + "extends": "../../../tsconfig.base.json", } diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index 02990bc3248..3634d5d5d8b 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -1029,6 +1029,8 @@ KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE else if (u16ncmp(p, u"10.0", 4) == 0) fk->version = VERSION_100; else if (u16ncmp(p, u"14.0", 4) == 0) fk->version = VERSION_140; // Adds support for #917 -- context() with notany() for KeymanWeb else if (u16ncmp(p, u"15.0", 4) == 0) fk->version = VERSION_150; // Adds support for U_xxxx_yyyy #2858 + else if (u16ncmp(p, u"16.0", 4) == 0) fk->version = VERSION_160; // KMXPlus + else if (u16ncmp(p, u"17.0", 4) == 0) fk->version = VERSION_170; // Flicks and gestures else return CERR_InvalidVersion; @@ -1058,7 +1060,7 @@ KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE u16ncpy(q, pp2, u16len(pp2) + 1); // Change compiled reference file extension to .kvk - pp2 = ( km_kbp_cp *) u16chr(q, 0) - 5; + pp2 = ( km_core_cp *) u16chr(q, 0) - 5; if (pp2 > q && u16icmp(pp2, u".kvks") == 0) { pp2[4] = 0; } diff --git a/developer/src/server/Makefile b/developer/src/server/Makefile index 0a580ea3d6a..9c865755740 100644 --- a/developer/src/server/Makefile +++ b/developer/src/server/Makefile @@ -5,7 +5,7 @@ !include ..\Defines.mak build: .virtual - $(GIT_BASH_FOR_KEYMAN) build.sh --production --test + $(GIT_BASH_FOR_KEYMAN) build.sh configure build test installer clean: .virtual #TODO: move to build.sh `clean` target @@ -14,7 +14,10 @@ clean: .virtual -del tsconfig.tsbuildinfo signcode: - @rem nothing to do + $(SIGNCODE) /d "Keyman Developer" $(DEVELOPER_PROGRAM)\server\dist\win32\console\node-hide-console-window.node + $(SIGNCODE) /d "Keyman Developer" $(DEVELOPER_PROGRAM)\server\dist\win32\console\node-hide-console-window.x64.node + $(SIGNCODE) /d "Keyman Developer" $(DEVELOPER_PROGRAM)\server\dist\win32\trayicon\addon.node + $(SIGNCODE) /d "Keyman Developer" $(DEVELOPER_PROGRAM)\server\dist\win32\trayicon\addon.x64.node wrap-symbols: @rem nothing to do diff --git a/developer/src/server/build-addins.inc.sh b/developer/src/server/build-addins.inc.sh index cce1e9ae6f0..d48d44d1e74 100644 --- a/developer/src/server/build-addins.inc.sh +++ b/developer/src/server/build-addins.inc.sh @@ -11,7 +11,7 @@ isNodeX64() { # [[ $(file -b "$(which node)" | grep x86-64) ]] && echo 1 || echo 0 } -build_addins() { +do_build_addins() { local NODEX64=$(isNodeX64) local ARCH=x64 local TRAYICON_TARGET=addon.x64.node @@ -29,8 +29,13 @@ build_addins() { echo "TRAYICON_TARGET=$TRAYICON_TARGET" echo "HIDECONSOLE_TARGET=$HIDECONSOLE_TARGET" - HIDECONSOLE_TARGET="$KEYMAN_ROOT/developer/src/server/src/win32/console/$HIDECONSOLE_TARGET" - TRAYICON_TARGET="$KEYMAN_ROOT/developer/src/server/src/win32/trayicon/$TRAYICON_TARGET" + local HIDECONSOLE_SRC_TARGET="$KEYMAN_ROOT/developer/src/server/src/win32/console/$HIDECONSOLE_TARGET" + local HIDECONSOLE_BIN_TARGET="$KEYMAN_ROOT/developer/src/server/build/src/win32/console/$HIDECONSOLE_TARGET" + local TRAYICON_SRC_TARGET="$KEYMAN_ROOT/developer/src/server/src/win32/trayicon/$TRAYICON_TARGET" + local TRAYICON_BIN_TARGET="$KEYMAN_ROOT/developer/src/server/build/src/win32/trayicon/$TRAYICON_TARGET" + + mkdir -p "$(dirname "$HIDECONSOLE_BIN_TARGET")" + mkdir -p "$(dirname "$TRAYICON_BIN_TARGET")" # # Build node-windows-trayicon @@ -39,7 +44,8 @@ build_addins() { pushd "$KEYMAN_ROOT/node_modules/node-windows-trayicon" rm -rf build npx node-gyp clean configure build --arch=$ARCH --silent - cp build/Release/addon.node "$TRAYICON_TARGET" + cp build/Release/addon.node "$TRAYICON_SRC_TARGET" + cp build/Release/addon.node "$TRAYICON_BIN_TARGET" popd # @@ -49,7 +55,8 @@ build_addins() { pushd "$KEYMAN_ROOT/node_modules/hetrodo-node-hide-console-window-napi" rm -rf build npx node-gyp clean configure build --arch=$ARCH --silent - cp build/Release/node-hide-console-window.node "$HIDECONSOLE_TARGET" + cp build/Release/node-hide-console-window.node "$HIDECONSOLE_SRC_TARGET" + cp build/Release/node-hide-console-window.node "$HIDECONSOLE_BIN_TARGET" popd # @@ -57,10 +64,10 @@ build_addins() { # if (( NODEX64 )); then - [[ $(isFileX64 "$TRAYICON_TARGET") == 1 ]] || builder_die "$TRAYICON_TARGET should be 64-bit" - [[ $(isFileX64 "$HIDECONSOLE_TARGET") == 1 ]] || builder_die "$HIDECONSOLE_TARGET should be 64-bit" + [[ $(isFileX64 "$TRAYICON_BIN_TARGET") == 1 ]] || builder_die "$TRAYICON_TARGET should be 64-bit" + [[ $(isFileX64 "$HIDECONSOLE_BIN_TARGET") == 1 ]] || builder_die "$HIDECONSOLE_TARGET should be 64-bit" else - [[ $(isFileX64 "$TRAYICON_TARGET") == 0 ]] || builder_die "$TRAYICON_TARGET should not be 64-bit" - [[ $(isFileX64 "$HIDECONSOLE_TARGET") == 0 ]] || builder_die "$HIDECONSOLE_TARGET should not be 64-bit" + [[ $(isFileX64 "$TRAYICON_BIN_TARGET") == 0 ]] || builder_die "$TRAYICON_TARGET should not be 64-bit" + [[ $(isFileX64 "$HIDECONSOLE_BIN_TARGET") == 0 ]] || builder_die "$HIDECONSOLE_TARGET should not be 64-bit" fi } diff --git a/developer/src/server/build.sh b/developer/src/server/build.sh index c735e26fecb..51523c52a3e 100755 --- a/developer/src/server/build.sh +++ b/developer/src/server/build.sh @@ -1,10 +1,4 @@ #!/usr/bin/env bash -# -# Compiles Keyman Developer Server for deployment -# - -# Exit on command failure and when using unset variables: -set -eu ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary @@ -16,121 +10,68 @@ EX_USAGE=64 . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" . "$KEYMAN_ROOT/resources/build/jq.inc.sh" -pushd "$(dirname "$THIS_SCRIPT")" - -# Build the main script. -build () { - npm run build || builder_die "Could not build top-level JavaScript file." +cd "$THIS_SCRIPT_PATH" + +builder_describe "Build Keyman Developer Server" \ + @/common/web/keyman-version \ + @/web \ + clean \ + configure \ + build \ + test \ + "installer Prepare for Keyman Developer installer" \ + "publish Publish to NPM" \ + ":server Keyman Developer Server main program" \ + ":addins Windows addins for GUI integration" + +builder_describe_internal_dependency \ + publish:server build:server \ + publish:server build:addins + +builder_describe_outputs \ + configure:server /node_modules \ + configure:addins /node_modules \ + build:server /developer/src/server/build/src/index.js \ + build:addins /developer/src/server/build/src/win32/trayicon/addon.node + +builder_parse "$@" + +#------------------------------------------------------------------------------------------------------------------- + +function clean_server() { + rm -rf "$THIS_SCRIPT_PATH/build" + rm -rf "$THIS_SCRIPT_PATH/node_modules" + rm -rf "$THIS_SCRIPT_PATH/tsconfig.tsbuildinfo" + rm -rf "$THIS_SCRIPT_PATH/src/site/resource" + + # No longer in use, cleanup from previous versions: + rm -rf "$THIS_SCRIPT_PATH/dist" } -display_usage ( ) { - echo "Usage: $0 [--production|--watch] [--test|--tdd]" - echo " $0 --help" - echo - echo " --help displays this screen and exits" - echo " --production, -p builds production release in /developer/bin/server/" - echo " --skip-package-install, -S don't run npm install (not valid with --production)" - echo " --test, -t runs unit tests after building" - #echo " --watch, -w builds dev server in watch mode" - echo " --tdd runs unit tests WITHOUT building" - echo " --no-build-addins don't build/copy Win32 addins" - echo " --no-build-kmw don't build KeymanWeb" - echo " --no-copy-kmw don't copy KeymanWeb" -} - -################################ Main script ################################ - -run_tests=0 -production=0 -build=1 -install_dependencies=1 -build_keymanweb=1 -copy_keymanweb=1 -build_addins=1 - -# Process command-line arguments -while [[ $# -gt 0 ]] ; do - key="$1" - case $key in - --help|-h|-?) - display_usage - exit - ;; - --production|-p) - production=1 - ;; - --skip-package-install|-S) - install_dependencies=0 - ;; - --no-build-kmw) - build_keymanweb=0 - ;; - --no-build-addins) - build_addins=0 - ;; - --no-copy-kmw) - copy_keymanweb=0 - ;; - --test) - run_tests=1 - ;; - --tdd) - run_tests=1 - build=0 - install_dependencies=0 - ;; - *) - echo "$0: invalid option: $key" - display_usage - exit $EX_USAGE - esac - shift # past the processed argument -done - -# ---------------------------------------- -# Install dependencies -# ---------------------------------------- - -# Check if Node.JS/npm is installed. -type npm >/dev/null ||\ - builder_die "Build environment setup error detected! Please ensure Node.js is installed!" - -if (( install_dependencies )) ; then +function configure_server() { verify_npm_setup # See https://github.com/bubenshchykov/ngrok/issues/254, https://github.com/bubenshchykov/ngrok/pull/255 # TODO: this is horrible; is there a way we can avoid this? rm -f "$KEYMAN_ROOT"/node_modules/ngrok/bin/ngrok.exe -fi - -# ---------------------------------------- -# Rebuild and bundle addins -# ---------------------------------------- +} -if (( build_addins )); then - . ./build-addins.inc.sh +function build_addins() { + # Rebuild and bundle addins + source ./build-addins.inc.sh # If we have an x64 version of node installed if [[ $(isNodeX64) ]]; then - build_addins + do_build_addins fi # Build with the Keyman Developer x86 version of node - PATH="$KEYMAN_ROOT/developer/src/inst/node/dist:$PATH" build_addins -fi - -# ---------------------------------------- -# Build and bundle KeymanWeb -# ---------------------------------------- - -if (( build_keymanweb )); then - pushd "$KEYMAN_ROOT/web/" - ./build.sh build --debug - popd -fi + PATH="$KEYMAN_ROOT/developer/src/inst/node/dist:$PATH" do_build_addins +} -if (( copy_keymanweb )); then - WEB_SRC="$KEYMAN_ROOT/web/build/publish/debug" - DST="$(dirname "$THIS_SCRIPT")/src/site/resource" +function build_server() { + # Copy keymanweb build artifacts + local WEB_SRC="$KEYMAN_ROOT/web/build/publish/debug" + local DST="$THIS_SCRIPT_PATH/src/site/resource" rm -rf "$DST" mkdir -p "$DST/osk" @@ -140,33 +81,26 @@ if (( copy_keymanweb )); then cp -R "$WEB_SRC/ui/"* "$DST/ui/" cp "$KEYMAN_ROOT/web/LICENSE" "$DST/" cp "$KEYMAN_ROOT/web/README.md" "$DST/" -fi - -# ---------------------------------------- -# Build the project -# ---------------------------------------- -npm run build || builder_die "Compilation failed." -echo "Typescript compilation successful." + # Build server + tsc --build -# ---------------------------------------- -# Unit tests -# ---------------------------------------- + # Post build + mkdir -p "$THIS_SCRIPT_PATH/build/src/site/" + mkdir -p "$THIS_SCRIPT_PATH/build/src/win32/" + cp -r "$THIS_SCRIPT_PATH/src/site/"** "$THIS_SCRIPT_PATH/build/src/site/" + cp -r "$THIS_SCRIPT_PATH/src/win32/"** "$THIS_SCRIPT_PATH/build/src/win32/" -if (( run_tests )); then - npm test || builder_die "Tests failed" -fi - -# ---------------------------------------- -# Deploy to dist/ -# ---------------------------------------- + replaceVersionStrings "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js.in" "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js" + rm "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js.in" +} -if (( production )) ; then +function installer_server() { # We need to build in a tmp folder so that npm doesn't get confused by our # monorepo setup, and so we can copy the relevant node_modules in, because # we'll need them in order to build the deployable version. - PRODBUILDTEMP=`mktemp -d` + local PRODBUILDTEMP=`mktemp -d` echo "Preparing in $PRODBUILDTEMP" # Remove @keymanapp devDependencies because they won't install outside the # monorepo context @@ -180,14 +114,35 @@ if (( production )) ; then rm -f node_modules/ngrok/bin/ngrok.exe popd - # @keymanapp/keyman-version is required in dist now but we need to copy it in manually + # @keymanapp/keyman-version is required in build/ now but we need to copy it in manually mkdir -p "$PRODBUILDTEMP/node_modules/@keymanapp/" cp -R "$KEYMAN_ROOT/node_modules/@keymanapp/keyman-version/" "$PRODBUILDTEMP/node_modules/@keymanapp/" # We'll build in the $KEYMAN_ROOT/developer/bin/server/ folder rm -rf "$KEYMAN_ROOT/developer/bin/server/" - mkdir -p "$KEYMAN_ROOT/developer/bin/server/dist/" - cp -R dist/* "$KEYMAN_ROOT/developer/bin/server/dist/" + mkdir -p "$KEYMAN_ROOT/developer/bin/server/build/" + cp -R build/* "$KEYMAN_ROOT/developer/bin/server/build/" cp -R "$PRODBUILDTEMP"/* "$KEYMAN_ROOT/developer/bin/server/" rm -rf "$PRODBUILDTEMP" -fi +} + +function test_server() { + # eslint . + tsc --build test + # c8 --reporter=lcov --reporter=text + mocha +} + +builder_run_action clean:server clean_server +builder_run_action configure:server configure_server +builder_run_action build:server build_server +builder_run_action build:addins build_addins +builder_run_action test:server test_server +# builder_run_action test:addins # no op +builder_run_action installer:server installer_server + +# TODO: consider 'watch' +# function watch_server() { +# tsc-watch --onSuccess "node --inspect ." --onFailure "node --inspect ." +# } +# builder_run_action watch:server watch_server diff --git a/developer/src/server/package.json b/developer/src/server/package.json index dd779db1a4d..fbba3454395 100644 --- a/developer/src/server/package.json +++ b/developer/src/server/package.json @@ -1,13 +1,11 @@ { "name": "@keymanapp/developer-server", "description": "Keyman Developer backend server", - "main": "dist/index.js", + "main": "build/src/index.js", + "type": "module", "scripts": { - "build": "tsc -b", - "postbuild": "npx gosh ./postbuild.sh", - "prod": "node .", - "test": "mocha", - "watch": "npm run postbuild && tsc-watch --onSuccess \"node --inspect .\" --onFailure \"node --inspect .\"" + "build": "npx gosh ./build.sh build", + "test": "npx gosh ./build.sh test" }, "license": "MIT", "dependencies": { @@ -24,13 +22,13 @@ "node-windows-trayicon": "keymanapp/node-windows-trayicon#keyman-16.0" }, "devDependencies": { - "@keymanapp/resources-gosh": "*", "@keymanapp/keyman-version": "*", + "@keymanapp/resources-gosh": "*", "@types/chai": "^4.3.0", "@types/express": "^4.17.13", "@types/mocha": "^9.1.0", "@types/multer": "^1.4.7", - "@types/node": "^17.0.0", + "@types/node": "^20.4.1", "@types/ws": "^8.2.2", "chai": "^4.3.4", "copyfiles": "^2.4.1", @@ -41,6 +39,6 @@ }, "mocha": { "require": "ts-node/register", - "spec": "**/*.test.ts" + "spec": "build/**/*.test.js" } } diff --git a/developer/src/server/postbuild.sh b/developer/src/server/postbuild.sh deleted file mode 100755 index e4b90e7e50b..00000000000 --- a/developer/src/server/postbuild.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -# -# postbuild script run by npm during/after a build -# - -# Exit on command failure and when using unset variables: -set -eu - -## START STANDARD BUILD SCRIPT INCLUDE -# adjust relative paths as necessary -THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" -. "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" -## END STANDARD BUILD SCRIPT INCLUDE - -. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" - -LOCAL_ROOT="$(dirname "$THIS_SCRIPT")" - -mkdir -p "$LOCAL_ROOT/dist/site/" -mkdir -p "$LOCAL_ROOT/dist/win32/" -cp -r "$LOCAL_ROOT/src/site/"** "$LOCAL_ROOT/dist/site/" -cp -r "$LOCAL_ROOT/src/win32/"** "$LOCAL_ROOT/dist/win32/" - -replaceVersionStrings "$LOCAL_ROOT/dist/site/lib/sentry/init.js.in" "$LOCAL_ROOT/dist/site/lib/sentry/init.js" -rm "$LOCAL_ROOT/dist/site/lib/sentry/init.js.in" diff --git a/developer/src/server/src/config.ts b/developer/src/server/src/config.ts index 5c67cd8c7e5..6197cde05aa 100644 --- a/developer/src/server/src/config.ts +++ b/developer/src/server/src/config.ts @@ -1,4 +1,4 @@ -import fs = require('fs'); +import * as fs from 'fs'; export class Configuration { public readonly appDataPath: string; diff --git a/developer/src/server/src/data.ts b/developer/src/server/src/data.ts index fcc750495d7..58763f07013 100644 --- a/developer/src/server/src/data.ts +++ b/developer/src/server/src/data.ts @@ -1,5 +1,5 @@ -import fs = require('fs'); -import { configuration } from './config'; +import * as fs from 'fs'; +import { configuration } from './config.js'; export interface DebugObject { id: string; diff --git a/developer/src/server/src/environment.ts b/developer/src/server/src/environment.ts index be359f81d32..f3e05660245 100644 --- a/developer/src/server/src/environment.ts +++ b/developer/src/server/src/environment.ts @@ -1,5 +1,5 @@ -import { extractVersionData } from './version-data'; +import { extractVersionData } from './version-data.js'; // TODO: environment should be just KEYMAN_VERSION -const KEYMAN_VERSION = require("@keymanapp/keyman-version").KEYMAN_VERSION; +import KEYMAN_VERSION from "@keymanapp/keyman-version"; export const environment = extractVersionData(KEYMAN_VERSION.VERSION_WITH_TAG); diff --git a/developer/src/server/src/handlers/api/debugobject/get.ts b/developer/src/server/src/handlers/api/debugobject/get.ts index 3da2896d556..a701ca3a8f3 100644 --- a/developer/src/server/src/handlers/api/debugobject/get.ts +++ b/developer/src/server/src/handlers/api/debugobject/get.ts @@ -1,6 +1,6 @@ -import chalk = require('chalk'); -import express = require('express'); -import { DebugObject, isValidId, simplifyId } from "../../../data"; +import * as express from 'express'; +import chalk from 'chalk'; +import { DebugObject, isValidId, simplifyId } from "../../../data.js"; export default function apiGet (data: { [id: string]: DebugObject }, req: express.Request, res: express.Response, next: express.NextFunction) { let id = req.query['id'] as string; diff --git a/developer/src/server/src/handlers/api/debugobject/register.ts b/developer/src/server/src/handlers/api/debugobject/register.ts index 9b52b577d88..a1f7a72cd4c 100644 --- a/developer/src/server/src/handlers/api/debugobject/register.ts +++ b/developer/src/server/src/handlers/api/debugobject/register.ts @@ -1,9 +1,9 @@ -import express = require('express'); -import { DebugObject, isValidId, simplifyId } from "../../../data"; -import fs = require('fs'); -import crypto = require('crypto'); -import { configuration } from '../../../config'; -import chalk = require('chalk'); +import * as express from 'express'; +import { DebugObject, isValidId, simplifyId } from "../../../data.js"; +import * as fs from 'fs'; +import * as crypto from 'crypto'; +import { configuration } from '../../../config.js'; +import chalk from 'chalk'; // We allow only 12 objects of each type in the cache const MAX_OBJECTS = 12; diff --git a/developer/src/server/src/handlers/api/debugobject/unregister.ts b/developer/src/server/src/handlers/api/debugobject/unregister.ts index 6473c2edbde..59a846d135d 100644 --- a/developer/src/server/src/handlers/api/debugobject/unregister.ts +++ b/developer/src/server/src/handlers/api/debugobject/unregister.ts @@ -1,7 +1,7 @@ -import express = require('express'); -import { DebugObject, isValidId, simplifyId } from "../../../data"; -import fs = require('fs'); -import chalk = require('chalk'); +import * as express from 'express'; +import { DebugObject, isValidId, simplifyId } from "../../../data.js"; +import * as fs from 'fs'; +import chalk from 'chalk'; export default function apiUnregister (root:{ [id: string]: O }, req: express.Request, res: express.Response, next: express.NextFunction) { let id = req.body['id']; diff --git a/developer/src/server/src/handlers/api/font/register.ts b/developer/src/server/src/handlers/api/font/register.ts index 14d60e8e12f..8da3646a63f 100644 --- a/developer/src/server/src/handlers/api/font/register.ts +++ b/developer/src/server/src/handlers/api/font/register.ts @@ -1,6 +1,6 @@ -import chalk = require('chalk'); -import express = require('express'); -import { data, DebugFont, simplifyId } from "../../../data"; +import chalk from 'chalk'; +import * as express from 'express'; +import { data, DebugFont, simplifyId } from "../../../data.js"; export default function apiKeyboardRegister (req: express.Request, res: express.Response, next: express.NextFunction) { const id = simplifyId(req.body['id']); diff --git a/developer/src/server/src/handlers/api/keyboard/register.ts b/developer/src/server/src/handlers/api/keyboard/register.ts index 02bdd3dde71..bb89d7b4c30 100644 --- a/developer/src/server/src/handlers/api/keyboard/register.ts +++ b/developer/src/server/src/handlers/api/keyboard/register.ts @@ -1,6 +1,6 @@ -import chalk = require('chalk'); -import express = require('express'); -import { data, DebugKeyboard } from "../../../data"; +import chalk from 'chalk'; +import * as express from 'express'; +import { data, DebugKeyboard } from "../../../data.js"; export default function apiKeyboardRegister (req: express.Request, res: express.Response, next: express.NextFunction) { const keyboard: DebugKeyboard = data.keyboards[req.body['id']]; diff --git a/developer/src/server/src/handlers/api/package/register.ts b/developer/src/server/src/handlers/api/package/register.ts index c21340c7fe7..cf6e2388468 100644 --- a/developer/src/server/src/handlers/api/package/register.ts +++ b/developer/src/server/src/handlers/api/package/register.ts @@ -1,6 +1,6 @@ -import chalk = require('chalk'); -import express = require('express'); -import { data, DebugPackage } from "../../../data"; +import chalk from 'chalk'; +import * as express from 'express'; +import { data, DebugPackage } from "../../../data.js"; export default function apiPackageRegister (req: express.Request, res: express.Response, next: express.NextFunction) { const kmp: DebugPackage = data.packages[req.body['id']]; diff --git a/developer/src/server/src/handlers/inc/keyboards-css.ts b/developer/src/server/src/handlers/inc/keyboards-css.ts index 9302fd11648..ed4cc7e15b8 100644 --- a/developer/src/server/src/handlers/inc/keyboards-css.ts +++ b/developer/src/server/src/handlers/inc/keyboards-css.ts @@ -1,6 +1,6 @@ -import express = require('express'); -import path = require('path'); -import { data, SiteData } from "../../data"; +import * as express from 'express'; +import * as path from 'path'; +import { data, SiteData } from "../../data.js"; export default function handleIncKeyboardsCss (req: express.Request, res: express.Response) { let headers = {"Content-Type": "text/css"}; diff --git a/developer/src/server/src/handlers/inc/keyboards-js.ts b/developer/src/server/src/handlers/inc/keyboards-js.ts index ee09fa0f377..3c42702bf95 100644 --- a/developer/src/server/src/handlers/inc/keyboards-js.ts +++ b/developer/src/server/src/handlers/inc/keyboards-js.ts @@ -1,5 +1,5 @@ -import express = require('express'); -import { SiteData, data } from "../../data"; +import * as express from 'express'; +import { SiteData, data } from "../../data.js"; export default function handleIncKeyboardsJs (req: express.Request, res: express.Response) { let headers = {"Content-Type": "application/javascript"}; diff --git a/developer/src/server/src/handlers/inc/packages-json.ts b/developer/src/server/src/handlers/inc/packages-json.ts index a27fb00615d..44449a5ef66 100644 --- a/developer/src/server/src/handlers/inc/packages-json.ts +++ b/developer/src/server/src/handlers/inc/packages-json.ts @@ -1,6 +1,6 @@ -import express = require('express'); -import { data } from "../../data"; -import { environment } from '../../environment'; +import * as express from 'express'; +import { data } from "../../data.js"; +import { environment } from '../../environment.js'; export default function handleIncPackagesJson (req: express.Request, res: express.Response) { const packages = Object.keys(data.packages).map(id => { return { id: id, filename: id+'.kmp', name: data.packages[id].name} }); diff --git a/developer/src/server/src/index.ts b/developer/src/server/src/index.ts index a6d109f1bad..a2975545730 100644 --- a/developer/src/server/src/index.ts +++ b/developer/src/server/src/index.ts @@ -1,21 +1,21 @@ -import { environment } from './environment'; +import { environment } from './environment.js'; -const Sentry = require("@sentry/node"); +import * as Sentry from '@sentry/node'; Sentry.init({ dsn: 'https://39b25a09410349a58fe12aaf721565af@o1005580.ingest.sentry.io/5983519', // Keyman Developer environment: environment.versionEnvironment, release: environment.versionGitTag }); -import express = require('express'); -import ws = require('ws'); -import os = require('os'); -import multer = require('multer'); -import fs = require('fs'); -import setupRoutes from './routes'; -import { configuration } from './config'; -import tray from './tray'; -import chalk = require('chalk'); +import express from 'express'; +import * as ws from 'ws'; +import * as os from 'os'; +import multer from 'multer'; +import * as fs from 'fs'; +import setupRoutes from './routes.js'; +import { configuration } from './config.js'; +import tray from './tray.js'; +import chalk from 'chalk'; const options = { ngrokLog: false, // Set this to true if you need to see ngrok logs in the console @@ -58,7 +58,7 @@ const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 102 /* Websockets */ -const wsServer = new ws.Server({ noServer: true }); +const wsServer = new ws.WebSocketServer({ noServer: true }); wsServer.on('connection', socket => { socket.on('message', (message) => { console.debug('wsServer.socket.onmessage: '+message.toString()); @@ -87,7 +87,7 @@ server.on('upgrade', (request, socket, head) => { configuration.ngrokEndpoint = ''; if(configuration.useNgrok && os.platform() == 'win32' && fs.existsSync(configuration.ngrokBinPath)) { - const ngrok = require('ngrok'); + const ngrok: any = await import('ngrok'); (async function() { configuration.ngrokEndpoint = await ngrok.connect({ proto: 'http', diff --git a/developer/src/server/src/ngrok.d.ts b/developer/src/server/src/ngrok.d.ts new file mode 100644 index 00000000000..61f00d7a0b3 --- /dev/null +++ b/developer/src/server/src/ngrok.d.ts @@ -0,0 +1 @@ +declare module 'ngrok'; \ No newline at end of file diff --git a/developer/src/server/src/routes.ts b/developer/src/server/src/routes.ts index fdd2e421aad..20c09f838f7 100644 --- a/developer/src/server/src/routes.ts +++ b/developer/src/server/src/routes.ts @@ -1,21 +1,21 @@ -import express = require('express'); -import multer = require('multer'); -import ws = require('ws'); -import handleIncKeyboardsJs from './handlers/inc/keyboards-js'; -import { data, DebugFont, DebugKeyboard, DebugModel, DebugObject, DebugPackage, isValidId } from './data'; -import apiGet from './handlers/api/debugobject/get'; -import apiRegister, { apiRegisterFile } from './handlers/api/debugobject/register'; -import apiKeyboardRegister from './handlers/api/keyboard/register'; -import apiFontRegister from './handlers/api/font/register'; -import apiUnregister from './handlers/api/debugobject/unregister'; -import handleIncPackagesJson from './handlers/inc/packages-json'; -import apiPackageRegister from './handlers/api/package/register'; -import handleIncKeyboardsCss from './handlers/inc/keyboards-css'; -import { Environment } from './version-data'; -import { configuration } from './config'; -import chalk = require('chalk'); - -export default function setupRoutes(app: express.Express, upload: multer.Multer, wsServer: ws.Server, environment: Environment ) { +import * as express from 'express'; +import * as ws from 'ws'; +import * as multer from 'multer'; +import handleIncKeyboardsJs from './handlers/inc/keyboards-js.js'; +import { data, DebugFont, DebugKeyboard, DebugModel, DebugObject, DebugPackage, isValidId } from './data.js'; +import apiGet from './handlers/api/debugobject/get.js'; +import apiRegister, { apiRegisterFile } from './handlers/api/debugobject/register.js'; +import apiKeyboardRegister from './handlers/api/keyboard/register.js'; +import apiFontRegister from './handlers/api/font/register.js'; +import apiUnregister from './handlers/api/debugobject/unregister.js'; +import handleIncPackagesJson from './handlers/inc/packages-json.js'; +import apiPackageRegister from './handlers/api/package/register.js'; +import handleIncKeyboardsCss from './handlers/inc/keyboards-css.js'; +import { Environment } from './version-data.js'; +import { configuration } from './config.js'; +import chalk from 'chalk'; + +export default function setupRoutes(app: express.Express, upload: multer.Multer, wsServer: ws.WebSocketServer, environment: Environment ) { /* Middleware - JSON and logging */ @@ -49,7 +49,7 @@ export default function setupRoutes(app: express.Express, upload: multer.Multer, /* All routes */ - app.use('/', express.static('dist/site')); + app.use('/', express.static('build/src/site')); app.post('/upload', localhostOnly, upload.single('file'), (req, res, next) => { const name = req.file.originalname; @@ -170,7 +170,7 @@ export default function setupRoutes(app: express.Express, upload: multer.Multer, /* Utility functions */ -function notifyClients(wsServer: ws.Server, res: express.Request, req: express.Response, next: express.NextFunction) { +function notifyClients(wsServer: ws.WebSocketServer, res: express.Request, req: express.Response, next: express.NextFunction) { wsServer.clients.forEach(c => { c.send('refresh', (err) => { if(err) console.error(chalk.red('Websocket send error '+err.message)); diff --git a/developer/src/server/src/tray.ts b/developer/src/server/src/tray.ts index 0c9c3bf2f65..780d9c792c4 100644 --- a/developer/src/server/src/tray.ts +++ b/developer/src/server/src/tray.ts @@ -1,4 +1,4 @@ -import os = require('os'); +import * as os from 'os'; class TrayStub { public start(localPort: number, ngrokAddress: string) {} @@ -9,7 +9,7 @@ class TrayStub { let tray = new TrayStub(); if(os.platform() == 'win32') { - const Win32Tray = require('./win32-tray'); + const { Win32Tray } = await import('./win32-tray.js'); tray = new Win32Tray(); } diff --git a/developer/src/server/src/win32-tray.ts b/developer/src/server/src/win32-tray.ts index b17c775f00c..02ef0a4db80 100644 --- a/developer/src/server/src/win32-tray.ts +++ b/developer/src/server/src/win32-tray.ts @@ -1,14 +1,15 @@ -import path = require("path"); +import * as path from "path"; +import * as url from 'url'; // TODO: this is a Windows-only tray icon. There are a number of // cross-platform solutions but none of them are wonderful. We // should replace this when we find a decent one. -const WindowsTrayicon = require("./win32/trayicon"); -const WindowsConsole = require("./win32/console"); -const open = require("open"); +import WindowsTrayicon from "./win32/trayicon/index.js"; +import WindowsConsole from "./win32/console/index.js"; +import open from 'open'; -module.exports = class Win32Tray { +export class Win32Tray { private myTrayApp: any; public restart(localPort: number, ngrokAddress: string) { @@ -55,7 +56,7 @@ module.exports = class Win32Tray { this.myTrayApp = new WindowsTrayicon({ title: "Keyman Developer Server", - icon: path.resolve(__dirname, "site", "favicon.ico"), + icon: path.resolve(url.fileURLToPath(new URL('.', import.meta.url)), "site", "favicon.ico"), menu: menu }); diff --git a/developer/src/server/src/win32/console/index.d.ts b/developer/src/server/src/win32/console/index.d.ts deleted file mode 100644 index ac9e647fa40..00000000000 --- a/developer/src/server/src/win32/console/index.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -declare module "node-hide-console-window" { - function hideConsole(): void - - function showConsole(): void -} \ No newline at end of file diff --git a/developer/src/server/src/win32/console/index.js b/developer/src/server/src/win32/console/index.js deleted file mode 100644 index 26026657a0b..00000000000 --- a/developer/src/server/src/win32/console/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const os = require('os'); -const {showConsole, hideConsole} = require(os.arch() == 'ia32' ? "./node-hide-console-window" : "./node-hide-console-window.x64"); - -module.exports = { - showConsole, - hideConsole -} \ No newline at end of file diff --git a/developer/src/server/src/win32/console/index.ts b/developer/src/server/src/win32/console/index.ts new file mode 100644 index 00000000000..1bee9ada877 --- /dev/null +++ b/developer/src/server/src/win32/console/index.ts @@ -0,0 +1,6 @@ +import * as os from 'os'; +import { createRequire } from 'node:module'; +const require = createRequire(import.meta.url); +const {showConsole, hideConsole} = require(os.arch() == 'ia32' ? "./node-hide-console-window" : "./node-hide-console-window.x64"); + +export default { showConsole, hideConsole }; diff --git a/developer/src/server/src/win32/trayicon/index.js b/developer/src/server/src/win32/trayicon/index.ts similarity index 68% rename from developer/src/server/src/win32/trayicon/index.js rename to developer/src/server/src/win32/trayicon/index.ts index 1e50cef3da0..6b313af262f 100644 --- a/developer/src/server/src/win32/trayicon/index.js +++ b/developer/src/server/src/win32/trayicon/index.ts @@ -1,8 +1,17 @@ -const os = require('os'); +import * as os from 'os'; +import { createRequire } from 'node:module'; +const require = createRequire(import.meta.url); const { CTrayIconContainer } = require(os.arch() == 'ia32' ? "./addon" : "./addon.x64"); class WindowsTrayicon { - constructor(options) { + __itemCallbacks: any[]; + __icon: any; + __trayTitle: any; + __menuItems: any; + __nativeTray: any; + + + constructor(options: any) { this.__itemCallbacks = []; this.__icon = options.icon; this.__trayTitle = options.title || ""; @@ -12,7 +21,7 @@ class WindowsTrayicon { for (const item of this.__menuItems) { this.__nativeTray.AddMenuItem(item.id, item.caption); } - this.__nativeTray.OnMenuItem((id) => { + this.__nativeTray.OnMenuItem((id: any) => { for (const cb of this.__itemCallbacks) { cb(id); } @@ -23,15 +32,15 @@ class WindowsTrayicon { } this.__nativeTray.Start(); } - item(cb) { + item(cb: any) { if ("function" === typeof cb) { this.__itemCallbacks.push(cb); } } - balloon(title, text, timeout = 5000) { + balloon(title: any, text: any, timeout = 5000) { return new Promise((resolve) => { this.__nativeTray.ShowBalloon(title, text, timeout, () => { - resolve(); + resolve(null); }) }); } @@ -40,4 +49,4 @@ class WindowsTrayicon { } } -module.exports = WindowsTrayicon; +export default WindowsTrayicon; diff --git a/developer/src/server/test/tsconfig.json b/developer/src/server/test/tsconfig.json new file mode 100644 index 00000000000..fa377b0fde1 --- /dev/null +++ b/developer/src/server/test/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../../../tsconfig.base.json", + + "compilerOptions": { + "rootDir": ".", + "rootDirs": ["./", "../src/"], + "outDir": "../build/test", + "baseUrl": ".", + }, + "include": [ + "**/*.test.ts" + ], + "references": [ + { "path": "../" }, + ] +} \ No newline at end of file diff --git a/developer/src/server/src/version-data.test.ts b/developer/src/server/test/version-data.test.ts similarity index 97% rename from developer/src/server/src/version-data.test.ts rename to developer/src/server/test/version-data.test.ts index 5f33932b3bd..74762b7d7f8 100644 --- a/developer/src/server/src/version-data.test.ts +++ b/developer/src/server/test/version-data.test.ts @@ -1,8 +1,6 @@ import {assert} from 'chai'; import 'mocha'; - -import { extractVersionData } from './version-data'; - +import { extractVersionData } from '../src/version-data.js'; describe('extractVersionData', function() { it('should parse version strings', function() { diff --git a/developer/src/server/tsconfig.json b/developer/src/server/tsconfig.json index 280b535dd9e..e5adde95784 100644 --- a/developer/src/server/tsconfig.json +++ b/developer/src/server/tsconfig.json @@ -1,13 +1,13 @@ { - "extends": "../../../tsconfig-base.json", + "extends": "../../../tsconfig.base.json", "compilerOptions": { - "module": "commonjs", "target": "es2022", - "moduleResolution": "node", "sourceMap": true, - "outDir": "dist/", + "outDir": "build/src/", "rootDir": "src/", + "baseUrl": ".", + "declaration": true, "alwaysStrict": true, "noImplicitThis": true, @@ -16,6 +16,7 @@ "strictBindCallApply": true, "strictFunctionTypes": true, "noUnusedLocals": true, + "allowJs": true, "lib": ["es2022"] }, "include": [ diff --git a/developer/src/tike/child/UfrmDebug.pas b/developer/src/tike/child/UfrmDebug.pas index 615cfebc809..30c91eba0c3 100644 --- a/developer/src/tike/child/UfrmDebug.pas +++ b/developer/src/tike/child/UfrmDebug.pas @@ -371,13 +371,13 @@ procedure TfrmDebug.memoMessage(Sender: TObject; var Message: TMessage; function TfrmDebug.SetKeyEventContext: Boolean; var - context: pkm_kbp_context; - context_items: TArray; + context: pkm_core_context; + context_items: TArray; n, i: Integer; ch: Char; dk: TDeadKeyInfo; begin - context := km_kbp_state_context(FDebugCore.State); + context := km_core_state_context(FDebugCore.State); if memo.SelLength > 0 then begin @@ -392,7 +392,7 @@ function TfrmDebug.SetKeyEventContext: Boolean; // backspace in the case of backspace key, rather // than deleting the last character of the selection // (Keyman Core is not aware of selection). - km_kbp_context_clear(context); + km_core_context_clear(context); Exit(True); end; @@ -405,28 +405,28 @@ function TfrmDebug.SetKeyEventContext: Boolean; if Uni_IsSurrogate1(ch) and (i < Length(memo.Text)) and Uni_IsSurrogate2(memo.Text[i+1]) then begin - context_items[n]._type := KM_KBP_CT_CHAR; + context_items[n]._type := KM_CORE_CT_CHAR; context_items[n].character := Uni_SurrogateToUTF32(ch, memo.Text[i+1]); Inc(i); end else if Ord(ch) = $FFFC then begin - context_items[n]._type := KM_KBP_CT_MARKER; + context_items[n]._type := KM_CORE_CT_MARKER; dk := FDeadkeys.GetFromPosition(i-1); Assert(Assigned(dk)); context_items[n].marker := dk.Deadkey.Value; end else begin - context_items[n]._type := KM_KBP_CT_CHAR; + context_items[n]._type := KM_CORE_CT_CHAR; context_items[n].character := Ord(ch); end; Inc(i); Inc(n); end; - context_items[n]._type := KM_KBP_CT_END; - Result := km_kbp_context_set(context, @context_items[0]) = KM_KBP_STATUS_OK; + context_items[n]._type := KM_CORE_CT_END; + Result := km_core_context_set(context, @context_items[0]) = KM_CORE_STATUS_OK; end; function TfrmDebug.ProcessKeyEvent(var Message: TMessage): Boolean; @@ -459,24 +459,24 @@ function TfrmDebug.ProcessKeyEvent(var Message: TMessage): Boolean; vkey := MapScanCodeToUSVK((Message.LParam and $FF0000) shr 16); modifier := 0; - if GetKeyState(VK_LCONTROL) < 0 then modifier := modifier or KM_KBP_MODIFIER_LCTRL; - if GetKeyState(VK_RCONTROL) < 0 then modifier := modifier or KM_KBP_MODIFIER_RCTRL; - if GetKeyState(VK_LMENU) < 0 then modifier := modifier or KM_KBP_MODIFIER_LALT; - if GetKeyState(VK_RMENU) < 0 then modifier := modifier or KM_KBP_MODIFIER_RALT; - if GetKeyState(VK_SHIFT) < 0 then modifier := modifier or KM_KBP_MODIFIER_SHIFT; - if (GetKeyState(VK_CAPITAL) and 1) = 1 then modifier := modifier or KM_KBP_MODIFIER_CAPS; + if GetKeyState(VK_LCONTROL) < 0 then modifier := modifier or KM_CORE_MODIFIER_LCTRL; + if GetKeyState(VK_RCONTROL) < 0 then modifier := modifier or KM_CORE_MODIFIER_RCTRL; + if GetKeyState(VK_LMENU) < 0 then modifier := modifier or KM_CORE_MODIFIER_LALT; + if GetKeyState(VK_RMENU) < 0 then modifier := modifier or KM_CORE_MODIFIER_RALT; + if GetKeyState(VK_SHIFT) < 0 then modifier := modifier or KM_CORE_MODIFIER_SHIFT; + if (GetKeyState(VK_CAPITAL) and 1) = 1 then modifier := modifier or KM_CORE_MODIFIER_CAPS; - if (modifier and (KM_KBP_MODIFIER_LCTRL or KM_KBP_MODIFIER_RALT)) = (KM_KBP_MODIFIER_LCTRL or KM_KBP_MODIFIER_RALT) then + if (modifier and (KM_CORE_MODIFIER_LCTRL or KM_CORE_MODIFIER_RALT)) = (KM_CORE_MODIFIER_LCTRL or KM_CORE_MODIFIER_RALT) then begin // #7506: Windows emits LCtrl+RAlt for AltGr for European keyboards; we want // to ignore this combination - modifier := modifier and not KM_KBP_MODIFIER_LCTRL; + modifier := modifier and not KM_CORE_MODIFIER_LCTRL; end; if not SetKeyEventContext then Exit(False); - if km_kbp_process_event(FDebugCore.State, Message.WParam, modifier, 1, KM_KBP_EVENT_FLAG_DEFAULT) = KM_KBP_STATUS_OK then + if km_core_process_event(FDebugCore.State, Message.WParam, modifier, 1, KM_CORE_EVENT_FLAG_DEFAULT) = KM_CORE_STATUS_OK then begin // Process keystroke -- true = swallow keystroke Result := True; @@ -531,7 +531,7 @@ procedure TfrmDebug.StepForward; StepTwice := (_FCurrentEvent < FEvents.Count) and (FEvents[_FCurrentEvent].EventType = etRuleMatch) and - (FEvents[_FCurrentEvent].Rule.ItemType = KM_KBP_DEBUG_SET_OPTION); + (FEvents[_FCurrentEvent].Rule.ItemType = KM_CORE_DEBUG_SET_OPTION); if _FCurrentEvent < FEvents.Count then begin @@ -646,11 +646,11 @@ procedure TfrmDebug.ExecuteEventRule(n: Integer); begin { Stop running, if breakpoint options are also met } if not (ItemType in [ - KM_KBP_DEBUG_GROUP_EXIT, - KM_KBP_DEBUG_RULE_EXIT, - KM_KBP_DEBUG_MATCH_EXIT, - KM_KBP_DEBUG_NOMATCH_EXIT, - KM_KBP_DEBUG_END + KM_CORE_DEBUG_GROUP_EXIT, + KM_CORE_DEBUG_RULE_EXIT, + KM_CORE_DEBUG_MATCH_EXIT, + KM_CORE_DEBUG_NOMATCH_EXIT, + KM_CORE_DEBUG_END ]) or FKeymanDeveloperOptions.DebuggerBreakWhenExitingLine then FFoundBreakpoint := True; end; @@ -659,21 +659,21 @@ procedure TfrmDebug.ExecuteEventRule(n: Integer); { Update call stack, execution point line } case ItemType of - KM_KBP_DEBUG_BEGIN: + KM_CORE_DEBUG_BEGIN: ExecuteBegin(FEvents[n]); - KM_KBP_DEBUG_GROUP_ENTER, - KM_KBP_DEBUG_RULE_ENTER, - KM_KBP_DEBUG_NOMATCH_ENTER, - KM_KBP_DEBUG_MATCH_ENTER: + KM_CORE_DEBUG_GROUP_ENTER, + KM_CORE_DEBUG_RULE_ENTER, + KM_CORE_DEBUG_NOMATCH_ENTER, + KM_CORE_DEBUG_MATCH_ENTER: frmDebugStatus.CallStack.CallStackPush(FEvents[n].Rule); - KM_KBP_DEBUG_RULE_EXIT, - KM_KBP_DEBUG_NOMATCH_EXIT, - KM_KBP_DEBUG_MATCH_EXIT, - KM_KBP_DEBUG_GROUP_EXIT: + KM_CORE_DEBUG_RULE_EXIT, + KM_CORE_DEBUG_NOMATCH_EXIT, + KM_CORE_DEBUG_MATCH_EXIT, + KM_CORE_DEBUG_GROUP_EXIT: frmDebugStatus.CallStack.CallStackPop; - KM_KBP_DEBUG_END: + KM_CORE_DEBUG_END: begin frmDebugStatus.CallStack.CallStackClear; ExecutionPointLine := -1; end; - KM_KBP_DEBUG_SET_OPTION: + KM_CORE_DEBUG_SET_OPTION: ExecuteSetOption(FEvents[n]); else Assert(False); @@ -723,7 +723,7 @@ TMemoSelectionState = record UpdateDeadkeys; end; - procedure DoBackspace(BackspaceType: km_kbp_backspace_type); + procedure DoBackspace(BackspaceType: km_core_backspace_type); var m, n: Integer; dk: TDeadKeyInfo; @@ -737,16 +737,16 @@ TMemoSelectionState = record if memo.SelLength > 0 then begin // If the memo has a selection, we have given Core an empty context, - // which forces it to emit a KM_KBP_BT_UNKNOWN backspace, which is + // which forces it to emit a KM_CORE_BT_UNKNOWN backspace, which is // exactly what we want here. We just delete the selection - Assert(BackspaceType = KM_KBP_BT_UNKNOWN); + Assert(BackspaceType = KM_CORE_BT_UNKNOWN); memo.SelText := ''; RealignMemoSelectionState(state); Exit; end; case BackspaceType of - KM_KBP_BT_MARKER: + KM_CORE_BT_MARKER: begin Assert(m >= 1); Assert(memo.Text[m] = #$FFFC); @@ -755,7 +755,7 @@ TMemoSelectionState = record dk.Delete; Dec(m); end; - KM_KBP_BT_CHAR: + KM_CORE_BT_CHAR: begin Assert(m >= 1); Assert(memo.Text[m] <> #$FFFC); @@ -766,7 +766,7 @@ TMemoSelectionState = record else Dec(m); end; - KM_KBP_BT_UNKNOWN: + KM_CORE_BT_UNKNOWN: begin while (m >= 1) and (memo.Text[m] = #$FFFC) do begin @@ -911,14 +911,14 @@ TMemoSelectionState = record with FEvents[n].Action do begin case ActionType of - KM_KBP_IT_EMIT_KEYSTROKE: DoEmitKeystroke(dwData); - KM_KBP_IT_CHAR: DoChar(Text); - KM_KBP_IT_MARKER: DoDeadkey(dwData); - KM_KBP_IT_ALERT: DoBell; - KM_KBP_IT_BACK: DoBackspace(km_kbp_backspace_type(dwData)); - KM_KBP_IT_PERSIST_OPT: ; //TODO - KM_KBP_IT_CAPSLOCK: ; //TODO - KM_KBP_IT_INVALIDATE_CONTEXT: ; // no-op + KM_CORE_IT_EMIT_KEYSTROKE: DoEmitKeystroke(dwData); + KM_CORE_IT_CHAR: DoChar(Text); + KM_CORE_IT_MARKER: DoDeadkey(dwData); + KM_CORE_IT_ALERT: DoBell; + KM_CORE_IT_BACK: DoBackspace(km_core_backspace_type(dwData)); + KM_CORE_IT_PERSIST_OPT: ; //TODO + KM_CORE_IT_CAPSLOCK: ; //TODO + KM_CORE_IT_INVALIDATE_CONTEXT: ; // no-op end; // AddDEBUG(Format('%d: %d [%s]', [ActionType, dwData, Text])); end; diff --git a/developer/src/tike/debug/Keyman.System.Debug.DebugCore.pas b/developer/src/tike/debug/Keyman.System.Debug.DebugCore.pas index 6b0a5b5fd5d..05ded33f79f 100644 --- a/developer/src/tike/debug/Keyman.System.Debug.DebugCore.pas +++ b/developer/src/tike/debug/Keyman.System.Debug.DebugCore.pas @@ -18,8 +18,8 @@ EDebugCore = class(Exception); TDebugCore = class private - FKeyboard: pkm_kbp_keyboard; - FState: pkm_kbp_state; + FKeyboard: pkm_core_keyboard; + FState: pkm_core_state; class var KeymanCoreLoaded: Boolean; class procedure InitKeymanCore; static; function GetKMXPlatform: string; @@ -30,8 +30,8 @@ TDebugCore = class function GetOption(const name: string): string; procedure SetOption(const name, value: string); property KMXPlatform: string read GetKMXPlatform write SetKMXPlatform; - property Keyboard: pkm_kbp_keyboard read FKeyboard; - property State: pkm_kbp_state read FState; + property Keyboard: pkm_core_keyboard read FKeyboard; + property State: pkm_core_state read FState; end; implementation @@ -43,7 +43,7 @@ implementation constructor TDebugCore.Create(const Filename: string; EnableDebug: Boolean); var - status: km_kbp_status; + status: km_core_status; begin inherited Create; @@ -52,18 +52,18 @@ constructor TDebugCore.Create(const Filename: string; EnableDebug: Boolean); FKeyboard := nil; FState := nil; - status := km_kbp_keyboard_load(PChar(FileName), FKeyboard); - if status <> KM_KBP_STATUS_OK then + status := km_core_keyboard_load(PChar(FileName), FKeyboard); + if status <> KM_CORE_STATUS_OK then raise EDebugCore.CreateFmt('Unable to start debugger -- keyboard load failed with error %x', [Ord(status)]); - status := km_kbp_state_create(FKeyboard, @KM_KBP_OPTIONS_END, FState); - if status <> KM_KBP_STATUS_OK then + status := km_core_state_create(FKeyboard, @KM_CORE_OPTIONS_END, FState); + if status <> KM_CORE_STATUS_OK then raise EDebugCore.CreateFmt('Unable to start debugger -- state creation failed with error %x', [Ord(status)]); if EnableDebug then begin - status := km_kbp_state_debug_set(FState, 1); - if status <> KM_KBP_STATUS_OK then + status := km_core_state_debug_set(FState, 1); + if status <> KM_CORE_STATUS_OK then raise EDebugCore.CreateFmt('Unable to start debugger -- enabling debug failed with error %x', [Ord(status)]); end; end; @@ -71,10 +71,10 @@ constructor TDebugCore.Create(const Filename: string; EnableDebug: Boolean); destructor TDebugCore.Destroy; begin if FState <> nil then - km_kbp_state_dispose(FState); + km_core_state_dispose(FState); FState := nil; if FKeyboard <> nil then - km_kbp_keyboard_dispose(FKeyboard); + km_core_keyboard_dispose(FKeyboard); FKeyboard := nil; inherited Destroy; end; @@ -87,7 +87,7 @@ class procedure TDebugCore.InitKeymanCore; begin path := TKeymanPaths.KeymanCoreLibraryPath(kmnkbp0); try - _km_kbp_set_library_path(path); + _km_core_set_library_path(path); except on E:Exception do raise EDebugCore.CreateFmt('Unable to load Keyman Core library at %s: %s %s', [path, E.ClassName, E.Message]); @@ -98,61 +98,61 @@ class procedure TDebugCore.InitKeymanCore; function TDebugCore.GetKMXPlatform: string; var - p: pkm_kbp_cp; - status: km_kbp_status; + p: pkm_core_cp; + status: km_core_status; begin - status := km_kbp_state_option_lookup( + status := km_core_state_option_lookup( FState, - KM_KBP_OPT_ENVIRONMENT, - pkm_kbp_cp(PWideChar(KM_KBP_KMX_ENV_PLATFORM)), + KM_CORE_OPT_ENVIRONMENT, + pkm_core_cp(PWideChar(KM_CORE_KMX_ENV_PLATFORM)), p ); - if status <> KM_KBP_STATUS_OK then + if status <> KM_CORE_STATUS_OK then raise EDebugCore.CreateFmt('Unable to locate platform, error %x', [Ord(status)]); Result := PWideChar(p); end; procedure TDebugCore.SetKMXPlatform(const Value: string); var - options: array[0..1] of km_kbp_option_item; - status: km_kbp_status; + options: array[0..1] of km_core_option_item; + status: km_core_status; begin - options[0].key := pkm_kbp_cp(PWideChar(KM_KBP_KMX_ENV_PLATFORM)); - options[0].value := pkm_kbp_cp(PWideChar(Value)); - options[0].scope := KM_KBP_OPT_ENVIRONMENT; - options[1] := KM_KBP_OPTIONS_END; - status := km_kbp_state_options_update(FState, @options[0]); - if status <> KM_KBP_STATUS_OK then + options[0].key := pkm_core_cp(PWideChar(KM_CORE_KMX_ENV_PLATFORM)); + options[0].value := pkm_core_cp(PWideChar(Value)); + options[0].scope := KM_CORE_OPT_ENVIRONMENT; + options[1] := KM_CORE_OPTIONS_END; + status := km_core_state_options_update(FState, @options[0]); + if status <> KM_CORE_STATUS_OK then raise EDebugCore.CreateFmt('Unable to set platform, error %x', [Ord(status)]); end; function TDebugCore.GetOption(const name: string): string; var - p: pkm_kbp_cp; - status: km_kbp_status; + p: pkm_core_cp; + status: km_core_status; begin - status := km_kbp_state_option_lookup( + status := km_core_state_option_lookup( FState, - KM_KBP_OPT_KEYBOARD, - pkm_kbp_cp(PWideChar(name)), + KM_CORE_OPT_KEYBOARD, + pkm_core_cp(PWideChar(name)), p ); - if status <> KM_KBP_STATUS_OK then + if status <> KM_CORE_STATUS_OK then raise EDebugCore.CreateFmt('Unable to locate option %s, error %x', [name, Ord(status)]); Result := PWideChar(p); end; procedure TDebugCore.SetOption(const name, value: string); var - options: array[0..1] of km_kbp_option_item; - status: km_kbp_status; + options: array[0..1] of km_core_option_item; + status: km_core_status; begin - options[0].key := pkm_kbp_cp(PWideChar(Name)); - options[0].value := pkm_kbp_cp(PWideChar(Value)); - options[0].scope := KM_KBP_OPT_KEYBOARD; - options[1] := KM_KBP_OPTIONS_END; - status := km_kbp_state_options_update(FState, @options[0]); - if status <> KM_KBP_STATUS_OK then + options[0].key := pkm_core_cp(PWideChar(Name)); + options[0].value := pkm_core_cp(PWideChar(Value)); + options[0].scope := KM_CORE_OPT_KEYBOARD; + options[1] := KM_CORE_OPTIONS_END; + status := km_core_state_options_update(FState, @options[0]); + if status <> KM_CORE_STATUS_OK then raise EDebugCore.CreateFmt('Unable to set option %s, error %x', [name, Ord(status)]); end; diff --git a/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas b/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas index 6a7e0b3f0ed..4f5ee402112 100644 --- a/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas +++ b/developer/src/tike/debug/Keyman.System.Debug.DebugEvent.pas @@ -31,7 +31,7 @@ TAIDebugKeyInfo = record { DebugEvent structure -- an event has occurred } TDebugEventActionData = class - ActionType: km_kbp_action_type; + ActionType: km_core_action_type; dwData: Integer; Text: WideString; end; @@ -47,7 +47,7 @@ TDebugEventRuleData = class Context: WideString; StoreOffsets: array[0..20] of Word; //TKeymanStoreEx; nStores: Integer; - procedure FillStoreList(event: pkm_kbp_state_debug_item; KeyboardMemory: PChar); + procedure FillStoreList(event: pkm_core_state_debug_item; KeyboardMemory: PChar); end; TDebugEventType = (etAction, etRuleMatch); @@ -68,28 +68,28 @@ TDebugEvent = class TDebugEventList = class(TObjectList) private - procedure Action_Char(const character: km_kbp_usv); + procedure Action_Char(const character: km_core_usv); procedure Action_DeleteBack(expected_type: uint8_t; expected_value: uintptr_t); procedure Action_EmitKeystroke(const key: Word); procedure Action_Marker(marker: uintptr_t); - function AddActionItem(key: Word; action: pkm_kbp_action_item): Boolean; + function AddActionItem(key: Word; action: pkm_core_action_item): Boolean; procedure AddDebugItem( - debug: pkm_kbp_state_debug_item; + debug: pkm_core_state_debug_item; debugkeyboard: TDebugKeyboard; vk: uint16_t; modifier_state: uint16_t ); public function AddStateItems( - state: pkm_kbp_state; + state: pkm_core_state; vk: uint16_t; modifier_state: uint16_t; debugkeyboard: TDebugKeyboard ): Boolean; overload; function AddStateItems( - state: pkm_kbp_state; + state: pkm_core_state; vk: uint16_t; modifier_state: uint16_t ): Boolean; overload; @@ -133,18 +133,18 @@ procedure TDebugEvent.SetEventType(const Value: TDebugEventType); end; end; -function TDebugEventList.AddActionItem(key: Word; action: pkm_kbp_action_item): Boolean; +function TDebugEventList.AddActionItem(key: Word; action: pkm_core_action_item): Boolean; begin Result := True; case action._type of - KM_KBP_IT_CHAR: Action_Char(action.character); - KM_KBP_IT_MARKER: Action_Marker(action.marker); // Correlates to kmn's "deadkey" markers. - KM_KBP_IT_ALERT: ; // TODO: The keyboard has triggered a alert/beep/bell. - KM_KBP_IT_BACK: Action_DeleteBack(action.backspace.expected_type, action.backspace.expected_value); - KM_KBP_IT_PERSIST_OPT: ; // TODO: The indicated option needs to be stored. - KM_KBP_IT_EMIT_KEYSTROKE: Action_EmitKeystroke(key); - KM_KBP_IT_CAPSLOCK: ; // TODO: Caps lock state needs to be updated - KM_KBP_IT_INVALIDATE_CONTEXT: ; + KM_CORE_IT_CHAR: Action_Char(action.character); + KM_CORE_IT_MARKER: Action_Marker(action.marker); // Correlates to kmn's "deadkey" markers. + KM_CORE_IT_ALERT: ; // TODO: The keyboard has triggered a alert/beep/bell. + KM_CORE_IT_BACK: Action_DeleteBack(action.backspace.expected_type, action.backspace.expected_value); + KM_CORE_IT_PERSIST_OPT: ; // TODO: The indicated option needs to be stored. + KM_CORE_IT_EMIT_KEYSTROKE: Action_EmitKeystroke(key); + KM_CORE_IT_CAPSLOCK: ; // TODO: Caps lock state needs to be updated + KM_CORE_IT_INVALIDATE_CONTEXT: ; else Assert(False, 'Action type '+IntToStr(Ord(action._type))+' is unexpected.'); end; end; @@ -156,12 +156,12 @@ procedure TDebugEventList.Action_EmitKeystroke(const key: Word); case key of VK_TAB: Action_Char(9); // Emit a tab character VK_RETURN: Action_Char(13); // New line character - VK_BACK: Action_DeleteBack(Ord(KM_KBP_BT_UNKNOWN), 0); + VK_BACK: Action_DeleteBack(Ord(KM_CORE_BT_UNKNOWN), 0); else begin event := TDebugEvent.Create; event.EventType := etAction; - event.Action.ActionType := KM_KBP_IT_EMIT_KEYSTROKE; + event.Action.ActionType := KM_CORE_IT_EMIT_KEYSTROKE; event.Action.dwData := key; Add(event); end; @@ -172,13 +172,13 @@ procedure TDebugEventList.Action_EmitKeystroke(const key: Word); /// Insert a UTF-32 character at the insertion point. /// TODO: define behaviour around selection /// -procedure TDebugEventList.Action_Char(const character: km_kbp_usv); +procedure TDebugEventList.Action_Char(const character: km_core_usv); var event: TDebugEvent; begin event := TDebugEvent.Create; event.EventType := etAction; - event.Action.ActionType := KM_KBP_IT_CHAR; + event.Action.ActionType := KM_CORE_IT_CHAR; event.Action.Text := Uni_UTF32CharToUTF16(character); Add(event); end; @@ -188,7 +188,7 @@ procedure TDebugEventList.Action_Char(const character: km_kbp_usv); /// TODO: define behaviour around selection /// procedure TDebugEventList.Action_DeleteBack( - expected_type: uint8_t; /// one of KM_KBP_BT_CHAR, KM_KBP_BT_MARKER, KM_KBP_BT_UNKNOWN + expected_type: uint8_t; /// one of KM_CORE_BT_CHAR, KM_CORE_BT_MARKER, KM_CORE_BT_UNKNOWN expected_value: uintptr_t /// used mainly in unit tests ); var @@ -196,7 +196,7 @@ procedure TDebugEventList.Action_DeleteBack( begin event := TDebugEvent.Create; event.EventType := etAction; - event.Action.ActionType := KM_KBP_IT_BACK; + event.Action.ActionType := KM_CORE_IT_BACK; event.Action.dwData := expected_type; Add(event); end; @@ -214,13 +214,13 @@ procedure TDebugEventList.Action_Marker(marker: uintptr_t); event := TDebugEvent.Create; event.EventType := etAction; - event.Action.ActionType := KM_KBP_IT_MARKER; + event.Action.ActionType := KM_CORE_IT_MARKER; event.Action.dwData := marker; Add(event); end; procedure TDebugEventList.AddDebugItem( - debug: pkm_kbp_state_debug_item; + debug: pkm_core_state_debug_item; debugkeyboard: TDebugKeyboard; vk: uint16_t; modifier_state: uint16_t); @@ -245,14 +245,14 @@ procedure TDebugEventList.AddDebugItem( end; case debug._type of - KM_KBP_DEBUG_END: Result := debugkeyboard.BeginUnicodeLine; - KM_KBP_DEBUG_BEGIN: Result := debugkeyboard.BeginUnicodeLine; - KM_KBP_DEBUG_GROUP_ENTER, - KM_KBP_DEBUG_GROUP_EXIT: if grp > -1 then Result := debugkeyboard.Groups[grp].Line; - KM_KBP_DEBUG_MATCH_ENTER, - KM_KBP_DEBUG_MATCH_EXIT: if grp > -1 then Result := debugkeyboard.Groups[grp].MatchLine; - KM_KBP_DEBUG_NOMATCH_ENTER, - KM_KBP_DEBUG_NOMATCH_EXIT: if grp > -1 then Result := debugkeyboard.Groups[grp].NomatchLine; + KM_CORE_DEBUG_END: Result := debugkeyboard.BeginUnicodeLine; + KM_CORE_DEBUG_BEGIN: Result := debugkeyboard.BeginUnicodeLine; + KM_CORE_DEBUG_GROUP_ENTER, + KM_CORE_DEBUG_GROUP_EXIT: if grp > -1 then Result := debugkeyboard.Groups[grp].Line; + KM_CORE_DEBUG_MATCH_ENTER, + KM_CORE_DEBUG_MATCH_EXIT: if grp > -1 then Result := debugkeyboard.Groups[grp].MatchLine; + KM_CORE_DEBUG_NOMATCH_ENTER, + KM_CORE_DEBUG_NOMATCH_EXIT: if grp > -1 then Result := debugkeyboard.Groups[grp].NomatchLine; end; end; @@ -297,13 +297,13 @@ procedure TDebugEventList.AddDebugItem( { Update user interface } - if ev.Rule.ItemType = KM_KBP_DEBUG_BEGIN then + if ev.Rule.ItemType = KM_CORE_DEBUG_BEGIN then begin ev.Rule.Key.VirtualKey := vk; ev.Rule.Key.Modifiers := modifier_state; end; - if ev.Rule.ItemType = KM_KBP_DEBUG_SET_OPTION then + if ev.Rule.ItemType = KM_CORE_DEBUG_SET_OPTION then begin store := PKeymanStore(debug.kmx_info.option.store); ev.Rule.OptionStoreName := store.dpName; @@ -312,16 +312,16 @@ procedure TDebugEventList.AddDebugItem( end; function TDebugEventList.AddStateItems( - state: pkm_kbp_state; + state: pkm_core_state; vk: uint16_t; modifier_state: uint16_t ): Boolean; var - action: pkm_kbp_action_item; + action: pkm_core_action_item; begin Result := True; - action := km_kbp_state_action_items(state, nil); - while (action._type <> KM_KBP_IT_END) do + action := km_core_state_action_items(state, nil); + while (action._type <> KM_CORE_IT_END) do begin Result := Result and AddActionItem(vk, action); Inc(action); @@ -329,25 +329,25 @@ function TDebugEventList.AddStateItems( end; function TDebugEventList.AddStateItems( - state: pkm_kbp_state; + state: pkm_core_state; vk: uint16_t; modifier_state: uint16_t; debugkeyboard: TDebugKeyboard ): Boolean; var - action: pkm_kbp_action_item; - debug: pkm_kbp_state_debug_item; + action: pkm_core_action_item; + debug: pkm_core_state_debug_item; action_index: Integer; begin Result := True; - debug := km_kbp_state_debug_items(state, nil); - action := km_kbp_state_action_items(state, nil); + debug := km_core_state_debug_items(state, nil); + action := km_core_state_action_items(state, nil); action_index := 0; - while debug._type <> KM_KBP_DEBUG_END do + while debug._type <> KM_CORE_DEBUG_END do begin if debug.kmx_info.first_action > action_index then begin - while (action._type <> KM_KBP_IT_END) and (action_index < debug.kmx_info.first_action) do + while (action._type <> KM_CORE_IT_END) and (action_index < debug.kmx_info.first_action) do begin Result := Result and AddActionItem(vk, action); Inc(action); @@ -360,7 +360,7 @@ function TDebugEventList.AddStateItems( AddDebugItem(debug, debugkeyboard, vk, modifier_state); - if action._type = KM_KBP_IT_EMIT_KEYSTROKE then + if action._type = KM_CORE_IT_EMIT_KEYSTROKE then begin // The EMIT_KEYSTROKE action comes after all rules have completed processing Result := Result and AddActionItem(vk, action); @@ -369,12 +369,12 @@ function TDebugEventList.AddStateItems( // By the time we get to the end of rule processing, all actions should have // already been undertaken - Assert(action._type = KM_KBP_IT_END); + Assert(action._type = KM_CORE_IT_END); end; { TDebugEventRuleData } -procedure TDebugEventRuleData.FillStoreList(event: pkm_kbp_state_debug_item; KeyboardMemory: PChar); +procedure TDebugEventRuleData.FillStoreList(event: pkm_core_state_debug_item; KeyboardMemory: PChar); function StoreOffset(kfh: PKeyboardFileHeader; i: Word): PChar; begin Result := KeyboardMemory; diff --git a/developer/src/tike/debug/UfrmDebugStatus_CallStack.pas b/developer/src/tike/debug/UfrmDebugStatus_CallStack.pas index a46caa0d091..4d47fd49857 100644 --- a/developer/src/tike/debug/UfrmDebugStatus_CallStack.pas +++ b/developer/src/tike/debug/UfrmDebugStatus_CallStack.pas @@ -1,18 +1,18 @@ (* Name: UfrmDebugStatus_CallStack Copyright: Copyright (C) SIL International. - Documentation: - Description: + Documentation: + Description: Create Date: 14 Sep 2006 Modified Date: 14 Sep 2006 Authors: mcdurdin - Related Files: - Dependencies: + Related Files: + Dependencies: - Bugs: - Todo: - Notes: + Bugs: + Todo: + Notes: History: 14 Sep 2006 - mcdurdin - Initial version *) unit UfrmDebugStatus_CallStack; @@ -73,9 +73,9 @@ procedure TfrmDebugStatus_CallStack.CallStackPush(rule: TDebugEventRuleData); s: string; begin case rule.ItemType of - KM_KBP_DEBUG_BEGIN: + KM_CORE_DEBUG_BEGIN: lbCallStack.Items.AddObject('begin Unicode', rule); - KM_KBP_DEBUG_GROUP_ENTER: + KM_CORE_DEBUG_GROUP_ENTER: if rule.Group.dpName <> '' then begin s := 'group('+rule.Group.dpName+')'; @@ -84,11 +84,11 @@ procedure TfrmDebugStatus_CallStack.CallStackPush(rule: TDebugEventRuleData); end else lbCallStack.Items.AddObject('Unknown group', rule); - KM_KBP_DEBUG_RULE_ENTER: + KM_CORE_DEBUG_RULE_ENTER: lbCallStack.Items.AddObject('rule at line '+IntToStr(rule.line), rule); - KM_KBP_DEBUG_MATCH_ENTER: + KM_CORE_DEBUG_MATCH_ENTER: lbCallStack.Items.AddObject('match rule', rule); - KM_KBP_DEBUG_NOMATCH_ENTER: + KM_CORE_DEBUG_NOMATCH_ENTER: lbCallStack.Items.AddObject('nomatch rule', rule); end; end; diff --git a/developer/src/tike/debug/UfrmDebugStatus_Events.pas b/developer/src/tike/debug/UfrmDebugStatus_Events.pas index 46a60e43d34..4726b081058 100644 --- a/developer/src/tike/debug/UfrmDebugStatus_Events.pas +++ b/developer/src/tike/debug/UfrmDebugStatus_Events.pas @@ -77,11 +77,11 @@ procedure TfrmDebugStatus_Events.AddRuleEvent(rule: TDebugEventRuleData); s: string; begin case rule.ItemType of - KM_KBP_DEBUG_BEGIN, - KM_KBP_DEBUG_END: - AddItem(rule.ItemType = KM_KBP_DEBUG_BEGIN, 'begin Unicode', rule); - KM_KBP_DEBUG_GROUP_ENTER, - KM_KBP_DEBUG_GROUP_EXIT: + KM_CORE_DEBUG_BEGIN, + KM_CORE_DEBUG_END: + AddItem(rule.ItemType = KM_CORE_DEBUG_BEGIN, 'begin Unicode', rule); + KM_CORE_DEBUG_GROUP_ENTER, + KM_CORE_DEBUG_GROUP_EXIT: begin if rule.Group.dpName <> '' then begin @@ -90,18 +90,18 @@ procedure TfrmDebugStatus_Events.AddRuleEvent(rule: TDebugEventRuleData); end else s := 'Unknown group'; - AddItem(rule.ItemType = KM_KBP_DEBUG_GROUP_ENTER, s, rule); + AddItem(rule.ItemType = KM_CORE_DEBUG_GROUP_ENTER, s, rule); end; - KM_KBP_DEBUG_RULE_ENTER, - KM_KBP_DEBUG_RULE_EXIT: - AddItem(rule.ItemType = KM_KBP_DEBUG_RULE_ENTER, 'rule at line '+IntToStr(rule.line), rule); - KM_KBP_DEBUG_MATCH_ENTER, - KM_KBP_DEBUG_MATCH_EXIT: - AddItem(rule.ItemType = KM_KBP_DEBUG_MATCH_ENTER, 'match rule', rule); - KM_KBP_DEBUG_NOMATCH_ENTER, - KM_KBP_DEBUG_NOMATCH_EXIT: - AddItem(rule.ItemType = KM_KBP_DEBUG_NOMATCH_ENTER, 'nomatch rule', rule); - KM_KBP_DEBUG_SET_OPTION: + KM_CORE_DEBUG_RULE_ENTER, + KM_CORE_DEBUG_RULE_EXIT: + AddItem(rule.ItemType = KM_CORE_DEBUG_RULE_ENTER, 'rule at line '+IntToStr(rule.line), rule); + KM_CORE_DEBUG_MATCH_ENTER, + KM_CORE_DEBUG_MATCH_EXIT: + AddItem(rule.ItemType = KM_CORE_DEBUG_MATCH_ENTER, 'match rule', rule); + KM_CORE_DEBUG_NOMATCH_ENTER, + KM_CORE_DEBUG_NOMATCH_EXIT: + AddItem(rule.ItemType = KM_CORE_DEBUG_NOMATCH_ENTER, 'nomatch rule', rule); + KM_CORE_DEBUG_SET_OPTION: AddItem(True, 'set option', rule); else lbCallStack.Items.AddObject('???', rule); @@ -115,16 +115,16 @@ procedure TfrmDebugStatus_Events.AddActionEvent(action: TDebugEventActionData); end; begin case action.ActionType of - KM_KBP_IT_EMIT_KEYSTROKE: AddItem('emit_keystroke', action); + KM_CORE_IT_EMIT_KEYSTROKE: AddItem('emit_keystroke', action); // QIT_VSHIFTDOWN: AddItem('vshiftdown', action); // QIT_VSHIFTUP: AddItem('vshiftup', action); - KM_KBP_IT_CHAR: AddItem('char', action); - KM_KBP_IT_MARKER: AddItem('marker', action); - KM_KBP_IT_ALERT: AddItem('alert', action); - KM_KBP_IT_BACK: AddItem('back', action); - KM_KBP_IT_PERSIST_OPT: AddItem('persist_opt', action); - KM_KBP_IT_INVALIDATE_CONTEXT: AddItem('invalidate_context', action); - KM_KBP_IT_CAPSLOCK: AddItem('capslock', action); + KM_CORE_IT_CHAR: AddItem('char', action); + KM_CORE_IT_MARKER: AddItem('marker', action); + KM_CORE_IT_ALERT: AddItem('alert', action); + KM_CORE_IT_BACK: AddItem('back', action); + KM_CORE_IT_PERSIST_OPT: AddItem('persist_opt', action); + KM_CORE_IT_INVALIDATE_CONTEXT: AddItem('invalidate_context', action); + KM_CORE_IT_CAPSLOCK: AddItem('capslock', action); else AddItem('Unknown action ???', action); end; end; diff --git a/developer/src/tike/main/Keyman.System.KeymanCore.pas b/developer/src/tike/main/Keyman.System.KeymanCore.pas index 29a2341b182..8abe0733175 100644 --- a/developer/src/tike/main/Keyman.System.KeymanCore.pas +++ b/developer/src/tike/main/Keyman.System.KeymanCore.pas @@ -1,7 +1,7 @@ { * Keyman is copyright (C) SIL International. MIT License. * - * Interface for Keyman Core, matches keyboardprocessor.h + * Interface for Keyman Core, matches keyman_core_api.h } unit Keyman.System.KeymanCore; @@ -17,63 +17,63 @@ interface uintptr_t = NativeUInt; char16_t = Char; - km_kbp_virtual_key = uint16_t; + km_core_virtual_key = uint16_t; - km_kbp_usv = uint32_t; // UTF-32 - km_kbp_cp = WideChar; - pkm_kbp_cp = ^km_kbp_cp; + km_core_usv = uint32_t; // UTF-32 + km_core_cp = WideChar; + pkm_core_cp = ^km_core_cp; - km_kbp_context = record end; - pkm_kbp_context = ^km_kbp_context; + km_core_context = record end; + pkm_core_context = ^km_core_context; - km_kbp_keyboard = record end; - pkm_kbp_keyboard = ^km_kbp_keyboard; + km_core_keyboard = record end; + pkm_core_keyboard = ^km_core_keyboard; - km_kbp_state = record end; - pkm_kbp_state = ^km_kbp_state; + km_core_state = record end; + pkm_core_state = ^km_core_state; - km_kbp_options = record end; - pkm_kbp_options = ^km_kbp_options; + km_core_options = record end; + pkm_core_options = ^km_core_options; - km_kbp_path_name = PWideChar; // on Windows - pkm_kbp_path_name = ^km_kbp_path_name; + km_core_path_name = PWideChar; // on Windows + pkm_core_path_name = ^km_core_path_name; type - km_kbp_status = ( - KM_KBP_STATUS_OK = 0, - KM_KBP_STATUS_NO_MEM = 1, - KM_KBP_STATUS_IO_ERROR = 2, - KM_KBP_STATUS_INVALID_ARGUMENT = 3, - KM_KBP_STATUS_KEY_ERROR = 4, - KM_KBP_STATUS_INSUFFICENT_BUFFER = 5, - KM_KBP_STATUS_INVALID_UTF = 6, - KM_KBP_STATUS_INVALID_KEYBOARD = 7 + km_core_status = ( + KM_CORE_STATUS_OK = 0, + KM_CORE_STATUS_NO_MEM = 1, + KM_CORE_STATUS_IO_ERROR = 2, + KM_CORE_STATUS_INVALID_ARGUMENT = 3, + KM_CORE_STATUS_KEY_ERROR = 4, + KM_CORE_STATUS_INSUFFICENT_BUFFER = 5, + KM_CORE_STATUS_INVALID_UTF = 6, + KM_CORE_STATUS_INVALID_KEYBOARD = 7 ); type - km_kbp_context_type = ( - KM_KBP_CT_END = 0, - KM_KBP_CT_CHAR, - KM_KBP_CT_MARKER + km_core_context_type = ( + KM_CORE_CT_END = 0, + KM_CORE_CT_CHAR, + KM_CORE_CT_MARKER ); - km_kbp_context_item = record - _type: km_kbp_context_type; + km_core_context_item = record + _type: km_core_context_type; {$IFDEF WIN64} _reserved: array[0..6] of uint8_t; {$ELSE} _reserved: array[0..2] of uint8_t; {$ENDIF} case integer of - 1: (character: km_kbp_usv); + 1: (character: km_core_usv); 2: (marker: uint32_t); end; - pkm_kbp_context_item = ^km_kbp_context_item; + pkm_core_context_item = ^km_core_context_item; const - KM_KBP_CONTEXT_ITEM_END: km_kbp_context_item = ( - _type: KM_KBP_CT_END; + KM_CORE_CONTEXT_ITEM_END: km_core_context_item = ( + _type: KM_CORE_CT_END; _reserved: (0,0,0); character: 0 ); @@ -81,111 +81,111 @@ km_kbp_context_item = record const kmnkbp0 = 'kmnkbp0-0.dll'; -function km_kbp_context_items_from_utf16( - const text: pkm_kbp_cp; - var out_ptr: pkm_kbp_context_item -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_context_items_from_utf16( + const text: pkm_core_cp; + var out_ptr: pkm_core_context_item +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_context_items_from_utf8( +function km_core_context_items_from_utf8( const text: PAnsiChar; - var out_ptr: pkm_kbp_context_item -): km_kbp_status; cdecl; external kmnkbp0 delayed; + var out_ptr: pkm_core_context_item +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_context_items_to_utf16( - const item: pkm_kbp_context_item; - buf: pkm_kbp_cp; +function km_core_context_items_to_utf16( + const item: pkm_core_context_item; + buf: pkm_core_cp; var buf_size: integer -): km_kbp_status; cdecl; external kmnkbp0 delayed; +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_context_items_to_utf8( - const item: pkm_kbp_context_item; +function km_core_context_items_to_utf8( + const item: pkm_core_context_item; buf: pansichar; var buf_size: integer -): km_kbp_status; cdecl; external kmnkbp0 delayed; +): km_core_status; cdecl; external kmnkbp0 delayed; -procedure km_kbp_context_items_dispose( - const context_items: km_kbp_context_item +procedure km_core_context_items_dispose( + const context_items: km_core_context_item ); cdecl; external kmnkbp0 delayed; -function km_kbp_context_set( - context: pkm_kbp_context; - context_items: pkm_kbp_context_item -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_context_set( + context: pkm_core_context; + context_items: pkm_core_context_item +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_context_get( - context: pkm_kbp_context; - var context_items: pkm_kbp_context_item -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_context_get( + context: pkm_core_context; + var context_items: pkm_core_context_item +): km_core_status; cdecl; external kmnkbp0 delayed; -procedure km_kbp_context_clear( - context: pkm_kbp_context +procedure km_core_context_clear( + context: pkm_core_context ); cdecl; external kmnkbp0 delayed; -function km_kbp_context_append( - context: pkm_kbp_context; - context_items: pkm_kbp_context_item -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_context_append( + context: pkm_core_context; + context_items: pkm_core_context_item +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_context_shrink( - context: pkm_kbp_context; +function km_core_context_shrink( + context: pkm_core_context; num: Integer; - prefix: pkm_kbp_context_item -): km_kbp_status; cdecl; external kmnkbp0 delayed; + prefix: pkm_core_context_item +): km_core_status; cdecl; external kmnkbp0 delayed; type - km_kbp_option_scope = ( - KM_KBP_OPT_UNKNOWN = 0, - KM_KBP_OPT_KEYBOARD = 1, - KM_KBP_OPT_ENVIRONMENT = 2, - KM_KBP_OPT_MAX_SCOPES + km_core_option_scope = ( + KM_CORE_OPT_UNKNOWN = 0, + KM_CORE_OPT_KEYBOARD = 1, + KM_CORE_OPT_ENVIRONMENT = 2, + KM_CORE_OPT_MAX_SCOPES ); - km_kbp_option_item = record - key: pkm_kbp_cp; - value: pkm_kbp_cp; - scope: km_kbp_option_scope; + km_core_option_item = record + key: pkm_core_cp; + value: pkm_core_cp; + scope: km_core_option_scope; end; - pkm_kbp_option_item = ^km_kbp_option_item; + pkm_core_option_item = ^km_core_option_item; const - KM_KBP_OPTIONS_END: km_kbp_option_item = (key: nil; value: nil; scope: KM_KBP_OPT_UNKNOWN); + KM_CORE_OPTIONS_END: km_core_option_item = (key: nil; value: nil; scope: KM_CORE_OPT_UNKNOWN); type - km_kbp_action_type = ( - KM_KBP_IT_END = 0, // Marks end of action items list. - KM_KBP_IT_CHAR = 1, // A Unicode character has been generated. - KM_KBP_IT_MARKER = 2, // Correlates to kmn's "deadkey" markers. - KM_KBP_IT_ALERT = 3, // The keyboard has triggered a alert/beep/bell. - KM_KBP_IT_BACK = 4, // Delete the codepoint preceding the insertion point. - KM_KBP_IT_PERSIST_OPT = 5, // The indicated option needs to be stored. - KM_KBP_IT_EMIT_KEYSTROKE = 6, // Emit the current keystroke to the application - KM_KBP_IT_INVALIDATE_CONTEXT = 7, + km_core_action_type = ( + KM_CORE_IT_END = 0, // Marks end of action items list. + KM_CORE_IT_CHAR = 1, // A Unicode character has been generated. + KM_CORE_IT_MARKER = 2, // Correlates to kmn's "deadkey" markers. + KM_CORE_IT_ALERT = 3, // The keyboard has triggered a alert/beep/bell. + KM_CORE_IT_BACK = 4, // Delete the codepoint preceding the insertion point. + KM_CORE_IT_PERSIST_OPT = 5, // The indicated option needs to be stored. + KM_CORE_IT_EMIT_KEYSTROKE = 6, // Emit the current keystroke to the application + KM_CORE_IT_INVALIDATE_CONTEXT = 7, // The processor requests that the context buffer be cleared; // for applications where context is cached, this clears the context; // for applications where context is read from the focused text store, // the context is just re-read and markers flushed. - KM_KBP_IT_CAPSLOCK = 8, // Enable or disable capsLock - KM_KBP_IT_MAX_TYPE_ID + KM_CORE_IT_CAPSLOCK = 8, // Enable or disable capsLock + KM_CORE_IT_MAX_TYPE_ID ); - km_kbp_backspace_type = ( - KM_KBP_BT_UNKNOWN = 0, // Used at beginning of context; user-initiated backspace - KM_KBP_BT_CHAR = 1, // Deleting a character prior to insertion point - KM_KBP_BT_MARKER = 2, // Deleting a marker prior to insertion point - KM_KBP_BT_MAX_TYPE_ID + km_core_backspace_type = ( + KM_CORE_BT_UNKNOWN = 0, // Used at beginning of context; user-initiated backspace + KM_CORE_BT_CHAR = 1, // Deleting a character prior to insertion point + KM_CORE_BT_MARKER = 2, // Deleting a marker prior to insertion point + KM_CORE_BT_MAX_TYPE_ID ); - km_kbp_backspace_item = record - expected_type: uint8_t; /// TODO: km_kbp_backspace_type + km_core_backspace_item = record + expected_type: uint8_t; /// TODO: km_core_backspace_type expected_value: uintptr_t; /// used mainly in unit tests end; - km_kbp_action_item = record - _type: km_kbp_action_type; + km_core_action_item = record + _type: km_core_action_type; {$IFDEF WIN64} _reserved: array[0..6] of uint8_t; {$ELSE} @@ -193,97 +193,97 @@ km_kbp_action_item = record {$ENDIF} case Integer of 0: (marker: uintptr_t); - 1: (option: pkm_kbp_option_item); - 2: (character: km_kbp_usv); - 3: (backspace: km_kbp_backspace_item); + 1: (option: pkm_core_option_item); + 2: (character: km_core_usv); + 3: (backspace: km_core_backspace_item); 4: (capsLock: uint8_t); // CAPSLOCK type, 1 to turn on, 0 to turn off end; - pkm_kbp_action_item = ^km_kbp_action_item; + pkm_core_action_item = ^km_core_action_item; // These types are used only for debugging convenience type - km_kbp_action_item_array = array[0..100] of km_kbp_action_item; - pkm_kbp_action_item_array = ^km_kbp_action_item_array; + km_core_action_item_array = array[0..100] of km_core_action_item; + pkm_core_action_item_array = ^km_core_action_item_array; -function km_kbp_options_list_size( - opts: pkm_kbp_option_item +function km_core_options_list_size( + opts: pkm_core_option_item ): Integer; cdecl; external kmnkbp0 delayed; -function km_kbp_state_option_lookup( - state: pkm_kbp_state; - scope: km_kbp_option_scope; - key: pkm_kbp_cp; - var value: pkm_kbp_cp -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_state_option_lookup( + state: pkm_core_state; + scope: km_core_option_scope; + key: pkm_core_cp; + var value: pkm_core_cp +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_state_options_update( - state: pkm_kbp_state; - new_opts: pkm_kbp_option_item -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_state_options_update( + state: pkm_core_state; + new_opts: pkm_core_option_item +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_state_options_to_json( - state: pkm_kbp_state; +function km_core_state_options_to_json( + state: pkm_core_state; buf: PAnsiChar; var space: Integer -): km_kbp_status; cdecl; external kmnkbp0 delayed; +): km_core_status; cdecl; external kmnkbp0 delayed; type - km_kbp_keyboard_attrs = record - version_string: pkm_kbp_cp; - id: pkm_kbp_cp; - folder_path: km_kbp_path_name; - default_optons: pkm_kbp_option_item + km_core_keyboard_attrs = record + version_string: pkm_core_cp; + id: pkm_core_cp; + folder_path: km_core_path_name; + default_optons: pkm_core_option_item end; - pkm_kbp_keyboard_attrs = ^km_kbp_keyboard_attrs; + pkm_core_keyboard_attrs = ^km_core_keyboard_attrs; -function km_kbp_keyboard_load( - kb_path: km_kbp_path_name; - var keyboard: pkm_kbp_keyboard -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_keyboard_load( + kb_path: km_core_path_name; + var keyboard: pkm_core_keyboard +): km_core_status; cdecl; external kmnkbp0 delayed; -procedure km_kbp_keyboard_dispose( - keyboard: pkm_kbp_keyboard +procedure km_core_keyboard_dispose( + keyboard: pkm_core_keyboard ); cdecl; external kmnkbp0 delayed; -function km_kbp_keyboard_get_attrs( - keyboard: pkm_kbp_keyboard; - var out: pkm_kbp_keyboard_attrs -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_keyboard_get_attrs( + keyboard: pkm_core_keyboard; + var out: pkm_core_keyboard_attrs +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_state_create( - keyboard: pkm_kbp_keyboard; - env: pkm_kbp_option_item; - var out: pkm_kbp_state -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_state_create( + keyboard: pkm_core_keyboard; + env: pkm_core_option_item; + var out: pkm_core_state +): km_core_status; cdecl; external kmnkbp0 delayed; -function km_kbp_state_clone( - state: pkm_kbp_state; - var out: pkm_kbp_state -): km_kbp_status; cdecl; external kmnkbp0 delayed; +function km_core_state_clone( + state: pkm_core_state; + var out: pkm_core_state +): km_core_status; cdecl; external kmnkbp0 delayed; -procedure km_kbp_state_dispose( - state: pkm_kbp_state +procedure km_core_state_dispose( + state: pkm_core_state ); cdecl; external kmnkbp0 delayed; -function km_kbp_state_context( - state: pkm_kbp_state -): pkm_kbp_context; cdecl; external kmnkbp0 delayed; +function km_core_state_context( + state: pkm_core_state +): pkm_core_context; cdecl; external kmnkbp0 delayed; -function km_kbp_state_action_items( - state: pkm_kbp_state; +function km_core_state_action_items( + state: pkm_core_state; num_items: pinteger -): pkm_kbp_action_item; cdecl; external kmnkbp0 delayed; +): pkm_core_action_item; cdecl; external kmnkbp0 delayed; -function km_kbp_state_to_json( - state: pkm_kbp_state; +function km_core_state_to_json( + state: pkm_core_state; buf: PAnsiChar; space: pinteger -): km_kbp_status; cdecl; external kmnkbp0 delayed; +): km_core_status; cdecl; external kmnkbp0 delayed; type - km_kbp_attr = record + km_core_attr = record max_context: Integer; // Maximum context size supported by processor. current: uint16_t; // Current API number supported. revision: uint16_t; // Implementation number of current API. @@ -293,344 +293,344 @@ km_kbp_attr = record vendor: pansichar // Implementor of the processor. end; - pkm_kbp_attr = ^km_kbp_attr; + pkm_core_attr = ^km_core_attr; - km_kbp_tech_value = ( - KM_KBP_TECH_UNSPECIFIED = 0, - KM_KBP_TECH_MOCK = 1 shl 0, - KM_KBP_TECH_KMX = 1 shl 1, - KM_KBP_TECH_LDML = 1 shl 2, - KM_KBP_TECH_RUST_MOCK = 1 shl 3 + km_core_tech_value = ( + KM_CORE_TECH_UNSPECIFIED = 0, + KM_CORE_TECH_MOCK = 1 shl 0, + KM_CORE_TECH_KMX = 1 shl 1, + KM_CORE_TECH_LDML = 1 shl 2, + KM_CORE_TECH_RUST_MOCK = 1 shl 3 ); -function km_kbp_get_engine_attrs( - state: pkm_kbp_state -): pkm_kbp_attr; cdecl; external kmnkbp0 delayed; +function km_core_get_engine_attrs( + state: pkm_core_state +): pkm_core_attr; cdecl; external kmnkbp0 delayed; function -km_kbp_process_event( - state: pkm_kbp_state; - vk: km_kbp_virtual_key; +km_core_process_event( + state: pkm_core_state; + vk: km_core_virtual_key; modifier_state: uint16_t; is_key_down: uint8_t; event_flags: uint16_t -): km_kbp_status; cdecl; external kmnkbp0 delayed; +): km_core_status; cdecl; external kmnkbp0 delayed; const - KM_KBP_EVENT_FLAG_DEFAULT = 0; // default value: hardware - KM_KBP_EVENT_FLAG_TOUCH = 1; // set if the event is touch, otherwise hardware + KM_CORE_EVENT_FLAG_DEFAULT = 0; // default value: hardware + KM_CORE_EVENT_FLAG_TOUCH = 1; // set if the event is touch, otherwise hardware -// keyboardprocessor_vkeys.h +// keyman_core_api_vkeys.h const -// enum km_kbp_modifier_state - matches Keyman32 shift states - KM_KBP_MODIFIER_LCTRL = 1 shl 0; - KM_KBP_MODIFIER_RCTRL = 1 shl 1; - KM_KBP_MODIFIER_LALT = 1 shl 2; - KM_KBP_MODIFIER_RALT = 1 shl 3; - KM_KBP_MODIFIER_SHIFT = 1 shl 4; - KM_KBP_MODIFIER_CTRL = 1 shl 5; - KM_KBP_MODIFIER_ALT = 1 shl 6; +// enum km_core_modifier_state - matches Keyman32 shift states + KM_CORE_MODIFIER_LCTRL = 1 shl 0; + KM_CORE_MODIFIER_RCTRL = 1 shl 1; + KM_CORE_MODIFIER_LALT = 1 shl 2; + KM_CORE_MODIFIER_RALT = 1 shl 3; + KM_CORE_MODIFIER_SHIFT = 1 shl 4; + KM_CORE_MODIFIER_CTRL = 1 shl 5; + KM_CORE_MODIFIER_ALT = 1 shl 6; { - KM_KBP_MODIFIER_META = 1 shl 7, // Either Meta-key flag (tentative). Not usable by keyboards currently + KM_CORE_MODIFIER_META = 1 shl 7, // Either Meta-key flag (tentative). Not usable by keyboards currently // Used internally (currently, only by KMW) to ensure Meta-key // shortcuts safely bypass rules // Meta key = Command key on macOS, Windows key on Windows } - KM_KBP_MODIFIER_CAPS = 1 shl 8; - KM_KBP_MODIFIER_NOCAPS = 1 shl 9; + KM_CORE_MODIFIER_CAPS = 1 shl 8; + KM_CORE_MODIFIER_NOCAPS = 1 shl 9; { - KM_KBP_MODIFIER_NUMLOCK = 1 << 10, - KM_KBP_MODIFIER_NONUMLOCK = 1 << 11, - KM_KBP_MODIFIER_SCROLLOCK = 1 << 12, - KM_KBP_MODIFIER_NOSCROLLOCK = 1 << 13, - KM_KBP_MODIFIER_VIRTUALKEY = 1 << 14, + KM_CORE_MODIFIER_NUMLOCK = 1 << 10, + KM_CORE_MODIFIER_NONUMLOCK = 1 << 11, + KM_CORE_MODIFIER_SCROLLOCK = 1 << 12, + KM_CORE_MODIFIER_NOSCROLLOCK = 1 << 13, + KM_CORE_MODIFIER_VIRTUALKEY = 1 << 14, } const -// enum km_kbp_modifier_mask - KM_KBP_MODIFIER_MASK_ALL = $7f; - KM_KBP_MODIFIER_MASK_ALT_GR_SIM = KM_KBP_MODIFIER_LCTRL or KM_KBP_MODIFIER_LALT; - KM_KBP_MODIFIER_MASK_CHIRAL = $1f; - KM_KBP_MODIFIER_MASK_IS_CHIRAL = $0f; - KM_KBP_MODIFIER_MASK_NON_CHIRAL = $7f; - KM_KBP_MODIFIER_MASK_CAPS = $0300; -{KM_KBP_MODIFIER_MASK_NUMLOCK = $0C00, - KM_KBP_MODIFIER_MASK_SCROLLLOCK = $3000,} +// enum km_core_modifier_mask + KM_CORE_MODIFIER_MASK_ALL = $7f; + KM_CORE_MODIFIER_MASK_ALT_GR_SIM = KM_CORE_MODIFIER_LCTRL or KM_CORE_MODIFIER_LALT; + KM_CORE_MODIFIER_MASK_CHIRAL = $1f; + KM_CORE_MODIFIER_MASK_IS_CHIRAL = $0f; + KM_CORE_MODIFIER_MASK_NON_CHIRAL = $7f; + KM_CORE_MODIFIER_MASK_CAPS = $0300; +{KM_CORE_MODIFIER_MASK_NUMLOCK = $0C00, + KM_CORE_MODIFIER_MASK_SCROLLLOCK = $3000,} // These are Windows API VKEYs, using Keyman VKEY names. const // enum km_kpb_virtual_key - KM_KBP_VKEY__00 = $00; - KM_KBP_VKEY_LBUTTON = $01; - KM_KBP_VKEY_RBUTTON = $02; - KM_KBP_VKEY_CANCEL = $03; - KM_KBP_VKEY_MBUTTON = $04; - KM_KBP_VKEY__05 = $05; - KM_KBP_VKEY__06 = $06; - KM_KBP_VKEY__07 = $07; - KM_KBP_VKEY_BKSP = $08; - KM_KBP_VKEY_TAB = $09; - KM_KBP_VKEY__0A = $0A; - KM_KBP_VKEY__0B = $0B; - KM_KBP_VKEY_KP5 = $0C; - KM_KBP_VKEY_ENTER = $0D; - KM_KBP_VKEY__0E = $0E; - KM_KBP_VKEY__0F = $0F; - KM_KBP_VKEY_SHIFT = $10; - KM_KBP_VKEY_CONTROL = $11; - KM_KBP_VKEY_ALT = $12; - KM_KBP_VKEY_PAUSE = $13; - KM_KBP_VKEY_CAPS = $14; - KM_KBP_VKEY__15 = $15; - KM_KBP_VKEY__16 = $16; - KM_KBP_VKEY__17 = $17; - KM_KBP_VKEY__18 = $18; - KM_KBP_VKEY__19 = $19; - KM_KBP_VKEY__1A = $1A; - KM_KBP_VKEY_ESC = $1B; - KM_KBP_VKEY__1C = $1C; - KM_KBP_VKEY__1D = $1D; - KM_KBP_VKEY__1E = $1E; - KM_KBP_VKEY__1F = $1F; - KM_KBP_VKEY_SPACE = $20; - KM_KBP_VKEY_PGUP = $21; - KM_KBP_VKEY_PGDN = $22; - KM_KBP_VKEY_END = $23; - KM_KBP_VKEY_HOME = $24; - KM_KBP_VKEY_LEFT = $25; - KM_KBP_VKEY_UP = $26; - KM_KBP_VKEY_RIGHT = $27; - KM_KBP_VKEY_DOWN = $28; - KM_KBP_VKEY_SEL = $29; - KM_KBP_VKEY_PRINT = $2A; - KM_KBP_VKEY_EXEC = $2B; - KM_KBP_VKEY_PRTSCN = $2C; - KM_KBP_VKEY_INS = $2D; - KM_KBP_VKEY_DEL = $2E; - KM_KBP_VKEY_HELP = $2F; - KM_KBP_VKEY_0 = $30; - KM_KBP_VKEY_1 = $31; - KM_KBP_VKEY_2 = $32; - KM_KBP_VKEY_3 = $33; - KM_KBP_VKEY_4 = $34; - KM_KBP_VKEY_5 = $35; - KM_KBP_VKEY_6 = $36; - KM_KBP_VKEY_7 = $37; - KM_KBP_VKEY_8 = $38; - KM_KBP_VKEY_9 = $39; - KM_KBP_VKEY__3A = $3A; - KM_KBP_VKEY__3B = $3B; - KM_KBP_VKEY__3C = $3C; - KM_KBP_VKEY__3D = $3D; - KM_KBP_VKEY__3E = $3E; - KM_KBP_VKEY__3F = $3F; - KM_KBP_VKEY__40 = $40; - KM_KBP_VKEY_A = $41; - KM_KBP_VKEY_B = $42; - KM_KBP_VKEY_C = $43; - KM_KBP_VKEY_D = $44; - KM_KBP_VKEY_E = $45; - KM_KBP_VKEY_F = $46; - KM_KBP_VKEY_G = $47; - KM_KBP_VKEY_H = $48; - KM_KBP_VKEY_I = $49; - KM_KBP_VKEY_J = $4A; - KM_KBP_VKEY_K = $4B; - KM_KBP_VKEY_L = $4C; - KM_KBP_VKEY_M = $4D; - KM_KBP_VKEY_N = $4E; - KM_KBP_VKEY_O = $4F; - KM_KBP_VKEY_P = $50; - KM_KBP_VKEY_Q = $51; - KM_KBP_VKEY_R = $52; - KM_KBP_VKEY_S = $53; - KM_KBP_VKEY_T = $54; - KM_KBP_VKEY_U = $55; - KM_KBP_VKEY_V = $56; - KM_KBP_VKEY_W = $57; - KM_KBP_VKEY_X = $58; - KM_KBP_VKEY_Y = $59; - KM_KBP_VKEY_Z = $5A; - KM_KBP_VKEY__5B = $5B; - KM_KBP_VKEY__5C = $5C; - KM_KBP_VKEY__5D = $5D; - KM_KBP_VKEY__5E = $5E; - KM_KBP_VKEY__5F = $5F; - KM_KBP_VKEY_NP0 = $60; - KM_KBP_VKEY_NP1 = $61; - KM_KBP_VKEY_NP2 = $62; - KM_KBP_VKEY_NP3 = $63; - KM_KBP_VKEY_NP4 = $64; - KM_KBP_VKEY_NP5 = $65; - KM_KBP_VKEY_NP6 = $66; - KM_KBP_VKEY_NP7 = $67; - KM_KBP_VKEY_NP8 = $68; - KM_KBP_VKEY_NP9 = $69; - KM_KBP_VKEY_NPSTAR = $6A; - KM_KBP_VKEY_NPPLUS = $6B; - KM_KBP_VKEY_SEPARATOR = $6C; - KM_KBP_VKEY_NPMINUS = $6D; - KM_KBP_VKEY_NPDOT = $6E; - KM_KBP_VKEY_NPSLASH = $6F; - KM_KBP_VKEY_F1 = $70; - KM_KBP_VKEY_F2 = $71; - KM_KBP_VKEY_F3 = $72; - KM_KBP_VKEY_F4 = $73; - KM_KBP_VKEY_F5 = $74; - KM_KBP_VKEY_F6 = $75; - KM_KBP_VKEY_F7 = $76; - KM_KBP_VKEY_F8 = $77; - KM_KBP_VKEY_F9 = $78; - KM_KBP_VKEY_F10 = $79; - KM_KBP_VKEY_F11 = $7A; - KM_KBP_VKEY_F12 = $7B; - KM_KBP_VKEY_F13 = $7C; - KM_KBP_VKEY_F14 = $7D; - KM_KBP_VKEY_F15 = $7E; - KM_KBP_VKEY_F16 = $7F; - KM_KBP_VKEY_F17 = $80; - KM_KBP_VKEY_F18 = $81; - KM_KBP_VKEY_F19 = $82; - KM_KBP_VKEY_F20 = $83; - KM_KBP_VKEY_F21 = $84; - KM_KBP_VKEY_F22 = $85; - KM_KBP_VKEY_F23 = $86; - KM_KBP_VKEY_F24 = $87; - KM_KBP_VKEY__88 = $88; - KM_KBP_VKEY__89 = $89; - KM_KBP_VKEY__8A = $8A; - KM_KBP_VKEY__8B = $8B; - KM_KBP_VKEY__8C = $8C; - KM_KBP_VKEY__8D = $8D; - KM_KBP_VKEY__8E = $8E; - KM_KBP_VKEY__8F = $8F; - KM_KBP_VKEY_NUMLOCK = $90; - KM_KBP_VKEY_SCROLL = $91; - KM_KBP_VKEY__92 = $92; - KM_KBP_VKEY__93 = $93; - KM_KBP_VKEY__94 = $94; - KM_KBP_VKEY__95 = $95; - KM_KBP_VKEY__96 = $96; - KM_KBP_VKEY__97 = $97; - KM_KBP_VKEY__98 = $98; - KM_KBP_VKEY__99 = $99; - KM_KBP_VKEY__9A = $9A; - KM_KBP_VKEY__9B = $9B; - KM_KBP_VKEY__9C = $9C; - KM_KBP_VKEY__9D = $9D; - KM_KBP_VKEY__9E = $9E; - KM_KBP_VKEY__9F = $9F; - KM_KBP_VKEY__A0 = $A0; - KM_KBP_VKEY__A1 = $A1; - KM_KBP_VKEY__A2 = $A2; - KM_KBP_VKEY__A3 = $A3; - KM_KBP_VKEY__A4 = $A4; - KM_KBP_VKEY__A5 = $A5; - KM_KBP_VKEY__A6 = $A6; - KM_KBP_VKEY__A7 = $A7; - KM_KBP_VKEY__A8 = $A8; - KM_KBP_VKEY__A9 = $A9; - KM_KBP_VKEY__AA = $AA; - KM_KBP_VKEY__AB = $AB; - KM_KBP_VKEY__AC = $AC; - KM_KBP_VKEY__AD = $AD; - KM_KBP_VKEY__AE = $AE; - KM_KBP_VKEY__AF = $AF; - KM_KBP_VKEY__B0 = $B0; - KM_KBP_VKEY__B1 = $B1; - KM_KBP_VKEY__B2 = $B2; - KM_KBP_VKEY__B3 = $B3; - KM_KBP_VKEY__B4 = $B4; - KM_KBP_VKEY__B5 = $B5; - KM_KBP_VKEY__B6 = $B6; - KM_KBP_VKEY__B7 = $B7; - KM_KBP_VKEY__B8 = $B8; - KM_KBP_VKEY__B9 = $B9; - KM_KBP_VKEY_COLON = $BA; - KM_KBP_VKEY_EQUAL = $BB; - KM_KBP_VKEY_COMMA = $BC; - KM_KBP_VKEY_HYPHEN = $BD; - KM_KBP_VKEY_PERIOD = $BE; - KM_KBP_VKEY_SLASH = $BF; - KM_KBP_VKEY_BKQUOTE = $C0; - KM_KBP_VKEY__C1 = $C1; - KM_KBP_VKEY__C2 = $C2; - KM_KBP_VKEY__C3 = $C3; - KM_KBP_VKEY__C4 = $C4; - KM_KBP_VKEY__C5 = $C5; - KM_KBP_VKEY__C6 = $C6; - KM_KBP_VKEY__C7 = $C7; - KM_KBP_VKEY__C8 = $C8; - KM_KBP_VKEY__C9 = $C9; - KM_KBP_VKEY__CA = $CA; - KM_KBP_VKEY__CB = $CB; - KM_KBP_VKEY__CC = $CC; - KM_KBP_VKEY__CD = $CD; - KM_KBP_VKEY__CE = $CE; - KM_KBP_VKEY__CF = $CF; - KM_KBP_VKEY__D0 = $D0; - KM_KBP_VKEY__D1 = $D1; - KM_KBP_VKEY__D2 = $D2; - KM_KBP_VKEY__D3 = $D3; - KM_KBP_VKEY__D4 = $D4; - KM_KBP_VKEY__D5 = $D5; - KM_KBP_VKEY__D6 = $D6; - KM_KBP_VKEY__D7 = $D7; - KM_KBP_VKEY__D8 = $D8; - KM_KBP_VKEY__D9 = $D9; - KM_KBP_VKEY__DA = $DA; - KM_KBP_VKEY_LBRKT = $DB; - KM_KBP_VKEY_BKSLASH = $DC; - KM_KBP_VKEY_RBRKT = $DD; - KM_KBP_VKEY_QUOTE = $DE; - KM_KBP_VKEY_oDF = $DF; - KM_KBP_VKEY_oE0 = $E0; - KM_KBP_VKEY_oE1 = $E1; - KM_KBP_VKEY_oE2 = $E2; // 102nd key on European layouts - KM_KBP_VKEY_oE3 = $E3; - KM_KBP_VKEY_oE4 = $E4; - KM_KBP_VKEY__E5 = $E5; - KM_KBP_VKEY_oE6 = $E6; - KM_KBP_VKEY__E7 = $E7; - KM_KBP_VKEY__E8 = $E8; - KM_KBP_VKEY_oE9 = $E9; - KM_KBP_VKEY_oEA = $EA; - KM_KBP_VKEY_oEB = $EB; - KM_KBP_VKEY_oEC = $EC; - KM_KBP_VKEY_oED = $ED; - KM_KBP_VKEY_oEE = $EE; - KM_KBP_VKEY_oEF = $EF; - KM_KBP_VKEY_oF0 = $F0; - KM_KBP_VKEY_oF1 = $F1; - KM_KBP_VKEY_oF2 = $F2; - KM_KBP_VKEY_oF3 = $F3; - KM_KBP_VKEY_oF4 = $F4; - KM_KBP_VKEY_oF5 = $F5; - KM_KBP_VKEY__F6 = $F6; - KM_KBP_VKEY__F7 = $F7; - KM_KBP_VKEY__F8 = $F8; - KM_KBP_VKEY__F9 = $F9; - KM_KBP_VKEY__FA = $FA; - KM_KBP_VKEY__FB = $FB; - KM_KBP_VKEY__FC = $FC; - KM_KBP_VKEY__FD = $FD; - KM_KBP_VKEY__FE = $FE; - KM_KBP_VKEY__FF = $FF; - -// keyboardprocessor_consts.h + KM_CORE_VKEY__00 = $00; + KM_CORE_VKEY_LBUTTON = $01; + KM_CORE_VKEY_RBUTTON = $02; + KM_CORE_VKEY_CANCEL = $03; + KM_CORE_VKEY_MBUTTON = $04; + KM_CORE_VKEY__05 = $05; + KM_CORE_VKEY__06 = $06; + KM_CORE_VKEY__07 = $07; + KM_CORE_VKEY_BKSP = $08; + KM_CORE_VKEY_TAB = $09; + KM_CORE_VKEY__0A = $0A; + KM_CORE_VKEY__0B = $0B; + KM_CORE_VKEY_KP5 = $0C; + KM_CORE_VKEY_ENTER = $0D; + KM_CORE_VKEY__0E = $0E; + KM_CORE_VKEY__0F = $0F; + KM_CORE_VKEY_SHIFT = $10; + KM_CORE_VKEY_CONTROL = $11; + KM_CORE_VKEY_ALT = $12; + KM_CORE_VKEY_PAUSE = $13; + KM_CORE_VKEY_CAPS = $14; + KM_CORE_VKEY__15 = $15; + KM_CORE_VKEY__16 = $16; + KM_CORE_VKEY__17 = $17; + KM_CORE_VKEY__18 = $18; + KM_CORE_VKEY__19 = $19; + KM_CORE_VKEY__1A = $1A; + KM_CORE_VKEY_ESC = $1B; + KM_CORE_VKEY__1C = $1C; + KM_CORE_VKEY__1D = $1D; + KM_CORE_VKEY__1E = $1E; + KM_CORE_VKEY__1F = $1F; + KM_CORE_VKEY_SPACE = $20; + KM_CORE_VKEY_PGUP = $21; + KM_CORE_VKEY_PGDN = $22; + KM_CORE_VKEY_END = $23; + KM_CORE_VKEY_HOME = $24; + KM_CORE_VKEY_LEFT = $25; + KM_CORE_VKEY_UP = $26; + KM_CORE_VKEY_RIGHT = $27; + KM_CORE_VKEY_DOWN = $28; + KM_CORE_VKEY_SEL = $29; + KM_CORE_VKEY_PRINT = $2A; + KM_CORE_VKEY_EXEC = $2B; + KM_CORE_VKEY_PRTSCN = $2C; + KM_CORE_VKEY_INS = $2D; + KM_CORE_VKEY_DEL = $2E; + KM_CORE_VKEY_HELP = $2F; + KM_CORE_VKEY_0 = $30; + KM_CORE_VKEY_1 = $31; + KM_CORE_VKEY_2 = $32; + KM_CORE_VKEY_3 = $33; + KM_CORE_VKEY_4 = $34; + KM_CORE_VKEY_5 = $35; + KM_CORE_VKEY_6 = $36; + KM_CORE_VKEY_7 = $37; + KM_CORE_VKEY_8 = $38; + KM_CORE_VKEY_9 = $39; + KM_CORE_VKEY__3A = $3A; + KM_CORE_VKEY__3B = $3B; + KM_CORE_VKEY__3C = $3C; + KM_CORE_VKEY__3D = $3D; + KM_CORE_VKEY__3E = $3E; + KM_CORE_VKEY__3F = $3F; + KM_CORE_VKEY__40 = $40; + KM_CORE_VKEY_A = $41; + KM_CORE_VKEY_B = $42; + KM_CORE_VKEY_C = $43; + KM_CORE_VKEY_D = $44; + KM_CORE_VKEY_E = $45; + KM_CORE_VKEY_F = $46; + KM_CORE_VKEY_G = $47; + KM_CORE_VKEY_H = $48; + KM_CORE_VKEY_I = $49; + KM_CORE_VKEY_J = $4A; + KM_CORE_VKEY_K = $4B; + KM_CORE_VKEY_L = $4C; + KM_CORE_VKEY_M = $4D; + KM_CORE_VKEY_N = $4E; + KM_CORE_VKEY_O = $4F; + KM_CORE_VKEY_P = $50; + KM_CORE_VKEY_Q = $51; + KM_CORE_VKEY_R = $52; + KM_CORE_VKEY_S = $53; + KM_CORE_VKEY_T = $54; + KM_CORE_VKEY_U = $55; + KM_CORE_VKEY_V = $56; + KM_CORE_VKEY_W = $57; + KM_CORE_VKEY_X = $58; + KM_CORE_VKEY_Y = $59; + KM_CORE_VKEY_Z = $5A; + KM_CORE_VKEY__5B = $5B; + KM_CORE_VKEY__5C = $5C; + KM_CORE_VKEY__5D = $5D; + KM_CORE_VKEY__5E = $5E; + KM_CORE_VKEY__5F = $5F; + KM_CORE_VKEY_NP0 = $60; + KM_CORE_VKEY_NP1 = $61; + KM_CORE_VKEY_NP2 = $62; + KM_CORE_VKEY_NP3 = $63; + KM_CORE_VKEY_NP4 = $64; + KM_CORE_VKEY_NP5 = $65; + KM_CORE_VKEY_NP6 = $66; + KM_CORE_VKEY_NP7 = $67; + KM_CORE_VKEY_NP8 = $68; + KM_CORE_VKEY_NP9 = $69; + KM_CORE_VKEY_NPSTAR = $6A; + KM_CORE_VKEY_NPPLUS = $6B; + KM_CORE_VKEY_SEPARATOR = $6C; + KM_CORE_VKEY_NPMINUS = $6D; + KM_CORE_VKEY_NPDOT = $6E; + KM_CORE_VKEY_NPSLASH = $6F; + KM_CORE_VKEY_F1 = $70; + KM_CORE_VKEY_F2 = $71; + KM_CORE_VKEY_F3 = $72; + KM_CORE_VKEY_F4 = $73; + KM_CORE_VKEY_F5 = $74; + KM_CORE_VKEY_F6 = $75; + KM_CORE_VKEY_F7 = $76; + KM_CORE_VKEY_F8 = $77; + KM_CORE_VKEY_F9 = $78; + KM_CORE_VKEY_F10 = $79; + KM_CORE_VKEY_F11 = $7A; + KM_CORE_VKEY_F12 = $7B; + KM_CORE_VKEY_F13 = $7C; + KM_CORE_VKEY_F14 = $7D; + KM_CORE_VKEY_F15 = $7E; + KM_CORE_VKEY_F16 = $7F; + KM_CORE_VKEY_F17 = $80; + KM_CORE_VKEY_F18 = $81; + KM_CORE_VKEY_F19 = $82; + KM_CORE_VKEY_F20 = $83; + KM_CORE_VKEY_F21 = $84; + KM_CORE_VKEY_F22 = $85; + KM_CORE_VKEY_F23 = $86; + KM_CORE_VKEY_F24 = $87; + KM_CORE_VKEY__88 = $88; + KM_CORE_VKEY__89 = $89; + KM_CORE_VKEY__8A = $8A; + KM_CORE_VKEY__8B = $8B; + KM_CORE_VKEY__8C = $8C; + KM_CORE_VKEY__8D = $8D; + KM_CORE_VKEY__8E = $8E; + KM_CORE_VKEY__8F = $8F; + KM_CORE_VKEY_NUMLOCK = $90; + KM_CORE_VKEY_SCROLL = $91; + KM_CORE_VKEY__92 = $92; + KM_CORE_VKEY__93 = $93; + KM_CORE_VKEY__94 = $94; + KM_CORE_VKEY__95 = $95; + KM_CORE_VKEY__96 = $96; + KM_CORE_VKEY__97 = $97; + KM_CORE_VKEY__98 = $98; + KM_CORE_VKEY__99 = $99; + KM_CORE_VKEY__9A = $9A; + KM_CORE_VKEY__9B = $9B; + KM_CORE_VKEY__9C = $9C; + KM_CORE_VKEY__9D = $9D; + KM_CORE_VKEY__9E = $9E; + KM_CORE_VKEY__9F = $9F; + KM_CORE_VKEY__A0 = $A0; + KM_CORE_VKEY__A1 = $A1; + KM_CORE_VKEY__A2 = $A2; + KM_CORE_VKEY__A3 = $A3; + KM_CORE_VKEY__A4 = $A4; + KM_CORE_VKEY__A5 = $A5; + KM_CORE_VKEY__A6 = $A6; + KM_CORE_VKEY__A7 = $A7; + KM_CORE_VKEY__A8 = $A8; + KM_CORE_VKEY__A9 = $A9; + KM_CORE_VKEY__AA = $AA; + KM_CORE_VKEY__AB = $AB; + KM_CORE_VKEY__AC = $AC; + KM_CORE_VKEY__AD = $AD; + KM_CORE_VKEY__AE = $AE; + KM_CORE_VKEY__AF = $AF; + KM_CORE_VKEY__B0 = $B0; + KM_CORE_VKEY__B1 = $B1; + KM_CORE_VKEY__B2 = $B2; + KM_CORE_VKEY__B3 = $B3; + KM_CORE_VKEY__B4 = $B4; + KM_CORE_VKEY__B5 = $B5; + KM_CORE_VKEY__B6 = $B6; + KM_CORE_VKEY__B7 = $B7; + KM_CORE_VKEY__B8 = $B8; + KM_CORE_VKEY__B9 = $B9; + KM_CORE_VKEY_COLON = $BA; + KM_CORE_VKEY_EQUAL = $BB; + KM_CORE_VKEY_COMMA = $BC; + KM_CORE_VKEY_HYPHEN = $BD; + KM_CORE_VKEY_PERIOD = $BE; + KM_CORE_VKEY_SLASH = $BF; + KM_CORE_VKEY_BKQUOTE = $C0; + KM_CORE_VKEY__C1 = $C1; + KM_CORE_VKEY__C2 = $C2; + KM_CORE_VKEY__C3 = $C3; + KM_CORE_VKEY__C4 = $C4; + KM_CORE_VKEY__C5 = $C5; + KM_CORE_VKEY__C6 = $C6; + KM_CORE_VKEY__C7 = $C7; + KM_CORE_VKEY__C8 = $C8; + KM_CORE_VKEY__C9 = $C9; + KM_CORE_VKEY__CA = $CA; + KM_CORE_VKEY__CB = $CB; + KM_CORE_VKEY__CC = $CC; + KM_CORE_VKEY__CD = $CD; + KM_CORE_VKEY__CE = $CE; + KM_CORE_VKEY__CF = $CF; + KM_CORE_VKEY__D0 = $D0; + KM_CORE_VKEY__D1 = $D1; + KM_CORE_VKEY__D2 = $D2; + KM_CORE_VKEY__D3 = $D3; + KM_CORE_VKEY__D4 = $D4; + KM_CORE_VKEY__D5 = $D5; + KM_CORE_VKEY__D6 = $D6; + KM_CORE_VKEY__D7 = $D7; + KM_CORE_VKEY__D8 = $D8; + KM_CORE_VKEY__D9 = $D9; + KM_CORE_VKEY__DA = $DA; + KM_CORE_VKEY_LBRKT = $DB; + KM_CORE_VKEY_BKSLASH = $DC; + KM_CORE_VKEY_RBRKT = $DD; + KM_CORE_VKEY_QUOTE = $DE; + KM_CORE_VKEY_oDF = $DF; + KM_CORE_VKEY_oE0 = $E0; + KM_CORE_VKEY_oE1 = $E1; + KM_CORE_VKEY_oE2 = $E2; // 102nd key on European layouts + KM_CORE_VKEY_oE3 = $E3; + KM_CORE_VKEY_oE4 = $E4; + KM_CORE_VKEY__E5 = $E5; + KM_CORE_VKEY_oE6 = $E6; + KM_CORE_VKEY__E7 = $E7; + KM_CORE_VKEY__E8 = $E8; + KM_CORE_VKEY_oE9 = $E9; + KM_CORE_VKEY_oEA = $EA; + KM_CORE_VKEY_oEB = $EB; + KM_CORE_VKEY_oEC = $EC; + KM_CORE_VKEY_oED = $ED; + KM_CORE_VKEY_oEE = $EE; + KM_CORE_VKEY_oEF = $EF; + KM_CORE_VKEY_oF0 = $F0; + KM_CORE_VKEY_oF1 = $F1; + KM_CORE_VKEY_oF2 = $F2; + KM_CORE_VKEY_oF3 = $F3; + KM_CORE_VKEY_oF4 = $F4; + KM_CORE_VKEY_oF5 = $F5; + KM_CORE_VKEY__F6 = $F6; + KM_CORE_VKEY__F7 = $F7; + KM_CORE_VKEY__F8 = $F8; + KM_CORE_VKEY__F9 = $F9; + KM_CORE_VKEY__FA = $FA; + KM_CORE_VKEY__FB = $FB; + KM_CORE_VKEY__FC = $FC; + KM_CORE_VKEY__FD = $FD; + KM_CORE_VKEY__FE = $FE; + KM_CORE_VKEY__FF = $FF; + +// keyman_core_api_consts.h const // Defined environment options for KMX processor - KM_KBP_KMX_ENV_PLATFORM = 'platform'; - KM_KBP_KMX_ENV_BASELAYOUT = 'baseLayout'; - KM_KBP_KMX_ENV_BASELAYOUTALT = 'baseLayoutAlt'; - KM_KBP_KMX_ENV_SIMULATEALTGR = 'simulateAltgr'; - KM_KBP_KMX_ENV_CAPSLOCK = 'capsLock'; - KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT = 'baseLayoutGivesCtrlRAltForRAlt'; + KM_CORE_KMX_ENV_PLATFORM = 'platform'; + KM_CORE_KMX_ENV_BASELAYOUT = 'baseLayout'; + KM_CORE_KMX_ENV_BASELAYOUTALT = 'baseLayoutAlt'; + KM_CORE_KMX_ENV_SIMULATEALTGR = 'simulateAltgr'; + KM_CORE_KMX_ENV_CAPSLOCK = 'capsLock'; + KM_CORE_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT = 'baseLayoutGivesCtrlRAltForRAlt'; -procedure _km_kbp_set_library_path(const path: string); +procedure _km_core_set_library_path(const path: string); implementation @@ -638,7 +638,7 @@ implementation System.SysUtils, Winapi.Windows; -procedure _km_kbp_set_library_path(const path: string); +procedure _km_core_set_library_path(const path: string); begin if LoadLibrary(PChar(path)) = 0 then RaiseLastOSError; diff --git a/developer/src/tike/main/Keyman.System.KeymanCoreDebug.pas b/developer/src/tike/main/Keyman.System.KeymanCoreDebug.pas index a1f63e3b38e..7aced230fbf 100644 --- a/developer/src/tike/main/Keyman.System.KeymanCoreDebug.pas +++ b/developer/src/tike/main/Keyman.System.KeymanCoreDebug.pas @@ -1,7 +1,7 @@ { * Keyman is copyright (C) SIL International. MIT License. * - * Debug interface for Keyman Core, matches keyboardprocessor_debug.h + * Debug interface for Keyman Core, matches keyman_core_api_debug.h } unit Keyman.System.KeymanCoreDebug; @@ -14,7 +14,7 @@ interface {$ALIGN 8} /// -/// The maximum size of context in km_kbp_cp units for a single debug +/// The maximum size of context in km_core_cp units for a single debug /// event. This is taken from MAXCONTEXT in keyman32 (Windows) and is purely /// a convenience value. We can increase it if there is a demonstrated need. /// @@ -32,32 +32,32 @@ interface /// These modifier flags are used internally in the kmx engine, so will be /// exposed only in debugging modifier states. /// -const KM_KBP_MODIFIER_VIRTUALKEY = $4000; -const KM_KBP_MODIFIER_VIRTUALCHARKEY = $8000; +const KM_CORE_MODIFIER_VIRTUALKEY = $4000; +const KM_CORE_MODIFIER_VIRTUALCHARKEY = $8000; /// /// Input key event data. The `character` member is derived from /// a US English key event for vk + modifier_state, and is 0 if /// the vk + modifier_state do not generate a character. /// -/// Used only in event type KM_KBP_DEBUG_BEGIN. +/// Used only in event type KM_CORE_DEBUG_BEGIN. /// type -km_kbp_state_debug_key_info = record +km_core_state_debug_key_info = record vk: uint16_t; modifier_state: uint16_t; character: char16_t; end; -pkm_kbp_state_debug_key_info = ^km_kbp_state_debug_key_info; +pkm_core_state_debug_key_info = ^km_core_state_debug_key_info; -km_kbp_state_debug_kmx_option_info = record +km_core_state_debug_kmx_option_info = record store: Pointer; // LPSTORE - value: array[0..DEBUG_MAX_CONTEXT-1] of km_kbp_cp; // value to be saved into the store + value: array[0..DEBUG_MAX_CONTEXT-1] of km_core_cp; // value to be saved into the store end; -pkm_kbp_state_debug_kmx_option_info = ^km_kbp_state_debug_kmx_option_info; +pkm_core_state_debug_kmx_option_info = ^km_core_state_debug_kmx_option_info; /// /// KMX processor data for each event. kmx_base.h defines the types that are @@ -67,11 +67,11 @@ km_kbp_state_debug_kmx_option_info = record /// The context value here will be an intermediate value, and may differ /// from event to event as the context can be rewritten for each rule match. /// -/// Used in all event types except KM_KBP_DEBUG_BEGIN, KM_KBP_DEBUG_END. +/// Used in all event types except KM_CORE_DEBUG_BEGIN, KM_CORE_DEBUG_END. /// -km_kbp_state_debug_kmx_info = record - context: array [0..DEBUG_MAX_CONTEXT-1] of km_kbp_cp; // The context matched by the rule (? may not need this?) // TODO: rename to context_matched +km_core_state_debug_kmx_info = record + context: array [0..DEBUG_MAX_CONTEXT-1] of km_core_cp; // The context matched by the rule (? may not need this?) // TODO: rename to context_matched group: Pointer; // LPGROUP rule: Pointer; // LPKEY store_offsets: array [0..DEBUG_STORE_OFFSETS_SIZE-1] of uint16_t; // pairs--store, char position, terminated by 0xFFFF // TODO use a better structure here @@ -80,10 +80,10 @@ km_kbp_state_debug_kmx_info = record /// the debugger; the debugger uses this to determine when to /// execute the actions when single-stepping. first_action: uint16_t; - option: km_kbp_state_debug_kmx_option_info; + option: km_core_state_debug_kmx_option_info; end; -pkm_kbp_state_debug_kmx_info = ^km_kbp_state_debug_kmx_info; +pkm_core_state_debug_kmx_info = ^km_core_state_debug_kmx_info; /// /// A single debug event. @@ -91,50 +91,50 @@ km_kbp_state_debug_kmx_info = record /// {$ALIGN 8} -km_kbp_state_debug_item = record +km_core_state_debug_item = record _type: uint32_t; // TODO: _type as enum, 8 bit with padding? 32 bits is better optimized than 8 bits flags: uint32_t; - key_info: km_kbp_state_debug_key_info; - kmx_info: km_kbp_state_debug_kmx_info; + key_info: km_core_state_debug_key_info; + kmx_info: km_core_state_debug_kmx_info; end; -pkm_kbp_state_debug_item = ^km_kbp_state_debug_item; +pkm_core_state_debug_item = ^km_core_state_debug_item; /// /// A single debug event. /// -km_kbp_debug_type = type uint32_t; +km_core_debug_type = type uint32_t; // These types are used only for debugging convenience type - km_kbp_state_debug_item_array = array[0..100] of km_kbp_state_debug_item; - pkm_kbp_state_debug_item_array = ^km_kbp_state_debug_item_array; + km_core_state_debug_item_array = array[0..100] of km_core_state_debug_item; + pkm_core_state_debug_item_array = ^km_core_state_debug_item_array; const - KM_KBP_DEBUG_BEGIN = 0; - //KM_KBP_DEBUG_BEGIN_ANSI: km_kbp_debug_type = 1, // not supported; instead rewrite ansi keyboards to Unicode with mcompile - KM_KBP_DEBUG_GROUP_ENTER = 2; - KM_KBP_DEBUG_GROUP_EXIT = 3; - KM_KBP_DEBUG_RULE_ENTER = 4; - KM_KBP_DEBUG_RULE_EXIT = 5; - KM_KBP_DEBUG_MATCH_ENTER = 6; - KM_KBP_DEBUG_MATCH_EXIT = 7; - KM_KBP_DEBUG_NOMATCH_ENTER = 8; - KM_KBP_DEBUG_NOMATCH_EXIT = 9; - KM_KBP_DEBUG_END = 10; - KM_KBP_DEBUG_SET_OPTION = 11; - -// Flags for KM_KBP_DEBUG_GROUP_EXIT -const KM_KBP_DEBUG_FLAG_RECURSIVE_OVERFLOW = $0001; -const KM_KBP_DEBUG_FLAG_NOMATCH = $0002; - -// Flags for KM_KBP_DEBUG_BEGIN + KM_CORE_DEBUG_BEGIN = 0; + //KM_CORE_DEBUG_BEGIN_ANSI: km_core_debug_type = 1, // not supported; instead rewrite ansi keyboards to Unicode with mcompile + KM_CORE_DEBUG_GROUP_ENTER = 2; + KM_CORE_DEBUG_GROUP_EXIT = 3; + KM_CORE_DEBUG_RULE_ENTER = 4; + KM_CORE_DEBUG_RULE_EXIT = 5; + KM_CORE_DEBUG_MATCH_ENTER = 6; + KM_CORE_DEBUG_MATCH_EXIT = 7; + KM_CORE_DEBUG_NOMATCH_ENTER = 8; + KM_CORE_DEBUG_NOMATCH_EXIT = 9; + KM_CORE_DEBUG_END = 10; + KM_CORE_DEBUG_SET_OPTION = 11; + +// Flags for KM_CORE_DEBUG_GROUP_EXIT +const KM_CORE_DEBUG_FLAG_RECURSIVE_OVERFLOW = $0001; +const KM_CORE_DEBUG_FLAG_NOMATCH = $0002; + +// Flags for KM_CORE_DEBUG_BEGIN // TODO: do we need this at all? -const KM_KBP_DEBUG_FLAG_UNICODE = $0001; // Always set +const KM_CORE_DEBUG_FLAG_UNICODE = $0001; // Always set -// Flags for KM_KBP_DEBUG_END -const KM_KBP_DEBUG_FLAG_OUTPUTKEYSTROKE = $0001; +// Flags for KM_CORE_DEBUG_END +const KM_CORE_DEBUG_FLAG_OUTPUTKEYSTROKE = $0001; /// /// Enable or disable debug tracing @@ -142,12 +142,12 @@ km_kbp_state_debug_item = record /// @param state Pointer to initialized state /// @param value Set to 1 to enable debugging, 0 to disable /// -/// @returns KM_KBP_STATUS_OK on success +/// @returns KM_CORE_STATUS_OK on success /// -function km_kbp_state_debug_set( - state: pkm_kbp_state; +function km_core_state_debug_set( + state: pkm_core_state; value: integer -): km_kbp_status; cdecl; external kmnkbp0 delayed; +): km_core_status; cdecl; external kmnkbp0 delayed; /// /// Get current debug tracing status @@ -156,8 +156,8 @@ function km_kbp_state_debug_set( /// /// @returns 1 if debugging is enabled, 0 otherwise /// -function km_kbp_state_debug_get( - state: pkm_kbp_state +function km_core_state_debug_get( + state: pkm_core_state ): uint8_t; cdecl; external kmnkbp0 delayed; /// @@ -168,12 +168,12 @@ function km_kbp_state_debug_get( /// nullptr if not required. /// /// @returns pointer to read only array of debug item events, -/// with last entry guaranteed to be KM_KBP_DEBUG_END. +/// with last entry guaranteed to be KM_CORE_DEBUG_END. /// -function km_kbp_state_debug_items( - state: pkm_kbp_state; +function km_core_state_debug_items( + state: pkm_core_state; num_items: PCardinal -): pkm_kbp_state_debug_item; cdecl; external kmnkbp0 delayed; +): pkm_core_state_debug_item; cdecl; external kmnkbp0 delayed; implementation @@ -181,18 +181,18 @@ initialization // Assertions generated by debug_api.cpp for win32 x86. // Usage: debug-api.exe --print-sizeof - //keyboardprocessor.h: - Assert(sizeof(km_kbp_context_item) = 8); - Assert(sizeof(km_kbp_context_item) = 8); - Assert(sizeof(km_kbp_action_item) = 12); - Assert(sizeof(km_kbp_option_item) = 12); - Assert(sizeof(km_kbp_keyboard_attrs) = 16); - Assert(sizeof(km_kbp_attr) = 16); - - //keyboardprocessor_debug.h: - Assert(sizeof(km_kbp_state_debug_item) = 432); - Assert(sizeof(km_kbp_state_debug_key_info) = 6); - Assert(sizeof(km_kbp_state_debug_kmx_info) = 416); - Assert(sizeof(km_kbp_state_debug_kmx_option_info) = 164); - Assert(sizeof(km_kbp_debug_type) = 4); + //keyman_core_api.h: + Assert(sizeof(km_core_context_item) = 8); + Assert(sizeof(km_core_context_item) = 8); + Assert(sizeof(km_core_action_item) = 12); + Assert(sizeof(km_core_option_item) = 12); + Assert(sizeof(km_core_keyboard_attrs) = 16); + Assert(sizeof(km_core_attr) = 16); + + //keyman_core_api_debug.h: + Assert(sizeof(km_core_state_debug_item) = 432); + Assert(sizeof(km_core_state_debug_key_info) = 6); + Assert(sizeof(km_core_state_debug_kmx_info) = 416); + Assert(sizeof(km_core_state_debug_kmx_option_info) = 164); + Assert(sizeof(km_core_debug_type) = 4); end. diff --git a/developer/src/tike/main/Keyman.System.VisualKeyboardImportKMX.pas b/developer/src/tike/main/Keyman.System.VisualKeyboardImportKMX.pas index e36216e1559..471162eded3 100644 --- a/developer/src/tike/main/Keyman.System.VisualKeyboardImportKMX.pas +++ b/developer/src/tike/main/Keyman.System.VisualKeyboardImportKMX.pas @@ -106,11 +106,11 @@ procedure TVisualKeyboardImportKMX.ImportKey(vk: TVKKey); var data: string; i: Integer; - context: pkm_kbp_context; + context: pkm_core_context; begin - context := km_kbp_state_context(FCore.State); - km_kbp_context_clear(context); - if km_kbp_process_event(FCore.State, vk.vkey, vk.kmshift, 1, KM_KBP_EVENT_FLAG_DEFAULT) = KM_KBP_STATUS_OK then + context := km_core_state_context(FCore.State); + km_core_context_clear(context); + if km_core_process_event(FCore.State, vk.vkey, vk.kmshift, 1, KM_CORE_EVENT_FLAG_DEFAULT) = KM_CORE_STATUS_OK then begin FEvents.Clear; FEvents.AddStateItems(FCore.State, vk.vkey, vk.kmshift); @@ -124,9 +124,9 @@ procedure TVisualKeyboardImportKMX.ImportKey(vk: TVKKey); end; case FEvents[i].Action.ActionType of - KM_KBP_IT_CHAR: + KM_CORE_IT_CHAR: data := data + FEvents[i].Action.Text; - KM_KBP_IT_BACK: + KM_CORE_IT_BACK: if data.Length > 0 then begin if (data.Length > 1) and @@ -201,7 +201,7 @@ procedure TVisualKeyboardImportKMX.Validate102Key; FShow102Key := False; for i := 0 to keys.Count - 1 do - if TVKKey(keys[i]).vkey = KM_KBP_VKEY_oE2 then + if TVKKey(keys[i]).vkey = KM_CORE_VKEY_oE2 then begin FShow102Key := True; Exit; diff --git a/developer/src/tools/verify_signatures/Makefile b/developer/src/tools/verify_signatures/Makefile new file mode 100644 index 00000000000..003f6aa5d50 --- /dev/null +++ b/developer/src/tools/verify_signatures/Makefile @@ -0,0 +1,19 @@ +# +# test for signatures and version information being correct in bin folder +# + +!include ..\..\Defines.mak + +test: prereq + $(SIGCHECK) $(DEVELOPER_PROGRAM)\* > sig1 + $(VERIFY_SIGNATURES) < sig1 + +# prereq may not be needed? +prereq: + cd $(VERIFY_SIGNATURES_PATH) + $(MAKE) + +clean: def-clean + -del sig1 + +!include ..\..\Target.mak diff --git a/docs/settings/linux/settings.json b/docs/settings/linux/settings.json index 891507dd2ec..f17739ece29 100644 --- a/docs/settings/linux/settings.json +++ b/docs/settings/linux/settings.json @@ -16,7 +16,7 @@ "python.pythonPath": "/usr/bin/python3", "files.associations": { "*.tcc": "cpp", - "keyboardprocessor.h": "c", + "keyman_core_api.h": "c", "engine.h": "c", "keyman-service.h": "c", "keymanutil.h": "c", diff --git a/ios/exportAppStore.plist b/ios/exportAppStore.plist index 6393f3c4cbf..48ef58f532d 100644 --- a/ios/exportAppStore.plist +++ b/ios/exportAppStore.plist @@ -7,9 +7,9 @@ teamID 3YE4W86L3G signingCertificate - 05473BF50CCD4B78B304656FB4D93FDC7EE7ACD0 + BB842A0081298BBA6D034C85451750B08FC9EE8A installerSigningCertificate - 05473BF50CCD4B78B304656FB4D93FDC7EE7ACD0 + BB842A0081298BBA6D034C85451750B08FC9EE8A provisioningProfiles Tavultesoft.Keyman diff --git a/linux/debian/libkmnkbp0-0.symbols b/linux/debian/libkmnkbp0-0.symbols index 0da5c771209..cbcbb6f4ced 100644 --- a/linux/debian/libkmnkbp0-0.symbols +++ b/linux/debian/libkmnkbp0-0.symbols @@ -2,42 +2,42 @@ libkmnkbp0.so.0 libkmnkbp0-0 #MINVER# * Build-Depends-Package: libkmnkbp-dev kbp_state_get_intermediate_context@Base 15.0 - km_kbp_context_append@Base 15.0 - km_kbp_context_clear@Base 15.0 - km_kbp_context_get@Base 15.0 - km_kbp_context_item_list_size@Base 15.0 - km_kbp_context_items_dispose@Base 15.0 - km_kbp_context_items_from_utf16@Base 15.0 - km_kbp_context_items_from_utf8@Base 15.0 - km_kbp_context_items_to_utf16@Base 15.0 - km_kbp_context_items_to_utf8@Base 15.0 - km_kbp_context_length@Base 15.0 - km_kbp_context_set@Base 15.0 - km_kbp_context_shrink@Base 15.0 - km_kbp_event@Base 16.0.105 - km_kbp_get_engine_attrs@Base 15.0 - km_kbp_keyboard_dispose@Base 15.0 - km_kbp_keyboard_get_attrs@Base 15.0 - km_kbp_keyboard_get_imx_list@Base 15.0 - km_kbp_keyboard_get_key_list@Base 15.0 - km_kbp_keyboard_imx_list_dispose@Base 15.0 - km_kbp_keyboard_key_list_dispose@Base 15.0 - km_kbp_keyboard_load@Base 15.0 - km_kbp_options_list_size@Base 15.0 - km_kbp_process_event@Base 15.0 - km_kbp_process_queued_actions@Base 15.0 - km_kbp_state_action_items@Base 15.0 - km_kbp_state_clone@Base 15.0 - km_kbp_state_context@Base 15.0 - km_kbp_state_create@Base 15.0 - km_kbp_state_debug_get@Base 15.0 - km_kbp_state_debug_items@Base 15.0 - km_kbp_state_debug_set@Base 15.0 - km_kbp_state_dispose@Base 15.0 - km_kbp_state_imx_deregister_callback@Base 15.0 - km_kbp_state_imx_register_callback@Base 15.0 - km_kbp_state_option_lookup@Base 15.0 - km_kbp_state_options_to_json@Base 15.0 - km_kbp_state_options_update@Base 15.0 - km_kbp_state_queue_action_items@Base 15.0 - km_kbp_state_to_json@Base 15.0 + km_core_context_append@Base 15.0 + km_core_context_clear@Base 15.0 + km_core_context_get@Base 15.0 + km_core_context_item_list_size@Base 15.0 + km_core_context_items_dispose@Base 15.0 + km_core_context_items_from_utf16@Base 15.0 + km_core_context_items_from_utf8@Base 15.0 + km_core_context_items_to_utf16@Base 15.0 + km_core_context_items_to_utf8@Base 15.0 + km_core_context_length@Base 15.0 + km_core_context_set@Base 15.0 + km_core_context_shrink@Base 15.0 + km_core_event@Base 16.0.105 + km_core_get_engine_attrs@Base 15.0 + km_core_keyboard_dispose@Base 15.0 + km_core_keyboard_get_attrs@Base 15.0 + km_core_keyboard_get_imx_list@Base 15.0 + km_core_keyboard_get_key_list@Base 15.0 + km_core_keyboard_imx_list_dispose@Base 15.0 + km_core_keyboard_key_list_dispose@Base 15.0 + km_core_keyboard_load@Base 15.0 + km_core_options_list_size@Base 15.0 + km_core_process_event@Base 15.0 + km_core_process_queued_actions@Base 15.0 + km_core_state_action_items@Base 15.0 + km_core_state_clone@Base 15.0 + km_core_state_context@Base 15.0 + km_core_state_create@Base 15.0 + km_core_state_debug_get@Base 15.0 + km_core_state_debug_items@Base 15.0 + km_core_state_debug_set@Base 15.0 + km_core_state_dispose@Base 15.0 + km_core_state_imx_deregister_callback@Base 15.0 + km_core_state_imx_register_callback@Base 15.0 + km_core_state_option_lookup@Base 15.0 + km_core_state_options_to_json@Base 15.0 + km_core_state_options_update@Base 15.0 + km_core_state_queue_action_items@Base 15.0 + km_core_state_to_json@Base 15.0 diff --git a/linux/debian/tests/test-build b/linux/debian/tests/test-build index db0a343849c..e9a989e36ff 100644 --- a/linux/debian/tests/test-build +++ b/linux/debian/tests/test-build @@ -11,8 +11,8 @@ cd "$WORKDIR" # Test all include files are available cat < keymantest.c -#include -km_kbp_context* c; +#include +km_core_context* c; EOF # shellcheck disable=SC2046 @@ -21,8 +21,8 @@ echo "build 1: OK" # Test pkg-config file - include without path cat < keymantest.c -#include -km_kbp_context* c; +#include +km_core_context* c; EOF # shellcheck disable=SC2046 diff --git a/linux/ibus-keyman/src/engine.c b/linux/ibus-keyman/src/engine.c index 49b9161f9a3..bc968858ae2 100644 --- a/linux/ibus-keyman/src/engine.c +++ b/linux/ibus-keyman/src/engine.c @@ -28,8 +28,8 @@ #include #include -#include -#include +#include +#include #include "config.h" #include "keymanutil.h" @@ -71,8 +71,8 @@ struct _IBusKeymanEngine { IBusEngine parent; /* members */ - km_kbp_keyboard *keyboard; - km_kbp_state *state; + km_core_keyboard *keyboard; + km_core_state *state; gchar *ldmlfile; gchar *kb_name; gboolean lctrl_pressed; @@ -204,18 +204,18 @@ ibus_keyman_engine_class_init (IBusKeymanEngineClass *klass) // engine_class->property_activate = ibus_keyman_engine_property_activate; } -static gchar *get_current_context_text(km_kbp_context *context) +static gchar *get_current_context_text(km_core_context *context) { size_t buf_size = 512; - km_kbp_context_item *context_items; + km_core_context_item *context_items; gchar *current_context_utf8 = g_new0(gchar, buf_size); - if (km_kbp_context_get(context, &context_items) == KM_KBP_STATUS_OK) { - km_kbp_context_items_to_utf8(context_items, + if (km_core_context_get(context, &context_items) == KM_CORE_STATUS_OK) { + km_core_context_items_to_utf8(context_items, current_context_utf8, &buf_size); } - km_kbp_context_items_dispose(context_items); - g_message("%s: current context is:%zu:%zu:%s:", __FUNCTION__, km_kbp_context_length(context), buf_size, current_context_utf8); + km_core_context_items_dispose(context_items); + g_message("%s: current context is:%zu:%zu:%s:", __FUNCTION__, km_core_context_length(context), buf_size, current_context_utf8); return current_context_utf8; } @@ -239,16 +239,16 @@ client_supports_surrounding_text(IBusEngine *engine) { static void reset_context(IBusEngine *engine) { IBusKeymanEngine *keyman = (IBusKeymanEngine *)engine; - km_kbp_context *context; + km_core_context *context; g_message("%s", __FUNCTION__); - context = km_kbp_state_context(keyman->state); + context = km_core_state_context(keyman->state); if (client_supports_surrounding_text(engine)) { IBusText *text; gchar *surrounding_text, *current_context_utf8; guint cursor_pos, anchor_pos, context_start, context_end; - km_kbp_context_item *context_items; + km_core_context_item *context_items; ibus_engine_get_surrounding_text(engine, &text, &cursor_pos, &anchor_pos); @@ -261,19 +261,19 @@ reset_context(IBusEngine *engine) { current_context_utf8 = get_current_context_text(context); if (!(*current_context_utf8) || !g_str_has_suffix(surrounding_text, current_context_utf8)) { g_message("%s: setting context because it has changed from expected", __FUNCTION__); - enum km_kbp_status_codes status = km_kbp_context_items_from_utf8(surrounding_text, &context_items); - if (status == KM_KBP_STATUS_OK) { - km_kbp_context_set(context, context_items); - km_kbp_context_items_dispose(context_items); + enum km_core_status_codes status = km_core_context_items_from_utf8(surrounding_text, &context_items); + if (status == KM_CORE_STATUS_OK) { + km_core_context_set(context, context_items); + km_core_context_items_dispose(context_items); } else { - km_kbp_context_clear(context); + km_core_context_clear(context); g_message("%s: setting context failed with status code %d", __FUNCTION__, status); } } g_free(surrounding_text); g_free(current_context_utf8); } else { - km_kbp_context_clear(context); + km_core_context_clear(context); g_message("%s: client does not support surrounding text", __FUNCTION__); } } @@ -299,7 +299,7 @@ ibus_keyman_engine_init(IBusKeymanEngine *keyman) { keyman->state = NULL; } -static km_kbp_cp* get_base_layout() +static km_core_cp* get_base_layout() { return u"en-US"; @@ -327,42 +327,42 @@ static km_kbp_cp* get_base_layout() lang = strdup("en-US"); } g_message("lang is %s", lang); - km_kbp_cp *cp = g_utf8_to_utf16(lang, -1, NULL, NULL, NULL); + km_core_cp *cp = g_utf8_to_utf16(lang, -1, NULL, NULL, NULL); return cp; // g_free(lang); #endif } -static km_kbp_status +static km_core_status setup_environment(IBusKeymanEngine *keyman) { g_assert(keyman); g_message("%s: setting up environment", __FUNCTION__); // Allocate enough options for: 3 environments plus 1 pad struct of 0's - km_kbp_option_item environment_opts[4] = {0}; + km_core_option_item environment_opts[4] = {0}; - environment_opts[0].scope = KM_KBP_OPT_ENVIRONMENT; - environment_opts[0].key = KM_KBP_KMX_ENV_PLATFORM; + environment_opts[0].scope = KM_CORE_OPT_ENVIRONMENT; + environment_opts[0].key = KM_CORE_KMX_ENV_PLATFORM; environment_opts[0].value = u"linux desktop hardware native"; - environment_opts[1].scope = KM_KBP_OPT_ENVIRONMENT; - environment_opts[1].key = KM_KBP_KMX_ENV_BASELAYOUT; + environment_opts[1].scope = KM_CORE_OPT_ENVIRONMENT; + environment_opts[1].key = KM_CORE_KMX_ENV_BASELAYOUT; environment_opts[1].value = u"kbdus.dll"; - environment_opts[2].scope = KM_KBP_OPT_ENVIRONMENT; - environment_opts[2].key = KM_KBP_KMX_ENV_BASELAYOUTALT; + environment_opts[2].scope = KM_CORE_OPT_ENVIRONMENT; + environment_opts[2].key = KM_CORE_KMX_ENV_BASELAYOUTALT; environment_opts[2].value = get_base_layout(); // TODO: free when mnemonic layouts are to be supported - km_kbp_status status = km_kbp_state_create(keyman->keyboard, environment_opts, &(keyman->state)); - if (status != KM_KBP_STATUS_OK) { - g_warning("%s: problem creating km_kbp_state. Status is %u.", __FUNCTION__, status); + km_core_status status = km_core_state_create(keyman->keyboard, environment_opts, &(keyman->state)); + if (status != KM_CORE_STATUS_OK) { + g_warning("%s: problem creating km_core_state. Status is %u.", __FUNCTION__, status); } return status; } -static km_kbp_status +static km_core_status load_keyboard_options(IBusKeymanEngine *keyman) { g_assert(keyman); @@ -374,14 +374,14 @@ load_keyboard_options(IBusKeymanEngine *keyman) int num_options = g_queue_get_length(queue_options); if (num_options < 1) { g_queue_free_full(queue_options, NULL); - return KM_KBP_STATUS_OK; + return KM_CORE_STATUS_OK; } // Allocate enough options for: num_options plus 1 pad struct of 0's - km_kbp_option_item *keyboard_opts = g_new0(km_kbp_option_item, num_options + 1); + km_core_option_item *keyboard_opts = g_new0(km_core_option_item, num_options + 1); for (int i = 0; i < num_options; i++) { - km_kbp_option_item *item = g_queue_pop_head(queue_options); + km_core_option_item *item = g_queue_pop_head(queue_options); keyboard_opts[i].scope = item->scope; keyboard_opts[i].key = item->key; keyboard_opts[i].value = item->value; @@ -389,14 +389,14 @@ load_keyboard_options(IBusKeymanEngine *keyman) // once we have the option list we can then update the options using the public api call - km_kbp_status status = km_kbp_state_options_update(keyman->state, keyboard_opts); + km_core_status status = km_core_state_options_update(keyman->state, keyboard_opts); - if (status != KM_KBP_STATUS_OK) { - g_warning("%s: problem creating km_kbp_state. Status is %u.", __FUNCTION__, status); + if (status != KM_CORE_STATUS_OK) { + g_warning("%s: problem creating km_core_state. Status is %u.", __FUNCTION__, status); } for (int i = 0; i < num_options; i++) { - g_free((km_kbp_cp *)keyboard_opts[i].key); - g_free((km_kbp_cp *)keyboard_opts[i].value); + g_free((km_core_cp *)keyboard_opts[i].key); + g_free((km_core_cp *)keyboard_opts[i].value); } g_queue_free_full(queue_options, NULL); g_free(keyboard_opts); @@ -470,25 +470,25 @@ ibus_keyman_engine_constructor( } g_free(kmx_file); - km_kbp_status status; + km_core_status status; - status = km_kbp_keyboard_load(abs_kmx_path, &(keyman->keyboard)); + status = km_core_keyboard_load(abs_kmx_path, &(keyman->keyboard)); g_free(abs_kmx_path); - if (status != KM_KBP_STATUS_OK) { - g_warning("%s: problem creating km_kbp_keyboard. Status is %u.", __FUNCTION__, status); + if (status != KM_CORE_STATUS_OK) { + g_warning("%s: problem creating km_core_keyboard. Status is %u.", __FUNCTION__, status); ibus_keyman_engine_destroy(keyman); return NULL; } status = setup_environment(keyman); - if (status != KM_KBP_STATUS_OK) { + if (status != KM_CORE_STATUS_OK) { ibus_keyman_engine_destroy(keyman); return NULL; } status = load_keyboard_options(keyman); - if (status != KM_KBP_STATUS_OK) { + if (status != KM_CORE_STATUS_OK) { ibus_keyman_engine_destroy(keyman); return NULL; } @@ -522,12 +522,12 @@ ibus_keyman_engine_destroy (IBusKeymanEngine *keyman) } if (keyman->state) { - km_kbp_state_dispose(keyman->state); + km_core_state_dispose(keyman->state); keyman->state = NULL; } if (keyman->keyboard) { - km_kbp_keyboard_dispose(keyman->keyboard); + km_core_keyboard_dispose(keyman->keyboard); keyman->keyboard = NULL; } @@ -566,7 +566,7 @@ static void forward_backspace(IBusKeymanEngine *keyman, unsigned int state) static gboolean process_unicode_char_action( IBusKeymanEngine *keyman, - const km_kbp_action_item *action_item + const km_core_action_item *action_item ) { g_assert(g_unichar_type(action_item->character) != G_UNICODE_SURROGATE); gchar *utf8 = (gchar *)g_new0(gchar, 12); @@ -603,12 +603,12 @@ static gboolean process_alert_action() { static gboolean process_backspace_action( IBusEngine *engine, - const km_kbp_action_item *action_items, + const km_core_action_item *action_items, int i, size_t num_action_items ) { IBusKeymanEngine *keyman = (IBusKeymanEngine *)engine; - if (action_items[i].backspace.expected_type == KM_KBP_IT_MARKER) { + if (action_items[i].backspace.expected_type == KM_CORE_IT_MARKER) { g_message("%s: skipping marker type", __FUNCTION__); } else if (keyman->commit_item->char_buffer != NULL) { g_message("%s: removing one utf8 char from CHAR buffer", __FUNCTION__); @@ -635,12 +635,12 @@ process_backspace_action( g_message("%s: increment consecutive backspaces to %d", __FUNCTION__, keyman->consecutive_backspaces); } else { g_message("%s: forwarding backspace with reset context", __FUNCTION__); - km_kbp_context_item *context_items; - km_kbp_context_get(km_kbp_state_context(keyman->state), &context_items); + km_core_context_item *context_items; + km_core_context_get(km_core_state_context(keyman->state), &context_items); reset_context(engine); forward_backspace(keyman, 0); - km_kbp_context_set(km_kbp_state_context(keyman->state), context_items); - km_kbp_context_items_dispose(context_items); + km_core_context_set(km_core_state_context(keyman->state), context_items); + km_core_context_items_dispose(context_items); } } return TRUE; @@ -664,18 +664,18 @@ finish_backspace_action( static gboolean process_persist_action( IBusKeymanEngine *keyman, - const km_kbp_action_item *action_item + const km_core_action_item *action_item ) { // Save keyboard option if (!action_item->option) return TRUE; // Allocate for 1 option plus 1 pad struct of 0's - km_kbp_option_item *keyboard_opts = g_new0(km_kbp_option_item, 2); - memmove(&(keyboard_opts[0]), action_item->option, sizeof(km_kbp_option_item)); - km_kbp_status event_status = km_kbp_state_options_update(keyman->state, keyboard_opts); - if (event_status != KM_KBP_STATUS_OK) { - g_warning("%s: problem saving option for km_kbp_keyboard", __FUNCTION__); + km_core_option_item *keyboard_opts = g_new0(km_core_option_item, 2); + memmove(&(keyboard_opts[0]), action_item->option, sizeof(km_core_option_item)); + km_core_status event_status = km_core_state_options_update(keyman->state, keyboard_opts); + if (event_status != KM_CORE_STATUS_OK) { + g_warning("%s: problem saving option for km_core_keyboard", __FUNCTION__); } g_free(keyboard_opts); @@ -711,7 +711,7 @@ process_invalidate_context_action(IBusEngine *engine) { static gboolean process_capslock_action( IBusKeymanEngine *keyman, - const km_kbp_action_item *action_item + const km_core_action_item *action_item ) { g_message("%s: %s caps-lock", __FUNCTION__, action_item->capsLock ? "Enable" : "Disable"); @@ -788,55 +788,55 @@ process_end_action(IBusKeymanEngine *keyman) { static gboolean process_actions( IBusEngine *engine, - const km_kbp_action_item *action_items, + const km_core_action_item *action_items, size_t num_action_items ) { IBusKeymanEngine *keyman = (IBusKeymanEngine *)engine; for (int i = 0; i < num_action_items; i++) { gboolean continue_with_next_action = TRUE; - if (action_items[i].type != KM_KBP_IT_BACK && keyman->consecutive_backspaces > 0) { + if (action_items[i].type != KM_CORE_IT_BACK && keyman->consecutive_backspaces > 0) { finish_backspace_action(engine); } switch (action_items[i].type) { - case KM_KBP_IT_CHAR: + case KM_CORE_IT_CHAR: g_message("CHAR action %d/%d", i + 1, (int)num_action_items); continue_with_next_action = process_unicode_char_action(keyman, &action_items[i]); g_assert(continue_with_next_action == TRUE); break; - case KM_KBP_IT_MARKER: + case KM_CORE_IT_MARKER: g_message("MARKER action %d/%d", i + 1, (int)num_action_items); break; - case KM_KBP_IT_ALERT: + case KM_CORE_IT_ALERT: g_message("ALERT action %d/%d", i + 1, (int)num_action_items); continue_with_next_action = process_alert_action(); g_assert(continue_with_next_action == TRUE); break; - case KM_KBP_IT_BACK: + case KM_CORE_IT_BACK: g_message("BACK action %d/%d", i + 1, (int)num_action_items); continue_with_next_action = process_backspace_action(engine, action_items, i, num_action_items); g_assert(continue_with_next_action == TRUE); break; - case KM_KBP_IT_PERSIST_OPT: + case KM_CORE_IT_PERSIST_OPT: g_message("PERSIST_OPT action %d/%d", i + 1, (int)num_action_items); continue_with_next_action = process_persist_action(keyman, &action_items[i]); g_assert(continue_with_next_action == TRUE); break; - case KM_KBP_IT_EMIT_KEYSTROKE: + case KM_CORE_IT_EMIT_KEYSTROKE: g_message("EMIT_KEYSTROKE action %d/%d", i + 1, (int)num_action_items); continue_with_next_action = process_emit_keystroke_action(keyman); g_assert(continue_with_next_action == TRUE); break; - case KM_KBP_IT_INVALIDATE_CONTEXT: + case KM_CORE_IT_INVALIDATE_CONTEXT: g_message("INVALIDATE_CONTEXT action %d/%d", i + 1, (int)num_action_items); continue_with_next_action = process_invalidate_context_action(engine); g_assert(continue_with_next_action == TRUE); break; - case KM_KBP_IT_CAPSLOCK: + case KM_CORE_IT_CAPSLOCK: g_message("CAPSLOCK action %d/%d", i + 1, (int)num_action_items); continue_with_next_action = process_capslock_action(keyman, &action_items[i]); g_assert(continue_with_next_action == TRUE); break; - case KM_KBP_IT_END: + case KM_CORE_IT_END: g_message("END action %d/%d", i + 1, (int)num_action_items); continue_with_next_action = process_end_action(keyman); break; @@ -904,49 +904,49 @@ ibus_keyman_engine_process_key_event( // keyman modifiers are different from X11/ibus uint16_t km_mod_state = 0; if (state & IBUS_SHIFT_MASK) { - km_mod_state |= KM_KBP_MODIFIER_SHIFT; + km_mod_state |= KM_CORE_MODIFIER_SHIFT; } if (state & IBUS_MOD5_MASK) { - km_mod_state |= KM_KBP_MODIFIER_RALT; - g_message("%s: modstate KM_KBP_MODIFIER_RALT from IBUS_MOD5_MASK", __FUNCTION__); + km_mod_state |= KM_CORE_MODIFIER_RALT; + g_message("%s: modstate KM_CORE_MODIFIER_RALT from IBUS_MOD5_MASK", __FUNCTION__); } if (state & IBUS_MOD1_MASK) { if (keyman->ralt_pressed) { - km_mod_state |= KM_KBP_MODIFIER_RALT; - g_message("%s: modstate KM_KBP_MODIFIER_RALT from ralt_pressed", __FUNCTION__); + km_mod_state |= KM_CORE_MODIFIER_RALT; + g_message("%s: modstate KM_CORE_MODIFIER_RALT from ralt_pressed", __FUNCTION__); } if (keyman->lalt_pressed) { - km_mod_state |= KM_KBP_MODIFIER_LALT; - g_message("%s: modstate KM_KBP_MODIFIER_LALT from lalt_pressed", __FUNCTION__); + km_mod_state |= KM_CORE_MODIFIER_LALT; + g_message("%s: modstate KM_CORE_MODIFIER_LALT from lalt_pressed", __FUNCTION__); } } if (state & IBUS_CONTROL_MASK) { if (keyman->rctrl_pressed) { - km_mod_state |= KM_KBP_MODIFIER_RCTRL; - g_message("%s: modstate KM_KBP_MODIFIER_RCTRL from rctrl_pressed", __FUNCTION__); + km_mod_state |= KM_CORE_MODIFIER_RCTRL; + g_message("%s: modstate KM_CORE_MODIFIER_RCTRL from rctrl_pressed", __FUNCTION__); } if (keyman->lctrl_pressed) { - km_mod_state |= KM_KBP_MODIFIER_LCTRL; - g_message("%s: modstate KM_KBP_MODIFIER_LCTRL from lctrl_pressed", __FUNCTION__); + km_mod_state |= KM_CORE_MODIFIER_LCTRL; + g_message("%s: modstate KM_CORE_MODIFIER_LCTRL from lctrl_pressed", __FUNCTION__); } } if (state & IBUS_LOCK_MASK) { - km_mod_state |= KM_KBP_MODIFIER_CAPS; + km_mod_state |= KM_CORE_MODIFIER_CAPS; } g_message("%s: before process key event", __FUNCTION__); - km_kbp_context *context = km_kbp_state_context(keyman->state); + km_core_context *context = km_core_state_context(keyman->state); g_free(get_current_context_text(context)); g_message("DAR: %s - km_mod_state=0x%x", __FUNCTION__, km_mod_state); - km_kbp_process_event(keyman->state, keycode_to_vk[keycode], km_mod_state, isKeyDown, KM_KBP_EVENT_FLAG_DEFAULT); - context = km_kbp_state_context(keyman->state); + km_core_process_event(keyman->state, keycode_to_vk[keycode], km_mod_state, isKeyDown, KM_CORE_EVENT_FLAG_DEFAULT); + context = km_core_state_context(keyman->state); g_message("%s: after process key event", __FUNCTION__); g_free(get_current_context_text(context)); - // km_kbp_state_action_items to get action items + // km_core_state_action_items to get action items size_t num_action_items; g_free(keyman->commit_item->char_buffer); keyman->commit_item->char_buffer = NULL; - const km_kbp_action_item *action_items = km_kbp_state_action_items(keyman->state, &num_action_items); + const km_core_action_item *action_items = km_core_state_action_items(keyman->state, &num_action_items); if (!process_actions(engine, action_items, num_action_items) && (!client_supports_prefilter(engine) || client_supports_surrounding_text(engine))) { @@ -956,7 +956,7 @@ ibus_keyman_engine_process_key_event( return FALSE; } - context = km_kbp_state_context(keyman->state); + context = km_core_state_context(keyman->state); g_message("%s: after processing all actions", __FUNCTION__); g_free(get_current_context_text(context)); return TRUE; @@ -1009,7 +1009,7 @@ ibus_keyman_engine_focus_out (IBusEngine *engine) IBusKeymanEngine *keyman = (IBusKeymanEngine *) engine; g_message("%s", __FUNCTION__); - km_kbp_context_clear(km_kbp_state_context(keyman->state)); + km_core_context_clear(km_core_state_context(keyman->state)); parent_class->focus_out (engine); } diff --git a/linux/ibus-keyman/src/keycodes.h b/linux/ibus-keyman/src/keycodes.h index 2735da48cb2..add902a838e 100644 --- a/linux/ibus-keyman/src/keycodes.h +++ b/linux/ibus-keyman/src/keycodes.h @@ -1,101 +1,101 @@ #ifndef __KEYCODES_H__ #define __KEYCODES_H__ -#include +#include // from android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMScanCodeMap.java // uses kernel keycodes which are (X11 keycode - 8) // see /usr/include/linux/input-event-codes.h -static km_kbp_virtual_key const keycode_to_vk[256] = { +static km_core_virtual_key const keycode_to_vk[256] = { 0, // KEY_RESERVED = 0x00; - KM_KBP_VKEY_ESC, // KEY_ESC = 0x01; - KM_KBP_VKEY_1, // KEY_1 = 0x02; - KM_KBP_VKEY_2, // KEY_2 = 0x03; - KM_KBP_VKEY_3, // KEY_3 = 0x04; - KM_KBP_VKEY_4, // KEY_4 = 0x05; - KM_KBP_VKEY_5, // KEY_5 = 0x06; - KM_KBP_VKEY_6, // KEY_6 = 0x07; - KM_KBP_VKEY_7, // KEY_7 = 0x08; - KM_KBP_VKEY_8, // KEY_8 = 0x09; - KM_KBP_VKEY_9, // KEY_9 = 0x0A; - KM_KBP_VKEY_0, // KEY_0 = 0x0B; - KM_KBP_VKEY_HYPHEN, // KEY_MINUS = 0x0C; - KM_KBP_VKEY_EQUAL, // KEY_EQUALS = 0x0D; - KM_KBP_VKEY_BKSP, // KEY_BACKSPACE = 0x0E; - KM_KBP_VKEY_TAB, // KEY_TAB = 0x0F; - KM_KBP_VKEY_Q, // KEY_Q = 0x10; - KM_KBP_VKEY_W, // KEY_W = 0x11; - KM_KBP_VKEY_E, // KEY_E = 0x12; - KM_KBP_VKEY_R, // KEY_R = 0x13; - KM_KBP_VKEY_T, // KEY_T = 0x14; - KM_KBP_VKEY_Y, // KEY_Y = 0x15; - KM_KBP_VKEY_U, // KEY_U = 0x16; - KM_KBP_VKEY_I, // KEY_I = 0x17; - KM_KBP_VKEY_O, // KEY_O = 0x18; - KM_KBP_VKEY_P, // KEY_P = 0x19; - KM_KBP_VKEY_LBRKT, // KEY_LEFTBRACE = 0x1A; - KM_KBP_VKEY_RBRKT, // KEY_RIGHTBRACE = 0x1B; - KM_KBP_VKEY_ENTER, // KEY_ENTER = 0x1C; - KM_KBP_VKEY_CONTROL, // KEY_LEFTCTRL = 0x1D; - KM_KBP_VKEY_A, // KEY_A = 0x1E; - KM_KBP_VKEY_S, // KEY_S = 0x1F; - KM_KBP_VKEY_D, // KEY_D = 0x20; - KM_KBP_VKEY_F, // KEY_F = 0x21; - KM_KBP_VKEY_G, // KEY_G = 0x22; - KM_KBP_VKEY_H, // KEY_H = 0x23; - KM_KBP_VKEY_J, // KEY_J = 0x24; - KM_KBP_VKEY_K, // KEY_K = 0x25; - KM_KBP_VKEY_L, // KEY_L = 0x26; - KM_KBP_VKEY_COLON, // KEY_SEMICOLON = 0x27; - KM_KBP_VKEY_QUOTE, // KEY_APOSTROPHE = 0x28; - KM_KBP_VKEY_BKQUOTE, // KEY_GRAVE = 0x29; - KM_KBP_VKEY_SHIFT, // KEY_LEFTSHIFT = 0x2A; - KM_KBP_VKEY_BKSLASH, // KEY_BACKSLASH = 0x2B; - KM_KBP_VKEY_Z, // KEY_Z = 0x2C; - KM_KBP_VKEY_X, // KEY_X = 0x2D; - KM_KBP_VKEY_C, // KEY_C = 0x2E; - KM_KBP_VKEY_V, // KEY_V = 0x2F; - KM_KBP_VKEY_B, // KEY_B = 0x30; - KM_KBP_VKEY_N, // KEY_N = 0x31; - KM_KBP_VKEY_M, // KEY_M = 0x32; - KM_KBP_VKEY_COMMA, // KEY_COMMA = 0x33; - KM_KBP_VKEY_PERIOD, // KEY_DOT = 0x34; - KM_KBP_VKEY_SLASH, // KEY_SLASH = 0x35; - KM_KBP_VKEY_SHIFT, // KEY_RIGHTSHIFT = 0x36; - KM_KBP_VKEY_NPSTAR, // KEY_KPASTERISK = 0x37; - KM_KBP_VKEY_ALT, // KEY_LEFTALT = 0x38; - KM_KBP_VKEY_SPACE, // KEY_SPACE = 0x39; - KM_KBP_VKEY_CAPS, // KEY_CAPSLOCK = 0x3A; - KM_KBP_VKEY_F1, // KEY_F1 = 0x3B; - KM_KBP_VKEY_F2, // KEY_F2 = 0x3C; - KM_KBP_VKEY_F3, // KEY_F3 = 0x3D; - KM_KBP_VKEY_F4, // KEY_F4 = 0x3E; - KM_KBP_VKEY_F5, // KEY_F5 = 0x3F; - KM_KBP_VKEY_F6, // KEY_F6 = 0x40; - KM_KBP_VKEY_F7, // KEY_F7 = 0x41; - KM_KBP_VKEY_F8, // KEY_F8 = 0x42; - KM_KBP_VKEY_F9, // KEY_F9 = 0x43; - KM_KBP_VKEY_F10, // KEY_F10 = 0x44; + KM_CORE_VKEY_ESC, // KEY_ESC = 0x01; + KM_CORE_VKEY_1, // KEY_1 = 0x02; + KM_CORE_VKEY_2, // KEY_2 = 0x03; + KM_CORE_VKEY_3, // KEY_3 = 0x04; + KM_CORE_VKEY_4, // KEY_4 = 0x05; + KM_CORE_VKEY_5, // KEY_5 = 0x06; + KM_CORE_VKEY_6, // KEY_6 = 0x07; + KM_CORE_VKEY_7, // KEY_7 = 0x08; + KM_CORE_VKEY_8, // KEY_8 = 0x09; + KM_CORE_VKEY_9, // KEY_9 = 0x0A; + KM_CORE_VKEY_0, // KEY_0 = 0x0B; + KM_CORE_VKEY_HYPHEN, // KEY_MINUS = 0x0C; + KM_CORE_VKEY_EQUAL, // KEY_EQUALS = 0x0D; + KM_CORE_VKEY_BKSP, // KEY_BACKSPACE = 0x0E; + KM_CORE_VKEY_TAB, // KEY_TAB = 0x0F; + KM_CORE_VKEY_Q, // KEY_Q = 0x10; + KM_CORE_VKEY_W, // KEY_W = 0x11; + KM_CORE_VKEY_E, // KEY_E = 0x12; + KM_CORE_VKEY_R, // KEY_R = 0x13; + KM_CORE_VKEY_T, // KEY_T = 0x14; + KM_CORE_VKEY_Y, // KEY_Y = 0x15; + KM_CORE_VKEY_U, // KEY_U = 0x16; + KM_CORE_VKEY_I, // KEY_I = 0x17; + KM_CORE_VKEY_O, // KEY_O = 0x18; + KM_CORE_VKEY_P, // KEY_P = 0x19; + KM_CORE_VKEY_LBRKT, // KEY_LEFTBRACE = 0x1A; + KM_CORE_VKEY_RBRKT, // KEY_RIGHTBRACE = 0x1B; + KM_CORE_VKEY_ENTER, // KEY_ENTER = 0x1C; + KM_CORE_VKEY_CONTROL, // KEY_LEFTCTRL = 0x1D; + KM_CORE_VKEY_A, // KEY_A = 0x1E; + KM_CORE_VKEY_S, // KEY_S = 0x1F; + KM_CORE_VKEY_D, // KEY_D = 0x20; + KM_CORE_VKEY_F, // KEY_F = 0x21; + KM_CORE_VKEY_G, // KEY_G = 0x22; + KM_CORE_VKEY_H, // KEY_H = 0x23; + KM_CORE_VKEY_J, // KEY_J = 0x24; + KM_CORE_VKEY_K, // KEY_K = 0x25; + KM_CORE_VKEY_L, // KEY_L = 0x26; + KM_CORE_VKEY_COLON, // KEY_SEMICOLON = 0x27; + KM_CORE_VKEY_QUOTE, // KEY_APOSTROPHE = 0x28; + KM_CORE_VKEY_BKQUOTE, // KEY_GRAVE = 0x29; + KM_CORE_VKEY_SHIFT, // KEY_LEFTSHIFT = 0x2A; + KM_CORE_VKEY_BKSLASH, // KEY_BACKSLASH = 0x2B; + KM_CORE_VKEY_Z, // KEY_Z = 0x2C; + KM_CORE_VKEY_X, // KEY_X = 0x2D; + KM_CORE_VKEY_C, // KEY_C = 0x2E; + KM_CORE_VKEY_V, // KEY_V = 0x2F; + KM_CORE_VKEY_B, // KEY_B = 0x30; + KM_CORE_VKEY_N, // KEY_N = 0x31; + KM_CORE_VKEY_M, // KEY_M = 0x32; + KM_CORE_VKEY_COMMA, // KEY_COMMA = 0x33; + KM_CORE_VKEY_PERIOD, // KEY_DOT = 0x34; + KM_CORE_VKEY_SLASH, // KEY_SLASH = 0x35; + KM_CORE_VKEY_SHIFT, // KEY_RIGHTSHIFT = 0x36; + KM_CORE_VKEY_NPSTAR, // KEY_KPASTERISK = 0x37; + KM_CORE_VKEY_ALT, // KEY_LEFTALT = 0x38; + KM_CORE_VKEY_SPACE, // KEY_SPACE = 0x39; + KM_CORE_VKEY_CAPS, // KEY_CAPSLOCK = 0x3A; + KM_CORE_VKEY_F1, // KEY_F1 = 0x3B; + KM_CORE_VKEY_F2, // KEY_F2 = 0x3C; + KM_CORE_VKEY_F3, // KEY_F3 = 0x3D; + KM_CORE_VKEY_F4, // KEY_F4 = 0x3E; + KM_CORE_VKEY_F5, // KEY_F5 = 0x3F; + KM_CORE_VKEY_F6, // KEY_F6 = 0x40; + KM_CORE_VKEY_F7, // KEY_F7 = 0x41; + KM_CORE_VKEY_F8, // KEY_F8 = 0x42; + KM_CORE_VKEY_F9, // KEY_F9 = 0x43; + KM_CORE_VKEY_F10, // KEY_F10 = 0x44; 0, // KEY_NUMLOCK = 0x45; 0, // KEY_SCROLLLOCK = 0x46; - KM_KBP_VKEY_NP7, // KEY_KP7 = 0x47; - KM_KBP_VKEY_NP8, // KEY_KP8 = 0x48; - KM_KBP_VKEY_NP9, // KEY_KP9 = 0x49; - KM_KBP_VKEY_NPMINUS, // KEY_KPMINUS = 0x4A; - KM_KBP_VKEY_NP4, // KEY_KP4 = 0x4B; - KM_KBP_VKEY_NP5, // KEY_KP5 = 0x4C; - KM_KBP_VKEY_NP6, // KEY_KP6 = 0x4D; - KM_KBP_VKEY_NPPLUS, // KEY_KPPLUS = 0x4E; - KM_KBP_VKEY_NP1, // KEY_KP1 = 0x4F; - KM_KBP_VKEY_NP2, // KEY_KP2 = 0x50; - KM_KBP_VKEY_NP3, // KEY_KP3 = 0x51; - KM_KBP_VKEY_NP0, // KEY_KP0 = 0x52; - KM_KBP_VKEY_NPDOT, // KEY_KPDOT = 0x53; + KM_CORE_VKEY_NP7, // KEY_KP7 = 0x47; + KM_CORE_VKEY_NP8, // KEY_KP8 = 0x48; + KM_CORE_VKEY_NP9, // KEY_KP9 = 0x49; + KM_CORE_VKEY_NPMINUS, // KEY_KPMINUS = 0x4A; + KM_CORE_VKEY_NP4, // KEY_KP4 = 0x4B; + KM_CORE_VKEY_NP5, // KEY_KP5 = 0x4C; + KM_CORE_VKEY_NP6, // KEY_KP6 = 0x4D; + KM_CORE_VKEY_NPPLUS, // KEY_KPPLUS = 0x4E; + KM_CORE_VKEY_NP1, // KEY_KP1 = 0x4F; + KM_CORE_VKEY_NP2, // KEY_KP2 = 0x50; + KM_CORE_VKEY_NP3, // KEY_KP3 = 0x51; + KM_CORE_VKEY_NP0, // KEY_KP0 = 0x52; + KM_CORE_VKEY_NPDOT, // KEY_KPDOT = 0x53; 0, // padding 0x54; 0, // KEY_ZENKAKUHANKAKU = 0x55; - KM_KBP_VKEY_oE2, // KEY_102ND = 0x56; - KM_KBP_VKEY_F11, // KEY_F11 = 0x57; - KM_KBP_VKEY_F12, // KEY_F12 = 0x58; + KM_CORE_VKEY_oE2, // KEY_102ND = 0x56; + KM_CORE_VKEY_F11, // KEY_F11 = 0x57; + KM_CORE_VKEY_F12, // KEY_F12 = 0x58; 0, // KEY_RO = 0x59; 0, // KEY_KATAKANA = 0x5a; 0, // KEY_HIRAGANA = 0x5b; @@ -104,10 +104,10 @@ static km_kbp_virtual_key const keycode_to_vk[256] = { 0, // KEY_MUHENKAN = 0x5e; 0, // KEY_KPJPCOMMA = 0x5f; 0, // KEY_KPENTER = 0x60; - KM_KBP_VKEY_CONTROL, // KEY_RIGHTCTRL = 0x61; + KM_CORE_VKEY_CONTROL, // KEY_RIGHTCTRL = 0x61; 0, // KEY_KPSLASH = 0x62; 0, // KEY_SYSRQ = 0x63; - KM_KBP_VKEY_ALT // KEY_RIGHTALT = 0x64; + KM_CORE_VKEY_ALT // KEY_RIGHTALT = 0x64; // Many more KEYS currently not used by KMW... }; diff --git a/linux/ibus-keyman/src/keymanutil.c b/linux/ibus-keyman/src/keymanutil.c index 9eb42c173b2..9043746c7cf 100644 --- a/linux/ibus-keyman/src/keymanutil.c +++ b/linux/ibus-keyman/src/keymanutil.c @@ -55,18 +55,19 @@ #include #include #include -#include +#include #include "bcp47util.h" -#include "keymanutil.h" #include "kmpdetails.h" #include "keyman-version.h" +#include "keymanutil.h" +#include "keymanutil_internal.h" #define N_(text) text // change to keyman_get_kmpdirs_fromdir // returns list of directories with kmp.json -GList * keyman_get_kmpdirs_fromdir( GList *keyboard_list, const gchar * path) +GList * keyman_get_kmpdirs_fromdir(GList *kmpdir_list, const gchar * path) { DIR *dir = opendir(path); @@ -80,13 +81,13 @@ GList * keyman_get_kmpdirs_fromdir( GList *keyboard_list, const gchar * path) if (S_ISDIR(filestat.st_mode)) { if(g_strcmp0(file->d_name, ".") != 0 && g_strcmp0(file->d_name, "..") != 0) - keyboard_list = keyman_get_kmpdirs_fromdir(keyboard_list, absfn); + kmpdir_list = keyman_get_kmpdirs_fromdir(kmpdir_list, absfn); } // Looking for kmp.json else if (S_ISREG(filestat.st_mode) && g_strcmp0(file->d_name, "kmp.json") == 0) { g_message("adding kmp path %s", path); - keyboard_list=g_list_append(keyboard_list, g_strdup(path)); + kmpdir_list=g_list_append(kmpdir_list, g_strdup(path)); } g_free(absfn); @@ -94,7 +95,7 @@ GList * keyman_get_kmpdirs_fromdir( GList *keyboard_list, const gchar * path) } closedir(dir); } - return keyboard_list; + return kmpdir_list; } gchar * keyman_get_icon_file(const gchar *kmx_file) @@ -115,7 +116,7 @@ gchar * keyman_get_icon_file(const gchar *kmx_file) return full_path_to_icon_file; } -static IBusEngineDesc * +IBusEngineDesc * ibus_keyman_engine_desc_new (gchar * file_name, gchar *name, gchar *description, @@ -152,127 +153,157 @@ ibus_keyman_engine_desc_new (gchar * file_name, return engine_desc; } -GList * -ibus_keyman_add_engines(GList * engines, GList * kmpdir_list) -{ - GList *p, *k, *l, *e; - - for (p=kmpdir_list; p != NULL; p = p->next) { - gchar * kmp_dir = (gchar *) p->data; - - kmp_details *details = g_new0(kmp_details, 1); - get_kmp_details(kmp_dir, details); - - for (k=details->keyboards; k != NULL; k = k->next) { - kmp_keyboard *keyboard = (kmp_keyboard *) k->data; - gboolean alreadyexists = FALSE; - - for (e=engines; e != NULL && alreadyexists == FALSE; e = e->next) { - IBusEngineDesc *engine_desc = (IBusEngineDesc *) e->data; - const gchar *version = ibus_engine_desc_get_version(engine_desc); - const gchar *engine_name = ibus_engine_desc_get_name(engine_desc); - gchar *kmx_file = g_path_get_basename(engine_name); - if (g_strcmp0(kmx_file, keyboard->kmx_file) == 0 && g_strcmp0(version, keyboard->version) >= 0) { - alreadyexists = TRUE; - g_debug("keyboard %s already exists at version %s which is newer or same as %s", kmx_file, version, keyboard->version); - } - g_free(kmx_file); - } +IBusEngineDesc * +get_engine_for_language( + kmp_keyboard *keyboard, + kmp_info *info, + keyboard_details *kbd_details, + gchar *kmp_dir, + gchar *lang_id, + gchar *lang_name) { + IBusEngineDesc* engine_desc = NULL; + if (!lang_id || !strlen(lang_id)) + return engine_desc; - if (!alreadyexists) { - gchar *abs_kmx = g_strjoin("/", kmp_dir, keyboard->kmx_file, NULL); - gchar *json_file = g_strjoin(".", keyboard->id, "json", NULL); - keyboard_details *kbd_details = g_new0(keyboard_details, 1); - get_keyboard_details(kmp_dir, json_file, kbd_details); - g_free(json_file); - - if (keyboard->languages != NULL) { - for (l=keyboard->languages; l != NULL; l = l->next) { - kmp_language *language = (kmp_language *) l->data; - if (language->id != NULL) { - int capacity = 255; - gchar *name_with_lang = NULL; - gchar *minimized_tag = g_new0(gchar, capacity); - int result = bcp47_minimize(language->id, minimized_tag, capacity); - if (result < 0) { - g_strlcpy(minimized_tag, language->id, capacity); - } - - gchar *lang_code = g_new0(gchar, capacity); - if (!bcp47_get_language_code(minimized_tag, lang_code, capacity)) { - g_strlcpy(lang_code, minimized_tag, capacity); - } - - // If ibus doesn't know about the language then append the - // language name to the keyboard name - if (language->name != NULL) { - gchar *ibus_lang = ibus_get_untranslated_language_name(lang_code); - g_debug("%s: untranslated ibus language for %s: %s", __FUNCTION__, minimized_tag, ibus_lang); - if (g_strcmp0(ibus_lang, "Other") == 0) { - name_with_lang = g_strjoin(" - ", keyboard->name, language->name, NULL); - } - g_free(ibus_lang); - } - - gchar *id_with_lang = g_strjoin(":", minimized_tag, abs_kmx, NULL); - - g_message("adding engine %s", id_with_lang); - engines = g_list_append( - engines, - ibus_keyman_engine_desc_new( - id_with_lang, // lang:kmx full path - name_with_lang ? name_with_lang : keyboard->name, // longname - kbd_details->description, // description - details->info.copyright, // copyright if available - lang_code, // language, most are ignored by ibus except major languages - kbd_details->license, // license - details->info.author_desc, // author name only, not email - keyman_get_icon_file(abs_kmx), // icon full path - "us", // layout defaulting to us (en-US) - keyboard->version)); - g_free(lang_code); - g_free(minimized_tag); - g_free(id_with_lang); - g_free(name_with_lang); - } - } - } - else { - g_message("adding engine %s", abs_kmx); - engines = g_list_append (engines, - ibus_keyman_engine_desc_new (abs_kmx, // kmx full path - keyboard->name, // longname - kbd_details->description, // description - details->info.copyright, // copyright if available - NULL, // language, most are ignored by ibus except major languages - kbd_details->license, // license - details->info.author_desc, // author name only, not email - keyman_get_icon_file(abs_kmx), // icon full path - "us", // layout defaulting to us (en-US) - keyboard->version)); - } - free_keyboard_details(kbd_details); - g_free(kbd_details); - g_free(abs_kmx); - } + int capacity = 255; + gchar *name_with_lang = NULL; + gchar *minimized_tag = g_new0(gchar, capacity); + int result = bcp47_minimize(lang_id, minimized_tag, capacity); + if (result < 0) { + g_strlcpy(minimized_tag, lang_id, capacity); + } + + gchar *lang_code = g_new0(gchar, capacity); + if (!bcp47_get_language_code(minimized_tag, lang_code, capacity)) { + g_strlcpy(lang_code, minimized_tag, capacity); + } + + // If ibus doesn't know about the language then append the + // language name to the keyboard name + if (lang_name != NULL) { + gchar *ibus_lang = ibus_get_untranslated_language_name(lang_code); + g_debug("%s: untranslated ibus language for %s: %s", __FUNCTION__, minimized_tag, ibus_lang); + if (g_strcmp0(ibus_lang, "Other") == 0) { + name_with_lang = g_strjoin(" - ", keyboard->name, lang_name, NULL); + } + g_free(ibus_lang); + } + + gchar *abs_kmx = g_strjoin("/", kmp_dir, keyboard->kmx_file, NULL); + gchar *id_with_lang = g_strjoin(":", minimized_tag, abs_kmx, NULL); + + g_message("adding engine %s", id_with_lang); + engine_desc = ibus_keyman_engine_desc_new( + id_with_lang, // lang:kmx full path + name_with_lang ? name_with_lang : keyboard->name, // longname + kbd_details->description, // description + info->copyright, // copyright if available + lang_code, // language, most are ignored by ibus except major languages + kbd_details->license, // license + info->author_desc, // author name only, not email + keyman_get_icon_file(abs_kmx), // icon full path + "us", // layout defaulting to us (en-US) + keyboard->version); + g_free(abs_kmx); + g_free(lang_code); + g_free(minimized_tag); + g_free(id_with_lang); + g_free(name_with_lang); + return engine_desc; +} + +// Add a keyboard (ibus engine) to the list of engines +void +keyman_add_keyboard(gpointer data, gpointer user_data) { + kmp_keyboard *keyboard = (kmp_keyboard *)data; + add_keyboard_data *kb_data = (add_keyboard_data *)user_data; + gboolean alreadyexists = FALSE; + + for (GList *e = kb_data->engines_list; e != NULL && alreadyexists == FALSE; e = e->next) { + IBusEngineDesc *engine_desc = (IBusEngineDesc *)e->data; + const gchar *version = ibus_engine_desc_get_version(engine_desc); + const gchar *engine_name = ibus_engine_desc_get_name(engine_desc); + gchar *kmx_file = g_path_get_basename(engine_name); + // If we already have an engine for this keyboard (in a different area), we + // don't want to add it again since we wouldn't add anything new + // if it's the same version + // TODO: fix version comparison (#9593) + if (g_strcmp0(kmx_file, keyboard->kmx_file) == 0 && g_strcmp0(version, keyboard->version) >= 0) { + alreadyexists = TRUE; + g_debug("keyboard %s already exists at version %s which is newer or same as %s", kmx_file, version, keyboard->version); + } + g_free(kmx_file); + } + + if (!alreadyexists) { + gchar *json_file = g_strjoin(".", keyboard->id, "json", NULL); + keyboard_details *kbd_details = g_new0(keyboard_details, 1); + get_keyboard_details(kb_data->kmp_dir, json_file, kbd_details); + g_free(json_file); + + if (keyboard->languages != NULL) { + for (GList *l = keyboard->languages; l != NULL; l = l->next) { + kmp_language *language = (kmp_language *)l->data; + IBusEngineDesc *engine_desc = + get_engine_for_language(keyboard, kb_data->info, kbd_details, kb_data->kmp_dir, language->id, language->name); + if (engine_desc) { + kb_data->engines_list = g_list_append(kb_data->engines_list, engine_desc); } - free_kmp_details(details); - g_free(details); + } + } else { + gchar *abs_kmx = g_strjoin("/", kb_data->kmp_dir, keyboard->kmx_file, NULL); + g_message("adding engine %s", abs_kmx); + kb_data->engines_list = g_list_append( + kb_data->engines_list, + ibus_keyman_engine_desc_new( + abs_kmx, // kmx full path + keyboard->name, // longname + kbd_details->description, // description + kb_data->info->copyright, // copyright if available + NULL, // language, most are ignored by ibus except major languages + kbd_details->license, // license + kb_data->info->author_desc, // author name only, not email + keyman_get_icon_file(abs_kmx), // icon full path + "us", // layout defaulting to us (en-US) + keyboard->version)); + g_free(abs_kmx); } - return engines; + free_keyboard_details(kbd_details); + g_free(kbd_details); + } +} + +// Add keyboards found in {kmp_dir}/kmp.json to engines_list +void +keyman_add_keyboards_from_dir(gpointer data, gpointer user_data) { + gchar * kmp_dir = (gchar *) data; + GList ** engines_list = (GList **)user_data; + + kmp_details *details = g_new0(kmp_details, 1); + if (get_kmp_details(kmp_dir, details) == JSON_OK) { + add_keyboard_data kb_data; + kb_data.engines_list = *engines_list; + kb_data.info = &details->info; + kb_data.kmp_dir = kmp_dir; + + g_list_foreach(details->keyboards, keyman_add_keyboard, &kb_data); + *engines_list = kb_data.engines_list; + } + free_kmp_details(details); + g_free(details); } GList * ibus_keyman_list_engines (void) { GList *engines = NULL; - GList *keyboard_list; + GList *kmpdir_list; gchar *local_keyboard_path, *xdgenv; g_debug("adding from /usr/share/keyman"); - keyboard_list = keyman_get_kmpdirs_fromdir(NULL, "/usr/share/keyman"); + kmpdir_list = keyman_get_kmpdirs_fromdir(NULL, "/usr/share/keyman"); g_debug("adding from /usr/local/share/keyman"); - keyboard_list = keyman_get_kmpdirs_fromdir(keyboard_list, "/usr/local/share/keyman"); + kmpdir_list = keyman_get_kmpdirs_fromdir(kmpdir_list, "/usr/local/share/keyman"); xdgenv = getenv("XDG_DATA_HOME"); if (xdgenv != NULL){ local_keyboard_path= g_strdup_printf("%s/keyman", xdgenv); @@ -282,10 +313,10 @@ ibus_keyman_list_engines (void) local_keyboard_path= g_strdup_printf("%s/.local/share/keyman", xdgenv); } g_debug("adding from %s", local_keyboard_path); - keyboard_list = keyman_get_kmpdirs_fromdir(keyboard_list, local_keyboard_path); + kmpdir_list = keyman_get_kmpdirs_fromdir(kmpdir_list, local_keyboard_path); g_free(local_keyboard_path); - engines = ibus_keyman_add_engines(engines, keyboard_list); - g_list_free(keyboard_list); + g_list_foreach(kmpdir_list, keyman_add_keyboards_from_dir, &engines); + g_list_free(kmpdir_list); return engines; } @@ -335,7 +366,7 @@ keyman_get_options_fromdconf(gchar *package_id, g_message("keyman_get_options_fromdconf"); // Obtain keyboard options from DConf - gchar *path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, package_id, keyboard_id); + g_autofree gchar *path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, package_id, keyboard_id); GSettings *child_settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); gchar **options = NULL; if (child_settings != NULL) @@ -344,12 +375,11 @@ keyman_get_options_fromdconf(gchar *package_id, } g_object_unref(G_OBJECT(child_settings)); - g_free(path); return options; } -// Obtain Keyboard Options from DConf and parse into a GQueue of struct km_kbp_option_item +// Obtain Keyboard Options from DConf and parse into a GQueue of struct km_core_option_item // // Parameters: // package_id (gchar *): Package ID @@ -364,7 +394,7 @@ keyman_get_options_queue_fromdconf(gchar *package_id, GQueue *queue_options = g_queue_new(); // Obtain keyboard options from DConf - gchar **options = keyman_get_options_fromdconf(package_id, keyboard_id); + g_auto(GStrv) options = keyman_get_options_fromdconf(package_id, keyboard_id); // Parse options into queue_options if (options != NULL) @@ -372,13 +402,13 @@ keyman_get_options_queue_fromdconf(gchar *package_id, int index = 0; while (options[index] != NULL) { - gchar **option_tokens = g_strsplit(options[index], "=", 2); + g_auto(GStrv) option_tokens = g_strsplit(options[index], "=", 2); if (option_tokens != NULL && option_tokens[0] != NULL && option_tokens[1] != NULL) { g_message("Keyboard Option [%d], %s=%s", index, option_tokens[0], option_tokens[1]); - km_kbp_option_item *opt = g_new0(km_kbp_option_item, 1); - opt[0].scope = KM_KBP_OPT_KEYBOARD; - km_kbp_cp *ocp = g_utf8_to_utf16(option_tokens[0], -1, NULL, NULL, NULL); + km_core_option_item *opt = g_new0(km_core_option_item, 1); + opt[0].scope = KM_CORE_OPT_KEYBOARD; + km_core_cp *ocp = g_utf8_to_utf16(option_tokens[0], -1, NULL, NULL, NULL); opt[0].key = ocp; ocp = g_utf8_to_utf16 (option_tokens[1], -1, NULL, NULL, NULL); opt[0].value = ocp; @@ -386,7 +416,6 @@ keyman_get_options_queue_fromdconf(gchar *package_id, } index++; } - g_strfreev(options); } return queue_options; @@ -415,60 +444,46 @@ keyman_put_options_todconf(gchar *package_id, } // Obtain keyboard options from DConf - gchar **options = keyman_get_options_fromdconf(package_id, keyboard_id); - gchar *needle = g_strdup_printf("%s=", option_key); + g_auto(GStrv) options = keyman_get_options_fromdconf(package_id, keyboard_id); + g_autofree gchar *needle = g_strdup_printf("%s=", option_key); gchar *kvp = g_strdup_printf("%s=%s", option_key, option_value); - if (options != NULL) - { - int index = 0; - gboolean option_updated = FALSE; - while (options[index] != NULL) - { - // If option_key already exists, update value with option_value - if (g_strrstr(options[index], needle) != NULL) - { - g_free(options[index]); - options[index] = kvp; - option_updated = TRUE; - break; - } - index++; - } + g_assert(options != NULL); - if (!option_updated) + int index = 0; + gboolean option_updated = FALSE; + while (options[index] != NULL) + { + // If option_key already exists, update value with option_value + if (g_strrstr(options[index], needle) != NULL) { - // Resize to add new option and null-terminate - int size = index + 2; // old size: index + 1, plus 1 new - options = g_renew(gchar*, options, size); + g_free(options[index]); options[index] = kvp; - options[index+1] = NULL; + option_updated = TRUE; + break; } + index++; } - else + + if (!option_updated) { - // we never should come here - keyman_get_options_fromdconf will create empty - // options if they don't yet exist. - // Allocate space for new option and null-terminate - options = g_new(gchar *, 2); - options[0] = kvp; - options[1] = NULL; + // Resize to add new option and null-terminate + int size = index + 2; // old size: index + 1, plus 1 new + options = g_renew(gchar*, options, size); + options[index] = kvp; + options[index+1] = NULL; } // Write to DConf - gchar *path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, package_id, keyboard_id); - GSettings *child_settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); + g_autofree gchar *path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, package_id, keyboard_id); + g_autoptr(GSettings) child_settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); if (child_settings != NULL) { g_message("writing keyboard options to DConf"); g_settings_set_strv(child_settings, KEYMAN_DCONF_OPTIONS_KEY, (const gchar *const *)options); } - g_object_unref(G_OBJECT(child_settings)); - g_free(path); - g_free(needle); - g_strfreev(options); - // kvp got assigned to options[x] and so got freed by g_strfreev() + // kvp got assigned to options[x] and so gets freed when options are freed } diff --git a/linux/ibus-keyman/src/keymanutil.h b/linux/ibus-keyman/src/keymanutil.h index 4b358c02ead..de1aef49fab 100644 --- a/linux/ibus-keyman/src/keymanutil.h +++ b/linux/ibus-keyman/src/keymanutil.h @@ -55,7 +55,7 @@ #include #include -#include +#include // Number of default Keyboard processor environment options for: "platform", "baseLayout", and "baseLayoutAlt" #define KEYMAN_ENVIRONMENT_OPTIONS 3 @@ -87,7 +87,7 @@ gchar** keyman_get_options_fromdconf (gchar *package_id, gchar *keyboard_id); -// Obtain Keyboard Options from DConf and parse into a GQueue of struct km_kbp_option_item +// Obtain Keyboard Options from DConf and parse into a GQueue of struct km_core_option_item // // Parameters: // package_id (gchar *): Package ID diff --git a/linux/ibus-keyman/src/keymanutil_internal.h b/linux/ibus-keyman/src/keymanutil_internal.h new file mode 100644 index 00000000000..112f7abd16e --- /dev/null +++ b/linux/ibus-keyman/src/keymanutil_internal.h @@ -0,0 +1,39 @@ +// Internal data structures used in the implementation of keymanutil methods +// and exposed for unit testing. + +#ifndef __KEYMANUTIL_INTERNAL_H__ +#define __KEYMANUTIL_INTERNAL_H__ + +#include +#include "kmpdetails.h" + +typedef struct { + GList *engines_list; + kmp_info *info; + gchar *kmp_dir; +} add_keyboard_data; + +IBusEngineDesc *ibus_keyman_engine_desc_new( + gchar *file_name, + gchar *name, + gchar *description, + gchar *copyright, + gchar *lang, + gchar *license, + gchar *author, + gchar *icon, + gchar *layout, + gchar *version); + +IBusEngineDesc *get_engine_for_language( + kmp_keyboard *keyboard, + kmp_info *info, + keyboard_details *kbd_details, + gchar *kmp_dir, + gchar *lang_id, + gchar *lang_name); + +void keyman_add_keyboard(gpointer data, gpointer user_data); +void keyman_add_keyboards_from_dir(gpointer data, gpointer user_data); + +#endif // __KEYMANUTIL_INTERNAL_H__ diff --git a/linux/ibus-keyman/src/kmpdetails.c b/linux/ibus-keyman/src/kmpdetails.c index eba95f4ef97..18ffde73ac8 100644 --- a/linux/ibus-keyman/src/kmpdetails.c +++ b/linux/ibus-keyman/src/kmpdetails.c @@ -455,6 +455,24 @@ kmp_json_status free_keyboard_details(keyboard_details *kbd_details) return JSON_OK; } +void free_info(gpointer data) { + kmp_info *info = (kmp_info *)data; + if (info->name) + g_free(info->name); + if (info->version) + g_free(info->version); + if (info->copyright) + g_free(info->copyright); + if (info->author_desc) + g_free(info->author_desc); + if (info->author_url) + g_free(info->author_url); + if (info->website_desc) + g_free(info->website_desc); + if (info->website_url) + g_free(info->website_url); +} + kmp_json_status free_kmp_details(kmp_details * details) { g_assert(details != NULL); @@ -462,15 +480,9 @@ kmp_json_status free_kmp_details(kmp_details * details) g_free(details->system.keymanDeveloperVersion); g_free(details->options.readmeFile); g_free(details->options.graphicFile); - g_free(details->info.name); - g_free(details->info.version); - g_free(details->info.copyright); - g_free(details->info.author_desc); - g_free(details->info.author_url); - g_free(details->info.website_desc); - g_free(details->info.website_url); + free_info(&details->info); if (details->keyboards != NULL) { - g_list_free_full(details->keyboards, (GDestroyNotify)free_keyboard); + g_list_free_full(details->keyboards, (GDestroyNotify)free_keyboard); } if (details->files != NULL) { g_list_free_full(details->files, (GDestroyNotify)free_fileinfo); diff --git a/linux/ibus-keyman/src/kmpdetails.h b/linux/ibus-keyman/src/kmpdetails.h index 3bcf6a97390..586f815baef 100644 --- a/linux/ibus-keyman/src/kmpdetails.h +++ b/linux/ibus-keyman/src/kmpdetails.h @@ -1,3 +1,6 @@ +#ifndef __KMPDETAILS_H__ +#define __KMPDETAILS_H__ + // kmp details from json #include @@ -75,4 +78,6 @@ kmp_json_status get_kmp_details(const gchar *kmp_dir, kmp_details *details); kmp_json_status free_kmp_details(kmp_details * details); kmp_json_status get_keyboard_details(const gchar *kmp_dir, const gchar *id, keyboard_details *details); kmp_json_status free_keyboard_details(keyboard_details * details); -kmp_json_status print_kmp_details(kmp_details * details); \ No newline at end of file +kmp_json_status print_kmp_details(kmp_details * details); + +#endif // __KMPDETAILS_H__ diff --git a/linux/ibus-keyman/src/test/keymanutil_tests.c b/linux/ibus-keyman/src/test/keymanutil_tests.c index 80f77a72ea6..499f044d55a 100644 --- a/linux/ibus-keyman/src/test/keymanutil_tests.c +++ b/linux/ibus-keyman/src/test/keymanutil_tests.c @@ -1,77 +1,157 @@ #include #include #include +#include +#include "kmpdetails.h" #include "keymanutil.h" +#include "keymanutil_internal.h" #define TEST_FIXTURE "keymanutil-test" void -delete_options_key(gchar* testname) { - gchar *path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, TEST_FIXTURE, testname); - GSettings *settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); +_delete_tst_options_key(gchar* testname) { + g_autofree gchar *path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, TEST_FIXTURE, testname); + g_autoptr(GSettings) settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); g_settings_reset(settings, KEYMAN_DCONF_OPTIONS_KEY); - g_object_unref(G_OBJECT(settings)); - g_free(path); } void -set_options_key(gchar* testname, gchar** options) { - gchar *path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, TEST_FIXTURE, testname); - GSettings *settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); +_set_tst_options_key(gchar* testname, gchar** options) { + g_autofree gchar* path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, TEST_FIXTURE, testname); + g_autoptr(GSettings) settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); g_settings_set_strv(settings, KEYMAN_DCONF_OPTIONS_KEY, (const gchar* const*)options); - g_object_unref(G_OBJECT(settings)); - g_free(path); } gchar** -get_options_key(gchar* testname) { - gchar* path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, TEST_FIXTURE, testname); - GSettings* settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); +_get_tst_options_key(gchar* testname) { + g_autofree gchar* path = g_strdup_printf("%s%s/%s/", KEYMAN_DCONF_OPTIONS_PATH, TEST_FIXTURE, testname); + g_autoptr(GSettings) settings = g_settings_new_with_path(KEYMAN_DCONF_OPTIONS_CHILD_NAME, path); gchar** result = g_settings_get_strv(settings, KEYMAN_DCONF_OPTIONS_KEY); - g_object_unref(G_OBJECT(settings)); - g_free(path); return result; } +kmp_keyboard* +_get_tst_kmp_keyboard(gchar* version, gchar** languages) { + kmp_keyboard* keyboard = g_new0(kmp_keyboard, 1); + keyboard->name = g_strdup("Testing"); + keyboard->id = g_strdup("tst"); + keyboard->version = g_strdup(version); + keyboard->kmx_file = g_strdup("tst.kmx"); + keyboard->kvk_file = g_strdup(""); + keyboard->languages = NULL; + for (gchar* lang = *languages++; lang; lang = *languages++) { + gchar** tokens = g_strsplit(lang, ":", 2); + kmp_language* kmp_lang = g_new0(kmp_language, 1); + kmp_lang->id = g_strdup(tokens[0]); + kmp_lang->name = g_strdup(tokens[1]); + g_strfreev(tokens); + keyboard->languages = g_list_append(keyboard->languages, kmp_lang); + } + return keyboard; +} + +kmp_info* +_get_tst_kmp_info(gchar * copyright, gchar * author_desc, gchar * author_url) { + kmp_info* info = g_new0(kmp_info, 1); + info->copyright = g_strdup(copyright); + info->author_desc = g_strdup(author_desc); + info->author_url = g_strdup(author_url); + return info; +} + +keyboard_details* +_get_tst_keyboard_details(gchar * description, gchar * license) { + keyboard_details* details = g_new0(keyboard_details, 1); + details->id = g_strdup("tst"); + details->description = g_strdup(description); + details->license = g_strdup(license); + return details; +} + +add_keyboard_data* +_get_tst_keyboard_data() { + add_keyboard_data* kb_data = g_new0(add_keyboard_data, 1); + kb_data->engines_list = NULL; + kb_data->info = _get_tst_kmp_info(NULL, NULL, NULL); + kb_data->kmp_dir = "/tmp"; + return kb_data; +} + +void +_free_tst_kb_data(add_keyboard_data* kb_data) { + if (kb_data->engines_list) + g_list_free(kb_data->engines_list); + if (kb_data->info) + g_free(kb_data->info); + g_free(kb_data); +} + +// defined in kmpdetails +void free_keyboard(gpointer data); +void free_info(gpointer data); +kmp_json_status free_keyboard_details(keyboard_details* kbd_details); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(add_keyboard_data, _free_tst_kb_data) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(kmp_keyboard, free_keyboard) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(kmp_info, free_info) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(keyboard_details, free_keyboard_details) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(IBusEngineDesc, g_object_unref) + +//---------------------------------------------------------------------------------------------- +void +test_keyman_put_options_todconf__invalid() { + // Initialize + gchar* testname = "test_keyman_put_options_todconf__test_keyman_put_options_todconf__invalid"; + _delete_tst_options_key(testname); + + // Execute + keyman_put_options_todconf(TEST_FIXTURE, testname, "new_key", NULL); + + // Verify + g_auto(GStrv) options = _get_tst_options_key(testname); + g_assert_nonnull(options); + g_assert_null(options[0]); + + // Cleanup + _delete_tst_options_key(testname); +} + void test_keyman_put_options_todconf__new_key() { // Initialize gchar* testname = "test_keyman_put_options_todconf__new_key"; - delete_options_key(testname); - gchar* value = g_strdup_printf("%d", g_test_rand_int()); + _delete_tst_options_key(testname); + g_autofree gchar* value = g_strdup_printf("%d", g_test_rand_int()); // Execute keyman_put_options_todconf(TEST_FIXTURE, testname, "new_key", value); // Verify - gchar** options = get_options_key(testname); - gchar* expected = g_strdup_printf("new_key=%s", value); + g_auto(GStrv) options = _get_tst_options_key(testname); + g_autofree gchar* expected = g_strdup_printf("new_key=%s", value); g_assert_nonnull(options); g_assert_cmpstr(options[0], ==, expected); g_assert_null(options[1]); // Cleanup - g_free(expected); - g_free(value); - g_strfreev(options); - delete_options_key(testname); + _delete_tst_options_key(testname); } void test_keyman_put_options_todconf__other_keys() { // Initialize gchar* testname = "test_keyman_put_options_todconf__other_keys"; - delete_options_key(testname); + _delete_tst_options_key(testname); gchar* existingKeys[] = {"key1=val1", "key2=val2", NULL}; - set_options_key(testname, existingKeys); - gchar* value = g_strdup_printf("%d", g_test_rand_int()); + _set_tst_options_key(testname, existingKeys); + g_autofree gchar* value = g_strdup_printf("%d", g_test_rand_int()); // Execute keyman_put_options_todconf(TEST_FIXTURE, testname, "new_key", value); // Verify - gchar** options = get_options_key(testname); - gchar* expected = g_strdup_printf("new_key=%s", value); + g_auto(GStrv) options = _get_tst_options_key(testname); + g_autofree gchar* expected = g_strdup_printf("new_key=%s", value); g_assert_nonnull(options); g_assert_cmpstr(options[0], ==, "key1=val1"); g_assert_cmpstr(options[1], ==, "key2=val2"); @@ -79,50 +159,547 @@ test_keyman_put_options_todconf__other_keys() { g_assert_null(options[3]); // Cleanup - g_free(expected); - g_free(value); - g_strfreev(options); - delete_options_key(testname); + _delete_tst_options_key(testname); } void test_keyman_put_options_todconf__existing_key() { // Initialize gchar* testname = "test_keyman_put_options_todconf__existing_key"; - delete_options_key(testname); + _delete_tst_options_key(testname); gchar* existingKeys[] = {"key1=val1", "new_key=val2", NULL}; - set_options_key(testname, existingKeys); - gchar* value = g_strdup_printf("%d", g_test_rand_int()); + _set_tst_options_key(testname, existingKeys); + g_autofree gchar* value = g_strdup_printf("%d", g_test_rand_int()); // Execute keyman_put_options_todconf(TEST_FIXTURE, testname, "new_key", value); // Verify - gchar** options = get_options_key(testname); - gchar* expected = g_strdup_printf("new_key=%s", value); + g_auto(GStrv) options = _get_tst_options_key(testname); + g_autofree gchar* expected = g_strdup_printf("new_key=%s", value); g_assert_nonnull(options); g_assert_cmpstr(options[0], ==, "key1=val1"); g_assert_cmpstr(options[1], ==, expected); g_assert_null(options[2]); // Cleanup - g_free(expected); - g_free(value); - g_strfreev(options); - delete_options_key(testname); + _delete_tst_options_key(testname); +} + +//---------------------------------------------------------------------------------------------- +void +test_ibus_keyman_engine_desc_new__all_set() { + // Execute + g_autoptr(IBusEngineDesc) desc = ibus_keyman_engine_desc_new("name", "longname", "description", "copyright", "lang", "license", "author", "icon", "layout", "version"); + + // Verify + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "name"); + g_assert_cmpstr(ibus_engine_desc_get_longname(desc), ==, "longname"); + g_assert_cmpstr(ibus_engine_desc_get_description(desc), ==, "description\ncopyright"); + g_assert_cmpstr(ibus_engine_desc_get_language(desc), ==, "lang"); + g_assert_cmpstr(ibus_engine_desc_get_license(desc), ==, "license"); + g_assert_cmpstr(ibus_engine_desc_get_author(desc), ==, "author"); + g_assert_cmpstr(ibus_engine_desc_get_icon(desc), ==, "icon"); + g_assert_cmpstr(ibus_engine_desc_get_layout(desc), ==, "layout"); + g_assert_cmpstr(ibus_engine_desc_get_version(desc), ==, "version"); +} + +void +test_ibus_keyman_engine_desc_new__only_description() { + // Execute + g_autoptr(IBusEngineDesc) desc = ibus_keyman_engine_desc_new( + "name", "longname", "description", NULL, "lang", "license", "author", "icon", "layout", "version"); + + // Verify + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "name"); + g_assert_cmpstr(ibus_engine_desc_get_longname(desc), ==, "longname"); + g_assert_cmpstr(ibus_engine_desc_get_description(desc), ==, "description\n(null)"); + g_assert_cmpstr(ibus_engine_desc_get_language(desc), ==, "lang"); + g_assert_cmpstr(ibus_engine_desc_get_license(desc), ==, "license"); + g_assert_cmpstr(ibus_engine_desc_get_author(desc), ==, "author"); + g_assert_cmpstr(ibus_engine_desc_get_icon(desc), ==, "icon"); + g_assert_cmpstr(ibus_engine_desc_get_layout(desc), ==, "layout"); + g_assert_cmpstr(ibus_engine_desc_get_version(desc), ==, "version"); +} + +void +test_ibus_keyman_engine_desc_new__only_copyright() { + // Execute + g_autoptr(IBusEngineDesc) desc = ibus_keyman_engine_desc_new( + "name", "longname", NULL, "copyright", "lang", "license", "author", "icon", "layout", "version"); + + // Verify + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "name"); + g_assert_cmpstr(ibus_engine_desc_get_longname(desc), ==, "longname"); + g_assert_cmpstr(ibus_engine_desc_get_description(desc), ==, "copyright"); + g_assert_cmpstr(ibus_engine_desc_get_language(desc), ==, "lang"); + g_assert_cmpstr(ibus_engine_desc_get_license(desc), ==, "license"); + g_assert_cmpstr(ibus_engine_desc_get_author(desc), ==, "author"); + g_assert_cmpstr(ibus_engine_desc_get_icon(desc), ==, "icon"); + g_assert_cmpstr(ibus_engine_desc_get_layout(desc), ==, "layout"); + g_assert_cmpstr(ibus_engine_desc_get_version(desc), ==, "version"); +} + +void +test_ibus_keyman_engine_desc_new__no_language_license_author_version() { + // Execute + g_autoptr(IBusEngineDesc) desc = ibus_keyman_engine_desc_new( + "name", "longname", "description", "copyright", NULL, NULL, NULL, "icon", "layout", NULL); + + // Verify + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "name"); + g_assert_cmpstr(ibus_engine_desc_get_longname(desc), ==, "longname"); + g_assert_cmpstr(ibus_engine_desc_get_description(desc), ==, "description\ncopyright"); + g_assert_cmpstr(ibus_engine_desc_get_language(desc), ==, "other"); + g_assert_cmpstr(ibus_engine_desc_get_license(desc), ==, ""); + g_assert_cmpstr(ibus_engine_desc_get_author(desc), ==, ""); + g_assert_cmpstr(ibus_engine_desc_get_icon(desc), ==, "icon"); + g_assert_cmpstr(ibus_engine_desc_get_layout(desc), ==, "layout"); + g_assert_cmpstr(ibus_engine_desc_get_version(desc), ==, ""); +} + +//---------------------------------------------------------------------------------------------- +void +test_get_engine_for_language__null_language() { + // Initialize + gchar* languages[] = {"en:English", NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(kmp_info) info = _get_tst_kmp_info("Copyright by me", "My Author", "myauthor@example.com"); + g_autoptr(keyboard_details) details = _get_tst_keyboard_details("my description", "MIT"); + + // Execute + g_autoptr(IBusEngineDesc) desc = get_engine_for_language(keyboard, info, details, "/tmp", NULL, NULL); + + // Verify + g_assert_null(desc); +} + +void +test_get_engine_for_language__empty_language() { + // Initialize + gchar* languages[] = {"en:English", NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(kmp_info) info = _get_tst_kmp_info("Copyright by me", "My Author", "myauthor@example.com"); + g_autoptr(keyboard_details) details = _get_tst_keyboard_details("my description", "MIT"); + + // Execute + g_autoptr(IBusEngineDesc) desc = get_engine_for_language(keyboard, info, details, "/tmp", "", ""); + + // Verify + g_assert_null(desc); +} + +void +test_get_engine_for_language__one_language() { + // Initialize + gchar* languages[] = {"en:English", NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(kmp_info) info = _get_tst_kmp_info("Copyright by me", "My Author", "myauthor@example.com"); + g_autoptr(keyboard_details) details = _get_tst_keyboard_details("my description", "MIT"); + + // Execute + g_autoptr(IBusEngineDesc) desc = get_engine_for_language(keyboard, info, details, "/tmp", "en", "English"); + + // Verify + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "en:/tmp/tst.kmx"); + g_assert_cmpstr(ibus_engine_desc_get_longname(desc), ==, "Testing"); + g_assert_cmpstr(ibus_engine_desc_get_language(desc), ==, "en"); +} + +void +test_get_engine_for_language__one_unknown_language() { + // Initialize + gchar* languages[] = {"foo:Foo", NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(kmp_info) info = _get_tst_kmp_info("Copyright by me", "My Author", "myauthor@example.com"); + g_autoptr(keyboard_details) details = _get_tst_keyboard_details("my description", "MIT"); + + // Execute + g_autoptr(IBusEngineDesc) desc = get_engine_for_language(keyboard, info, details, "/tmp", "foo", "Foo"); + + // Verify + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "foo:/tmp/tst.kmx"); + g_assert_cmpstr(ibus_engine_desc_get_longname(desc), ==, "Testing - Foo"); + g_assert_cmpstr(ibus_engine_desc_get_language(desc), ==, "foo"); +} + +void +test_get_engine_for_language__different_languages() { + // Initialize + gchar* languages[] = {"en:English", NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(kmp_info) info = _get_tst_kmp_info("Copyright by me", "My Author", "myauthor@example.com"); + g_autoptr(keyboard_details) details = _get_tst_keyboard_details("my description", "MIT"); + + // Execute + g_autoptr(IBusEngineDesc) desc = get_engine_for_language(keyboard, info, details, "/tmp", "foo", "Foo"); + + // Verify + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "foo:/tmp/tst.kmx"); + g_assert_cmpstr(ibus_engine_desc_get_longname(desc), ==, "Testing - Foo"); + g_assert_cmpstr(ibus_engine_desc_get_language(desc), ==, "foo"); +} + +void +test_get_engine_for_language__no_kbd_language() { + // Initialize + gchar* languages[] = {NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(kmp_info) info = _get_tst_kmp_info("Copyright by me", "My Author", "myauthor@example.com"); + g_autoptr(keyboard_details) details = _get_tst_keyboard_details("my description", "MIT"); + + // Execute + g_autoptr(IBusEngineDesc) desc = get_engine_for_language(keyboard, info, details, "/tmp", "en", "English"); + + // Verify + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "en:/tmp/tst.kmx"); + g_assert_cmpstr(ibus_engine_desc_get_longname(desc), ==, "Testing"); + g_assert_cmpstr(ibus_engine_desc_get_language(desc), ==, "en"); +} + +//---------------------------------------------------------------------------------------------- +void +test_keyman_add_keyboard__no_language() { + // Initialize + gchar* languages[] = {NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(add_keyboard_data) kb_data = _get_tst_keyboard_data(); + + // Execute + keyman_add_keyboard(keyboard, kb_data); + + // Verify + g_assert_nonnull(kb_data->engines_list->data); + IBusEngineDesc* desc = (IBusEngineDesc*)kb_data->engines_list->data; + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "/tmp/tst.kmx"); + g_assert_null(kb_data->engines_list->next); +} + +void +test_keyman_add_keyboard__one_language() { + // Initialize + gchar* languages[] = {"en:English", NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(add_keyboard_data) kb_data = _get_tst_keyboard_data(); + + // Execute + keyman_add_keyboard(keyboard, kb_data); + + // Verify + g_assert_nonnull(kb_data->engines_list->data); + IBusEngineDesc* desc = (IBusEngineDesc*)kb_data->engines_list->data; + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "en:/tmp/tst.kmx"); + g_assert_null(kb_data->engines_list->next); } -int -main(int argc, char* argv[]) { +void +test_keyman_add_keyboard__two_languages() { + // Initialize + gchar* languages[] = {"en:English", "fr:French", NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(add_keyboard_data) kb_data = _get_tst_keyboard_data(); + + // Execute + keyman_add_keyboard(keyboard, kb_data); + + // Verify + g_assert_nonnull(kb_data->engines_list->data); + IBusEngineDesc* desc = (IBusEngineDesc*)kb_data->engines_list->data; + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "en:/tmp/tst.kmx"); + g_assert_nonnull(kb_data->engines_list->next); + g_assert_nonnull(kb_data->engines_list->next->data); + desc = (IBusEngineDesc*)kb_data->engines_list->next->data; + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, "fr:/tmp/tst.kmx"); + g_assert_null(kb_data->engines_list->next->next); +} + +void +test_keyman_add_keyboard__prev_engine_adding_same_version() { + // Initialize + gchar* languages[] = {"en:English", NULL}; + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.0", languages); + g_autoptr(add_keyboard_data) kb_data = _get_tst_keyboard_data(); + IBusEngineDesc* desc = ibus_keyman_engine_desc_new("en:/usr/share/keyman/tst.kmx", "Testing", NULL, NULL, "en", NULL, NULL, "", "us", "1.0"); + kb_data->engines_list = g_list_append(kb_data->engines_list, desc); + + // Execute + keyman_add_keyboard(keyboard, kb_data); + + // Verify + GList* list = kb_data->engines_list; + g_assert_nonnull(list->data); + g_assert_cmpstr(ibus_engine_desc_get_name((IBusEngineDesc*)list->data), ==, "en:/usr/share/keyman/tst.kmx"); + g_assert_null(list->next); +} + +void +test_keyman_add_keyboard__prev_engine_adding_newer_version() { + // Initialize + gchar* languages[] = {"en:English", "fr:French", NULL}; // New version adds French + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.1", languages); + g_autoptr(add_keyboard_data) kb_data = _get_tst_keyboard_data(); + IBusEngineDesc* desc = + ibus_keyman_engine_desc_new("en:/usr/share/keyman/tst.kmx", "Testing", NULL, NULL, "en", NULL, NULL, "", "us", "1.0"); + kb_data->engines_list = g_list_append(kb_data->engines_list, desc); + + // Execute + keyman_add_keyboard(keyboard, kb_data); + + // Verify + GList* list = kb_data->engines_list; + g_assert_nonnull(list->data); + g_assert_cmpstr(ibus_engine_desc_get_name((IBusEngineDesc*)list->data), ==, "en:/usr/share/keyman/tst.kmx"); + g_assert_nonnull(list->next); + list = list->next; + g_assert_nonnull(list->data); + g_assert_cmpstr(ibus_engine_desc_get_name((IBusEngineDesc*)list->data), ==, "en:/tmp/tst.kmx"); + g_assert_nonnull(list->next); + list = list->next; + g_assert_nonnull(list->data); + g_assert_cmpstr(ibus_engine_desc_get_name((IBusEngineDesc*)list->data), ==, "fr:/tmp/tst.kmx"); + g_assert_null(list->next); +} + +void +test_keyman_add_keyboard__prev_engine_adding_newer_version_9593() { + // This tests bug #9593: We add keyboard version 1.10 while 1.9 is already in + // the list. + + // Initialize + gchar* languages[] = {"en:English", "fr:French", NULL}; // New version adds French + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("1.10", languages); + g_autoptr(add_keyboard_data) kb_data = _get_tst_keyboard_data(); + IBusEngineDesc* desc = + ibus_keyman_engine_desc_new("en:/usr/share/keyman/tst.kmx", "Testing", NULL, NULL, "en", NULL, NULL, "", "us", "1.9"); + kb_data->engines_list = g_list_append(kb_data->engines_list, desc); + + // Execute + keyman_add_keyboard(keyboard, kb_data); + + // Verify + GList* list = kb_data->engines_list; + g_assert_nonnull(list->data); + g_assert_cmpstr(ibus_engine_desc_get_name((IBusEngineDesc*)list->data), ==, "en:/usr/share/keyman/tst.kmx"); + g_assert_nonnull(list->next); + list = list->next; + g_assert_nonnull(list->data); + g_assert_cmpstr(ibus_engine_desc_get_name((IBusEngineDesc*)list->data), ==, "en:/tmp/tst.kmx"); + g_assert_nonnull(list->next); + list = list->next; + g_assert_nonnull(list->data); + g_assert_cmpstr(ibus_engine_desc_get_name((IBusEngineDesc*)list->data), ==, "fr:/tmp/tst.kmx"); + g_assert_null(list->next); +} + +void +test_keyman_add_keyboard__prev_engine_adding_older_version() { + // Initialize + gchar* languages[] = {"en:English", "fr:French", NULL}; // Old version has additional French + g_autoptr(kmp_keyboard) keyboard = _get_tst_kmp_keyboard("0.9", languages); + g_autoptr(add_keyboard_data) kb_data = _get_tst_keyboard_data(); + IBusEngineDesc* desc = + ibus_keyman_engine_desc_new("en:/usr/share/keyman/tst.kmx", "Testing", NULL, NULL, "en", NULL, NULL, "", "us", "1.0"); + kb_data->engines_list = g_list_append(kb_data->engines_list, desc); + + // Execute + keyman_add_keyboard(keyboard, kb_data); + + // Verify + GList* list = kb_data->engines_list; + g_assert_nonnull(list->data); + g_assert_cmpstr(ibus_engine_desc_get_name((IBusEngineDesc*)list->data), ==, "en:/usr/share/keyman/tst.kmx"); + g_assert_null(list->next); +} + +//---------------------------------------------------------------------------------------------- +gchar* testdata_dir; + +gboolean +delete_directory(gchar* path) { + g_autoptr(GFile) file = g_file_new_for_path(path); + if (g_file_test(path, G_FILE_TEST_IS_DIR)) { + g_autoptr(GFileEnumerator) enumerator = NULL; + + enumerator = g_file_enumerate_children(file, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); + + while (enumerator != NULL) { + GFile* child; + + if (!g_file_enumerator_iterate(enumerator, NULL, &child, NULL, NULL)) + return FALSE; + if (child == NULL) + break; + if (!delete_directory(g_file_get_path(child))) + return FALSE; + } + } + + return g_file_delete(file, NULL, NULL); +} + +void clear_kmpdir(gchar* dir) { + delete_directory(dir); + g_free(dir); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(gchar, clear_kmpdir); + +void copy_test_data(gchar* kmp_dir, gchar* name) { + g_autofree gchar* oldfile = g_strdup_printf("%s/%s", testdata_dir, name); + g_autoptr(GFile) source = g_file_new_for_path(oldfile); + g_autofree gchar* newfile = g_strdup_printf("%s/kmp.json", kmp_dir); + g_autoptr(GFile) dest = g_file_new_for_path(newfile); + g_file_copy(source, dest, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL); +} + +void +test_keyman_add_keyboards_from_dir__no_kmpjson() { + // Initialize + g_autolist(GList) keyboards = NULL; + g_autoptr(gchar) kmp_dir = g_dir_make_tmp(NULL, NULL); + + // Execute + keyman_add_keyboards_from_dir(kmp_dir, &keyboards); + + // Verify + g_assert_cmpint(g_list_length(keyboards), ==, 0); +} + +void +test_keyman_add_keyboards_from_dir__one_dir() { + // Initialize + g_autoptr(GList) keyboards = NULL; + g_autoptr(gchar) kmp_dir = g_dir_make_tmp(NULL, NULL); + copy_test_data(kmp_dir, "kmp1.json"); + + // Execute + keyman_add_keyboards_from_dir(kmp_dir, &keyboards); + + // Verify + g_assert_cmpint(g_list_length(keyboards), ==, 1); + + IBusEngineDesc* desc = IBUS_ENGINE_DESC(keyboards->data); + g_autofree gchar* expected_name = g_strdup_printf("bza:%s/test1.kmx", kmp_dir); + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, expected_name); +} + +void +test_keyman_add_keyboards_from_dir__two_langs() { + // Initialize + g_autoptr(GList) keyboards = NULL; + g_autoptr(gchar) kmp_dir = g_dir_make_tmp(NULL, NULL); + copy_test_data(kmp_dir, "kmp2.json"); + + // Execute + keyman_add_keyboards_from_dir(kmp_dir, &keyboards); + + // Verify + g_assert_cmpint(g_list_length(keyboards), ==, 2); + + IBusEngineDesc* desc = IBUS_ENGINE_DESC(keyboards->data); + g_autofree gchar* expected_name1 = g_strdup_printf("bmf-Latn:%s/test2.kmx", kmp_dir); + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, expected_name1); + desc = IBUS_ENGINE_DESC(keyboards->next->data); + g_autofree gchar* expected_name2 = g_strdup_printf("bun-Latn:%s/test2.kmx", kmp_dir); + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, expected_name2); +} + +void +test_keyman_add_keyboards_from_dir__prev_keyboards() { + // Initialize + g_autoptr(GList) keyboards = NULL; + g_autoptr(gchar) kmp_dir = g_dir_make_tmp(NULL, NULL); + copy_test_data(kmp_dir, "kmp2.json"); + keyman_add_keyboards_from_dir(kmp_dir, &keyboards); + copy_test_data(kmp_dir, "kmp1.json"); + + // Execute + keyman_add_keyboards_from_dir(kmp_dir, &keyboards); + + // Verify + g_assert_cmpint(g_list_length(keyboards), ==, 3); + + IBusEngineDesc* desc = IBUS_ENGINE_DESC(keyboards->data); + g_autofree gchar* expected_name1 = g_strdup_printf("bmf-Latn:%s/test2.kmx", kmp_dir); + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, expected_name1); + desc = IBUS_ENGINE_DESC(keyboards->next->data); + g_autofree gchar* expected_name2 = g_strdup_printf("bun-Latn:%s/test2.kmx", kmp_dir); + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, expected_name2); + desc = IBUS_ENGINE_DESC(keyboards->next->next->data); + g_autofree gchar* expected_name = g_strdup_printf("bza:%s/test1.kmx", kmp_dir); + g_assert_cmpstr(ibus_engine_desc_get_name(desc), ==, expected_name); +} + +//---------------------------------------------------------------------------------------------- +void +print_usage() { + printf( + "Usage: %s --testdata \n\n", + g_get_prgname()); + printf("Arguments:\n"); + printf("\t--testdata \tThe directory containing test kmp.json files for the tests.\n\n"); +} + +int main(int argc, char* argv[]) { gtk_init(&argc, &argv); g_test_init(&argc, &argv, NULL); g_test_set_nonfatal_assertions(); + if (argc < 3 || strcmp(argv[1], "--testdata") != 0) { + print_usage(); + return 1; + } + + testdata_dir = argv[2]; + + if (!g_file_test(testdata_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { + printf("ERROR: Testdata directory %s does not exist\n\n", testdata_dir); + print_usage(); + return 2; + } + // Add tests + g_test_add_func("/keymanutil/keyman_put_options_todconf/invalid", test_keyman_put_options_todconf__invalid); g_test_add_func("/keymanutil/keyman_put_options_todconf/new_key", test_keyman_put_options_todconf__new_key); g_test_add_func("/keymanutil/keyman_put_options_todconf/other_keys", test_keyman_put_options_todconf__other_keys); g_test_add_func("/keymanutil/keyman_put_options_todconf/existing_key", test_keyman_put_options_todconf__existing_key); + g_test_add_func("/keymanutil/ibus_keyman_engine_desc_new/all_set", test_ibus_keyman_engine_desc_new__all_set); + g_test_add_func("/keymanutil/ibus_keyman_engine_desc_new/only_description", test_ibus_keyman_engine_desc_new__only_description); + g_test_add_func("/keymanutil/ibus_keyman_engine_desc_new/only_copyright", test_ibus_keyman_engine_desc_new__only_copyright); + g_test_add_func( + "/keymanutil/ibus_keyman_engine_desc_new/no_language_license_author_version", + test_ibus_keyman_engine_desc_new__no_language_license_author_version); + + g_test_add_func("/keymanutil/get_engine_for_language/null_language", test_get_engine_for_language__null_language); + g_test_add_func("/keymanutil/get_engine_for_language/empty_language", test_get_engine_for_language__empty_language); + g_test_add_func("/keymanutil/get_engine_for_language/one_language", test_get_engine_for_language__one_language); + g_test_add_func("/keymanutil/get_engine_for_language/one_unknown_language", test_get_engine_for_language__one_unknown_language); + g_test_add_func("/keymanutil/get_engine_for_language/different_languages", test_get_engine_for_language__different_languages); + g_test_add_func("/keymanutil/get_engine_for_language/no_kbd_language", test_get_engine_for_language__no_kbd_language); + + g_test_add_func("/keymanutil/keyman_add_keyboard/no_language", test_keyman_add_keyboard__no_language); + g_test_add_func("/keymanutil/keyman_add_keyboard/one_language", test_keyman_add_keyboard__one_language); + g_test_add_func("/keymanutil/keyman_add_keyboard/two_languages", test_keyman_add_keyboard__two_languages); + g_test_add_func( + "/keymanutil/keyman_add_keyboard/prev_engine_adding_same_version", + test_keyman_add_keyboard__prev_engine_adding_same_version); + g_test_add_func( + "/keymanutil/keyman_add_keyboard/prev_engine_adding_newer_version", + test_keyman_add_keyboard__prev_engine_adding_newer_version); + // #9593 + // g_test_add_func( + // "/keymanutil/keyman_add_keyboard/prev_engine_adding_newer_version_versioncompare", + // test_keyman_add_keyboard__prev_engine_adding_newer_version_9593); + g_test_add_func( + "/keymanutil/keyman_add_keyboard/prev_engine_adding_older_version", + test_keyman_add_keyboard__prev_engine_adding_older_version); + + g_test_add_func("/keymanutil/keyman_add_keyboards_from_dir/no_kmpjson", test_keyman_add_keyboards_from_dir__no_kmpjson); + g_test_add_func("/keymanutil/keyman_add_keyboards_from_dir/one_dir", test_keyman_add_keyboards_from_dir__one_dir); + g_test_add_func("/keymanutil/keyman_add_keyboards_from_dir/two_langs", test_keyman_add_keyboards_from_dir__two_langs); + g_test_add_func("/keymanutil/keyman_add_keyboards_from_dir/prev_keyboards", test_keyman_add_keyboards_from_dir__prev_keyboards); + // Run tests int retVal = g_test_run(); diff --git a/linux/ibus-keyman/src/test/meson.build b/linux/ibus-keyman/src/test/meson.build index 3c8c1044c0d..02631e27f79 100644 --- a/linux/ibus-keyman/src/test/meson.build +++ b/linux/ibus-keyman/src/test/meson.build @@ -84,7 +84,7 @@ test( test( 'keymanutil-tests', run_src_test, - args: [ '--tap', '-k', '--env', env_file, '--', keymanutil_tests], + args: [ '--tap', '-k', '--env', env_file, '--', keymanutil_tests, '--testdata', meson.current_source_dir() / 'testdata'], env: test_env, priority: -2, is_parallel: false, @@ -103,7 +103,7 @@ test( test( 'print-kmp-test', run_src_test, - args: [ '--', print_kmp_test, meson.current_source_dir() / 'kmp.json' ], + args: [ '--', print_kmp_test, meson.current_source_dir() / 'testdata/kmp.json' ], env: test_env, priority: -2, protocol: 'exitcode', diff --git a/linux/ibus-keyman/src/test/run-tests.sh b/linux/ibus-keyman/src/test/run-tests.sh index efeb747ddc7..ae005fcbd6b 100755 --- a/linux/ibus-keyman/src/test/run-tests.sh +++ b/linux/ibus-keyman/src/test/run-tests.sh @@ -58,4 +58,4 @@ glib-compile-schemas "$SCHEMA_DIR" export GSETTINGS_BACKEND=memory -"${G_TEST_BUILDDIR:-.}/keymanutil-tests" "$@" +"${G_TEST_BUILDDIR:-.}/keymanutil-tests" "$@" --testdata "${SRCDIR}/src/test/testdata" diff --git a/linux/ibus-keyman/src/test/setup-tests.sh b/linux/ibus-keyman/src/test/setup-tests.sh index 07e7d5462b3..79bb765f509 100755 --- a/linux/ibus-keyman/src/test/setup-tests.sh +++ b/linux/ibus-keyman/src/test/setup-tests.sh @@ -3,4 +3,4 @@ set -eu . "$(dirname "$0")/../../tests/scripts/test-helper.inc.sh" -setup_display_server_only "$1" "$2" "$3" "$4" +setup_display_server_only "${1:-x11}" "${2:-/tmp/env-src-test.txt}" "${3:-/tmp/ibus-keyman-src-test-pids}" "${4:-/tmp/ibus-keyman-src-test-pids.pids}" diff --git a/linux/ibus-keyman/src/test/kmp.json b/linux/ibus-keyman/src/test/testdata/kmp.json similarity index 95% rename from linux/ibus-keyman/src/test/kmp.json rename to linux/ibus-keyman/src/test/testdata/kmp.json index dc659d324e7..d2ee4fa9e13 100644 --- a/linux/ibus-keyman/src/test/kmp.json +++ b/linux/ibus-keyman/src/test/testdata/kmp.json @@ -1,267 +1,267 @@ -{ - "system": { - "keymanDeveloperVersion": "10.0.1202.0", - "fileVersion": "7.0" - }, - "options": { - "readmeFile": "readme.htm" - }, - "info": { - "version": { - "description": "1.6.1" - }, - "name": { - "description": "LIBTRALO" - }, - "copyright": { - "description": "\u00A9 2008-2018 SIL International" - }, - "author": { - "description": "support@keyman.com", - "url": "mailto:support@keyman.com" - } - }, - "files": [ - { - "name": "libtralo.kmx", - "description": "Keyboard LIBTRALO" - }, - { - "name": "readme.htm", - "description": "File readme.htm" - }, - { - "name": "libtralo.png", - "description": "File libtralo.png" - }, - { - "name": "welcome.htm", - "description": "File welcome.htm" - }, - { - "name": "Charis_SIL_README.txt", - "description": "File Charis_SIL_README.txt" - }, - { - "name": "CharisSIL-B.ttf", - "description": "Font Charis SIL Bold" - }, - { - "name": "CharisSIL-BI.ttf", - "description": "Font Charis SIL Bold Italic" - }, - { - "name": "CharisSIL-I.ttf", - "description": "Font Charis SIL Italic" - }, - { - "name": "CharisSIL-R.ttf", - "description": "Font Charis SIL" - }, - { - "name": "FONTLOG.txt", - "description": "File FONTLOG.txt" - }, - { - "name": "OFL.txt", - "description": "File OFL.txt" - }, - { - "name": "OFL-FAQ.txt", - "description": "File OFL-FAQ.txt" - }, - { - "name": "CharisSILDan-Bold.ttf", - "description": "Font Charis SIL Dan Bold" - }, - { - "name": "CharisSILDan-BoldItalic.ttf", - "description": "Font Charis SIL Dan Bold Italic" - }, - { - "name": "CharisSILDan-Italic.ttf", - "description": "Font Charis SIL Dan Italic" - }, - { - "name": "CharisSILDan-Regular.ttf", - "description": "Font Charis SIL Dan" - }, - { - "name": "libtralo.js", - "description": "File libtralo.js" - }, - { - "name": "libtralo.kvk", - "description": "File libtralo.kvk" - }, - { - "name": "CharisSILDan_FONTLOG.txt", - "description": "File CharisSILDan_FONTLOG.txt" - }, - { - "name": "kmp.inf", - "description": "Package information" - }, - { - "name": "kmp.json", - "description": "Package information (JSON)" - } - ], - "keyboards": [ - { - "name": "LIBTRALO", - "id": "libtralo", - "version": "1.6.1", - "languages": [ - { - "name": "Bandi", - "id": "bza-Latn" - }, - { - "name": "Bassa", - "id": "bsq-Latn" - }, - { - "name": "Glio-Oubi", - "id": "oub-Latn" - }, - { - "name": "Gola", - "id": "gol-Latn" - }, - { - "name": "Northern Grebo", - "id": "gbo-Latn" - }, - { - "name": "Southern Kisi", - "id": "kss-Latn" - }, - { - "name": "Klao", - "id": "klu-Latn" - }, - { - "name": "Liberia Kpelle (Latin)", - "id": "xpe-Latn" - }, - { - "name": "Eastern Krahn", - "id": "kqo-Latn" - }, - { - "name": "Western Krahn", - "id": "krw-Latn" - }, - { - "name": "Kuwaa", - "id": "blh-Latn" - }, - { - "name": "Loma (Liberia) (Latin)", - "id": "lom-Latn" - }, - { - "name": "Mano", - "id": "mev-Latn" - }, - { - "name": "Manya", - "id": "mzj-Latn" - }, - { - "name": "Sapo", - "id": "krn-Latn" - }, - { - "name": "Bullom So", - "id": "buy-Latn" - }, - { - "name": "Kono (Sierra Leone)", - "id": "kno-Latn" - }, - { - "name": "Krio", - "id": "kri-Latn" - }, - { - "name": "Kuranko", - "id": "knk-Latn" - }, - { - "name": "West-Central Limba", - "id": "lia-Latn" - }, - { - "name": "Loko", - "id": "lok-Latn" - }, - { - "name": "Mende (Sierra Leone)", - "id": "men" - }, - { - "name": "Timne", - "id": "tem" - }, - { - "name": "Vai (Latin)", - "id": "vai-Latn" - }, - { - "name": "Dewoin (Latin)", - "id": "dee-Latn" - }, - { - "name": "Dan (Western) (Latin)", - "id": "dnj-Latn-LR" - }, - { - "name": "Gbii (Latin)", - "id": "ggb-Latn" - }, - { - "name": "Glaro-Twabo (Latin)", - "id": "glr-Latn" - }, - { - "name": "Grebo (Latin)", - "id": "grb-Latn" - }, - { - "name": "Barclayville Grebo (Latin)", - "id": "gry-Latn" - }, - { - "name": "Central Grebo (Latin)", - "id": "grv-Latn" - }, - { - "name": "Gboloo Grebo (Latin)", - "id": "gec-Latn" - }, - { - "name": "Southern Grebo (Latin)", - "id": "grj-Latn" - }, - { - "name": "Kpelle (Latin)", - "id": "kpe-Latn" - }, - { - "name": "Tajuasohn (Latin)", - "id": "tja-Latn" - }, - { - "name": "Bom-Kim (Latin)", - "id": "bmf-Latn" - }, - { - "name": "Sherbro (Latin)", - "id": "bun-Latn" - } - ] - } - ] -} +{ + "system": { + "keymanDeveloperVersion": "10.0.1202.0", + "fileVersion": "7.0" + }, + "options": { + "readmeFile": "readme.htm" + }, + "info": { + "version": { + "description": "1.6.1" + }, + "name": { + "description": "LIBTRALO" + }, + "copyright": { + "description": "\u00A9 2008-2018 SIL International" + }, + "author": { + "description": "support@keyman.com", + "url": "mailto:support@keyman.com" + } + }, + "files": [ + { + "name": "libtralo.kmx", + "description": "Keyboard LIBTRALO" + }, + { + "name": "readme.htm", + "description": "File readme.htm" + }, + { + "name": "libtralo.png", + "description": "File libtralo.png" + }, + { + "name": "welcome.htm", + "description": "File welcome.htm" + }, + { + "name": "Charis_SIL_README.txt", + "description": "File Charis_SIL_README.txt" + }, + { + "name": "CharisSIL-B.ttf", + "description": "Font Charis SIL Bold" + }, + { + "name": "CharisSIL-BI.ttf", + "description": "Font Charis SIL Bold Italic" + }, + { + "name": "CharisSIL-I.ttf", + "description": "Font Charis SIL Italic" + }, + { + "name": "CharisSIL-R.ttf", + "description": "Font Charis SIL" + }, + { + "name": "FONTLOG.txt", + "description": "File FONTLOG.txt" + }, + { + "name": "OFL.txt", + "description": "File OFL.txt" + }, + { + "name": "OFL-FAQ.txt", + "description": "File OFL-FAQ.txt" + }, + { + "name": "CharisSILDan-Bold.ttf", + "description": "Font Charis SIL Dan Bold" + }, + { + "name": "CharisSILDan-BoldItalic.ttf", + "description": "Font Charis SIL Dan Bold Italic" + }, + { + "name": "CharisSILDan-Italic.ttf", + "description": "Font Charis SIL Dan Italic" + }, + { + "name": "CharisSILDan-Regular.ttf", + "description": "Font Charis SIL Dan" + }, + { + "name": "libtralo.js", + "description": "File libtralo.js" + }, + { + "name": "libtralo.kvk", + "description": "File libtralo.kvk" + }, + { + "name": "CharisSILDan_FONTLOG.txt", + "description": "File CharisSILDan_FONTLOG.txt" + }, + { + "name": "kmp.inf", + "description": "Package information" + }, + { + "name": "kmp.json", + "description": "Package information (JSON)" + } + ], + "keyboards": [ + { + "name": "LIBTRALO", + "id": "libtralo", + "version": "1.6.1", + "languages": [ + { + "name": "Bandi", + "id": "bza-Latn" + }, + { + "name": "Bassa", + "id": "bsq-Latn" + }, + { + "name": "Glio-Oubi", + "id": "oub-Latn" + }, + { + "name": "Gola", + "id": "gol-Latn" + }, + { + "name": "Northern Grebo", + "id": "gbo-Latn" + }, + { + "name": "Southern Kisi", + "id": "kss-Latn" + }, + { + "name": "Klao", + "id": "klu-Latn" + }, + { + "name": "Liberia Kpelle (Latin)", + "id": "xpe-Latn" + }, + { + "name": "Eastern Krahn", + "id": "kqo-Latn" + }, + { + "name": "Western Krahn", + "id": "krw-Latn" + }, + { + "name": "Kuwaa", + "id": "blh-Latn" + }, + { + "name": "Loma (Liberia) (Latin)", + "id": "lom-Latn" + }, + { + "name": "Mano", + "id": "mev-Latn" + }, + { + "name": "Manya", + "id": "mzj-Latn" + }, + { + "name": "Sapo", + "id": "krn-Latn" + }, + { + "name": "Bullom So", + "id": "buy-Latn" + }, + { + "name": "Kono (Sierra Leone)", + "id": "kno-Latn" + }, + { + "name": "Krio", + "id": "kri-Latn" + }, + { + "name": "Kuranko", + "id": "knk-Latn" + }, + { + "name": "West-Central Limba", + "id": "lia-Latn" + }, + { + "name": "Loko", + "id": "lok-Latn" + }, + { + "name": "Mende (Sierra Leone)", + "id": "men" + }, + { + "name": "Timne", + "id": "tem" + }, + { + "name": "Vai (Latin)", + "id": "vai-Latn" + }, + { + "name": "Dewoin (Latin)", + "id": "dee-Latn" + }, + { + "name": "Dan (Western) (Latin)", + "id": "dnj-Latn-LR" + }, + { + "name": "Gbii (Latin)", + "id": "ggb-Latn" + }, + { + "name": "Glaro-Twabo (Latin)", + "id": "glr-Latn" + }, + { + "name": "Grebo (Latin)", + "id": "grb-Latn" + }, + { + "name": "Barclayville Grebo (Latin)", + "id": "gry-Latn" + }, + { + "name": "Central Grebo (Latin)", + "id": "grv-Latn" + }, + { + "name": "Gboloo Grebo (Latin)", + "id": "gec-Latn" + }, + { + "name": "Southern Grebo (Latin)", + "id": "grj-Latn" + }, + { + "name": "Kpelle (Latin)", + "id": "kpe-Latn" + }, + { + "name": "Tajuasohn (Latin)", + "id": "tja-Latn" + }, + { + "name": "Bom-Kim (Latin)", + "id": "bmf-Latn" + }, + { + "name": "Sherbro (Latin)", + "id": "bun-Latn" + } + ] + } + ] +} diff --git a/linux/ibus-keyman/src/test/testdata/kmp1.json b/linux/ibus-keyman/src/test/testdata/kmp1.json new file mode 100644 index 00000000000..5d9954c330e --- /dev/null +++ b/linux/ibus-keyman/src/test/testdata/kmp1.json @@ -0,0 +1,123 @@ +{ + "system": { + "keymanDeveloperVersion": "10.0.1202.0", + "fileVersion": "7.0" + }, + "options": { + "readmeFile": "readme.htm" + }, + "info": { + "version": { + "description": "1.6.1" + }, + "name": { + "description": "LIBTRALO" + }, + "copyright": { + "description": "\u00A9 2008-2018 SIL International" + }, + "author": { + "description": "support@keyman.com", + "url": "mailto:support@keyman.com" + } + }, + "files": [ + { + "name": "libtralo.kmx", + "description": "Keyboard LIBTRALO" + }, + { + "name": "readme.htm", + "description": "File readme.htm" + }, + { + "name": "libtralo.png", + "description": "File libtralo.png" + }, + { + "name": "welcome.htm", + "description": "File welcome.htm" + }, + { + "name": "Charis_SIL_README.txt", + "description": "File Charis_SIL_README.txt" + }, + { + "name": "CharisSIL-B.ttf", + "description": "Font Charis SIL Bold" + }, + { + "name": "CharisSIL-BI.ttf", + "description": "Font Charis SIL Bold Italic" + }, + { + "name": "CharisSIL-I.ttf", + "description": "Font Charis SIL Italic" + }, + { + "name": "CharisSIL-R.ttf", + "description": "Font Charis SIL" + }, + { + "name": "FONTLOG.txt", + "description": "File FONTLOG.txt" + }, + { + "name": "OFL.txt", + "description": "File OFL.txt" + }, + { + "name": "OFL-FAQ.txt", + "description": "File OFL-FAQ.txt" + }, + { + "name": "CharisSILDan-Bold.ttf", + "description": "Font Charis SIL Dan Bold" + }, + { + "name": "CharisSILDan-BoldItalic.ttf", + "description": "Font Charis SIL Dan Bold Italic" + }, + { + "name": "CharisSILDan-Italic.ttf", + "description": "Font Charis SIL Dan Italic" + }, + { + "name": "CharisSILDan-Regular.ttf", + "description": "Font Charis SIL Dan" + }, + { + "name": "libtralo.js", + "description": "File libtralo.js" + }, + { + "name": "libtralo.kvk", + "description": "File libtralo.kvk" + }, + { + "name": "CharisSILDan_FONTLOG.txt", + "description": "File CharisSILDan_FONTLOG.txt" + }, + { + "name": "kmp.inf", + "description": "Package information" + }, + { + "name": "kmp.json", + "description": "Package information (JSON)" + } + ], + "keyboards": [ + { + "name": "TEST1", + "id": "test1", + "version": "1.6.1", + "languages": [ + { + "name": "Bandi", + "id": "bza-Latn" + } + ] + } + ] +} diff --git a/linux/ibus-keyman/src/test/testdata/kmp2.json b/linux/ibus-keyman/src/test/testdata/kmp2.json new file mode 100644 index 00000000000..5e889091f72 --- /dev/null +++ b/linux/ibus-keyman/src/test/testdata/kmp2.json @@ -0,0 +1,127 @@ +{ + "system": { + "keymanDeveloperVersion": "10.0.1202.0", + "fileVersion": "7.0" + }, + "options": { + "readmeFile": "readme.htm" + }, + "info": { + "version": { + "description": "1.6.1" + }, + "name": { + "description": "LIBTRALO" + }, + "copyright": { + "description": "\u00A9 2008-2018 SIL International" + }, + "author": { + "description": "support@keyman.com", + "url": "mailto:support@keyman.com" + } + }, + "files": [ + { + "name": "libtralo.kmx", + "description": "Keyboard LIBTRALO" + }, + { + "name": "readme.htm", + "description": "File readme.htm" + }, + { + "name": "libtralo.png", + "description": "File libtralo.png" + }, + { + "name": "welcome.htm", + "description": "File welcome.htm" + }, + { + "name": "Charis_SIL_README.txt", + "description": "File Charis_SIL_README.txt" + }, + { + "name": "CharisSIL-B.ttf", + "description": "Font Charis SIL Bold" + }, + { + "name": "CharisSIL-BI.ttf", + "description": "Font Charis SIL Bold Italic" + }, + { + "name": "CharisSIL-I.ttf", + "description": "Font Charis SIL Italic" + }, + { + "name": "CharisSIL-R.ttf", + "description": "Font Charis SIL" + }, + { + "name": "FONTLOG.txt", + "description": "File FONTLOG.txt" + }, + { + "name": "OFL.txt", + "description": "File OFL.txt" + }, + { + "name": "OFL-FAQ.txt", + "description": "File OFL-FAQ.txt" + }, + { + "name": "CharisSILDan-Bold.ttf", + "description": "Font Charis SIL Dan Bold" + }, + { + "name": "CharisSILDan-BoldItalic.ttf", + "description": "Font Charis SIL Dan Bold Italic" + }, + { + "name": "CharisSILDan-Italic.ttf", + "description": "Font Charis SIL Dan Italic" + }, + { + "name": "CharisSILDan-Regular.ttf", + "description": "Font Charis SIL Dan" + }, + { + "name": "libtralo.js", + "description": "File libtralo.js" + }, + { + "name": "libtralo.kvk", + "description": "File libtralo.kvk" + }, + { + "name": "CharisSILDan_FONTLOG.txt", + "description": "File CharisSILDan_FONTLOG.txt" + }, + { + "name": "kmp.inf", + "description": "Package information" + }, + { + "name": "kmp.json", + "description": "Package information (JSON)" + } + ], + "keyboards": [ + { + "name": "TEST2", + "id": "test2", + "version": "1.6.1", + "languages": [ + { + "name": "Bom-Kim (Latin)", + "id": "bmf-Latn" + }, + { + "name": "Sherbro (Latin)", + "id": "bun-Latn" + } + ] + } + ] +} diff --git a/linux/ibus-keyman/tests/testfixture.cpp b/linux/ibus-keyman/tests/testfixture.cpp index 84aab933c83..cfc1530a75a 100644 --- a/linux/ibus-keyman/tests/testfixture.cpp +++ b/linux/ibus-keyman/tests/testfixture.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include @@ -193,28 +193,28 @@ get_involved_keys(IBusKeymanTestsFixture *fixture, km::tests::key_event test_eve // process all modifiers std::list result; - if (test_event.modifier_state & KM_KBP_MODIFIER_SHIFT) { + if (test_event.modifier_state & KM_CORE_MODIFIER_SHIFT) { // we don't distinguish between R and L Shift result.push_back(get_key_event_for_modifier(IBUS_SHIFT_MASK, modifiers, GDK_KEY_Shift_L, KEY_LEFTSHIFT)); } - if (test_event.modifier_state & KM_KBP_MODIFIER_ALT || test_event.modifier_state & KM_KBP_MODIFIER_LALT) { + if (test_event.modifier_state & KM_CORE_MODIFIER_ALT || test_event.modifier_state & KM_CORE_MODIFIER_LALT) { result.push_back(get_key_event_for_modifier(IBUS_MOD1_MASK, modifiers, GDK_KEY_Alt_L, KEY_LEFTALT)); } - if (test_event.modifier_state & KM_KBP_MODIFIER_RALT) { + if (test_event.modifier_state & KM_CORE_MODIFIER_RALT) { if (test_event.vk == KEYMAN_RALT) result.push_back(get_key_event_for_modifier(IBUS_MOD1_MASK, modifiers, GDK_KEY_Alt_R, KEY_RIGHTALT)); else result.push_back(get_key_event_for_modifier(IBUS_MOD5_MASK, modifiers, GDK_KEY_Alt_R, KEY_RIGHTALT)); } - if (test_event.modifier_state & KM_KBP_MODIFIER_CTRL || test_event.modifier_state & KM_KBP_MODIFIER_LCTRL) { + if (test_event.modifier_state & KM_CORE_MODIFIER_CTRL || test_event.modifier_state & KM_CORE_MODIFIER_LCTRL) { result.push_back(get_key_event_for_modifier(IBUS_CONTROL_MASK, modifiers, GDK_KEY_Control_L, KEY_LEFTCTRL)); } - if (test_event.modifier_state & KM_KBP_MODIFIER_RCTRL) { + if (test_event.modifier_state & KM_CORE_MODIFIER_RCTRL) { result.push_back(get_key_event_for_modifier(IBUS_CONTROL_MASK, modifiers, GDK_KEY_Control_R, KEY_RIGHTCTRL)); } // process key - guint keyval = (test_event.modifier_state & KM_KBP_MODIFIER_SHIFT) ? gdk_keyval_to_upper(test_event.vk) + guint keyval = (test_event.modifier_state & KM_CORE_MODIFIER_SHIFT) ? gdk_keyval_to_upper(test_event.vk) : gdk_keyval_to_lower(test_event.vk); // REVIEW: the keyval we use here are not correct for < 0x20 and >= 0x7f @@ -244,7 +244,7 @@ get_context_keys(std::u16string context) { } result.push_back( {km::kbp::kmx::s_char_to_vkey[(int)utf8[0] - 32].vk, - (uint16_t)(km::kbp::kmx::s_char_to_vkey[(int)utf8[0] - 32].shifted ? KM_KBP_MODIFIER_SHIFT : 0)}); + (uint16_t)(km::kbp::kmx::s_char_to_vkey[(int)utf8[0] - 32].shifted ? KM_CORE_MODIFIER_SHIFT : 0)}); } return result; } diff --git a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMBinaryFileFormat.h b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMBinaryFileFormat.h index 97907c67c1f..d91f9b4f40e 100644 --- a/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMBinaryFileFormat.h +++ b/mac/KeymanEngine4Mac/KeymanEngine4Mac/KME/KMBinaryFileFormat.h @@ -45,8 +45,9 @@ struct COMP_KEYBOARD { #define VERSION_140 0x00000E00 #define VERSION_150 0x00000F00 #define VERSION_160 0x00001000 +#define VERSION_170 0x00001100 #define VERSION_MIN VERSION_50 -#define VERSION_MAX VERSION_160 +#define VERSION_MAX VERSION_170 struct COMP_GROUP { DWORD dpName; // string (only debug) diff --git a/package-lock.json b/package-lock.json index a0baec246a4..acb9bb8db7e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -404,16 +404,9 @@ "name": "@keymanapp/keyman-version", "license": "MIT", "devDependencies": { - "@types/node": "^20.4.1", "typescript": "^4.9.5" } }, - "common/web/keyman-version/node_modules/@types/node": { - "version": "20.4.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.1.tgz", - "integrity": "sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==", - "dev": true - }, "common/web/lm-message-types": { "name": "@keymanapp/lm-message-types", "license": "MIT", @@ -2730,7 +2723,7 @@ "@types/express": "^4.17.13", "@types/mocha": "^9.1.0", "@types/multer": "^1.4.7", - "@types/node": "^17.0.0", + "@types/node": "^20.4.1", "@types/ws": "^8.2.2", "chai": "^4.3.4", "copyfiles": "^2.4.1", @@ -2750,9 +2743,10 @@ "license": "MIT" }, "developer/src/server/node_modules/@types/node": { - "version": "17.0.45", - "dev": true, - "license": "MIT" + "version": "20.8.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz", + "integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==", + "dev": true }, "developer/src/server/node_modules/busboy": { "version": "1.6.0", @@ -3932,6 +3926,21 @@ "@types/node": "*" } }, + "node_modules/@types/yargs": { + "version": "17.0.26", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz", + "integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", + "dev": true + }, "node_modules/@types/yauzl": { "version": "2.9.2", "license": "MIT", @@ -4857,6 +4866,7 @@ }, "node_modules/camelcase": { "version": "5.3.1", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5252,6 +5262,7 @@ }, "node_modules/decamelize": { "version": "1.2.0", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5988,7 +5999,6 @@ }, "node_modules/escalade": { "version": "3.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -9681,6 +9691,7 @@ }, "node_modules/p-try": { "version": "2.2.0", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -9711,6 +9722,7 @@ }, "node_modules/path-exists": { "version": "4.0.0", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10044,6 +10056,7 @@ }, "node_modules/require-main-filename": { "version": "2.0.0", + "dev": true, "license": "ISC" }, "node_modules/requirejs": { @@ -10284,6 +10297,7 @@ }, "node_modules/set-blocking": { "version": "2.0.0", + "devOptional": true, "license": "ISC" }, "node_modules/set-immediate-shim": { @@ -11268,6 +11282,7 @@ }, "node_modules/which-module": { "version": "2.0.0", + "dev": true, "license": "ISC" }, "node_modules/which-typed-array": { @@ -11327,7 +11342,6 @@ }, "node_modules/wrap-ansi": { "version": "7.0.0", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -11343,7 +11357,6 @@ }, "node_modules/wrap-ansi/node_modules/ansi-regex": { "version": "5.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -11351,7 +11364,6 @@ }, "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -11359,7 +11371,6 @@ }, "node_modules/wrap-ansi/node_modules/string-width": { "version": "4.2.2", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -11372,7 +11383,6 @@ }, "node_modules/wrap-ansi/node_modules/strip-ansi": { "version": "6.0.0", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.0" @@ -11433,7 +11443,6 @@ }, "node_modules/y18n": { "version": "5.0.8", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -11593,16 +11602,14 @@ "@actions/core": "^1.9.1", "@actions/github": "^2.1.0", "typescript": "^4.9.5", - "yargs": "^15.1.0" + "yargs": "^17.7.2" }, "devDependencies": { "@types/node": "^13.7.0", "@types/semver": "^7.1.0", + "@types/yargs": "^17.0.26", "semver": "^7.5.2", "ts-node": "^10.9.1" - }, - "engines": { - "node": ">=16.0" } }, "resources/build/version/node_modules/@types/node": { @@ -11612,74 +11619,37 @@ }, "resources/build/version/node_modules/ansi-regex": { "version": "5.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "engines": { "node": ">=8" } }, "resources/build/version/node_modules/cliui": { - "version": "6.0.0", - "license": "ISC", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "resources/build/version/node_modules/find-up": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, "resources/build/version/node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "resources/build/version/node_modules/locate-path": { - "version": "5.0.0", - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "resources/build/version/node_modules/p-limit": { - "version": "2.3.0", - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "resources/build/version/node_modules/p-locate": { - "version": "4.1.0", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "engines": { "node": ">=8" } }, "resources/build/version/node_modules/string-width": { "version": "4.2.3", - "license": "MIT", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -11691,7 +11661,8 @@ }, "resources/build/version/node_modules/strip-ansi": { "version": "6.0.1", - "license": "MIT", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -11699,51 +11670,29 @@ "node": ">=8" } }, - "resources/build/version/node_modules/wrap-ansi": { - "version": "6.2.0", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "resources/build/version/node_modules/y18n": { - "version": "4.0.3", - "license": "ISC" - }, "resources/build/version/node_modules/yargs": { - "version": "15.4.1", - "license": "MIT", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=8" + "node": ">=12" } }, "resources/build/version/node_modules/yargs-parser": { - "version": "18.1.3", - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "engines": { - "node": ">=6" + "node": ">=12" } }, "resources/gosh": { diff --git a/resources/build/increment-version.sh b/resources/build/increment-version.sh index 445459da161..0f5e2d0608f 100755 --- a/resources/build/increment-version.sh +++ b/resources/build/increment-version.sh @@ -88,9 +88,7 @@ echo "increment-version.sh: building resources/build/version" pushd "$KEYMAN_ROOT" npm ci -pushd "$KEYMAN_ROOT/resources/build/version" -npm run build:ts -popd +"$KEYMAN_ROOT/resources/build/version/build.sh" echo "increment-version.sh: running resources/build/version" pushd "$KEYMAN_ROOT" diff --git a/resources/build/version/.gitignore b/resources/build/version/.gitignore index 687e3299fe0..3e42060cc69 100644 --- a/resources/build/version/.gitignore +++ b/resources/build/version/.gitignore @@ -47,3 +47,4 @@ coverage # Build output dist lib +build diff --git a/resources/build/version/build.sh b/resources/build/version/build.sh new file mode 100755 index 00000000000..64892803bc8 --- /dev/null +++ b/resources/build/version/build.sh @@ -0,0 +1,24 @@ +#!/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 + +. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" + +# This script runs from its own folder +cd "$THIS_SCRIPT_PATH" + +################################ Main script ################################ + +builder_describe "Build version tooling" clean configure build +builder_describe_outputs \ + configure /resources/build/version/node_modules \ + build /resources/build/version/build/src/index.js + +builder_parse "$@" + +builder_run_action clean rm -rf build/ node_modules/ dist/ lib/ +builder_run_action configure verify_npm_setup +builder_run_action build tsc --build diff --git a/resources/build/version/package.json b/resources/build/version/package.json index 93911e79701..57264f02e44 100644 --- a/resources/build/version/package.json +++ b/resources/build/version/package.json @@ -1,25 +1,24 @@ { + "description": "Automatically updates HISTORY.md based on pull requests", + "type": "module", "dependencies": { "@actions/core": "^1.9.1", "@actions/github": "^2.1.0", "typescript": "^4.9.5", - "yargs": "^15.1.0" + "yargs": "^17.7.2" }, - "description": "Automatically updates HISTORY.md based on pull requests", "devDependencies": { "@types/node": "^13.7.0", "@types/semver": "^7.1.0", + "@types/yargs": "^17.0.26", "semver": "^7.5.2", "ts-node": "^10.9.1" }, - "engines": { - "node": ">=16.0" - }, "files": [ "src" ], "license": "MIT", - "main": "lib/index.js", + "main": "build/src/index.js", "name": "@keymanapp/auto-history-action", "private": true, "scripts": { diff --git a/resources/build/version/src/fixupHistory.ts b/resources/build/version/src/fixupHistory.ts index 2145fa94656..9f48f4851dd 100644 --- a/resources/build/version/src/fixupHistory.ts +++ b/resources/build/version/src/fixupHistory.ts @@ -5,7 +5,7 @@ import { import { GitHub } from '@actions/github'; import { readFileSync, writeFileSync } from 'fs'; import { gt } from 'semver'; -import { reportHistory } from './reportHistory'; +import { reportHistory } from './reportHistory.js'; interface PRInformation { title: string; @@ -42,7 +42,8 @@ const splicePullsIntoHistory = async (pulls: PRInformation[]): Promise<{count: n const versionMatch = new RegExp(`^## ${version} ${tier}`, 'i'); let historyChunks: { heading: string[]; newer: string[]; current: string[]; older: string[] } = {heading:[], newer:[], current:[], older:[]}; - let state = "heading"; + type ChunkType = keyof typeof historyChunks; + let state: ChunkType = "heading"; for(const line of history) { if(line.match(versionMatch)) { // We are in the correct section of history @@ -90,7 +91,7 @@ const splicePullsIntoHistory = async (pulls: PRInformation[]): Promise<{count: n let found = false; // Look for the PR in any other chunk -- can be found with merges of master into PR or chained PRs - for(const chunk of ['newer','current','older']) { + for(const chunk of ['newer','current','older'] as ChunkType[]) { for(const line of historyChunks[chunk]) { if(line.match(pullNumberRe)) { found = true; diff --git a/resources/build/version/src/index.ts b/resources/build/version/src/index.ts index 3d5f896650d..69776231c62 100644 --- a/resources/build/version/src/index.ts +++ b/resources/build/version/src/index.ts @@ -1,13 +1,14 @@ import { info as logInfo } from '@actions/core'; import { GitHub } from '@actions/github'; -import { sendCommentToPullRequestAndRelatedIssues, fixupHistory } from './fixupHistory'; -import { incrementVersion } from './incrementVersion'; -const yargs = require('yargs'); +import { sendCommentToPullRequestAndRelatedIssues, fixupHistory } from './fixupHistory.js'; +import { incrementVersion } from './incrementVersion.js'; +import yargs from 'yargs'; +import { hideBin } from 'yargs/helpers'; import { readFileSync } from 'fs'; -import { reportHistory } from './reportHistory'; +import { reportHistory } from './reportHistory.js'; -const argv = yargs +const argv = await yargs(hideBin(process.argv)) .command(['history'], 'Fixes up HISTORY.md with pull request data') .command(['version'], 'Increments the current patch version in VERSION.md') .command(['report-history'], 'Print list of outstanding PRs waiting for the next build') @@ -81,10 +82,10 @@ const main = async (): Promise => { if(argv._.includes('report-history')) { let pulls = await reportHistory(octokit, argv.base, argv.force, argv['github-pr'], argv.from, argv.to); - let versions = {}; + let versions: {[index:string]:any} = {}; pulls.forEach((item) => { if(typeof item.version == 'string') { - if(typeof versions[item.version] == 'undefined') { + if(typeof (versions)[item.version] == 'undefined') { versions[item.version] = {data: item.tag_data, pulls: []}; } // We want to invert the order of the pulls as we go to diff --git a/resources/build/version/src/reportHistory.ts b/resources/build/version/src/reportHistory.ts index bf726063339..2fae1ab628e 100644 --- a/resources/build/version/src/reportHistory.ts +++ b/resources/build/version/src/reportHistory.ts @@ -2,8 +2,8 @@ import { warning as logWarning, info as logInfo } from '@actions/core'; import { GitHub } from '@actions/github'; -import { findLastHistoryPR, getAssociatedPR} from './graphql/queries'; -import { spawnChild } from './util/spawnAwait'; +import { findLastHistoryPR, getAssociatedPR} from './graphql/queries.js'; +import { spawnChild } from './util/spawnAwait.js'; const getPullRequestInformation = async ( octokit: GitHub, base: string @@ -67,7 +67,7 @@ const getAssociatedPRInformation = async ( } }: any = response; - const node = nodes.find(node => node.state == 'MERGED'); + const node = nodes.find((node:any) => node.state == 'MERGED'); return node ? { title: node.title, number: node.number } : undefined; }; diff --git a/resources/build/version/tsconfig.json b/resources/build/version/tsconfig.json index 655da5e8afc..2d99762ca9b 100644 --- a/resources/build/version/tsconfig.json +++ b/resources/build/version/tsconfig.json @@ -1,7 +1,8 @@ { + "extends": "../../../tsconfig.base.json", "compilerOptions": { - "rootDir": "." + "rootDir": ".", + "outDir": "build/", }, - "extends": "./tsconfig.production.json", - "include": ["./**/*"] + "include": ["./**/*.ts"] } diff --git a/resources/build/version/tsconfig.production.json b/resources/build/version/tsconfig.production.json deleted file mode 100644 index 2189a3042d4..00000000000 --- a/resources/build/version/tsconfig.production.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "allowSyntheticDefaultImports": true, - "alwaysStrict": true, - "charset": "utf-8", - "declaration": true, - "declarationMap": true, - "downlevelIteration": true, - "forceConsistentCasingInFileNames": true, - "lib": ["es2017"], - "module": "commonjs", - "noImplicitAny": false, - "noImplicitReturns": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "outDir": "lib", - "pretty": true, - "rootDir": "src", - "sourceMap": true, - "strict": true, - "strictNullChecks": true, - "target": "es2017" - }, - "files": ["./src/index.ts"] -} diff --git a/resources/standards-data/ldml-keyboards/techpreview/3.0/fr-t-k0-azerty.xml b/resources/standards-data/ldml-keyboards/techpreview/3.0/fr-t-k0-azerty.xml index 4ccedc062f3..190700d496a 100644 --- a/resources/standards-data/ldml-keyboards/techpreview/3.0/fr-t-k0-azerty.xml +++ b/resources/standards-data/ldml-keyboards/techpreview/3.0/fr-t-k0-azerty.xml @@ -23,22 +23,6 @@ - - - - - - - - - - - - - - - - @@ -34,15 +35,15 @@ - + - - + + diff --git a/resources/standards-data/ldml-keyboards/techpreview/cldr_info.json b/resources/standards-data/ldml-keyboards/techpreview/cldr_info.json index 601f341a251..e9907a447a3 100644 --- a/resources/standards-data/ldml-keyboards/techpreview/cldr_info.json +++ b/resources/standards-data/ldml-keyboards/techpreview/cldr_info.json @@ -1,5 +1,5 @@ { - "sha": "f3daab445e2e3ee88f8b94c6b46d380777035051", - "description": "release-44-alpha3-4-gf3daab445e", - "date": "Wed, 20 Sep 2023 22:27:35 +0000" + "sha": "2aa2275158c29e8e41c7f0b67c8fb786a453b89c", + "description": "release-44-alpha3-14-g2aa2275158", + "date": "Mon, 09 Oct 2023 19:18:13 +0000" } diff --git a/resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard3.dtd b/resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard3.dtd index 25d03368f86..92cda0eddf7 100644 --- a/resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard3.dtd +++ b/resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard3.dtd @@ -10,7 +10,7 @@ The CLDR Keyboard Subcommittee is currently developing major changes to the CLDR Please view the subcommittee page for the most recent information. --> - + @@ -77,17 +77,6 @@ Please view the subcommittee page for the most recent information. - - - - - - - - - - - diff --git a/resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard3.xsd b/resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard3.xsd index f3a7b8bed8e..47f299571bf 100644 --- a/resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard3.xsd +++ b/resources/standards-data/ldml-keyboards/techpreview/dtd/ldmlKeyboard3.xsd @@ -25,7 +25,6 @@ Note: DTD @-annotations are not currently converted to .xsd. For full CLDR file - @@ -148,26 +147,6 @@ Note: DTD @-annotations are not currently converted to .xsd. For full CLDR file - - - - - - - - - - - - - - - - - - - - diff --git a/resources/standards-data/ldml-keyboards/techpreview/fixup-schema.js b/resources/standards-data/ldml-keyboards/techpreview/fixup-schema.js index 84f00f6711a..e1a2d1f393a 100644 --- a/resources/standards-data/ldml-keyboards/techpreview/fixup-schema.js +++ b/resources/standards-data/ldml-keyboards/techpreview/fixup-schema.js @@ -80,6 +80,12 @@ if (data.title.endsWith('ldmlKeyboard3.xsd')) { } } +if (data.title.endsWith('ldmlKeyboardTest3.xsd')) { + if (data?.properties?.keyboardTest3) { + data.properties.keyboardTest3.type = 'object'; + } +} + // Write stuff const outstr = JSON.stringify(data, null, " "); writeFileSync(argv[2] || 1, outstr, "utf-8"); diff --git a/resources/standards-data/ldml-keyboards/techpreview/import/scanCodes-implied.xml b/resources/standards-data/ldml-keyboards/techpreview/import/scanCodes-implied.xml index 2ebb0ac85aa..e1ba3309d64 100644 --- a/resources/standards-data/ldml-keyboards/techpreview/import/scanCodes-implied.xml +++ b/resources/standards-data/ldml-keyboards/techpreview/import/scanCodes-implied.xml @@ -9,6 +9,7 @@ Values are space separated hex bytes. Frame keys are not included. --> +
@@ -16,13 +17,37 @@ - -
- - + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + + - \ No newline at end of file + diff --git a/resources/standards-data/ldml-keyboards/techpreview/ldml-keyboard3.schema.json b/resources/standards-data/ldml-keyboards/techpreview/ldml-keyboard3.schema.json index c5d13311ef8..6d6ba9d2a9d 100644 --- a/resources/standards-data/ldml-keyboards/techpreview/ldml-keyboard3.schema.json +++ b/resources/standards-data/ldml-keyboards/techpreview/ldml-keyboard3.schema.json @@ -635,46 +635,6 @@ } }, "type": "object" - }, - "vkey": { - "additionalProperties": false, - "properties": { - "from": { - "type": "string" - }, - "to": { - "type": "string" - } - }, - "required": [ - "from", - "to" - ], - "type": "object" - }, - "vkeys": { - "additionalProperties": false, - "properties": { - "import": { - "items": { - "$ref": "#/definitions/import" - }, - "type": "array" - }, - "special": { - "items": { - "$ref": "#/definitions/special" - }, - "type": "array" - }, - "vkey": { - "items": { - "$ref": "#/definitions/vkey" - }, - "type": "array" - } - }, - "type": "object" } }, "properties": { @@ -740,9 +700,6 @@ }, "version": { "$ref": "#/definitions/version" - }, - "vkeys": { - "$ref": "#/definitions/vkeys" } }, "required": [ diff --git a/resources/standards-data/ldml-keyboards/techpreview/ldml-keyboardtest3.schema.json b/resources/standards-data/ldml-keyboards/techpreview/ldml-keyboardtest3.schema.json index cbf09b39d5b..476574112be 100644 --- a/resources/standards-data/ldml-keyboards/techpreview/ldml-keyboardtest3.schema.json +++ b/resources/standards-data/ldml-keyboards/techpreview/ldml-keyboardtest3.schema.json @@ -210,7 +210,8 @@ "required": [ "info", "conformsTo" - ] + ], + "type": "object" } }, "required": [ diff --git a/tsconfig-base.json b/tsconfig.base.json similarity index 65% rename from tsconfig-base.json rename to tsconfig.base.json index 8e3eafb6cf4..2c56fd70794 100644 --- a/tsconfig-base.json +++ b/tsconfig.base.json @@ -1,5 +1,18 @@ { "compilerOptions": { + "module": "ES2022", + "target": "es2022", + "moduleResolution": "node16", + "forceConsistentCasingInFileNames": true, + "sourceMap": true, + "alwaysStrict": true, + "noImplicitThis": true, + "noImplicitReturns": true, + "noImplicitAny": true, + "strictBindCallApply": true, + "strictFunctionTypes": true, + "noUnusedLocals": true, + "rootDir": ".", // TODO: move all compiler options here @@ -9,7 +22,9 @@ "declarationMap": true, "baseUrl": ".", + "paths": { + "@keymanapp/common-types": ["./common/web/types/src/main"], "@keymanapp/input-processor": ["./common/web/input-processor/src"], "@keymanapp/keyboard-processor": ["./common/web/keyboard-processor/src"], "@keymanapp/keyman": ["./web" ], diff --git a/tsconfig.cjs.json b/tsconfig.cjs.json deleted file mode 100644 index 3dff61f8b64..00000000000 --- a/tsconfig.cjs.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - // Lists only CommonJS or 'none' modules; as we move modules from cjs/none to - // esm, we should move them from here into tsconfig.esm.json. Eventually, when - // we have only ES modules, we'll delete this file. - "files": [], - "include": [], - "references": [ - { "path": "./common/predictive-text/testing/one-stage-embedded-webworker/tsconfig.json" }, - { "path": "./common/predictive-text/testing/two-stage-embedded-webworker/tsconfig.json" }, - { "path": "./common/predictive-text/testing/two-stage-embedded-webworker/worker/tsconfig.json" }, - - { "path": "./developer/src/server/tsconfig.json" }, - - { "path": "./resources/build/version/tsconfig.json" }, - { "path": "./resources/build/version/tsconfig.production.json" }, - // { "path": "./web/bulk_rendering/tsconfig.json" }, - ] -} \ No newline at end of file diff --git a/tsconfig.esm-base.json b/tsconfig.esm-base.json deleted file mode 100644 index d17d505e5c2..00000000000 --- a/tsconfig.esm-base.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": "./tsconfig-base.json", - - "compilerOptions": { - "module": "ES2022", - "target": "es2022", - "moduleResolution": "Node16", - "forceConsistentCasingInFileNames": true, - "sourceMap": true, - "alwaysStrict": true, - "noImplicitThis": true, - "noImplicitReturns": true, - "noImplicitAny": true, - "strictBindCallApply": true, - "strictFunctionTypes": true, - "noUnusedLocals": true, - - "paths": { - "@keymanapp/keyman-version": ["./common/web/keyman-version/keyman-version.mts"], - "@keymanapp/common-types": ["./common/web/types/src/main"], - // "@keymanapp/": ["core/include/ldml/ldml-keyboard-constants"], - }, - }, -} diff --git a/tsconfig.esm.json b/tsconfig.json similarity index 85% rename from tsconfig.esm.json rename to tsconfig.json index 055e1787004..6e1510f0b04 100644 --- a/tsconfig.esm.json +++ b/tsconfig.json @@ -1,19 +1,30 @@ { - // Lists only ES modules; as we move modules from cjs/none to esm, we should - // move them from tsconfig.cjs.json to here. Eventually, when we have only ES - // modules, we can rename this to tsconfig.json. - "files": [], - "include": [], "references": [ { "path": "./core/include/ldml/tsconfig.json" }, - //{ "path": "./developer/src/kmc/test/tsconfig.json" }, + { "path": "./common/models/templates/tsconfig.json" }, + { "path": "./common/models/types/tsconfig.json" }, + { "path": "./common/models/wordbreakers/tsconfig.json" }, + { "path": "./common/predictive-text/tsconfig.all.json" }, + { "path": "./common/tools/hextobin/" }, + { "path": "./common/web/gesture-recognizer/tsconfig.json" }, + { "path": "./common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json" }, + { "path": "./common/web/input-processor/tsconfig.json" }, + { "path": "./common/web/keyboard-processor/tsconfig.json" }, + { "path": "./common/web/keyman-version" }, + { "path": "./common/web/lm-message-types/" }, + { "path": "./common/web/lm-worker/" }, + { "path": "./common/web/recorder/tsconfig.json" }, + { "path": "./common/web/sentry-manager/src/tsconfig.json" }, + { "path": "./common/web/types/" }, + { "path": "./common/web/utils/tsconfig.json" }, + { "path": "./developer/src/common/web/test-helpers/tsconfig.json" }, { "path": "./developer/src/kmc/tsconfig.json" }, - - // { "path": "./developer/src/kmc-analyze/test/tsconfig.json" }, + { "path": "./developer/src/kmc/test/tsconfig.json" }, { "path": "./developer/src/kmc-analyze/tsconfig.json" }, + // { "path": "./developer/src/kmc-analyze/test/tsconfig.json" }, { "path": "./developer/src/kmc-kmn/test/tsconfig.json" }, { "path": "./developer/src/kmc-kmn/tsconfig.json" }, { "path": "./developer/src/kmc-keyboard-info/test/tsconfig.json" }, @@ -26,27 +37,12 @@ { "path": "./developer/src/kmc-model-info/tsconfig.json" }, { "path": "./developer/src/kmc-package/test/tsconfig.json" }, { "path": "./developer/src/kmc-package/tsconfig.json" }, + { "path": "./developer/src/server/tsconfig.json" }, - { "path": "./common/web/keyman-version" }, - { "path": "./common/web/types/" }, - - { "path": "./common/web/gesture-recognizer/tsconfig.json" }, - { "path": "./common/web/gesture-recognizer/src/tools/unit-test-resources/tsconfig.json" }, - { "path": "./common/web/input-processor/tsconfig.json" }, - { "path": "./common/web/keyboard-processor/tsconfig.json" }, - { "path": "./common/web/recorder/tsconfig.json" }, - { "path": "./common/web/sentry-manager/src/tsconfig.json" }, - { "path": "./common/web/utils/tsconfig.json" }, - - { "path": "./common/models/templates/tsconfig.json" }, - { "path": "./common/models/types/tsconfig.json" }, - { "path": "./common/models/wordbreakers/tsconfig.json" }, - { "path": "./common/predictive-text/tsconfig.json" }, + { "path": "./resources/build/version/" }, { "path": "./web/src/tsconfig.all.json" }, // { "path": "./web/tools/recorder/tsconfig.json" }, // { "path": "./web/tools/sourcemap-root/tsconfig.json" }, - { "path": "./common/web/lm-message-types/" }, - { "path": "./common/web/lm-worker/" }, ] } \ No newline at end of file diff --git a/web/src/app/ui/kmwuitoolbar.ts b/web/src/app/ui/kmwuitoolbar.ts index 0be3f2cf0f3..68799cd35cc 100644 --- a/web/src/app/ui/kmwuitoolbar.ts +++ b/web/src/app/ui/kmwuitoolbar.ts @@ -824,10 +824,12 @@ if(!keyman?.ui?.name) { this.selectedLanguage = kbd.LanguageCode; // Return focus to input area and activate the selected keyboard - this.setLastFocus(); //*****this seems out of sequence??? this.addKeyboardToList(lang, kbd); if(updateKeyman) { - keymanweb.setActiveKeyboard(kbd.InternalName, kbd.LanguageCode); + keymanweb.setActiveKeyboard(kbd.InternalName, kbd.LanguageCode).then(() => { + // Restore focus _after_ the keyboard finishes loading. + this.setLastFocus(); + }); } this.listedKeyboards[this.findListedKeyboard(lang)].buttonNode.className = 'kmw_button_selected'; diff --git a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts index e36b24b0e82..8482aa85e85 100644 --- a/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts +++ b/web/src/engine/osk/src/input/gestures/browser/subkeyPopup.ts @@ -36,6 +36,9 @@ export default class SubkeyPopup implements RealizedGesture { public readonly baseKey: KeyElement; public readonly promise: Promise; + private initialX: number; + private initialY: number; + // Resolves the promise that generated this SubkeyPopup. private resolver: (keyEvent: KeyEvent) => void; @@ -219,25 +222,26 @@ export default class SubkeyPopup implements RealizedGesture { let skElement = popupBase.childNodes[i].firstChild; // Preference order: - // #1: if a default subkey has been specified, select it. (pending, for 15.0+) + // #1: if a default subkey has been specified, select it. // #2: if no default subkey is specified, default to a subkey with the same // key ID and layer / modifier spec. - //if(skSpec.isDefault) { TODO for 15.0 - // bk = skElement; - // break; - //} else - if(!baseKey.key || !baseKey.key.spec) { + if(skSpec.default) { + bk = skElement; + break; + } else if(!baseKey.key || !baseKey.key.spec) { continue; } if(skSpec.elementID == baseKey.key.spec.elementID) { bk = skElement; - break; // Best possible match has been found. (Disable 'break' once above block is implemented.) } } if(bk) { + // Prevent sticky-highlighting should the default key be selected. + vkbd.keyPending?.key.highlight(false); vkbd.keyPending = bk; + this.currentSelection = bk; // Subkeys never get key previews, so we can directly highlight the subkey. bk.key.highlight(true); } @@ -268,7 +272,33 @@ export default class SubkeyPopup implements RealizedGesture { } updateTouch(input: InputEventCoordinate) { - this.currentSelection = null; + // For 'default' subkey handling, we want a small fudge factor. + if(this.initialX === undefined || this.initialY === undefined) { + this.initialX = input.x; + this.initialY = input.y; + } + + const deltaX = this.initialX - input.x; + const deltaY = this.initialY - input.y; + const dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + + if(dist > 5) { + this.initialX = Number.MAX_SAFE_INTEGER; // it'll always exceed the threshold hereafter. + this.currentSelection = null; + } else { + // The function that calls this to perform subkey updates auto-unhighlights the active selection; + // make sure that highlighting is maintained if no new key was selected, but we haven't cancelled + // default-selection mode yet. + this.currentSelection.key.highlight(true); + + // Even if we technically have a different subkey underneath the touchpoint, we're still in + // default-selection mode. Require more movement before cancelling default-selection mode. + // + // Can occur for large subkey menus or when subkey menus are "constrained" within OSK bounds, + // as with the iOS app. + return; + } + this.baseKey.key.highlight(false); for(let i=0; i < this.baseKey['subKeys'].length; i++) { diff --git a/web/src/engine/osk/src/keyboard-layout/oskKey.ts b/web/src/engine/osk/src/keyboard-layout/oskKey.ts index b99d2076253..77d8927b60a 100644 --- a/web/src/engine/osk/src/keyboard-layout/oskKey.ts +++ b/web/src/engine/osk/src/keyboard-layout/oskKey.ts @@ -25,6 +25,7 @@ export class OSKKeySpec implements LayoutKey { nextlayer?: string; pad?: number; sk?: OSKKeySpec[]; + default?: boolean; constructor(id: string, text?: string, width?: number, sp?: ButtonClass, nextlayer?: string, pad?: number) { this.id = id; diff --git a/web/src/engine/osk/src/specialCharacters.ts b/web/src/engine/osk/src/specialCharacters.ts index 0f2a3adb955..ebd17ab06cb 100644 --- a/web/src/engine/osk/src/specialCharacters.ts +++ b/web/src/engine/osk/src/specialCharacters.ts @@ -1,5 +1,5 @@ -// Defines the PUA code mapping for the various 'special' modifier/control keys on keyboards. -// `specialCharacters` must be kept in sync with the same variable in builder.js. See also CompileKeymanWeb.pas: CSpecialText10 +// Defines the PUA code mapping for the various 'special' modifier/control/non-printing keys on keyboards. +// `specialCharacters` must be kept in sync with the same variable in constants.js. See also CompileKeymanWeb.pas: CSpecialText10 let specialCharacters = { '*Shift*': 8, '*Enter*': 5, @@ -43,6 +43,30 @@ let specialCharacters = { '*ZWNJ*': 0x75, // If this one is specified, auto-detection will kick in. '*ZWNJiOS*': 0x75, // The iOS version will be used by default, but the '*ZWNJAndroid*': 0x76, // Android platform has its own default glyph. + // Added in Keyman 17.0. + // Reference: https://github.com/silnrsi/font-symchar/blob/v4.000/documentation/encoding.md + '*ZWNJGeneric*': 0x79, // Generic version of ZWNJ (no override) + '*Sp*': 0x80, // Space + '*NBSp*': 0x82, // No-break Space + '*NarNBSp*': 0x83, // Narrow No-break Space + '*EnQ*': 0x84, // En Quad + '*EmQ*': 0x85, // Em Quad + '*EnSp*': 0x86, // En Space + '*EmSp*': 0x87, // Em Space + // TODO: Skipping #-per-em-space + '*PunctSp*': 0x8c, // Punctuation Space + '*ThSp*': 0x8d, // Thin Space + '*HSp*': 0x8e, // Hair Space + '*ZWSp*': 0x81, // Zero Width Space + '*ZWJ*': 0x77, // Zero Width Joiner + '*WJ*': 0x78, // Word Joiner + '*CGJ*': 0x7a, // Combining Grapheme Joiner + '*LTRM*': 0x90, // Left-to-right Mark + '*RTLM*': 0x91, // Right-to-left Mark + '*SH*': 0xa1, // Soft Hyphen + '*HTab*': 0xa2, // Horizontal Tabulation + // TODO: Skipping size references + }; export default specialCharacters; \ No newline at end of file diff --git a/web/src/resources/osk/keymanweb-osk.ttf b/web/src/resources/osk/keymanweb-osk.ttf index 5b3c6219797..e0651b14d4f 100644 Binary files a/web/src/resources/osk/keymanweb-osk.ttf and b/web/src/resources/osk/keymanweb-osk.ttf differ diff --git a/web/src/test/manual/web/default-subkey/default_subkey.js b/web/src/test/manual/web/default-subkey/default_subkey.js new file mode 100644 index 00000000000..556acda19a2 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/default_subkey.js @@ -0,0 +1 @@ +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_default_subkey());}function Keyboard_default_subkey(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_default_subkey";this.KN="default-subkey";this.KMINVER="10.0";this.KV={F:' 1em "Arial"',K102:0};this.KV.KLS={};this.KV.BK=(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})(this.KV.KLS);this.KDU=0;this.KH='';this.KM=0;this.KBVER="1.0";this.KMBM=0x0000;this.KVKD="T_d_default";this.KVKL={"tablet":{"font":"Tahoma","displayUnderlying":false,"layer":[{"id":"default","row":[{"id":"1","key":[{"id":"K_Q","text":"q"},{"id":"K_W","text":"w"},{"id":"K_E","text":"e"},{"id":"K_R","text":"r"},{"id":"K_T","text":"t"},{"id":"K_Y","text":"y"},{"id":"K_U","text":"u"},{"id":"K_I","text":"i"},{"id":"K_O","text":"o"},{"id":"K_P","text":"p"}]},{"id":"2","key":[{"id":"K_A","pad":"70","text":"a","sk":[{"id":"U_00E1","text":"\u00E1"},{"id":"U_00E0","text":"\u00E0"},{"id":"K_A","text":"a"},{"id":"U_00E4","text":"\u00E4"},{"id":"U_00E5","text":"\u00E5"},{"id":"U_00E2","text":"\u00E2"},{"id":"U_00E3","text":"\u00E3"}]},{"id":"K_S","text":"s"},{"id":"K_D","text":"d","sk":[{"id":"K_D","text":"d"},{"id":"U_010F","text":"\u010F"},{"id":"U_0111","text":"\u0111"},{"id":"U_0257","text":"\u0257"},{"id":"T_d_default","text":"default","default":true},{"id":"U_0221","text":"\u0221"}]},{"id":"K_F","text":"f"},{"id":"K_G","text":"g"},{"id":"K_H","text":"h"},{"id":"K_J","text":"j"},{"id":"K_K","text":"k"},{"id":"K_L","text":"l"},{"width":"10","id":"T_new_88","sp":"10"}]},{"id":"3","key":[{"nextlayer":"shift","width":"110","id":"K_SHIFT","sp":"1","text":"*Shift*"},{"id":"K_Z","text":"z"},{"id":"K_X","text":"x"},{"id":"K_C","text":"c"},{"id":"K_V","text":"v"},{"id":"K_B","text":"b"},{"id":"K_N","text":"n"},{"id":"K_M","text":"m"},{"id":"K_PERIOD","text":".","sk":[{"id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"id":"K_COLON","text":";"}]},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"140","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"shift","row":[{"id":"1","key":[{"id":"K_Q","text":"Q"},{"id":"K_W","text":"W"},{"id":"K_E","text":"E"},{"id":"K_R","text":"R"},{"id":"K_T","text":"T"},{"id":"K_Y","text":"Y"},{"id":"K_U","text":"U"},{"id":"K_I","text":"I"},{"id":"K_O","text":"O"},{"id":"K_P","text":"P"}]},{"id":"2","key":[{"id":"K_A","pad":"70","text":"A"},{"id":"K_S","text":"S"},{"id":"K_D","text":"D"},{"id":"K_F","text":"F"},{"id":"K_G","text":"G"},{"id":"K_H","text":"H"},{"id":"K_J","text":"J"},{"id":"K_K","text":"K"},{"id":"K_L","text":"L"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"nextlayer":"default","width":"110","id":"K_SHIFT","sp":"2","text":"*Shift*"},{"id":"K_Z","text":"Z"},{"id":"K_X","text":"X"},{"id":"K_C","text":"C"},{"id":"K_V","text":"V"},{"id":"K_B","text":"B"},{"id":"K_N","text":"N"},{"id":"K_M","text":"M"},{"layer":"default","id":"K_PERIOD","text":".","sk":[{"layer":"default","id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"layer":"default","id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"layer":"default","id":"K_COLON","text":";"}]},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"140","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"numeric","row":[{"id":"1","key":[{"id":"K_1","text":"1"},{"id":"K_2","text":"2"},{"id":"K_3","text":"3"},{"id":"K_4","text":"4"},{"id":"K_5","text":"5"},{"id":"K_6","text":"6"},{"id":"K_7","text":"7"},{"id":"K_8","text":"8"},{"id":"K_9","text":"9"},{"id":"K_0","text":"0"}]},{"id":"2","key":[{"layer":"shift","id":"K_4","pad":"70","text":"$"},{"layer":"shift","id":"K_2","text":"@"},{"layer":"shift","id":"K_3","text":"#"},{"layer":"shift","id":"K_5","text":"%"},{"layer":"shift","id":"K_7","text":"&"},{"layer":"shift","id":"K_HYPHEN","text":"_"},{"layer":"default","id":"K_EQUAL","text":"="},{"layer":"shift","id":"K_BKSLASH","text":"|"},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"width":"110","id":"K_SHIFT","sp":"1","text":"*Shift*"},{"id":"K_LBRKT","text":"[","sk":[{"id":"U_00AB","text":"\u00AB"},{"layer":"shift","id":"K_COMMA","text":"<"},{"layer":"shift","id":"K_LBRKT","text":"{"}]},{"layer":"shift","id":"K_9","text":"("},{"layer":"shift","id":"K_0","text":")"},{"id":"K_RBRKT","text":"]","sk":[{"id":"U_00BB","text":"\u00BB"},{"layer":"shift","id":"K_PERIOD","text":">"},{"layer":"shift","id":"K_RBRKT","text":"}"}]},{"layer":"shift","id":"K_EQUAL","text":"+"},{"layer":"default","id":"K_HYPHEN","text":"-"},{"layer":"shift","id":"K_8","text":"*"},{"layer":"default","id":"K_SLASH","text":"\/"},{"width":"90","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"default","width":"140","id":"K_LOWER","sp":"1","text":"*abc*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"630","id":"K_SPACE"},{"width":"140","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]}]}};this.KVER="17.0.162.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;if(k.KKM(e,16384,256)) {if(1){r=m=1;k.KDC(0,t);k.KO(-1,t,"default");}}return r;};} \ No newline at end of file diff --git a/web/src/test/manual/web/default-subkey/index.html b/web/src/test/manual/web/default-subkey/index.html new file mode 100644 index 00000000000..728355c43b4 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/index.html @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + KeymanWeb Testing Page - Predictive Text: robust testing + + + + + + + + + + + + + + + + +

KeymanWeb Sample Page - default subkey bootstrap-testing

+

Note: the intended tests require use of a touch-form-factor device or emulation thereof. +

+

+ The primary test is held on the default layer's 'd' key - the key labeled 'default' should + be autoselected. +

+

+ A secondary test is held on the default layer's 'a' key - the key labeled 'a', matching the + base key, should be autoselected. +

+
+ +
+ +

Type in your language in this text area:

+ + +

or in this input field:

+ + +

Return to testing home page

+
+ + + + + diff --git a/web/src/test/manual/web/default-subkey/kbd_source/HISTORY.md b/web/src/test/manual/web/default-subkey/kbd_source/HISTORY.md new file mode 100644 index 00000000000..cbd807699c4 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/HISTORY.md @@ -0,0 +1,6 @@ +default-subkey Change History +==================== + +1.0 (2023-08-21) +---------------- +* Created by SIL International diff --git a/web/src/test/manual/web/default-subkey/kbd_source/LICENSE.md b/web/src/test/manual/web/default-subkey/kbd_source/LICENSE.md new file mode 100644 index 00000000000..b582b3f9086 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +© 2023 SIL International + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/web/src/test/manual/web/default-subkey/kbd_source/README.md b/web/src/test/manual/web/default-subkey/kbd_source/README.md new file mode 100644 index 00000000000..9fb82bd00ba --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/README.md @@ -0,0 +1,30 @@ +default-subkey keyboard +============== + +Version 1.0 + +Description +----------- +default-subkey generated from template + +Links +----- + +Copyright +--------- +See [LICENSE.md](LICENSE.md) + +Supported Platforms +------------------- + * Windows + * macOS + * Linux + * Web + * iPhone + * iPad + * Android phone + * Android tablet + * Mobile devices + * Desktop devices + * Tablet devices + diff --git a/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.keyboard_info b/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.keyboard_info new file mode 100644 index 00000000000..1677ce4c2f4 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.keyboard_info @@ -0,0 +1,7 @@ +{ + "license": "mit", + "languages": [ + + ], + "description": "default-subkey generated from template" +} diff --git a/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.kpj b/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.kpj new file mode 100644 index 00000000000..4de714dbd3b --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/default_subkey.kpj @@ -0,0 +1,110 @@ + + + + $PROJECTPATH\build + True + True + True + keyboard + + + + id_8305ac63cf6c1388736030b6b94f996d + default_subkey.kmn + source\default_subkey.kmn + 1.0 + .kmn +
+ default-subkey + © SIL International +
+
+ + id_f586f51f683bde64c75f566e643e59bd + default_subkey.kps + source\default_subkey.kps + + .kps +
+ default-subkey + © SIL International +
+
+ + id_ede98e4633e239f933cbfd1f4e1b766c + HISTORY.md + HISTORY.md + + .md + + + id_53e892b8b41cc4caece1cfd5ef21d6e7 + LICENSE.md + LICENSE.md + + .md + + + id_0730bb7c2e8f9ea2438b52e419dd86c9 + README.md + README.md + + .md + + + id_9cc75be74cee7f9a4937893e80b91b5f + default_subkey.keyboard_info + default_subkey.keyboard_info + + .keyboard_info + + + id_d8483af80632f8b611983c11137efccd + default_subkey.ico + source\default_subkey.ico + + .ico + id_8305ac63cf6c1388736030b6b94f996d + + + id_5086f2e8ef1d731c015a78f418aba1e8 + default_subkey.kmx + source\..\build\default_subkey.kmx + + .kmx + id_f586f51f683bde64c75f566e643e59bd + + + id_c8c9acd9c28010e45856034bff6c9d90 + default_subkey.js + source\..\build\default_subkey.js + + .js + id_f586f51f683bde64c75f566e643e59bd + + + id_7b38ddd4f3836ebf9365696475ade08a + default_subkey.kvk + source\..\build\default_subkey.kvk + + .kvk + id_f586f51f683bde64c75f566e643e59bd + + + id_356e5d149c1e539356d72698c1e401a6 + welcome.htm + source\welcome.htm + + .htm + id_f586f51f683bde64c75f566e643e59bd + + + id_8da344c4cea6f467013357fe099006f5 + readme.htm + source\readme.htm + + .htm + id_f586f51f683bde64c75f566e643e59bd + +
+
diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.ico b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.ico new file mode 100644 index 00000000000..e3628ccc9b2 Binary files /dev/null and b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.ico differ diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.keyman-touch-layout b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.keyman-touch-layout new file mode 100644 index 00000000000..41cbf16e1d9 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.keyman-touch-layout @@ -0,0 +1,721 @@ +{ + "tablet": { + "font": "Tahoma", + "layer": [ + { + "id": "default", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_Q", + "text": "q" + }, + { + "id": "K_W", + "text": "w" + }, + { + "id": "K_E", + "text": "e" + }, + { + "id": "K_R", + "text": "r" + }, + { + "id": "K_T", + "text": "t" + }, + { + "id": "K_Y", + "text": "y" + }, + { + "id": "K_U", + "text": "u" + }, + { + "id": "K_I", + "text": "i" + }, + { + "id": "K_O", + "text": "o" + }, + { + "id": "K_P", + "text": "p" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_A", + "text": "a", + "pad": 70, + "sk": [ + { + "text": "á", + "id": "U_00E1" + }, + { + "text": "à", + "id": "U_00E0" + }, + { + "text": "a", + "id": "K_A" + }, + { + "text": "ä", + "id": "U_00E4" + }, + { + "text": "å", + "id": "U_00E5" + }, + { + "text": "â", + "id": "U_00E2" + }, + { + "text": "ã", + "id": "U_00E3" + } + ] + }, + { + "id": "K_S", + "text": "s" + }, + { + "id": "K_D", + "text": "d", + "sk": [ + { + "text": "d", + "id": "K_D" + }, + { + "text": "ď", + "id": "U_010F" + }, + { + "text": "đ", + "id": "U_0111" + }, + { + "text": "ɗ", + "id": "U_0257" + }, + { + "text": "default", + "id": "T_d_default", + "default": true + }, + { + "text": "ȡ", + "id": "U_0221" + } + ] + }, + { + "id": "K_F", + "text": "f" + }, + { + "id": "K_G", + "text": "g" + }, + { + "id": "K_H", + "text": "h" + }, + { + "id": "K_J", + "text": "j" + }, + { + "id": "K_K", + "text": "k" + }, + { + "id": "K_L", + "text": "l" + }, + { + "id": "T_new_88", + "width": 10, + "sp": 10 + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": 110, + "sp": 1, + "nextlayer": "shift" + }, + { + "id": "K_Z", + "text": "z" + }, + { + "id": "K_X", + "text": "x" + }, + { + "id": "K_C", + "text": "c" + }, + { + "id": "K_V", + "text": "v" + }, + { + "id": "K_B", + "text": "b" + }, + { + "id": "K_N", + "text": "n" + }, + { + "id": "K_M", + "text": "m" + }, + { + "id": "K_PERIOD", + "text": ".", + "sk": [ + { + "text": ",", + "id": "K_COMMA" + }, + { + "text": "!", + "id": "K_1", + "layer": "shift" + }, + { + "text": "?", + "id": "K_SLASH", + "layer": "shift" + }, + { + "text": "'", + "id": "K_QUOTE" + }, + { + "text": "\"", + "id": "K_QUOTE", + "layer": "shift" + }, + { + "text": "\\", + "id": "K_BKSLASH" + }, + { + "text": ":", + "id": "K_COLON", + "layer": "shift" + }, + { + "text": ";", + "id": "K_COLON" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": 90, + "sp": 1 + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_NUMLOCK", + "text": "*123*", + "width": 140, + "sp": 1, + "nextlayer": "numeric" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": 120, + "sp": 1 + }, + { + "id": "K_SPACE", + "text": "", + "width": 630, + "sp": 0 + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": 140, + "sp": 1 + } + ] + } + ] + }, + { + "id": "shift", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_Q", + "text": "Q" + }, + { + "id": "K_W", + "text": "W" + }, + { + "id": "K_E", + "text": "E" + }, + { + "id": "K_R", + "text": "R" + }, + { + "id": "K_T", + "text": "T" + }, + { + "id": "K_Y", + "text": "Y" + }, + { + "id": "K_U", + "text": "U" + }, + { + "id": "K_I", + "text": "I" + }, + { + "id": "K_O", + "text": "O" + }, + { + "id": "K_P", + "text": "P" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_A", + "text": "A", + "pad": 70 + }, + { + "id": "K_S", + "text": "S" + }, + { + "id": "K_D", + "text": "D" + }, + { + "id": "K_F", + "text": "F" + }, + { + "id": "K_G", + "text": "G" + }, + { + "id": "K_H", + "text": "H" + }, + { + "id": "K_J", + "text": "J" + }, + { + "id": "K_K", + "text": "K" + }, + { + "id": "K_L", + "text": "L" + }, + { + "sp": 10, + "width": 10 + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": 110, + "sp": 2, + "nextlayer": "default" + }, + { + "id": "K_Z", + "text": "Z" + }, + { + "id": "K_X", + "text": "X" + }, + { + "id": "K_C", + "text": "C" + }, + { + "id": "K_V", + "text": "V" + }, + { + "id": "K_B", + "text": "B" + }, + { + "id": "K_N", + "text": "N" + }, + { + "id": "K_M", + "text": "M" + }, + { + "id": "K_PERIOD", + "text": ".", + "layer": "default", + "sk": [ + { + "text": ",", + "id": "K_COMMA", + "layer": "default" + }, + { + "text": "!", + "id": "K_1", + "layer": "shift" + }, + { + "text": "?", + "id": "K_SLASH", + "layer": "shift" + }, + { + "text": "'", + "id": "K_QUOTE", + "layer": "default" + }, + { + "text": "\"", + "id": "K_QUOTE", + "layer": "shift" + }, + { + "text": "\\", + "id": "K_BKSLASH", + "layer": "default" + }, + { + "text": ":", + "id": "K_COLON", + "layer": "shift" + }, + { + "text": ";", + "id": "K_COLON", + "layer": "default" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": 90, + "sp": 1 + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_NUMLOCK", + "text": "*123*", + "width": 140, + "sp": 1, + "nextlayer": "numeric" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": 120, + "sp": 1 + }, + { + "id": "K_SPACE", + "text": "", + "width": 630, + "sp": 0 + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": 140, + "sp": 1 + } + ] + } + ] + }, + { + "id": "numeric", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "1" + }, + { + "id": "K_2", + "text": "2" + }, + { + "id": "K_3", + "text": "3" + }, + { + "id": "K_4", + "text": "4" + }, + { + "id": "K_5", + "text": "5" + }, + { + "id": "K_6", + "text": "6" + }, + { + "id": "K_7", + "text": "7" + }, + { + "id": "K_8", + "text": "8" + }, + { + "id": "K_9", + "text": "9" + }, + { + "id": "K_0", + "text": "0" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_4", + "text": "$", + "layer": "shift", + "pad": 70 + }, + { + "id": "K_2", + "text": "@", + "layer": "shift" + }, + { + "id": "K_3", + "text": "#", + "layer": "shift" + }, + { + "id": "K_5", + "text": "%", + "layer": "shift" + }, + { + "id": "K_7", + "text": "&", + "layer": "shift" + }, + { + "id": "K_HYPHEN", + "text": "_", + "layer": "shift" + }, + { + "id": "K_EQUAL", + "text": "=", + "layer": "default" + }, + { + "id": "K_BKSLASH", + "text": "|", + "layer": "shift" + }, + { + "id": "K_BKSLASH", + "text": "\\", + "layer": "default" + }, + { + "text": "", + "width": 10, + "sp": 10 + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": 110, + "sp": 1 + }, + { + "id": "K_LBRKT", + "text": "[", + "sk": [ + { + "id": "U_00AB", + "text": "«" + }, + { + "id": "K_COMMA", + "text": "<", + "layer": "shift" + }, + { + "id": "K_LBRKT", + "text": "{", + "layer": "shift" + } + ] + }, + { + "id": "K_9", + "text": "(", + "layer": "shift" + }, + { + "id": "K_0", + "text": ")", + "layer": "shift" + }, + { + "id": "K_RBRKT", + "text": "]", + "sk": [ + { + "id": "U_00BB", + "text": "»" + }, + { + "id": "K_PERIOD", + "text": ">", + "layer": "shift" + }, + { + "id": "K_RBRKT", + "text": "}", + "layer": "shift" + } + ] + }, + { + "id": "K_EQUAL", + "text": "+", + "layer": "shift" + }, + { + "id": "K_HYPHEN", + "text": "-", + "layer": "default" + }, + { + "id": "K_8", + "text": "*", + "layer": "shift" + }, + { + "id": "K_SLASH", + "text": "/", + "layer": "default" + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": 90, + "sp": 1 + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_LOWER", + "text": "*abc*", + "width": 140, + "sp": 1, + "nextlayer": "default" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": 120, + "sp": 1 + }, + { + "id": "K_SPACE", + "text": "", + "width": 630, + "sp": 0 + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": 140, + "sp": 1 + } + ] + } + ] + } + ] + } +} \ No newline at end of file diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kmn b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kmn new file mode 100644 index 00000000000..f1ac06ea5e9 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kmn @@ -0,0 +1,16 @@ +c default_subkey generated from template at 2023-08-21 10:14:50 +c with name "default-subkey" +store(&VERSION) '10.0' +store(&NAME) 'default-subkey' +store(©RIGHT) '© SIL International' +store(&KEYBOARDVERSION) '1.0' +store(&TARGETS) 'any' +store(&BITMAP) 'default_subkey.ico' +store(&VISUALKEYBOARD) 'default_subkey.kvks' +store(&LAYOUTFILE) 'default_subkey.keyman-touch-layout' + +begin Unicode > use(main) + +group(main) using keys + ++ [ T_d_default ] > "default" diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps new file mode 100644 index 00000000000..97cbafecd72 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kps @@ -0,0 +1,67 @@ + + + + 17.0.162.0 + 7.0 + + + + readme.htm + + + + + + + + + + default-subkey + © SIL International + SIL International + + + + + ..\build\default_subkey.kmx + + 0 + .kmx + + + ..\build\default_subkey.js + + 0 + .js + + + ..\build\default_subkey.kvk + + 0 + .kvk + + + welcome.htm + + 0 + .htm + + + readme.htm + + 0 + .htm + + + + + default-subkey + default_subkey + 1.0 + + English + + + + + diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kvks b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kvks new file mode 100644 index 00000000000..830237b17e9 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/default_subkey.kvks @@ -0,0 +1,8 @@ + + +
+ 10.0 + default_subkey + +
+
diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/readme.htm b/web/src/test/manual/web/default-subkey/kbd_source/source/readme.htm new file mode 100644 index 00000000000..8bce21ff5d7 --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/readme.htm @@ -0,0 +1,24 @@ + + + + + + default-subkey + + + + +

default-subkey

+ +

+ default-subkey 1.0 generated from template. +

+ +

© SIL International

+ + + diff --git a/web/src/test/manual/web/default-subkey/kbd_source/source/welcome.htm b/web/src/test/manual/web/default-subkey/kbd_source/source/welcome.htm new file mode 100644 index 00000000000..cdf7e1e234b --- /dev/null +++ b/web/src/test/manual/web/default-subkey/kbd_source/source/welcome.htm @@ -0,0 +1,26 @@ + + + + + + Start Using default-subkey + + + + +

Start Using default-subkey

+ +

+ default-subkey 1.0 generated from template. +

+ +

Keyboard Layout

+ + + + + \ No newline at end of file diff --git a/web/src/test/manual/web/index.html b/web/src/test/manual/web/index.html index f251408f3a2..164254a3469 100644 --- a/web/src/test/manual/web/index.html +++ b/web/src/test/manual/web/index.html @@ -66,6 +66,7 @@

Test Caps Lock Layer (#3620)

Test Start of Sentence (#3621)

Test start of sentence keyboard rules (#5963)

Tests predictive text & other handling of rule matching when the final rule group does not match (#6005)

+

Tests handling of new default-subkey feature (#9430)

Test special characters rendering with keymanweb-osk.ttf (#9469)

Other

Keystroke processing regression test engine.

diff --git a/web/src/test/manual/web/issue9469/test9469/HISTORY.md b/web/src/test/manual/web/issue9469/test9469/HISTORY.md index 8e3fdbb7ced..d520e029426 100644 --- a/web/src/test/manual/web/issue9469/test9469/HISTORY.md +++ b/web/src/test/manual/web/issue9469/test9469/HISTORY.md @@ -1,6 +1,10 @@ test9469 Change History ==================== +1.1 (2023-09-12) +---------------- +* Add non-printing space characters + 1.0 (2023-08-17) ---------------- * Created by SIL International diff --git a/web/src/test/manual/web/issue9469/test9469/build/test9469.js b/web/src/test/manual/web/issue9469/test9469/build/test9469.js index 624b9990bd7..10e028fdd68 100644 --- a/web/src/test/manual/web/issue9469/test9469/build/test9469.js +++ b/web/src/test/manual/web/issue9469/test9469/build/test9469.js @@ -1 +1 @@ -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_test9469());}function Keyboard_test9469(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_test9469";this.KN="test9469";this.KMINVER="10.0";this.KV={F:' 1em "Arial"',K102:0};this.KV.KLS={};this.KV.BK=(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})(this.KV.KLS);this.KDU=0;this.KH='';this.KM=0;this.KBVER="1.0";this.KMBM=0x0000;this.KVKL={"phone":{"font":"Tahoma","displayUnderlying":false,"layer":[{"id":"default","row":[{"id":"1","key":[{"id":"K_TAB","text":"*Tab*"},{"id":"T_TABLEFT","text":"*TabLeft*"},{"id":"K_E","text":"e"},{"id":"K_R","text":"r"},{"id":"K_T","text":"t"},{"id":"K_Y","text":"y"},{"id":"K_U","text":"u"},{"id":"K_I","text":"i"},{"id":"K_O","text":"o"},{"id":"K_P","text":"p"}]},{"id":"2","key":[{"id":"K_A","pad":"50","text":"a"},{"id":"K_S","text":"s"},{"id":"K_D","text":"d"},{"id":"K_F","text":"f"},{"id":"K_G","text":"g"},{"id":"K_H","text":"h"},{"id":"K_J","text":"j"},{"id":"K_K","text":"k"},{"id":"T_RTLBKSP","sp":"1","text":this._v>13?"*RTLBkSp*":"*BkSp*"},{"id":"T_new_338","sp":"1","text":this._v>13?"*LTRBkSp*":"*BkSp*"}]},{"id":"3","key":[{"nextlayer":"shift","id":"K_SHIFT","sp":"1","text":"*Shift*","sk":[{"id":"T_new_206","text":"*Alt*"},{"id":"T_new_205","text":"*Ctrl*"},{"id":"T_new_207","text":"*Caps*"},{"id":"T_new_208","text":"*ABC*"},{"id":"T_new_209","text":"*abc*"},{"id":"T_new_210","text":"*Symbol*"},{"id":"T_new_211","text":"*AltGr*"},{"id":"T_new_212","text":"*LAlt*"},{"id":"T_new_258","text":"*RAlt*"},{"id":"T_new_259","text":"*LCtrl*"},{"id":"T_new_260","text":"*RCtrl*"},{"id":"T_new_261","text":"*LAltCtrlShift*"},{"id":"T_new_262","text":"*RAltCtrlShift*"},{"id":"T_new_263","text":"*AltShift*"},{"id":"T_new_264","text":"*CtrlShift*"},{"id":"T_new_265","text":"*AltCtrlShift*"},{"id":"T_new_266","text":"*LAltShift*"},{"id":"T_new_267","text":"*RAltShift*"},{"id":"T_new_268","text":"*LCtrlShift*"},{"id":"T_new_269","text":"*RCtrlShift*"},{"id":"T_new_292","text":this._v>13?"*ShiftLock*":"*Shift*"},{"id":"T_new_293","text":this._v>13?"*ShiftedLock*":"*Shifted*"}]},{"id":"T_ZWNJ","text":this._v>13?"*ZWNJ*":"<|>"},{"id":"T_ZWNJIOS","text":this._v>13?"*ZWNJiOS*":"<|>"},{"id":"T_ZWNJANDROID","text":this._v>13?"*ZWNJAndroid*":"<|>"},{"id":"K_V","text":"v"},{"id":"K_B","text":"b"},{"id":"K_N","text":"n"},{"id":"K_M","text":"m"},{"id":"K_PERIOD","text":".","sk":[{"id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"id":"K_COLON","text":";"}]},{"width":"100","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"150","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"610","id":"K_SPACE"},{"id":"K_ROPT","text":"*Hide*"},{"width":"150","id":"K_ENTER","sp":"1","text":"*Enter*","sk":[{"id":"T_new_270","text":this._v>13?"*RTLEnter*":"*Enter*"},{"id":"T_new_295","text":this._v>13?"*LTREnter*":"*Enter*"}]}]}]},{"id":"shift","row":[{"id":"1","key":[{"id":"K_Q","text":"*Alt*"},{"id":"K_W","text":"*Ctrl*"},{"id":"K_E","text":"*Caps*"},{"id":"K_R","text":"*ABC*"},{"id":"K_T","text":"*abc*"},{"id":"K_Y","text":"*123*"},{"id":"K_U","text":"*Symbol*"},{"id":"K_I","text":"*Currency*"},{"id":"K_O","text":"*Shifted*"},{"id":"K_P","text":"*AltGr*"}]},{"id":"2","key":[{"id":"K_A","pad":"50","text":"*LAlt*"},{"id":"K_S","text":"*RAlt*"},{"id":"K_D","text":"*LCtrl*"},{"id":"K_F","text":"*RCtrl*"},{"id":"K_G","text":"*LAltCtrl*"},{"id":"K_H","text":"*RAltCtrl*"},{"id":"K_J","text":"*LAltCtrlShift*"},{"id":"K_K","text":"*RAltCtrlShift*"},{"id":"K_L","text":"*AltShift*"},{"id":"T_new_232","text":"*CtrlShift*"}]},{"id":"3","key":[{"nextlayer":"default","id":"K_SHIFT","sp":"2","text":"*Shifted*"},{"id":"K_Z","text":"*AltCtrlShift*"},{"id":"K_X","text":"*LAltShift*"},{"id":"K_C","text":"*RAltShift*"},{"id":"K_V","text":"*RAltShift*"},{"id":"K_B","text":"*RCtrlShift*"},{"id":"K_N","text":this._v>13?"*RTLEnter*":"*Enter*"},{"id":"K_M","text":this._v>13?"*LTREnter*":"*Enter*"},{"layer":"default","id":"K_PERIOD","text":".","sk":[{"layer":"default","id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"layer":"default","id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"layer":"default","id":"K_COLON","text":";"}]},{"id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"150","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"610","id":"K_SPACE"},{"width":"150","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"numeric","row":[{"id":"1","key":[{"id":"K_1","text":"1"},{"id":"K_2","text":"2"},{"id":"K_3","text":"3"},{"id":"K_4","text":"4"},{"id":"K_5","text":"5"},{"id":"K_6","text":"6"},{"id":"K_7","text":"7"},{"id":"K_8","text":"8"},{"id":"K_9","text":"9"},{"id":"K_0","text":"0"}]},{"id":"2","key":[{"layer":"shift","id":"K_4","pad":"50","text":"$"},{"layer":"shift","id":"K_2","text":"@"},{"layer":"shift","id":"K_3","text":"#"},{"layer":"shift","id":"K_5","text":"%"},{"layer":"shift","id":"K_7","text":"&"},{"layer":"shift","id":"K_HYPHEN","text":"_"},{"layer":"default","id":"K_EQUAL","text":"="},{"layer":"shift","id":"K_BKSLASH","text":"|"},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"id":"K_LBRKT","pad":"110","text":"[","sk":[{"id":"U_00AB","text":"\u00AB"},{"layer":"shift","id":"K_COMMA","text":"<"},{"layer":"shift","id":"K_LBRKT","text":"{"}]},{"layer":"shift","id":"K_9","text":"("},{"layer":"shift","id":"K_0","text":")"},{"id":"K_RBRKT","text":"]","sk":[{"id":"U_00BB","text":"\u00BB"},{"layer":"shift","id":"K_PERIOD","text":">"},{"layer":"shift","id":"K_RBRKT","text":"}"}]},{"layer":"shift","id":"K_EQUAL","text":"+"},{"id":"K_HYPHEN","text":"-"},{"layer":"shift","id":"K_8","text":"*"},{"id":"K_SLASH","text":"\/"},{"width":"100","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"default","width":"150","id":"K_LOWER","sp":"1","text":"*abc*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"610","id":"K_SPACE"},{"width":"150","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]}]}};this.KVER="16.0.141.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;return r;};} \ No newline at end of file +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_test9469());}function Keyboard_test9469(){this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;this.KI="Keyboard_test9469";this.KN="test9469";this.KMINVER="10.0";this.KV={F:' 1em "Arial"',K102:0};this.KV.KLS={};this.KV.BK=(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})(this.KV.KLS);this.KDU=0;this.KH='';this.KM=0;this.KBVER="1.1";this.KMBM=0x0000;this.KVKD="T_ZWNJ T_ZWNJIOS T_ZWNJANDROID";this.KVKL={"phone":{"font":"Tahoma","displayUnderlying":false,"layer":[{"id":"default","row":[{"id":"1","key":[{"id":"K_TAB","text":"*Tab*"},{"id":"T_TABLEFT","text":"*TabLeft*"},{"id":"U_0020","text":"*Sp*"},{"id":"U_00A0","text":"*NBSp*"},{"id":"U_202F","text":"*NarNBSp*"},{"id":"U_2000","text":"*EnQ*"},{"id":"U_2001","text":"*EmQ*"},{"id":"U_2002","text":"*EnSp*"},{"id":"U_2003","text":"*EmSp*"},{"id":"U_2008","text":"*PunctSp*"}]},{"id":"2","key":[{"id":"U_2009","pad":"50","text":"*ThSp*"},{"id":"U_200A","text":"*HSp*"},{"id":"U_200B","text":"*ZWSp*"},{"id":"U_200E","text":"*LTRM*"},{"id":"U_200F","text":"*RTLM*"},{"id":"U_00AD","text":"*SH*"},{"id":"T_0009","text":"*HTab*"},{"id":"U_200F","text":"*RTLM*"},{"id":"T_RTLBKSP","sp":"1","text":this._v>13?"*RTLBkSp*":"*BkSp*"},{"id":"T_new_338","sp":"1","text":this._v>13?"*LTRBkSp*":"*BkSp*"}]},{"id":"3","key":[{"nextlayer":"shift","id":"K_SHIFT","sp":"1","text":"*Shift*","sk":[{"id":"T_new_206","text":"*Alt*"},{"id":"T_new_205","text":"*Ctrl*"},{"id":"T_new_207","text":"*Caps*"},{"id":"T_new_208","text":"*ABC*"},{"id":"T_new_209","text":"*abc*"},{"id":"T_new_210","text":"*Symbol*"},{"id":"T_new_211","text":"*AltGr*"},{"id":"T_new_212","text":"*LAlt*"},{"id":"T_new_258","text":"*RAlt*"},{"id":"T_new_259","text":"*LCtrl*"},{"id":"T_new_260","text":"*RCtrl*"},{"id":"T_new_261","text":"*LAltCtrlShift*"},{"id":"T_new_262","text":"*RAltCtrlShift*"},{"id":"T_new_263","text":"*AltShift*"},{"id":"T_new_264","text":"*CtrlShift*"},{"id":"T_new_265","text":"*AltCtrlShift*"},{"id":"T_new_266","text":"*LAltShift*"},{"id":"T_new_267","text":"*RAltShift*"},{"id":"T_new_268","text":"*LCtrlShift*"},{"id":"T_new_269","text":"*RCtrlShift*"},{"id":"T_new_292","text":this._v>13?"*ShiftLock*":"*Shift*"},{"id":"T_new_293","text":this._v>13?"*ShiftedLock*":"*Shifted*"}]},{"id":"T_ZWNJ","text":"*ZWNJGeneric*"},{"id":"T_ZWNJIOS","text":this._v>13?"*ZWNJiOS*":"<|>"},{"id":"T_ZWNJANDROID","text":this._v>13?"*ZWNJAndroid*":"<|>"},{"id":"U_200D","text":"*ZWJ*"},{"id":"U_2060","text":"*WJ*"},{"id":"U_034F","text":"*CGJ*"},{"id":"K_M","text":"m"},{"id":"K_PERIOD","text":".","sk":[{"id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"id":"K_COLON","text":";"}]},{"width":"100","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"150","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"590","id":"K_SPACE"},{"id":"K_ROPT","text":"*Hide*"},{"width":"150","id":"K_ENTER","sp":"1","text":"*Enter*","sk":[{"id":"T_new_270","text":this._v>13?"*RTLEnter*":"*Enter*"},{"id":"T_new_295","text":this._v>13?"*LTREnter*":"*Enter*"}]}]}]},{"id":"shift","row":[{"id":"1","key":[{"id":"K_Q","text":"*Alt*"},{"id":"K_W","text":"*Ctrl*"},{"id":"K_E","text":"*Caps*"},{"id":"K_R","text":"*ABC*"},{"id":"K_T","text":"*abc*"},{"id":"K_Y","text":"*123*"},{"id":"K_U","text":"*Symbol*"},{"id":"K_I","text":"*Currency*"},{"id":"K_O","text":"*Shifted*"},{"id":"K_P","text":"*AltGr*"}]},{"id":"2","key":[{"id":"K_A","pad":"50","text":"*LAlt*"},{"id":"K_S","text":"*RAlt*"},{"id":"K_D","text":"*LCtrl*"},{"id":"K_F","text":"*RCtrl*"},{"id":"K_G","text":"*LAltCtrl*"},{"id":"K_H","text":"*RAltCtrl*"},{"id":"K_J","text":"*LAltCtrlShift*"},{"id":"K_K","text":"*RAltCtrlShift*"},{"id":"K_L","text":"*AltShift*"},{"id":"T_new_232","text":"*CtrlShift*"}]},{"id":"3","key":[{"nextlayer":"default","id":"K_SHIFT","sp":"2","text":"*Shifted*"},{"id":"K_Z","text":"*AltCtrlShift*"},{"id":"K_X","text":"*LAltShift*"},{"id":"K_C","text":"*RAltShift*"},{"id":"K_V","text":"*RAltShift*"},{"id":"K_B","text":"*RCtrlShift*"},{"id":"K_N","text":this._v>13?"*RTLEnter*":"*Enter*"},{"id":"K_M","text":this._v>13?"*LTREnter*":"*Enter*"},{"layer":"default","id":"K_PERIOD","text":".","sk":[{"layer":"default","id":"K_COMMA","text":","},{"layer":"shift","id":"K_1","text":"!"},{"layer":"shift","id":"K_SLASH","text":"?"},{"layer":"default","id":"K_QUOTE","text":"'"},{"layer":"shift","id":"K_QUOTE","text":"\""},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"layer":"shift","id":"K_COLON","text":":"},{"layer":"default","id":"K_COLON","text":";"}]},{"id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"numeric","width":"150","id":"K_NUMLOCK","sp":"1","text":"*123*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"610","id":"K_SPACE"},{"width":"150","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]},{"id":"numeric","row":[{"id":"1","key":[{"id":"K_1","text":"1"},{"id":"K_2","text":"2"},{"id":"K_3","text":"3"},{"id":"K_4","text":"4"},{"id":"K_5","text":"5"},{"id":"K_6","text":"6"},{"id":"K_7","text":"7"},{"id":"K_8","text":"8"},{"id":"K_9","text":"9"},{"id":"K_0","text":"0"}]},{"id":"2","key":[{"layer":"shift","id":"K_4","pad":"50","text":"$"},{"layer":"shift","id":"K_2","text":"@"},{"layer":"shift","id":"K_3","text":"#"},{"layer":"shift","id":"K_5","text":"%"},{"layer":"shift","id":"K_7","text":"&"},{"layer":"shift","id":"K_HYPHEN","text":"_"},{"layer":"default","id":"K_EQUAL","text":"="},{"layer":"shift","id":"K_BKSLASH","text":"|"},{"layer":"default","id":"K_BKSLASH","text":"\\"},{"width":"10","sp":"10"}]},{"id":"3","key":[{"id":"K_LBRKT","pad":"110","text":"[","sk":[{"id":"U_00AB","text":"\u00AB"},{"layer":"shift","id":"K_COMMA","text":"<"},{"layer":"shift","id":"K_LBRKT","text":"{"}]},{"layer":"shift","id":"K_9","text":"("},{"layer":"shift","id":"K_0","text":")"},{"id":"K_RBRKT","text":"]","sk":[{"id":"U_00BB","text":"\u00BB"},{"layer":"shift","id":"K_PERIOD","text":">"},{"layer":"shift","id":"K_RBRKT","text":"}"}]},{"layer":"shift","id":"K_EQUAL","text":"+"},{"id":"K_HYPHEN","text":"-"},{"layer":"shift","id":"K_8","text":"*"},{"id":"K_SLASH","text":"\/"},{"width":"100","id":"K_BKSP","sp":"1","text":"*BkSp*"}]},{"id":"4","key":[{"nextlayer":"default","width":"150","id":"K_LOWER","sp":"1","text":"*abc*"},{"width":"120","id":"K_LOPT","sp":"1","text":"*Menu*"},{"width":"610","id":"K_SPACE"},{"width":"150","id":"K_ENTER","sp":"1","text":"*Enter*"}]}]}]}};this.KVER="16.0.141.0";this.KVS=[];this.gs=function(t,e) {return this.g0(t,e);};this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;if(k.KKM(e,16384,256)) {if(1){r=m=1;k.KDC(0,t);k.KO(-1,t,"‌");}}else if(k.KKM(e,16384,257)) {if(1){r=m=1;k.KDC(0,t);k.KO(-1,t,"‌");}}else if(k.KKM(e,16384,258)) {if(1){r=m=1;k.KDC(0,t);k.KO(-1,t,"‌");}}return r;};} \ No newline at end of file diff --git a/web/src/test/manual/web/issue9469/test9469/source/test9469.keyman-touch-layout b/web/src/test/manual/web/issue9469/test9469/source/test9469.keyman-touch-layout index b771afc4e7d..5f8ac2101a1 100644 --- a/web/src/test/manual/web/issue9469/test9469/source/test9469.keyman-touch-layout +++ b/web/src/test/manual/web/issue9469/test9469/source/test9469.keyman-touch-layout @@ -17,36 +17,36 @@ "text": "*TabLeft*" }, { - "id": "K_E", - "text": "e" + "id": "U_0020", + "text": "*Sp*" }, { - "id": "K_R", - "text": "r" + "id": "U_00A0", + "text": "*NBSp*" }, { - "id": "K_T", - "text": "t" + "id": "U_202F", + "text": "*NarNBSp*" }, { - "id": "K_Y", - "text": "y" + "id": "U_2000", + "text": "*EnQ*" }, { - "id": "K_U", - "text": "u" + "id": "U_2001", + "text": "*EmQ*" }, { - "id": "K_I", - "text": "i" + "id": "U_2002", + "text": "*EnSp*" }, { - "id": "K_O", - "text": "o" + "id": "U_2003", + "text": "*EmSp*" }, { - "id": "K_P", - "text": "p" + "id": "U_2008", + "text": "*PunctSp*" } ] }, @@ -54,37 +54,37 @@ "id": 2, "key": [ { - "id": "K_A", - "text": "a", + "id": "U_2009", + "text": "*ThSp*", "pad": 50 }, { - "id": "K_S", - "text": "s" + "id": "U_200A", + "text": "*HSp*" }, { - "id": "K_D", - "text": "d" + "id": "U_200B", + "text": "*ZWSp*" }, { - "id": "K_F", - "text": "f" + "id": "U_200E", + "text": "*LTRM*" }, { - "id": "K_G", - "text": "g" + "id": "U_200F", + "text": "*RTLM*" }, { - "id": "K_H", - "text": "h" + "id": "U_00AD", + "text": "*SH*" }, { - "id": "K_J", - "text": "j" + "id": "T_0009", + "text": "*HTab*" }, { - "id": "K_K", - "text": "k" + "id": "U_200F", + "text": "*RTLM*" }, { "id": "T_RTLBKSP", @@ -199,7 +199,7 @@ }, { "id": "T_ZWNJ", - "text": "*ZWNJ*" + "text": "*ZWNJGeneric*" }, { "id": "T_ZWNJIOS", @@ -210,16 +210,16 @@ "text": "*ZWNJAndroid*" }, { - "id": "K_V", - "text": "v" + "id": "U_200D", + "text": "*ZWJ*" }, { - "id": "K_B", - "text": "b" + "id": "U_2060", + "text": "*WJ*" }, { - "id": "K_N", - "text": "n" + "id": "U_034F", + "text": "*CGJ*" }, { "id": "K_M", @@ -294,7 +294,7 @@ { "id": "K_SPACE", "text": "", - "width": 610, + "width": 590, "sp": 0 }, { diff --git a/web/src/test/manual/web/issue9469/test9469/source/test9469.kmn b/web/src/test/manual/web/issue9469/test9469/source/test9469.kmn index 966efcc6f9a..d0f84c749af 100644 --- a/web/src/test/manual/web/issue9469/test9469/source/test9469.kmn +++ b/web/src/test/manual/web/issue9469/test9469/source/test9469.kmn @@ -3,7 +3,7 @@ c with name "test9469" store(&VERSION) '10.0' store(&NAME) 'test9469' store(©RIGHT) '© 2023 SIL International' -store(&KEYBOARDVERSION) '1.0' +store(&KEYBOARDVERSION) '1.1' store(&TARGETS) 'any' store(&BITMAP) 'test9469.ico' store(&VISUALKEYBOARD) 'test9469.kvks' @@ -14,4 +14,7 @@ begin Unicode > use(main) group(main) using keys -c This keyboard is just to visually inspect the touch layout key caps / longpress so none of the T_new_ keys are defined +c This keyboard is just to visually inspect the touch layout key caps / longpress so nearly all of the T_new_ keys are not defined ++ [T_ZWNJ] > U+200C ++ [T_ZWNJIOS] > U+200C ++ [T_ZWNJANDROID] > U+200C diff --git a/web/src/test/manual/web/issue9469/test9469/test9469.kpj b/web/src/test/manual/web/issue9469/test9469/test9469.kpj index a1608952d87..d5530227c2f 100644 --- a/web/src/test/manual/web/issue9469/test9469/test9469.kpj +++ b/web/src/test/manual/web/issue9469/test9469/test9469.kpj @@ -12,7 +12,7 @@ id_9f818ee943306f4c53feb65bb5cadcce test9469.kmn source\test9469.kmn - 1.0 + 1.1 .kmn
test9469 diff --git a/web/tsconfig.base.json b/web/tsconfig.base.json index a2b78b7b15f..ccb568c867c 100644 --- a/web/tsconfig.base.json +++ b/web/tsconfig.base.json @@ -1,15 +1,24 @@ { - "extends": "../tsconfig-base.json", + "extends": "../tsconfig.base.json", + // TODO: eliminate settings duplicated in ../tsconfig.base.json "compilerOptions": { // Primary settings - the version of ES6 we can target in TS, our downcompile target, // and our module-related settings. "allowSyntheticDefaultImports": true, + "lib": ["es6"], "module": "es6", - "moduleResolution": "Node16", "target": "es5", + // TODO: These override ../tsconfig.base.json settings, and so should be removed if possible, + // but existing code in web/ breaks some of these settinsg + "noImplicitThis": false, + "noImplicitReturns": false, + "noImplicitAny": false, + "strictFunctionTypes": false, + "noUnusedLocals": false, + // Other settings - declaration files, sourcemapping, and other miscellaneous bits. "allowJs": false, "declaration": true, diff --git a/windows/src/Defines.mak b/windows/src/Defines.mak index bf8f77b9987..9506dfa6df0 100644 --- a/windows/src/Defines.mak +++ b/windows/src/Defines.mak @@ -322,3 +322,12 @@ SYMSTORE="C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\symstore.exe" add /compress /f CLEAN=-del /S /Q + +# +# Signature checks +# + +VERIFY_SIGNATURES_PATH=$(KEYMAN_ROOT)\common\windows\delphi\tools\verify_signatures +# Note: hyphen prefix is important to ignore return value from sigcheck +SIGCHECK=-$(VERIFY_SIGNATURES_PATH)\$(WIN32_TARGET_PATH)\sigcheck -q -s -e -v -accepteula +VERIFY_SIGNATURES=$(VERIFY_SIGNATURES_PATH)\$(WIN32_TARGET_PATH)\verify_signatures -d $(KEYMAN_ROOT)\VERSION.md diff --git a/windows/src/Makefile b/windows/src/Makefile index 7dda8852632..e9048fcf71b 100644 --- a/windows/src/Makefile +++ b/windows/src/Makefile @@ -81,7 +81,7 @@ support: global $(MAKE) $(TARGET) cd $(ROOT)\src -test: +test: .virtual cd $(ROOT)\src\test $(MAKE) $(TARGET) cd $(ROOT)\src diff --git a/windows/src/desktop/inst/download.in b/windows/src/desktop/inst/download.in index 0bf062eeba4..17b832210cc 100644 --- a/windows/src/desktop/inst/download.in +++ b/windows/src/desktop/inst/download.in @@ -17,6 +17,10 @@ copyredist-desktop: copy /Y keymandesktop.exe $(ROOT)\release\$Version\keyman-$Version.exe copy /Y $(ROOT)\bin\desktop\setup.exe $(ROOT)\release\$Version\setup.exe + $(SIGCHECK) $(ROOT)\release\$Version\* > sig1 + $(VERIFY_SIGNATURES) < sig1 + -del sig1 + # Copy the unsigned setup.exe for use in bundling scenarios; zip it up for clarity $(WZZIP) $(ROOT)\release\$Version\setup-redist.zip $(ROOT)\bin\desktop\setup-redist.exe diff --git a/windows/src/desktop/insthelp/Makefile b/windows/src/desktop/insthelp/Makefile index b3d4dcdf070..b1ca957636e 100644 --- a/windows/src/desktop/insthelp/Makefile +++ b/windows/src/desktop/insthelp/Makefile @@ -11,9 +11,9 @@ build: version.res dirs $(COPY) $(WIN32_TARGET_PATH)\insthelp.exe $(ROOT)\bin\desktop\insthelp.exe test-manifest: - # test that (a) linked manifest exists and correct, and (b) has uiAccess=true +# test that (a) linked manifest exists and correct, and (b) has uiAccess=true @rem $(MT) -nologo -inputresource:$(PROGRAM)\desktop\insthelp.exe -validate_manifest - # TODO: Investigate why no manifest included? +# TODO: Investigate why no manifest included? clean: def-clean diff --git a/windows/src/desktop/kmconfig/Makefile b/windows/src/desktop/kmconfig/Makefile index d7f308f9d65..98028758335 100644 --- a/windows/src/desktop/kmconfig/Makefile +++ b/windows/src/desktop/kmconfig/Makefile @@ -21,7 +21,7 @@ wrap-symbols: $(SYMSTORE) $(DEBUGPATH)\desktop\kmconfig.dbg /t keyman-windows test-manifest: - # test that linked manifest exists and correct +# test that linked manifest exists and correct $(MT) -nologo -inputresource:$(PROGRAM)\desktop\kmconfig.exe -validate_manifest install: diff --git a/windows/src/desktop/kmshell/Makefile b/windows/src/desktop/kmshell/Makefile index caaa7da54e0..773942d0a1b 100644 --- a/windows/src/desktop/kmshell/Makefile +++ b/windows/src/desktop/kmshell/Makefile @@ -39,7 +39,7 @@ wrap-symbols: $(SYMSTORE) $(DEBUGPATH)\desktop\kmshell.dbg /t keyman-windows test-manifest: - # test that (a) linked manifest exists and correct, and (b) has uiAccess=true +# test that (a) linked manifest exists and correct, and (b) has uiAccess=true $(MT) -nologo -inputresource:$(PROGRAM)\desktop\kmshell.exe -validate_manifest install: .virtual diff --git a/windows/src/engine/keyman32/CoreEnvironment.cpp b/windows/src/engine/keyman32/CoreEnvironment.cpp index cd0cfc13573..108de26bc09 100644 --- a/windows/src/engine/keyman32/CoreEnvironment.cpp +++ b/windows/src/engine/keyman32/CoreEnvironment.cpp @@ -2,36 +2,36 @@ #define WINDOWS_PLATFORM_ENV u"windows hardware desktop native" -BOOL SetupCoreEnvironment(km_kbp_option_item **core_environment) { - km_kbp_option_item *items = new km_kbp_option_item[6]; +BOOL SetupCoreEnvironment(km_core_option_item **core_environment) { + km_core_option_item *items = new km_core_option_item[6]; - items[0].scope = KM_KBP_OPT_ENVIRONMENT; - items[0].key = KM_KBP_KMX_ENV_BASELAYOUT; - items[0].value = reinterpret_cast(Globals::get_BaseKeyboardName()); + items[0].scope = KM_CORE_OPT_ENVIRONMENT; + items[0].key = KM_CORE_KMX_ENV_BASELAYOUT; + items[0].value = reinterpret_cast(Globals::get_BaseKeyboardName()); - items[1].scope = KM_KBP_OPT_ENVIRONMENT; - items[1].key = KM_KBP_KMX_ENV_BASELAYOUTALT; - items[1].value = reinterpret_cast(Globals::get_BaseKeyboardNameAlt()); + items[1].scope = KM_CORE_OPT_ENVIRONMENT; + items[1].key = KM_CORE_KMX_ENV_BASELAYOUTALT; + items[1].value = reinterpret_cast(Globals::get_BaseKeyboardNameAlt()); - items[2].scope = KM_KBP_OPT_ENVIRONMENT; - items[2].key = KM_KBP_KMX_ENV_SIMULATEALTGR; + items[2].scope = KM_CORE_OPT_ENVIRONMENT; + items[2].key = KM_CORE_KMX_ENV_SIMULATEALTGR; items[2].value = Globals::get_SimulateAltGr() ? u"1" : u"0"; - items[3].scope = KM_KBP_OPT_ENVIRONMENT; - items[3].key = KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT; + items[3].scope = KM_CORE_OPT_ENVIRONMENT; + items[3].key = KM_CORE_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT; items[3].value = KeyboardGivesCtrlRAltForRAlt() ? u"1" : u"0"; - items[4].scope = KM_KBP_OPT_ENVIRONMENT; - items[4].key = KM_KBP_KMX_ENV_PLATFORM; + items[4].scope = KM_CORE_OPT_ENVIRONMENT; + items[4].key = KM_CORE_KMX_ENV_PLATFORM; items[4].value = WINDOWS_PLATFORM_ENV; - items[5] = KM_KBP_OPTIONS_END; + items[5] = KM_CORE_OPTIONS_END; *core_environment = items; return TRUE; } -void DeleteCoreEnvironment(km_kbp_option_item *core_environment) { +void DeleteCoreEnvironment(km_core_option_item *core_environment) { // All keys and values are pointers to owned memory, so only need to delete // the array of options delete [] core_environment; diff --git a/windows/src/engine/keyman32/K32_load.cpp b/windows/src/engine/keyman32/K32_load.cpp index e29e504b2a1..999d8941c9c 100644 --- a/windows/src/engine/keyman32/K32_load.cpp +++ b/windows/src/engine/keyman32/K32_load.cpp @@ -79,44 +79,44 @@ BOOL LoadlpKeyboard(int i) if (_td->lpActiveKeyboard == &_td->lpKeyboards[i]) _td->lpActiveKeyboard = NULL; // I822 TSF not working if (_td->lpKeyboards[i].lpCoreKeyboardState) { - SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: a keyboard km_kbp_state exits without matching keyboard - disposing of state"); - km_kbp_state_dispose(_td->lpKeyboards[i].lpCoreKeyboardState); + SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: a keyboard km_core_state exits without matching keyboard - disposing of state"); + km_core_state_dispose(_td->lpKeyboards[i].lpCoreKeyboardState); _td->lpKeyboards[i].lpCoreKeyboardState = NULL; } char buf[256]; if (!GetKeyboardFileName(_td->lpKeyboards[i].Name, buf, 255)) return FALSE; PWCHAR keyboardPath = strtowstr(buf); - km_kbp_status err_status = km_kbp_keyboard_load(keyboardPath, &_td->lpKeyboards[i].lpCoreKeyboard); - if (err_status != KM_KBP_STATUS_OK) { - SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: km_kbp_keyboard_load failed for %ls with error status [%d]", keyboardPath, err_status); + km_core_status err_status = km_core_keyboard_load(keyboardPath, &_td->lpKeyboards[i].lpCoreKeyboard); + if (err_status != KM_CORE_STATUS_OK) { + SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: km_core_keyboard_load failed for %ls with error status [%d]", keyboardPath, err_status); delete keyboardPath; return FALSE; } delete keyboardPath; - km_kbp_option_item *core_environment = nullptr; + km_core_option_item *core_environment = nullptr; if(!SetupCoreEnvironment(&core_environment)) { SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: Unable to set environment options for keyboard %ls", keyboardPath); return FALSE; } - err_status = km_kbp_state_create(_td->lpKeyboards[i].lpCoreKeyboard, core_environment, &_td->lpKeyboards[i].lpCoreKeyboardState); + err_status = km_core_state_create(_td->lpKeyboards[i].lpCoreKeyboard, core_environment, &_td->lpKeyboards[i].lpCoreKeyboardState); DeleteCoreEnvironment(core_environment); - if (err_status != KM_KBP_STATUS_OK) { + if (err_status != KM_CORE_STATUS_OK) { SendDebugMessageFormat( - 0, sdmLoad, 0, "LoadlpKeyboard: km_kbp_state_create failed with error status [%d]", err_status); + 0, sdmLoad, 0, "LoadlpKeyboard: km_core_state_create failed with error status [%d]", err_status); // Dispose of the keyboard to leave us in a consistent state ReleaseKeyboardMemoryCore(&_td->lpKeyboards[i].lpCoreKeyboard); return FALSE; } // Register callback? - err_status = km_kbp_keyboard_get_imx_list(_td->lpKeyboards[i].lpCoreKeyboard, &_td->lpKeyboards[i].lpIMXList); - if (err_status != KM_KBP_STATUS_OK) { - SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: km_kbp_keyboard_get_imx_list failed with error status [%d]", err_status); + err_status = km_core_keyboard_get_imx_list(_td->lpKeyboards[i].lpCoreKeyboard, &_td->lpKeyboards[i].lpIMXList); + if (err_status != KM_CORE_STATUS_OK) { + SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboard: km_core_keyboard_get_imx_list failed with error status [%d]", err_status); // Dispose of the keyboard to leave us in a consistent state ReleaseKeyboardMemoryCore(&_td->lpKeyboards[i].lpCoreKeyboard); return FALSE; diff --git a/windows/src/engine/keyman32/appint/aiTIP.cpp b/windows/src/engine/keyman32/appint/aiTIP.cpp index 34f3afc867f..b6f591845b5 100644 --- a/windows/src/engine/keyman32/appint/aiTIP.cpp +++ b/windows/src/engine/keyman32/appint/aiTIP.cpp @@ -160,7 +160,7 @@ extern "C" __declspec(dllexport) BOOL WINAPI TIPProcessKey(WPARAM wParam, LPARAM DWORD LocalShiftState = Globals::get_ShiftState(); // Only the modifer flag 'f_ShiftState' is changed before sending the key stroke to the // core processor. The core processor has the keyboard Caps Lock stores and will - // queue an action 'KM_KBP_IT_CAPSLOCK'. In processing the action the Windows engine will synthesise keystrokes + // queue an action 'KM_CORE_IT_CAPSLOCK'. In processing the action the Windows engine will synthesise keystrokes // to ensure caps lock is in the correct state. if (!Preserved) { switch (wParam) { diff --git a/windows/src/engine/keyman32/appint/appint.cpp b/windows/src/engine/keyman32/appint/appint.cpp index d23c962d941..8a2b92e5aa3 100644 --- a/windows/src/engine/keyman32/appint/appint.cpp +++ b/windows/src/engine/keyman32/appint/appint.cpp @@ -227,11 +227,11 @@ AppIntegration::AppIntegration() FShiftFlags = 0; } -BOOL ContextItemsFromAppContext(WCHAR const* buf, km_kbp_context_item** outPtr) +BOOL ContextItemsFromAppContext(WCHAR const* buf, km_core_context_item** outPtr) { assert(buf); assert(outPtr); - km_kbp_context_item* context_items = new km_kbp_context_item[wcslen(buf) + 1]; + km_core_context_item* context_items = new km_core_context_item[wcslen(buf) + 1]; WCHAR const *p = buf; uint8_t contextIndex = 0; while (*p) { @@ -240,18 +240,18 @@ BOOL ContextItemsFromAppContext(WCHAR const* buf, km_kbp_context_item** outPtr) // we know the only uc_sentinel code in the context is code_deadkey, which has only 1 parameter: uc_sentinel code_deadkey // setup dead key context item p += 2; - context_items[contextIndex++] = km_kbp_context_item{ KM_KBP_CT_MARKER, {0,}, {*p} }; + context_items[contextIndex++] = km_core_context_item{ KM_CORE_CT_MARKER, {0,}, {*p} }; } else if (Uni_IsSurrogate1(*p) && Uni_IsSurrogate2(*(p + 1))) { // handle surrogate - context_items[contextIndex++] = km_kbp_context_item{ KM_KBP_CT_CHAR, {0,}, {(char32_t)Uni_SurrogateToUTF32(*p, *(p + 1))} }; + context_items[contextIndex++] = km_core_context_item{ KM_CORE_CT_CHAR, {0,}, {(char32_t)Uni_SurrogateToUTF32(*p, *(p + 1))} }; p++; } else { - context_items[contextIndex++] = km_kbp_context_item{ KM_KBP_CT_CHAR, {0,}, {*p} }; + context_items[contextIndex++] = km_core_context_item{ KM_CORE_CT_CHAR, {0,}, {*p} }; } p++; } // terminate the context_items array. - context_items[contextIndex] = km_kbp_context_item KM_KBP_CONTEXT_ITEM_END; + context_items[contextIndex] = km_core_context_item KM_CORE_CONTEXT_ITEM_END; *outPtr = context_items; return true; @@ -259,34 +259,34 @@ BOOL ContextItemsFromAppContext(WCHAR const* buf, km_kbp_context_item** outPtr) BOOL -ContextItemToAppContext(km_kbp_context_item *contextItems, PWSTR outBuf, DWORD len) { +ContextItemToAppContext(km_core_context_item *contextItems, PWSTR outBuf, DWORD len) { assert(contextItems); assert(outBuf); - km_kbp_context_item *km_kbp_context_it = contextItems; + km_core_context_item *km_core_context_it = contextItems; uint8_t contextLen = 0; - for (; km_kbp_context_it->type != KM_KBP_CT_END; ++km_kbp_context_it) { + for (; km_core_context_it->type != KM_CORE_CT_END; ++km_core_context_it) { ++contextLen; } WCHAR *buf = new WCHAR[(contextLen*3)+ 1 ]; // *3 if every context item was a deadkey uint8_t idx = 0; - km_kbp_context_it = contextItems; - for (; km_kbp_context_it->type != KM_KBP_CT_END; ++km_kbp_context_it) { - switch (km_kbp_context_it->type) { - case KM_KBP_CT_CHAR: - if (Uni_IsSMP(km_kbp_context_it->character)) { - buf[idx++] = static_cast Uni_UTF32ToSurrogate1(km_kbp_context_it->character); - buf[idx++] = static_cast Uni_UTF32ToSurrogate2(km_kbp_context_it->character); + km_core_context_it = contextItems; + for (; km_core_context_it->type != KM_CORE_CT_END; ++km_core_context_it) { + switch (km_core_context_it->type) { + case KM_CORE_CT_CHAR: + if (Uni_IsSMP(km_core_context_it->character)) { + buf[idx++] = static_cast Uni_UTF32ToSurrogate1(km_core_context_it->character); + buf[idx++] = static_cast Uni_UTF32ToSurrogate2(km_core_context_it->character); } else { - buf[idx++] = (km_kbp_cp)km_kbp_context_it->character; + buf[idx++] = (km_core_cp)km_core_context_it->character; } break; - case KM_KBP_CT_MARKER: - assert(km_kbp_context_it->marker > 0); + case KM_CORE_CT_MARKER: + assert(km_core_context_it->marker > 0); buf[idx++] = UC_SENTINEL; buf[idx++] = CODE_DEADKEY; - buf[idx++] = static_cast(km_kbp_context_it->marker); + buf[idx++] = static_cast(km_core_context_it->marker); break; } } diff --git a/windows/src/engine/keyman32/appint/appint.h b/windows/src/engine/keyman32/appint/appint.h index 6fe7ca7e201..8048c4a8a94 100644 --- a/windows/src/engine/keyman32/appint/appint.h +++ b/windows/src/engine/keyman32/appint/appint.h @@ -201,21 +201,21 @@ class AppIntegration:public AppActionQueue * @param outPtr The ouput array of context items. caller to free memory * @return BOOL True if array created successfully */ -BOOL ContextItemsFromAppContext(WCHAR const* buf, km_kbp_context_item** outPtr); +BOOL ContextItemsFromAppContext(WCHAR const* buf, km_core_context_item** outPtr); /** - * Convert km_kbp_context_item array into an kmx char buffer. + * Convert km_core_context_item array into an kmx char buffer. * Caller is responsible for freeing the memory. * The length is restricted to a maximum of MAXCONTEXT length. If the number - * of input km_kbp_context_items exceeds this length the characters furthest + * of input km_core_context_items exceeds this length the characters furthest * from the caret will be truncated. * - * @param contextItems the input core context array. (km_kbp_context_item) + * @param contextItems the input core context array. (km_core_context_item) * @param [out] outBuf the kmx character array output. caller to free memory. * * @return BOOL True if array created successfully */ -BOOL ContextItemToAppContext(km_kbp_context_item *contextItems, PWSTR outBuf, DWORD len); +BOOL ContextItemToAppContext(km_core_context_item *contextItems, PWSTR outBuf, DWORD len); extern const LPSTR ItemTypes[]; diff --git a/windows/src/engine/keyman32/calldll.cpp b/windows/src/engine/keyman32/calldll.cpp index f0c623373c2..0c1fce80b8c 100644 --- a/windows/src/engine/keyman32/calldll.cpp +++ b/windows/src/engine/keyman32/calldll.cpp @@ -93,33 +93,33 @@ static LPIMDLL AddIMDLL(LPINTKEYBOARDINFO lpkbi, LPSTR kbdpath, LPSTR dllfilenam return imd; } -static km_kbp_action_item* +static km_core_action_item* kmnToCoreActionItem(int ItemType, DWORD dwData, WORD wVkey) { - km_kbp_action_item *actionItems = new km_kbp_action_item[2]; - actionItems[0].type = KM_KBP_IT_END; - actionItems[1].type = KM_KBP_IT_END; + km_core_action_item *actionItems = new km_core_action_item[2]; + actionItems[0].type = KM_CORE_IT_END; + actionItems[1].type = KM_CORE_IT_END; switch (ItemType) { case QIT_CHAR: - actionItems[0].type = KM_KBP_IT_CHAR; + actionItems[0].type = KM_CORE_IT_CHAR; actionItems[0].character = dwData; break; case QIT_DEADKEY: - actionItems[0].type = KM_KBP_IT_MARKER; + actionItems[0].type = KM_CORE_IT_MARKER; actionItems[0].marker = dwData; break; case QIT_BELL: - actionItems[0].type = KM_KBP_IT_ALERT; + actionItems[0].type = KM_CORE_IT_ALERT; break; case QIT_BACK: switch (dwData) { case BK_DEFAULT: - actionItems[0].type = KM_KBP_IT_BACK; - actionItems[0].backspace.expected_type = KM_KBP_BT_CHAR; + actionItems[0].type = KM_CORE_IT_BACK; + actionItems[0].backspace.expected_type = KM_CORE_BT_CHAR; break; case BK_DEADKEY: - actionItems[0].type = KM_KBP_IT_BACK; - actionItems[0].backspace.expected_type = KM_KBP_BT_MARKER; + actionItems[0].type = KM_CORE_IT_BACK; + actionItems[0].backspace.expected_type = KM_CORE_BT_MARKER; break; } break; @@ -127,7 +127,7 @@ kmnToCoreActionItem(int ItemType, DWORD dwData, WORD wVkey) { case QIT_VKEYUP: if (dwData == wVkey) { SendDebugMessageFormat(0, sdmKeyboard, 0, "kmnToCoreActionItem: Emit Action:[%s] Key:[%x] ", ItemTypes[ItemType], dwData); - actionItems[0].type = KM_KBP_IT_EMIT_KEYSTROKE; + actionItems[0].type = KM_CORE_IT_EMIT_KEYSTROKE; actionItems[0].character = dwData; } else{ SendDebugMessageFormat( @@ -138,7 +138,7 @@ kmnToCoreActionItem(int ItemType, DWORD dwData, WORD wVkey) { SendDebugMessageFormat(0, sdmKeyboard, 0, "kmnToCoreActionItem: Unhandled Action: [%s] [%x] ", ItemTypes[ItemType], dwData); break; ; case QIT_INVALIDATECONTEXT: - actionItems[0].type = KM_KBP_IT_INVALIDATE_CONTEXT; + actionItems[0].type = KM_CORE_IT_INVALIDATE_CONTEXT; break; } @@ -150,40 +150,40 @@ kmnToCoreActionItem(int ItemType, DWORD dwData, WORD wVkey) { #define CONTEXT_CORE 0 #define CONTEXT_INT 1 static BOOL -LogContext(km_kbp_state *lpCoreKeyboardState, uint8_t context_type) { +LogContext(km_core_state *lpCoreKeyboardState, uint8_t context_type) { if (!lpCoreKeyboardState) { return FALSE; } - km_kbp_context_item *citems = nullptr; - km_kbp_status error_status; + km_core_context_item *citems = nullptr; + km_core_status error_status; char *log_str_title = nullptr; char* const int_context = "Intermediate Context"; char* const core_context = "Core Context"; switch(context_type){ case CONTEXT_CORE: - error_status = (km_kbp_status_codes)km_kbp_context_get(km_kbp_state_context(lpCoreKeyboardState), &citems); + error_status = (km_core_status_codes)km_core_context_get(km_core_state_context(lpCoreKeyboardState), &citems); log_str_title = int_context; break; case CONTEXT_INT: - error_status = (km_kbp_status_codes)kbp_state_get_intermediate_context(lpCoreKeyboardState, &citems); + error_status = (km_core_status_codes)kbp_state_get_intermediate_context(lpCoreKeyboardState, &citems); log_str_title = core_context; break; default: - error_status = KM_KBP_STATUS_INVALID_ARGUMENT; + error_status = KM_CORE_STATUS_INVALID_ARGUMENT; } - if (error_status != KM_KBP_STATUS_OK){ - km_kbp_context_items_dispose(citems); + if (error_status != KM_CORE_STATUS_OK){ + km_core_context_items_dispose(citems); return FALSE; } - DWORD context_length = (DWORD)km_kbp_context_item_list_size(citems); + DWORD context_length = (DWORD)km_core_context_item_list_size(citems); WCHAR *buf = new WCHAR[(context_length * 3) +1 ]; // *3 if every context item was a deadkey if (!ContextItemToAppContext(citems, buf, context_length)) { - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); delete[] buf; return FALSE; } - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); SendDebugMessageFormat(0, sdmKeyboard, 0, "%s: [%s]", log_str_title, Debug_UnicodeString(buf)); delete[] buf; return TRUE; @@ -226,7 +226,7 @@ BOOL UnloadDLLs(LPINTKEYBOARDINFO lpkbi) lpkbi->nIMDLLs = 0; if (lpkbi->lpCoreKeyboardState) { - km_kbp_state_imx_deregister_callback(lpkbi->lpCoreKeyboardState); + km_core_state_imx_deregister_callback(lpkbi->lpCoreKeyboardState); } return TRUE; } @@ -254,7 +254,7 @@ BOOL DeactivateDLLs(LPINTKEYBOARDINFO lpkbi) } // The callback function called by the Core Keyboardprocessor -extern "C" uint8_t IM_CallBackCore(km_kbp_state *km_state, uint32_t UniqueStoreNo, void *callbackObject) { +extern "C" uint8_t IM_CallBackCore(km_core_state *km_state, uint32_t UniqueStoreNo, void *callbackObject) { //SendDebugMessageFormat(0, sdmKeyboard, 0, "IM_CallBackCore: Enter"); if (callbackObject == NULL) { return FALSE; @@ -312,32 +312,32 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMSetOutput(PWSTR buf, DWORD backlen } DWORD numActions = backlen + (DWORD)wcslen(buf); DWORD idx = 0; - km_kbp_action_item *actionItems = new km_kbp_action_item[numActions + 1]; + km_core_action_item *actionItems = new km_core_action_item[numActions + 1]; // The actions sent to the core processor need to set the expected_type // correctly. To do this need to check the context as we process the // backspaces. - km_kbp_context_item *citems = nullptr; - if (KM_KBP_STATUS_OK != kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) { + km_core_context_item *citems = nullptr; + if (KM_CORE_STATUS_OK != kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) { delete[] actionItems; return FALSE; } - DWORD context_length = (DWORD)km_kbp_context_item_list_size(citems); + DWORD context_length = (DWORD)km_core_context_item_list_size(citems); WCHAR *contextString = new WCHAR[(context_length * 3) + 1]; // *3 if every context item was a deadkey if (!ContextItemToAppContext(citems, contextString, context_length)) { - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); delete[] contextString; delete[] actionItems; return FALSE; } - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); AppContext context; context.Set(contextString); delete[] contextString; while (backlen-- > 0) { - actionItems[idx].type = KM_KBP_IT_BACK; + actionItems[idx].type = KM_CORE_IT_BACK; WCHAR *CodeUnitPtr; const int DeadKeyLength = 3; const int SurrogateLength = 2; @@ -345,18 +345,18 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMSetOutput(PWSTR buf, DWORD backlen if (context.CharIsDeadkey()) { CodeUnitPtr = context.BufMax(DeadKeyLength); CodeUnitPtr += 2; - actionItems[idx].backspace.expected_type = KM_KBP_BT_MARKER; + actionItems[idx].backspace.expected_type = KM_CORE_BT_MARKER; actionItems[idx].backspace.expected_value = (uintptr_t)*CodeUnitPtr; } else if (context.CharIsSurrogatePair()) { CodeUnitPtr = context.BufMax(SurrogateLength); - actionItems[idx].backspace.expected_type = KM_KBP_BT_CHAR; + actionItems[idx].backspace.expected_type = KM_CORE_BT_CHAR; actionItems[idx].backspace.expected_value = (DWORD)Uni_SurrogateToUTF32(*CodeUnitPtr, *(CodeUnitPtr + 1)); } else if (!context.IsEmpty()) { CodeUnitPtr = context.BufMax(SingleCharLength); - actionItems[idx].backspace.expected_type = KM_KBP_BT_CHAR; + actionItems[idx].backspace.expected_type = KM_CORE_BT_CHAR; actionItems[idx].backspace.expected_value = (DWORD)*CodeUnitPtr; } else { - actionItems[idx].backspace.expected_type = KM_KBP_BT_UNKNOWN; + actionItems[idx].backspace.expected_type = KM_CORE_BT_UNKNOWN; actionItems[idx].backspace.expected_value = 0; } context.Delete(); @@ -364,7 +364,7 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMSetOutput(PWSTR buf, DWORD backlen } while (*buf) { - actionItems[idx].type = KM_KBP_IT_CHAR; + actionItems[idx].type = KM_CORE_IT_CHAR; if (Uni_IsSurrogate1(*buf) && Uni_IsSurrogate2(*(buf + 1))) { actionItems[idx].character = Uni_SurrogateToUTF32(*buf, *(buf + 1)); buf++; @@ -374,8 +374,8 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMSetOutput(PWSTR buf, DWORD backlen buf++; idx++; } - actionItems[idx].type = KM_KBP_IT_END; - if (KM_KBP_STATUS_OK != km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItems)) { + actionItems[idx].type = KM_CORE_IT_END; + if (KM_CORE_STATUS_OK != km_core_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItems)) { delete[] actionItems; return FALSE; } @@ -397,10 +397,10 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMQueueAction(int ItemType, DWORD dw return FALSE; } - km_kbp_action_item *actionItem = kmnToCoreActionItem(ItemType, dwData, _td->state.vkey); - km_kbp_status_codes error_status = - (km_kbp_status_codes)km_kbp_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItem); - if (error_status != KM_KBP_STATUS_OK) { + km_core_action_item *actionItem = kmnToCoreActionItem(ItemType, dwData, _td->state.vkey); + km_core_status_codes error_status = + (km_core_status_codes)km_core_state_queue_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, actionItem); + if (error_status != KM_CORE_STATUS_OK) { delete[] actionItem; SendDebugMessageFormat(0, sdmKeyboard, 0, "KMQueueAction: Error core queue_action_items error status:[%lu]",error_status); return FALSE; @@ -427,16 +427,16 @@ extern "C" BOOL _declspec(dllexport) WINAPI KMGetContext(PWSTR buf, DWORD len) return FALSE; } - km_kbp_context_item *citems = nullptr; - if (KM_KBP_STATUS_OK != kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) { + km_core_context_item *citems = nullptr; + if (KM_CORE_STATUS_OK != kbp_state_get_intermediate_context(_td->lpActiveKeyboard->lpCoreKeyboardState, &citems)) { return FALSE; } if (!ContextItemToAppContext(citems, buf, len)) { - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); return FALSE; } - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); //SendDebugMessageFormat(0, sdmKeyboard, 0, "KMGetContext: Exit"); return TRUE; @@ -579,7 +579,7 @@ LoadDLLs(LPINTKEYBOARDINFO lpkbi) { return FALSE; } - km_kbp_keyboard_imx *imx_list = lpkbi->lpIMXList; + km_core_keyboard_imx *imx_list = lpkbi->lpIMXList; BOOL result = false; for (; imx_list->library_name; ++imx_list) { LPIMDLL imd = AddIMDLL(lpkbi, fullname, wstrtostr(reinterpret_cast(imx_list->library_name))); @@ -594,7 +594,7 @@ LoadDLLs(LPINTKEYBOARDINFO lpkbi) { } // If result is true register a callback with the core if (result) { - km_kbp_state_imx_register_callback(lpkbi->lpCoreKeyboardState, IM_CallBackCore, (void *)lpkbi); + km_core_state_imx_register_callback(lpkbi->lpCoreKeyboardState, IM_CallBackCore, (void *)lpkbi); } //SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadDLLs: Exit"); return TRUE; diff --git a/windows/src/engine/keyman32/calldll.h b/windows/src/engine/keyman32/calldll.h index 6e719bde9ac..d5918574dcd 100644 --- a/windows/src/engine/keyman32/calldll.h +++ b/windows/src/engine/keyman32/calldll.h @@ -33,7 +33,7 @@ BOOL ActivateDLLs(LPINTKEYBOARDINFO lpkbi); BOOL IsIMWindow(HWND hwnd); // Callback function used by the core processor to call out to 3rd Party Library functions -extern "C" uint8_t IM_CallBackCore(km_kbp_state *km_state, uint32_t UniqueStoreNo, void *callbackObject); +extern "C" uint8_t IM_CallBackCore(km_core_state *km_state, uint32_t UniqueStoreNo, void *callbackObject); extern "C" BOOL _declspec(dllexport) WINAPI KMDisplayIM(HWND hwnd, BOOL FShowAlways); extern "C" BOOL _declspec(dllexport) WINAPI KMHideIM(); diff --git a/windows/src/engine/keyman32/keyboardoptions.cpp b/windows/src/engine/keyman32/keyboardoptions.cpp index 96deb57590d..cc838286254 100644 --- a/windows/src/engine/keyman32/keyboardoptions.cpp +++ b/windows/src/engine/keyman32/keyboardoptions.cpp @@ -19,18 +19,18 @@ */ #include "pch.h" -BOOL IntLoadKeyboardOptionsRegistrytoCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state* const state); +BOOL IntLoadKeyboardOptionsRegistrytoCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_core_state* const state); void IntSaveKeyboardOptionCoretoRegistry(LPCSTR REGKey, LPINTKEYBOARDINFO kp, LPCWSTR key, LPWSTR value); -static km_kbp_cp* CloneKMKBPCP(const km_kbp_cp* cp) { +static km_core_cp* CloneKMKBPCP(const km_core_cp* cp) { LPCWSTR buf = reinterpret_cast(cp); - km_kbp_cp* clone = new km_kbp_cp[wcslen(buf) + 1]; + km_core_cp* clone = new km_core_cp[wcslen(buf) + 1]; wcscpy_s(reinterpret_cast(clone), wcslen(buf) + 1, buf); return clone; } -static km_kbp_cp* CloneKMKBPCPFromWSTR(LPWSTR buf) { - km_kbp_cp* clone = new km_kbp_cp[wcslen(buf) + 1]; +static km_core_cp* CloneKMKBPCPFromWSTR(LPWSTR buf) { + km_core_cp* clone = new km_core_cp[wcslen(buf) + 1]; wcscpy_s(reinterpret_cast(clone), wcslen(buf) + 1, buf); return clone; } @@ -54,38 +54,38 @@ void IntSaveKeyboardOptionCoretoRegistry(LPCSTR REGKey, LPINTKEYBOARDINFO kp, LP } } -void LoadKeyboardOptionsRegistrytoCore(LPINTKEYBOARDINFO kp, km_kbp_state* const state) +void LoadKeyboardOptionsRegistrytoCore(LPINTKEYBOARDINFO kp, km_core_state* const state) { SendDebugMessageFormat(0, sdmKeyboard, 0, "LoadKeyboardOptionsRegistrytoCore: Enter"); IntLoadKeyboardOptionsRegistrytoCore(REGSZ_KeyboardOptions, kp, state); } -BOOL IntLoadKeyboardOptionsRegistrytoCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_kbp_state* const state) +BOOL IntLoadKeyboardOptionsRegistrytoCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_core_state* const state) { assert(key != NULL); assert(kp != NULL); // Get the list of default options to determine size of list - const km_kbp_keyboard_attrs* keyboardAttrs; - km_kbp_status err_status = km_kbp_keyboard_get_attrs(kp->lpCoreKeyboard, &keyboardAttrs); - if (err_status != KM_KBP_STATUS_OK) { + const km_core_keyboard_attrs* keyboardAttrs; + km_core_status err_status = km_core_keyboard_get_attrs(kp->lpCoreKeyboard, &keyboardAttrs); + if (err_status != KM_CORE_STATUS_OK) { SendDebugMessageFormat( - 0, sdmKeyboard, 0, "LoadKeyboardOptionsRegistrytoCore: km_kbp_keyboard_get_attrs failed with error status [%d]", err_status); + 0, sdmKeyboard, 0, "LoadKeyboardOptionsRegistrytoCore: km_core_keyboard_get_attrs failed with error status [%d]", err_status); return FALSE; } - size_t listSize = km_kbp_options_list_size(keyboardAttrs->default_options); + size_t listSize = km_core_options_list_size(keyboardAttrs->default_options); if (listSize == 0){ return TRUE; } - km_kbp_option_item* keyboardOpts = new km_kbp_option_item[listSize + 1]; + km_core_option_item* keyboardOpts = new km_core_option_item[listSize + 1]; RegistryReadOnly r(HKEY_CURRENT_USER); BOOL hasData = r.OpenKeyReadOnly(REGSZ_KeymanActiveKeyboards) && r.OpenKeyReadOnly(kp->Name) && r.OpenKeyReadOnly(key); int n = 0; for (auto kpc = keyboardAttrs->default_options; kpc->key; kpc++) { - keyboardOpts[n].scope = KM_KBP_OPT_KEYBOARD; + keyboardOpts[n].scope = KM_CORE_OPT_KEYBOARD; keyboardOpts[n].key = kpc->key; LPCWSTR coreKey = reinterpret_cast(kpc->key); WCHAR val[256]; @@ -96,13 +96,13 @@ BOOL IntLoadKeyboardOptionsRegistrytoCore(LPCSTR key, LPINTKEYBOARDINFO kp, km_k } n++; } - keyboardOpts[n] = KM_KBP_OPTIONS_END; + keyboardOpts[n] = KM_CORE_OPTIONS_END; // once we have the option list we can then update the options using the public api call - err_status = km_kbp_state_options_update(state, keyboardOpts); - if (err_status != KM_KBP_STATUS_OK) { + err_status = km_core_state_options_update(state, keyboardOpts); + if (err_status != KM_CORE_STATUS_OK) { SendDebugMessageFormat( - 0, sdmKeyboard, 0, "LoadKeyboardOptionsRegistrytoCore: km_kbp_state_options_update failed with error status [%d]", err_status); + 0, sdmKeyboard, 0, "LoadKeyboardOptionsRegistrytoCore: km_core_state_options_update failed with error status [%d]", err_status); } for (int i = 0; i < n; i++) { delete[] keyboardOpts[i].value; diff --git a/windows/src/engine/keyman32/keyboardoptions.h b/windows/src/engine/keyman32/keyboardoptions.h index f55b0bcc77d..919b0bb71fa 100644 --- a/windows/src/engine/keyman32/keyboardoptions.h +++ b/windows/src/engine/keyman32/keyboardoptions.h @@ -24,7 +24,7 @@ * @param kp keyboard info object with options to be updated * @param state core keyboard state used to update keyboard options */ -void LoadKeyboardOptionsRegistrytoCore(LPINTKEYBOARDINFO kp, km_kbp_state* state); +void LoadKeyboardOptionsRegistrytoCore(LPINTKEYBOARDINFO kp, km_core_state* state); /** * Saves the keyboard option to the windows registry diff --git a/windows/src/engine/keyman32/keyman32.cpp b/windows/src/engine/keyman32/keyman32.cpp index 86eda219a23..5dfdaab0793 100644 --- a/windows/src/engine/keyman32/keyman32.cpp +++ b/windows/src/engine/keyman32/keyman32.cpp @@ -565,17 +565,17 @@ BOOL ReleaseKeyboardMemory(LPKEYBOARD kbd) return TRUE; } -BOOL ReleaseStateMemoryCore(km_kbp_state **state) { +BOOL ReleaseStateMemoryCore(km_core_state **state) { if (!*state) return TRUE; - km_kbp_state_dispose(*state); + km_core_state_dispose(*state); *state = NULL; return TRUE; } -BOOL ReleaseKeyboardMemoryCore(km_kbp_keyboard **kbd) { +BOOL ReleaseKeyboardMemoryCore(km_core_keyboard **kbd) { if (!*kbd) return TRUE; - km_kbp_keyboard_dispose(*kbd); + km_core_keyboard_dispose(*kbd); *kbd = NULL; return TRUE; } diff --git a/windows/src/engine/keyman32/keymanengine.h b/windows/src/engine/keyman32/keymanengine.h index f40aeaf3728..65fc9ec1e58 100644 --- a/windows/src/engine/keyman32/keymanengine.h +++ b/windows/src/engine/keyman32/keymanengine.h @@ -18,11 +18,11 @@ #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT 1 #endif -// For keyboardprocessor_bits.h +// For keyman_core_api_bits.h #ifndef KMN_KBP_STATIC #define KMN_KBP_STATIC #endif -// For keyboardprocessor_bits.h +// For keyman_core_api_bits.h #ifndef _WIN32 #define _WIN32 1 #endif @@ -39,8 +39,8 @@ #include #include #include "../../../../common/windows/cpp/include/legacy_kmx_file.h" -#include -#include +#include +#include /***************************************************************************/ @@ -86,10 +86,10 @@ typedef struct tagINTKEYBOARDINFO int __filler2; // makes same as KEYBOARDINFO int nProfiles; LPINTKEYBOARDPROFILE Profiles; - km_kbp_keyboard* lpCoreKeyboard; - km_kbp_option_item* lpCoreKeyboardOptions; - km_kbp_state* lpCoreKeyboardState; - km_kbp_keyboard_imx* lpIMXList; + km_core_keyboard* lpCoreKeyboard; + km_core_option_item* lpCoreKeyboardOptions; + km_core_state* lpCoreKeyboardState; + km_core_keyboard_imx* lpIMXList; } INTKEYBOARDINFO, * LPINTKEYBOARDINFO; typedef struct tagINI @@ -107,7 +107,7 @@ typedef struct tagKMSTATE WCHAR charCode; // I4582 BOOL windowunicode; // I4287 BOOL isDown; - km_kbp_keyboard* lpCoreKb; // future use with IMDLL + km_core_keyboard* lpCoreKb; // future use with IMDLL } KMSTATE; // I3616 @@ -121,8 +121,8 @@ LRESULT CALLBACK kmnLowLevelKeyboardProc( // I4124 _In_ LPARAM lParam ); -BOOL ReleaseStateMemoryCore(km_kbp_state** state); -BOOL ReleaseKeyboardMemoryCore(km_kbp_keyboard** kbd); +BOOL ReleaseStateMemoryCore(km_core_state** state); +BOOL ReleaseKeyboardMemoryCore(km_core_keyboard** kbd); void PostGETNEXT(HWND hwnd); BOOL CompareMsg(LPMSG MsgA, LPMSG MsgB); @@ -264,7 +264,7 @@ BOOL SelectKeyboardTSF(DWORD KeymanID, BOOL foreground); // I3933 // I3949 BOOL ReportKeyboardChanged(WORD wCommand, DWORD dwProfileType, UINT langid, HKL hkl, GUID clsid, GUID guidProfile); void ProcessModifierChange(UINT key, BOOL isUp, BOOL isExtended); // I4793 -BOOL SetupCoreEnvironment(km_kbp_option_item **test_env_opts); -void DeleteCoreEnvironment(km_kbp_option_item *test_env_opts); +BOOL SetupCoreEnvironment(km_core_option_item **test_env_opts); +void DeleteCoreEnvironment(km_core_option_item *test_env_opts); #endif // _KEYMANENGINE_H diff --git a/windows/src/engine/keyman32/kmhook_getmessage.cpp b/windows/src/engine/keyman32/kmhook_getmessage.cpp index 562c455abb3..e129a0b8da3 100644 --- a/windows/src/engine/keyman32/kmhook_getmessage.cpp +++ b/windows/src/engine/keyman32/kmhook_getmessage.cpp @@ -287,7 +287,7 @@ LRESULT _kmnGetMessageProc(int nCode, WPARAM wParam, LPARAM lParam) if (!_td->lpActiveKeyboard) { return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam); } - if (KM_KBP_STATUS_OK != km_kbp_process_queued_actions(_td->lpActiveKeyboard->lpCoreKeyboardState)) { + if (KM_CORE_STATUS_OK != km_core_process_queued_actions(_td->lpActiveKeyboard->lpCoreKeyboardState)) { SendDebugMessageFormat(0, sdmGlobal, 0, "_kmnGetMessageProc wm_keymanim_close process event fail"); return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam); } diff --git a/windows/src/engine/keyman32/kmprocess.cpp b/windows/src/engine/keyman32/kmprocess.cpp index 64a6a48e98d..5772836de2a 100644 --- a/windows/src/engine/keyman32/kmprocess.cpp +++ b/windows/src/engine/keyman32/kmprocess.cpp @@ -99,20 +99,20 @@ char *getcontext_debug() { static BOOL Process_Event_Core(PKEYMAN64THREADDATA _td) { PWSTR contextBuf = _td->app->ContextBufMax(MAXCONTEXT); - km_kbp_context_item *citems = nullptr; + km_core_context_item *citems = nullptr; ContextItemsFromAppContext(contextBuf, &citems); - if (KM_KBP_STATUS_OK != km_kbp_context_set(km_kbp_state_context(_td->lpActiveKeyboard->lpCoreKeyboardState), citems)) { - km_kbp_context_items_dispose(citems); + if (KM_CORE_STATUS_OK != km_core_context_set(km_core_state_context(_td->lpActiveKeyboard->lpCoreKeyboardState), citems)) { + km_core_context_items_dispose(citems); return FALSE; } - km_kbp_context_items_dispose(citems); + km_core_context_items_dispose(citems); SendDebugMessageFormat( 0, sdmGlobal, 0, "ProcessEvent: vkey[%d] ShiftState[%d] isDown[%d]", _td->state.vkey, - static_cast(Globals::get_ShiftState() & (KM_KBP_MODIFIER_MASK_ALL | KM_KBP_MODIFIER_MASK_CAPS)), (uint8_t)_td->state.isDown); - // Mask the bits supported according to `km_kbp_modifier_state` enum, update the mask if this enum is expanded. - if (KM_KBP_STATUS_OK != km_kbp_process_event( + static_cast(Globals::get_ShiftState() & (KM_CORE_MODIFIER_MASK_ALL | KM_CORE_MODIFIER_MASK_CAPS)), (uint8_t)_td->state.isDown); + // Mask the bits supported according to `km_core_modifier_state` enum, update the mask if this enum is expanded. + if (KM_CORE_STATUS_OK != km_core_process_event( _td->lpActiveKeyboard->lpCoreKeyboardState, _td->state.vkey, - static_cast(Globals::get_ShiftState() & (KM_KBP_MODIFIER_MASK_ALL | KM_KBP_MODIFIER_MASK_CAPS)), (uint8_t)_td->state.isDown, KM_KBP_EVENT_FLAG_DEFAULT)) { + static_cast(Globals::get_ShiftState() & (KM_CORE_MODIFIER_MASK_ALL | KM_CORE_MODIFIER_MASK_CAPS)), (uint8_t)_td->state.isDown, KM_CORE_EVENT_FLAG_DEFAULT)) { SendDebugMessageFormat(0, sdmGlobal, 0, "ProcessEvent CoreProcessEvent Result:False %d ", FALSE); return FALSE; } diff --git a/windows/src/engine/keyman32/kmprocessactions.cpp b/windows/src/engine/keyman32/kmprocessactions.cpp index 33df6d96ea5..c9d607a596c 100644 --- a/windows/src/engine/keyman32/kmprocessactions.cpp +++ b/windows/src/engine/keyman32/kmprocessactions.cpp @@ -6,7 +6,7 @@ */ #include "pch.h" -static BOOL processUnicodeChar(AITIP* app, const km_kbp_action_item* actionItem) { +static BOOL processUnicodeChar(AITIP* app, const km_core_action_item* actionItem) { if (Uni_IsSMP(actionItem->character)) { app->QueueAction(QIT_CHAR, (Uni_UTF32ToSurrogate1(actionItem->character))); app->QueueAction(QIT_CHAR, (Uni_UTF32ToSurrogate2(actionItem->character))); @@ -17,7 +17,7 @@ static BOOL processUnicodeChar(AITIP* app, const km_kbp_action_item* actionItem) return TRUE; } -static BOOL processMarker(AITIP* app, const km_kbp_action_item* actionItem) { +static BOOL processMarker(AITIP* app, const km_core_action_item* actionItem) { app->QueueAction(QIT_DEADKEY, (DWORD)actionItem->marker); return TRUE; } @@ -27,10 +27,10 @@ static BOOL processAlert(AITIP* app) { return TRUE; } -static BOOL processBack(AITIP* app, const km_kbp_action_item* actionItem) { - if (actionItem->backspace.expected_type == KM_KBP_BT_MARKER) { +static BOOL processBack(AITIP* app, const km_core_action_item* actionItem) { + if (actionItem->backspace.expected_type == KM_CORE_BT_MARKER) { app->QueueAction(QIT_BACK, BK_DEADKEY); - } else if(actionItem->backspace.expected_type == KM_KBP_BT_CHAR) { + } else if(actionItem->backspace.expected_type == KM_CORE_BT_CHAR) { // If this is a TSF-aware app we need to set the BK_SURROGATE flag to delete // both parts of the surrogate pair. Legacy apps receive a BKSP WM_KEYDOWN event // which results in deleting both parts in one action. @@ -39,27 +39,27 @@ static BOOL processBack(AITIP* app, const km_kbp_action_item* actionItem) { } else { app->QueueAction(QIT_BACK, BK_DEFAULT); } - } else { // KM_KBP_BT_UNKNOWN + } else { // KM_CORE_BT_UNKNOWN app->QueueAction(QIT_BACK, BK_DEFAULT); } return TRUE; } static BOOL processPersistOpt( - const km_kbp_action_item* actionItem, - km_kbp_state* keyboardState, + const km_core_action_item* actionItem, + km_core_state* keyboardState, LPINTKEYBOARDINFO activeKeyboard ) { if (actionItem->option != NULL) { - // Allocate for 1 option plus 1 pad struct of 0's for KM_KBP_IT_END - km_kbp_option_item keyboardOpts[2] = { 0 }; + // Allocate for 1 option plus 1 pad struct of 0's for KM_CORE_IT_END + km_core_option_item keyboardOpts[2] = { 0 }; keyboardOpts[0].key = actionItem->option->key; keyboardOpts[0].value = actionItem->option->value; - km_kbp_status eventStatus = (km_kbp_status_codes)km_kbp_state_options_update(keyboardState, keyboardOpts); - if (eventStatus != KM_KBP_STATUS_OK) + km_core_status eventStatus = (km_core_status_codes)km_core_state_options_update(keyboardState, keyboardOpts); + if (eventStatus != KM_CORE_STATUS_OK) { - // log warning "problem saving option for km_kbp_keyboard"); + // log warning "problem saving option for km_core_keyboard"); SendDebugMessageFormat(0, sdmGlobal, 0, "ProcessHook: Error %d saving option for keyboard [%s].", eventStatus, activeKeyboard->Name); } @@ -79,15 +79,15 @@ static BOOL processPersistOpt( static BOOL processInvalidateContext( AITIP* app, - km_kbp_state* keyboardState + km_core_state* keyboardState ) { - km_kbp_context_clear(km_kbp_state_context(keyboardState)); + km_core_context_clear(km_core_state_context(keyboardState)); app->ResetContext(); return TRUE; } static BOOL -processCapsLock(const km_kbp_action_item* actionItem, BOOL isUp, BOOL Updateable, BOOL externalEvent) { +processCapsLock(const km_core_action_item* actionItem, BOOL isUp, BOOL Updateable, BOOL externalEvent) { // We only want to process the Caps Lock key event once -- // in the first pass (!Updateable). @@ -134,36 +134,36 @@ BOOL ProcessActions(BOOL* emitKeyStroke) // Process the action items from the core. This actions will modify the windows context (AppContext). // Therefore it is not required to copy the context from the core to the windows context. - for (auto act = km_kbp_state_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, nullptr); act->type != KM_KBP_IT_END; act++) { + for (auto act = km_core_state_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, nullptr); act->type != KM_CORE_IT_END; act++) { BOOL continueProcessingActions = TRUE; SendDebugMessageFormat(0, sdmGlobal, 0, "ProcessActions : act->type=%d", act->type); switch (act->type) { - case KM_KBP_IT_CHAR: + case KM_CORE_IT_CHAR: continueProcessingActions = processUnicodeChar(_td->app, act); break; - case KM_KBP_IT_MARKER: + case KM_CORE_IT_MARKER: continueProcessingActions = processMarker(_td->app, act); break; - case KM_KBP_IT_ALERT: + case KM_CORE_IT_ALERT: continueProcessingActions = processAlert(_td->app); break; - case KM_KBP_IT_BACK: + case KM_CORE_IT_BACK: continueProcessingActions = processBack(_td->app, act); break; - case KM_KBP_IT_PERSIST_OPT: + case KM_CORE_IT_PERSIST_OPT: continueProcessingActions = processPersistOpt(act, _td->lpActiveKeyboard->lpCoreKeyboardState, _td->lpActiveKeyboard); break; - case KM_KBP_IT_EMIT_KEYSTROKE: + case KM_CORE_IT_EMIT_KEYSTROKE: *emitKeyStroke = TRUE; continueProcessingActions = TRUE; break; - case KM_KBP_IT_INVALIDATE_CONTEXT: + case KM_CORE_IT_INVALIDATE_CONTEXT: continueProcessingActions = processInvalidateContext(_td->app, _td->lpActiveKeyboard->lpCoreKeyboardState); break; - case KM_KBP_IT_CAPSLOCK: + case KM_CORE_IT_CAPSLOCK: continueProcessingActions = processCapsLock(act, !_td->state.isDown, _td->TIPFUpdateable, FALSE); break; - case KM_KBP_IT_END: + case KM_CORE_IT_END: // fallthrough default: assert(false); // NOT SUPPORTED @@ -190,18 +190,18 @@ ProcessActionsNonUpdatableParse(BOOL* emitKeyStroke) { _td->CoreProcessEventRun = TRUE; BOOL continueProcessingActions = TRUE; - for (auto act = km_kbp_state_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, nullptr); act->type != KM_KBP_IT_END; act++) { + for (auto act = km_core_state_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, nullptr); act->type != KM_CORE_IT_END; act++) { switch (act->type) { - case KM_KBP_IT_EMIT_KEYSTROKE: + case KM_CORE_IT_EMIT_KEYSTROKE: *emitKeyStroke = TRUE; SendDebugMessageFormat(0, sdmGlobal, 0, "ProcessActionsNonUpdatableParse EMIT_KEYSTROKE: act->type=[%d]", act->type); continueProcessingActions = TRUE; _td->CoreProcessEventRun = FALSE; // If we emit the key stroke on this parse we don't need the second parse break; - case KM_KBP_IT_CAPSLOCK: + case KM_CORE_IT_CAPSLOCK: continueProcessingActions = processCapsLock(act, !_td->state.isDown, _td->TIPFUpdateable, FALSE); break; - case KM_KBP_IT_INVALIDATE_CONTEXT: + case KM_CORE_IT_INVALIDATE_CONTEXT: continueProcessingActions = processInvalidateContext(_td->app, _td->lpActiveKeyboard->lpCoreKeyboardState); break; } @@ -221,13 +221,13 @@ ProcessActionsExternalEvent() { // Currently only a subset of actions are handled. // Other actions will be added when needed. BOOL continueProcessingActions = TRUE; - for (auto act = km_kbp_state_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, nullptr); act->type != KM_KBP_IT_END; + for (auto act = km_core_state_action_items(_td->lpActiveKeyboard->lpCoreKeyboardState, nullptr); act->type != KM_CORE_IT_END; act++) { switch (act->type) { - case KM_KBP_IT_CAPSLOCK: + case KM_CORE_IT_CAPSLOCK: continueProcessingActions = processCapsLock(act, !_td->state.isDown, FALSE, TRUE); break; - case KM_KBP_IT_INVALIDATE_CONTEXT: + case KM_CORE_IT_INVALIDATE_CONTEXT: continueProcessingActions = processInvalidateContext(_td->app, _td->lpActiveKeyboard->lpCoreKeyboardState); break; } diff --git a/windows/src/engine/keyman32/kmprocessactions.h b/windows/src/engine/keyman32/kmprocessactions.h index ceac83ba77e..66bb70570c2 100644 --- a/windows/src/engine/keyman32/kmprocessactions.h +++ b/windows/src/engine/keyman32/kmprocessactions.h @@ -30,7 +30,7 @@ BOOL ProcessActionsNonUpdatableParse(BOOL* emitKeyStroke); * This function processes the actions queued in the core processor in * the external event case. That is actions not caused by a keystroke but from selecting a * different keyboard for example. - * Currently only KM_KBP_IT_CAPSLOCK and KM_KBP_IT_INVALIDATE_CONTEXT are processed. + * Currently only KM_CORE_IT_CAPSLOCK and KM_CORE_IT_INVALIDATE_CONTEXT are processed. * * @return BOOL TRUE if actions were successfully processed */ diff --git a/windows/src/engine/keyman32/preservedkeymap.cpp b/windows/src/engine/keyman32/preservedkeymap.cpp index 1fd803838d7..6170d40bda7 100644 --- a/windows/src/engine/keyman32/preservedkeymap.cpp +++ b/windows/src/engine/keyman32/preservedkeymap.cpp @@ -49,13 +49,13 @@ class PreservedKeyMap * @param cPreservedKeys number of preserved keys in pPreservedKeys - or the size pPreservedKeys needs to be * @return BOOL return TRUE on success */ - BOOL MapKeyboard(km_kbp_keyboard *pKeyboard, PreservedKey **pPreservedKeys, size_t *cPreservedKeys); + BOOL MapKeyboard(km_core_keyboard *pKeyboard, PreservedKey **pPreservedKeys, size_t *cPreservedKeys); private: BOOL m_BaseKeyboardUsesAltGr; // I4592 UINT ShiftToTSFShift(UINT ShiftFlags); BOOL MapUSCharToVK(UINT *puKey, UINT *puShiftFlags); - BOOL MapKeyRule(km_kbp_keyboard_key *pKeyRule, TF_PRESERVEDKEY *pPreservedKey); + BOOL MapKeyRule(km_core_keyboard_key *pKeyRule, TF_PRESERVEDKEY *pPreservedKey); BOOL IsMatchingKey(PreservedKey *pKey, PreservedKey *pKeys, size_t cKeys); }; @@ -198,7 +198,7 @@ UINT PreservedKeyMap::ShiftToTSFShift(UINT ShiftFlags) } BOOL -PreservedKeyMap::MapKeyRule(km_kbp_keyboard_key *pKeyRule, TF_PRESERVEDKEY *pPreservedKey) { +PreservedKeyMap::MapKeyRule(km_core_keyboard_key *pKeyRule, TF_PRESERVEDKEY *pPreservedKey) { UINT ShiftFlags; UINT Key; @@ -242,7 +242,7 @@ BOOL PreservedKeyMap::IsMatchingKey(PreservedKey *pKey, PreservedKey *pKeys, siz } BOOL -PreservedKeyMap::MapKeyboard(km_kbp_keyboard *pKeyboard, PreservedKey **pPreservedKeys, size_t *cPreservedKeys) { +PreservedKeyMap::MapKeyboard(km_core_keyboard *pKeyboard, PreservedKey **pPreservedKeys, size_t *cPreservedKeys) { size_t cKeys = 0, cRules = 0, n = 0; DWORD i; @@ -259,20 +259,20 @@ PreservedKeyMap::MapKeyboard(km_kbp_keyboard *pKeyboard, PreservedKey **pPreserv const UINT RALT_MATCHING_MASK = TF_MOD_CONTROL | TF_MOD_ALT | TF_MOD_LCONTROL | TF_MOD_RCONTROL | TF_MOD_LALT | TF_MOD_RALT; // This is where we will call down to the api to get list of keys used in the keyboard rules - km_kbp_keyboard_key *kb_key_list; + km_core_keyboard_key *kb_key_list; - km_kbp_status err_status = km_kbp_keyboard_get_key_list(pKeyboard, &kb_key_list); - if ((err_status != KM_KBP_STATUS_OK) || (kb_key_list ==nullptr)) { + km_core_status err_status = km_core_keyboard_get_key_list(pKeyboard, &kb_key_list); + if ((err_status != KM_CORE_STATUS_OK) || (kb_key_list ==nullptr)) { return FALSE; } - km_kbp_keyboard_key *key_rule_it = kb_key_list; + km_core_keyboard_key *key_rule_it = kb_key_list; for (; key_rule_it->key; ++key_rule_it) { ++cRules; } cKeys = cRules; if (cKeys == 0) { - km_kbp_keyboard_key_list_dispose(kb_key_list); + km_core_keyboard_key_list_dispose(kb_key_list); return FALSE; } @@ -283,12 +283,12 @@ PreservedKeyMap::MapKeyboard(km_kbp_keyboard *pKeyboard, PreservedKey **pPreserv if (pPreservedKeys == NULL) { *cPreservedKeys = cKeys; - km_kbp_keyboard_key_list_dispose(kb_key_list); + km_core_keyboard_key_list_dispose(kb_key_list); return TRUE; } if (*cPreservedKeys < cKeys) { - km_kbp_keyboard_key_list_dispose(kb_key_list); + km_core_keyboard_key_list_dispose(kb_key_list); return FALSE; } @@ -315,7 +315,7 @@ PreservedKeyMap::MapKeyboard(km_kbp_keyboard *pKeyboard, PreservedKey **pPreserv } } - km_kbp_keyboard_key_list_dispose(kb_key_list); + km_core_keyboard_key_list_dispose(kb_key_list); *cPreservedKeys = n; // return actual count of allocated keys, usually smaller than allocated count return TRUE; diff --git a/windows/src/engine/keyman32/selectkeyboard.cpp b/windows/src/engine/keyman32/selectkeyboard.cpp index bfa08cea034..61222856d40 100644 --- a/windows/src/engine/keyman32/selectkeyboard.cpp +++ b/windows/src/engine/keyman32/selectkeyboard.cpp @@ -102,9 +102,9 @@ BOOL SelectKeyboard(DWORD KeymanID) ActivateDLLs(_td->lpActiveKeyboard); - if (KM_KBP_STATUS_OK != - km_kbp_event(_td->lpActiveKeyboard->lpCoreKeyboardState, KM_KBP_EVENT_KEYBOARD_ACTIVATED, nullptr)) { - SendDebugMessageFormat(0, sdmGlobal, 0, "km_kbp_event Failed Result: %d ", FALSE); + if (KM_CORE_STATUS_OK != + km_core_event(_td->lpActiveKeyboard->lpCoreKeyboardState, KM_CORE_EVENT_KEYBOARD_ACTIVATED, nullptr)) { + SendDebugMessageFormat(0, sdmGlobal, 0, "km_core_event Failed Result: %d ", FALSE); } else { ProcessActionsExternalEvent(); } diff --git a/windows/src/engine/keyman32/tests/keyman-engine-tests/keyboardoptionstests.cpp b/windows/src/engine/keyman32/tests/keyman-engine-tests/keyboardoptionstests.cpp index 795f89fe447..308f86d0fa6 100644 --- a/windows/src/engine/keyman32/tests/keyman-engine-tests/keyboardoptionstests.cpp +++ b/windows/src/engine/keyman32/tests/keyman-engine-tests/keyboardoptionstests.cpp @@ -6,44 +6,44 @@ #include -// Test SetupCoreEnvironment and also test km_kbp_state_options_update +// Test SetupCoreEnvironment and also test km_core_state_options_update TEST(KEYBOARDOPTIONS, SetupCoreEnvironment) { LPINTKEYBOARDINFO kp = new INTKEYBOARDINFO; memset(kp, 0, sizeof(INTKEYBOARDINFO)); - km_kbp_option_item *core_env_opts = nullptr; + km_core_option_item *core_env_opts = nullptr; - km_kbp_path_name dummyPath = L"dummyActions.mock"; + km_core_path_name dummyPath = L"dummyActions.mock"; EXPECT_EQ(SetupCoreEnvironment(&core_env_opts), TRUE); - EXPECT_EQ(km_kbp_keyboard_load(dummyPath, &kp->lpCoreKeyboard), KM_KBP_STATUS_OK); - EXPECT_EQ(km_kbp_state_create(kp->lpCoreKeyboard, core_env_opts, &kp->lpCoreKeyboardState), KM_KBP_STATUS_OK); + EXPECT_EQ(km_core_keyboard_load(dummyPath, &kp->lpCoreKeyboard), KM_CORE_STATUS_OK); + EXPECT_EQ(km_core_state_create(kp->lpCoreKeyboard, core_env_opts, &kp->lpCoreKeyboardState), KM_CORE_STATUS_OK); - km_kbp_option_item *expected_items = new km_kbp_option_item[5]; + km_core_option_item *expected_items = new km_core_option_item[5]; // These are taken from SetupCoreEnvironment in CoreEnvironment.cpp - expected_items[0].scope = KM_KBP_OPT_ENVIRONMENT; - expected_items[0].key = KM_KBP_KMX_ENV_BASELAYOUT; - expected_items[0].value = reinterpret_cast(Globals::get_BaseKeyboardName()); + expected_items[0].scope = KM_CORE_OPT_ENVIRONMENT; + expected_items[0].key = KM_CORE_KMX_ENV_BASELAYOUT; + expected_items[0].value = reinterpret_cast(Globals::get_BaseKeyboardName()); - expected_items[1].scope = KM_KBP_OPT_ENVIRONMENT; - expected_items[1].key = KM_KBP_KMX_ENV_BASELAYOUTALT; - expected_items[1].value = reinterpret_cast(Globals::get_BaseKeyboardNameAlt()); + expected_items[1].scope = KM_CORE_OPT_ENVIRONMENT; + expected_items[1].key = KM_CORE_KMX_ENV_BASELAYOUTALT; + expected_items[1].value = reinterpret_cast(Globals::get_BaseKeyboardNameAlt()); - expected_items[2].scope = KM_KBP_OPT_ENVIRONMENT; - expected_items[2].key = KM_KBP_KMX_ENV_SIMULATEALTGR; + expected_items[2].scope = KM_CORE_OPT_ENVIRONMENT; + expected_items[2].key = KM_CORE_KMX_ENV_SIMULATEALTGR; expected_items[2].value = Globals::get_SimulateAltGr() ? u"1" : u"0"; - expected_items[3].scope = KM_KBP_OPT_ENVIRONMENT; - expected_items[3].key = KM_KBP_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT; + expected_items[3].scope = KM_CORE_OPT_ENVIRONMENT; + expected_items[3].key = KM_CORE_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT; expected_items[3].value = KeyboardGivesCtrlRAltForRAlt() ? u"1" : u"0"; - expected_items[4] = KM_KBP_OPTIONS_END; - km_kbp_cp const* retValue = nullptr; + expected_items[4] = KM_CORE_OPTIONS_END; + km_core_cp const* retValue = nullptr; std::u16string value = u""; std::u16string expectedValue = u""; for (int i = 0; i < 4; ++i) { - EXPECT_EQ(km_kbp_state_option_lookup(kp->lpCoreKeyboardState, KM_KBP_OPT_ENVIRONMENT, expected_items[i].key, &retValue), KM_KBP_STATUS_OK); + EXPECT_EQ(km_core_state_option_lookup(kp->lpCoreKeyboardState, KM_CORE_OPT_ENVIRONMENT, expected_items[i].key, &retValue), KM_CORE_STATUS_OK); value = retValue; expectedValue = expected_items[i].value; EXPECT_TRUE(expectedValue == value); @@ -53,12 +53,12 @@ TEST(KEYBOARDOPTIONS, SetupCoreEnvironment) { expected_items[0].value = u"updated"; expected_items[3].value = u"updated"; - EXPECT_EQ(km_kbp_state_options_update(kp->lpCoreKeyboardState, expected_items), KM_KBP_STATUS_OK); + EXPECT_EQ(km_core_state_options_update(kp->lpCoreKeyboardState, expected_items), KM_CORE_STATUS_OK); for (int i = 0; i < 4; ++i) { EXPECT_EQ( - km_kbp_state_option_lookup(kp->lpCoreKeyboardState, KM_KBP_OPT_ENVIRONMENT, expected_items[i].key, &retValue), - KM_KBP_STATUS_OK); + km_core_state_option_lookup(kp->lpCoreKeyboardState, KM_CORE_OPT_ENVIRONMENT, expected_items[i].key, &retValue), + KM_CORE_STATUS_OK); value = retValue; expectedValue = expected_items[i].value; EXPECT_TRUE(expectedValue == value); diff --git a/windows/src/engine/keyman32/tests/keyman-engine-tests/kmprocessactionstests.cpp b/windows/src/engine/keyman32/tests/keyman-engine-tests/kmprocessactionstests.cpp index 5b4e2bfff85..7af218cd77b 100644 --- a/windows/src/engine/keyman32/tests/keyman-engine-tests/kmprocessactionstests.cpp +++ b/windows/src/engine/keyman32/tests/keyman-engine-tests/kmprocessactionstests.cpp @@ -2,7 +2,7 @@ #include "kmprocessactions.cpp" // Test the Process Actions private functions -// TODO: The following actions are not tested KM_KBP_IT_ALERT, KM_KBP_IT_PERSIST_OPT, KM_KBP_IT_EMIT_KEYSTROKE +// TODO: The following actions are not tested KM_CORE_IT_ALERT, KM_CORE_IT_PERSIST_OPT, KM_CORE_IT_EMIT_KEYSTROKE // Fixture for kmprocessactons tests class KMPROCESSACTIONS : public ::testing::Test { @@ -23,62 +23,62 @@ class KMPROCESSACTIONS : public ::testing::Test { ~KMPROCESSACTIONS() {} }; -// KM_KBP_IT_CHAR - processUnicodeChar +// KM_CORE_IT_CHAR - processUnicodeChar TEST_F(KMPROCESSACTIONS, processUnicodeChartest) { WCHAR callbuf[MAXCONTEXT]; AITIP testApp; WCHAR *expectedContext = L"A"; - km_kbp_action_item itemAddChar = { KM_KBP_IT_CHAR, {0,}, {'A'}}; + km_core_action_item itemAddChar = { KM_CORE_IT_CHAR, {0,}, {'A'}}; processUnicodeChar(&testApp, &itemAddChar); WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT); EXPECT_STREQ(contextBuf, expectedContext); - km_kbp_usv testSurrogateChar = Uni_SurrogateToUTF32(0xD801, 0xDC37); //𐐷'; - km_kbp_action_item itemAddChar2 = {KM_KBP_IT_CHAR, {0,}, {testSurrogateChar}}; + km_core_usv testSurrogateChar = Uni_SurrogateToUTF32(0xD801, 0xDC37); //𐐷'; + km_core_action_item itemAddChar2 = {KM_CORE_IT_CHAR, {0,}, {testSurrogateChar}}; WCHAR expectedStringSurrogate[] = {'A', 0xD801, 0xDC37, 0}; processUnicodeChar(&testApp, &itemAddChar2); contextBuf = testApp.ContextBufMax(MAXCONTEXT); EXPECT_STREQ(contextBuf, &expectedStringSurrogate[0]); } -// KM_KBP_IT_MARKER - processMarker Deadkey +// KM_CORE_IT_MARKER - processMarker Deadkey TEST_F(KMPROCESSACTIONS, processMarkertest) { WCHAR callbuf[MAXCONTEXT]; AITIP testApp; WCHAR expectedContext[] = {UC_SENTINEL, CODE_DEADKEY, 2, 0}; uintptr_t marker = 2; - km_kbp_action_item itemAddMarker = {KM_KBP_IT_MARKER, {0,}, {marker}}; + km_core_action_item itemAddMarker = {KM_CORE_IT_MARKER, {0,}, {marker}}; processMarker(&testApp, &itemAddMarker); WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT); EXPECT_STREQ(contextBuf, expectedContext); } -// KM_KBP_IT_BACK - processBack +// KM_CORE_IT_BACK - processBack // First test processing a backspace for a deadkey TEST_F(KMPROCESSACTIONS, processBackDeadkeytest) { WCHAR callbuf[MAXCONTEXT]; AITIP testApp; WCHAR expectedContext[] = {'A', 0}; - km_kbp_action_item itemAddChar = {KM_KBP_IT_CHAR, {0,}, {'A'}}; + km_core_action_item itemAddChar = {KM_CORE_IT_CHAR, {0,}, {'A'}}; processUnicodeChar(&testApp, &itemAddChar); uintptr_t marker = 2; - km_kbp_action_item itemAddMarker = {KM_KBP_IT_MARKER, {0,}, {marker}}; + km_core_action_item itemAddMarker = {KM_CORE_IT_MARKER, {0,}, {marker}}; processMarker(&testApp, &itemAddMarker); - km_kbp_action_item itemBackSpace = {KM_KBP_IT_BACK}; - itemBackSpace.backspace.expected_type = KM_KBP_IT_MARKER; + km_core_action_item itemBackSpace = {KM_CORE_IT_BACK}; + itemBackSpace.backspace.expected_type = KM_CORE_IT_MARKER; itemBackSpace.backspace.expected_value = marker; processBack(&testApp, &itemBackSpace); WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT); EXPECT_STREQ(contextBuf, expectedContext); } -// KM_KBP_IT_BACK - processBack +// KM_CORE_IT_BACK - processBack // Press Backspace for a normal character // Also test for Unknown Character TEST_F(KMPROCESSACTIONS, processBackCharactertest) { @@ -87,42 +87,42 @@ TEST_F(KMPROCESSACTIONS, processBackCharactertest) { AITIP testApp; WCHAR expectedContext[] = {'A', 0}; WCHAR expectedContextFinal[] = {0}; - km_kbp_action_item itemAddChar = {KM_KBP_IT_CHAR, {0,}, {'A'}}; + km_core_action_item itemAddChar = {KM_CORE_IT_CHAR, {0,}, {'A'}}; processUnicodeChar(&testApp, &itemAddChar); itemAddChar.character = 'B'; processUnicodeChar(&testApp, &itemAddChar); - km_kbp_action_item itemBackSpace = {KM_KBP_IT_BACK}; - itemBackSpace.backspace.expected_type = KM_KBP_IT_CHAR; + km_core_action_item itemBackSpace = {KM_CORE_IT_BACK}; + itemBackSpace.backspace.expected_type = KM_CORE_IT_CHAR; itemBackSpace.backspace.expected_value = 'B'; // backspace processBack(&testApp, &itemBackSpace); WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT); EXPECT_STREQ(contextBuf, expectedContext); // backspace for unknown it should backspace a character - itemBackSpace.type = KM_KBP_BT_UNKNOWN; + itemBackSpace.type = KM_CORE_BT_UNKNOWN; processBack(&testApp, &itemBackSpace); contextBuf = testApp.ContextBufMax(MAXCONTEXT); EXPECT_STREQ(contextBuf, expectedContextFinal); } -// KM_KBP_IT_BACK - processBack +// KM_CORE_IT_BACK - processBack // Press Backspace for a surrogate character. // TODO: This test doesn't test for the PostKey handling -// of TSF and two backspaces being sent to the App. +// of TSF and two backspaces being sent to the App. TEST_F(KMPROCESSACTIONS, processBackSurrogateTSFtest) { WCHAR callbuf[MAXCONTEXT]; AITIP testApp; WCHAR expectedContext[] = { 0 }; WCHAR expectedStringSurrogate[] = {0xD801, 0xDC37, 0}; - km_kbp_usv testSurrogateChar = Uni_SurrogateToUTF32(0xD801, 0xDC37); //𐐷'; - km_kbp_action_item itemAddChar = {KM_KBP_IT_CHAR, {0,}, {testSurrogateChar}}; + km_core_usv testSurrogateChar = Uni_SurrogateToUTF32(0xD801, 0xDC37); //𐐷'; + km_core_action_item itemAddChar = {KM_CORE_IT_CHAR, {0,}, {testSurrogateChar}}; processUnicodeChar(&testApp, &itemAddChar); - km_kbp_action_item itemBackSpace = {KM_KBP_IT_BACK}; - itemBackSpace.backspace.expected_type = KM_KBP_IT_CHAR; + km_core_action_item itemBackSpace = {KM_CORE_IT_BACK}; + itemBackSpace.backspace.expected_type = KM_CORE_IT_CHAR; itemBackSpace.backspace.expected_value = testSurrogateChar; WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT); EXPECT_STREQ(contextBuf, expectedStringSurrogate); @@ -132,7 +132,7 @@ TEST_F(KMPROCESSACTIONS, processBackSurrogateTSFtest) { EXPECT_STREQ(contextBuf, expectedContext); } -// KM_KBP_IT_BACK - processBack +// KM_CORE_IT_BACK - processBack // Press Backspace for a character doesn't match expected character // Note currently we don't check for a character match this should be updated @@ -141,13 +141,13 @@ TEST_F(KMPROCESSACTIONS, processBackUnexpectedChartest) { WCHAR callbuf[MAXCONTEXT]; AITIP testApp; WCHAR expectedContext[] = {'A', 0}; - km_kbp_action_item itemAddChar = {KM_KBP_IT_CHAR, {0,}, {'A'}}; + km_core_action_item itemAddChar = {KM_CORE_IT_CHAR, {0,}, {'A'}}; processUnicodeChar(&testApp, &itemAddChar); itemAddChar.character = 'C'; processUnicodeChar(&testApp, &itemAddChar); - km_kbp_action_item itemBackSpace = {KM_KBP_IT_BACK}; - itemBackSpace.backspace.expected_type = KM_KBP_IT_CHAR; + km_core_action_item itemBackSpace = {KM_CORE_IT_BACK}; + itemBackSpace.backspace.expected_type = KM_CORE_IT_CHAR; itemBackSpace.backspace.expected_value = 'B'; // backspace processBack(&testApp, &itemBackSpace); @@ -155,32 +155,32 @@ TEST_F(KMPROCESSACTIONS, processBackUnexpectedChartest) { EXPECT_STREQ(contextBuf, expectedContext); } -// KM_KBP_IT_INVALIDATE_CONTEXT - processInvalidateContext +// KM_CORE_IT_INVALIDATE_CONTEXT - processInvalidateContext TEST_F(KMPROCESSACTIONS, processInvalidateContextTest) { WCHAR callbuf[MAXCONTEXT]; AITIP testApp; WCHAR expectedContext[] = {0}; - km_kbp_action_item itemAddChar = {KM_KBP_IT_CHAR, {0,}, {'A'}}; + km_core_action_item itemAddChar = {KM_CORE_IT_CHAR, {0,}, {'A'}}; processUnicodeChar(&testApp, &itemAddChar); itemAddChar.character = 'B'; processUnicodeChar(&testApp, &itemAddChar); // A keyboard a state is need to test processInvalidateContext - km_kbp_option_item test_env_opts[] = {{u"hello", u"world", KM_KBP_OPT_KEYBOARD}, KM_KBP_OPTIONS_END}; - km_kbp_keyboard *testKB = nullptr; - km_kbp_state *testState = nullptr; - km_kbp_path_name dummyPath = L"dummyActions.mock"; - EXPECT_EQ(km_kbp_keyboard_load(dummyPath, &testKB), KM_KBP_STATUS_OK); - EXPECT_EQ(km_kbp_state_create(testKB, test_env_opts, &testState), KM_KBP_STATUS_OK); + km_core_option_item test_env_opts[] = {{u"hello", u"world", KM_CORE_OPT_KEYBOARD}, KM_CORE_OPTIONS_END}; + km_core_keyboard *testKB = nullptr; + km_core_state *testState = nullptr; + km_core_path_name dummyPath = L"dummyActions.mock"; + EXPECT_EQ(km_core_keyboard_load(dummyPath, &testKB), KM_CORE_STATUS_OK); + EXPECT_EQ(km_core_state_create(testKB, test_env_opts, &testState), KM_CORE_STATUS_OK); processInvalidateContext(&testApp,testState); WCHAR *contextBuf = testApp.ContextBufMax(MAXCONTEXT); EXPECT_STREQ(contextBuf, expectedContext); // dispose keyboard - km_kbp_state_dispose(testState); - km_kbp_keyboard_dispose(testKB); + km_core_state_dispose(testState); + km_core_keyboard_dispose(testKB); } diff --git a/windows/src/support/charident/Makefile b/windows/src/support/charident/Makefile index dd6721c5c0a..cff67416776 100644 --- a/windows/src/support/charident/Makefile +++ b/windows/src/support/charident/Makefile @@ -15,6 +15,6 @@ signcode: wrap-symbols: $(SYMSTORE) $(PROGRAM)\support\charident.exe /t keyman-windows - #TODO: $(SYMSTORE) $(DEBUGPATH)\support\charident.dbg /t keyman-windows +#TODO: $(SYMSTORE) $(DEBUGPATH)\support\charident.dbg /t keyman-windows !include ..\..\Target.mak diff --git a/windows/src/support/km_yim/Makefile b/windows/src/support/km_yim/Makefile index f0f93e6fe22..1aef5f80f02 100644 --- a/windows/src/support/km_yim/Makefile +++ b/windows/src/support/km_yim/Makefile @@ -4,12 +4,13 @@ !include ..\..\Defines.mak -build: # version.res +build: +# version.res $(DCC32) km_yim.dpr rem $(TDSPACK) $(PROGRAM)\desktop\km_yim.exe km_yim.tds rem $(TDS2DBG) $(PROGRAM)\desktop\km_yim.exe $(WZZIP) inst_km_yim.zip km_yim.exe - # $(WZSE) inst_km_yim -setup -t inst_km_yim.dialog.txt -st "Tavultesoft Keyman Desktop Yahoo Messenger Addin" -c km_yim.exe +# $(WZSE) inst_km_yim -setup -t inst_km_yim.dialog.txt -st "Tavultesoft Keyman Desktop Yahoo Messenger Addin" -c km_yim.exe clean: def-clean if exist inst_km_yim.zip del inst_km_yim.zip diff --git a/windows/src/test/Makefile b/windows/src/test/Makefile index 5df2892dfad..2087f3d8a00 100644 --- a/windows/src/test/Makefile +++ b/windows/src/test/Makefile @@ -4,12 +4,14 @@ # ---------------------------------------------------------------------- +# TODO: both test-manifest-exec and verify_signatures are really part of buildtools + !ifdef NODELPHI TARGETS=.virtual !else -TARGETS=test_i3633 +TARGETS=verify_signatures !endif -CLEAN=test_i3633 +CLEAN=verify_signatures test: test-manifest-exec $(MAKE) "TARGET=test" $(TARGETS) @@ -22,10 +24,10 @@ test-manifest-exec: $(MAKE) test-manifest cd test -# test_i3633: validate certificates and binary metadata on executables -# TODO: Move this to buildtools -test_i3633: - cd $(ROOT)\src\test\test_i3633 +# validate certificates and binary metadata on executables +# TODO: move to buildtools? +verify_signatures: .virtual + cd $(ROOT)\src\test\verify_signatures $(MAKE) $(TARGET) # ---------------------------------------------------------------------- diff --git a/windows/src/test/test_i3633/Makefile b/windows/src/test/test_i3633/Makefile deleted file mode 100644 index 575d77e7e83..00000000000 --- a/windows/src/test/test_i3633/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -# -# test for signatures and version information being correct in ?install directory or ?bin directory -# - -!include ..\..\Defines.mak - -SIGCHECK=-$(WIN32_TARGET_PATH)\sigcheck -q -s -e -v -accepteula -VERIFY=$(WIN32_TARGET_PATH)\verify -d $(KEYMAN_ROOT)\VERSION.md - -test: test-bin - -test-bin: prereq - $(SIGCHECK) $(ROOT)\bin\desktop\* > sig1 - $(SIGCHECK) $(ROOT)\bin\developer\* >> sig1 - $(SIGCHECK) $(ROOT)\bin\engine\* >> sig1 - $(SIGCHECK) $(ROOT)\bin\inst\* >> sig1 - $(VERIFY) < sig1 - -test-install: prereq - - -prereq: - $(DELPHI_MSBUILD) verify.dproj "/p:Platform=Win32" - copy sigcheck.bin $(WIN32_TARGET_PATH)\sigcheck.exe - - -clean: def-clean - -del sig1 - -del sig2 - -!include ..\..\Target.mak diff --git a/windows/src/test/verify_signatures/Makefile b/windows/src/test/verify_signatures/Makefile new file mode 100644 index 00000000000..607e5d22cf9 --- /dev/null +++ b/windows/src/test/verify_signatures/Makefile @@ -0,0 +1,21 @@ +# +# test for signatures and version information being correct in bin folder +# + +!include ..\..\Defines.mak + +test: prereq + $(SIGCHECK) $(ROOT)\bin\desktop\* > sig1 + $(SIGCHECK) $(ROOT)\bin\engine\* >> sig1 + $(SIGCHECK) $(ROOT)\bin\inst\* >> sig1 + $(VERIFY_SIGNATURES) < sig1 + +# prereq may not be needed? +prereq: + cd $(VERIFY_SIGNATURES_PATH) + $(MAKE) + +clean: def-clean + -del sig1 + +!include ..\..\Target.mak