From 878f0fc7690c3d1338e5aa0cca64362f7ff127d1 Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Tue, 20 Aug 2024 14:19:14 +0700 Subject: [PATCH 01/52] fix(web): fix documentation-keyboard spacebar-text scaling Fixes: #12231 Cherry-pick-of: #12232 --- web/src/engine/osk/src/visualKeyboard.ts | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index af8324f03e..b8a378a27e 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1267,6 +1267,7 @@ export default class VisualKeyboard extends EventEmitter implements Ke const groupStyle = getComputedStyle(this.layerGroup.element); const isInDOM = computedStyle.height != '' && computedStyle.height != 'auto'; + const isGroupInDOM = groupStyle.height != '' && groupStyle.height != 'auto'; if (computedStyle.border) { this._borderWidth = new ParsedLengthStyle(computedStyle.borderWidth).val; @@ -1279,10 +1280,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke this._computedHeight = this.height; } else if (isInDOM) { this._computedWidth = parseInt(computedStyle.width, 10); - if (!this._computedWidth) { - this._computedWidth = parseInt(groupStyle.width, 10); - } this._computedHeight = parseInt(computedStyle.height, 10); + } else if (isGroupInDOM) { + // May occur for documentation-keyboards, which are detached from their VisualKeyboard base. + this._computedWidth = parseInt(groupStyle.width, 10); + this._computedHeight = parseInt(groupStyle.height, 10); } else { // Cannot perform layout operations! return; @@ -1619,6 +1621,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke // the page. kbdObj.appendStyleSheet(); + // Unset the width + height we used thus far; this method's consumer may choose to rescale + // the returned element. If so, we don't want to use our outdated value by mistake. + delete kbdObj._width; + delete kbdObj._height; + return classWrapper; } From 672ba858123c9ab272ad10b01bb269eb1bf42a6b Mon Sep 17 00:00:00 2001 From: "Joshua A. Horton" Date: Wed, 21 Aug 2024 09:05:48 +0700 Subject: [PATCH 02/52] docs(web): extends doc-comment per review comment --- web/src/engine/osk/src/visualKeyboard.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/web/src/engine/osk/src/visualKeyboard.ts b/web/src/engine/osk/src/visualKeyboard.ts index b8a378a27e..d41b1b4c19 100644 --- a/web/src/engine/osk/src/visualKeyboard.ts +++ b/web/src/engine/osk/src/visualKeyboard.ts @@ -1623,6 +1623,11 @@ export default class VisualKeyboard extends EventEmitter implements Ke // Unset the width + height we used thus far; this method's consumer may choose to rescale // the returned element. If so, we don't want to use our outdated value by mistake. + // + // While `kbdObj.setSize()` could be used in theory, it _also_ unsets the element styling. + // We actually wish to _leave_ this styling in place - one of our parameters is `height`, and + // it should remain in place in the styling on the output element as the default in case + // the consumer _doesn't_ add styling afterward. delete kbdObj._width; delete kbdObj._height; From 47e87b0f6af0a9e5c1d38d41d621135e690797b9 Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Thu, 15 Aug 2024 13:18:05 +0700 Subject: [PATCH 03/52] change(ios): defer registration of fonts past initialization Cherry-pick-of: #12190 --- ios/engine/KMEI/KeymanEngine/Classes/Manager.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift b/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift index 5b77f79307..d1d134b249 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Manager.swift @@ -831,12 +831,22 @@ public class Manager: NSObject, UIGestureRecognizerDelegate { shared.copyUserDefaults(to: nonShared, withKeys: keysToCopy, shouldOverwrite: true) do { try shared.copyFiles(to: nonShared) - FontManager.shared.registerCustomFonts() } catch { let message = ("Failed to copy from shared container: \(error)") os_log("%{public}s", log:KeymanEngineLogger.settings, type: .error, message) SentryManager.capture(error, message:message) } + + // This operation has a surprisingly high cost and isn't critical + // for getting the keyboard loaded and available to the OS. + // + // We certainly want it done _soon_... but we don't want it to cause + // the primary, synchronous initialization call from the OS to run so + // long that the keyboard fails to start due to its enforced time + // constraints. + DispatchQueue.main.async { + FontManager.shared.registerCustomFonts() + } } } From a2344abb6470828fe3260e027a7d7910f0bb4c6f Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 21 Aug 2024 14:24:10 +0200 Subject: [PATCH 04/52] chore(developer): enable build for emscripten 3.1.60+ Emscripten 3.1.60 made a breaking change to `BindingType::toWireType` (why is this done in a patch version?) so this change ensures that we can continue to build on 3.1.58 and 3.1.64 (which is needed for #12234), as a bridging strategy. We will need to merge this into 17.0-stable as well so that we can upgrade the build agents to 3.1.64. Relates-to: emscripten-core/emscripten#21692 Relates-to: #12234 --- developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp b/developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp index 977b3b7443..3a0351f80f 100644 --- a/developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp +++ b/developer/src/kmcmplib/src/CompilerInterfacesWasm.cpp @@ -90,9 +90,16 @@ struct BindingType> { using ValBinding = BindingType; using WireType = ValBinding::WireType; +#if __EMSCRIPTEN_major__ == 3 && __EMSCRIPTEN_minor__ == 1 && __EMSCRIPTEN_tiny__ >= 60 + // emscripten-core/emscripten#21692 + static WireType toWireType(const std::vector &vec, rvp::default_tag) { + return ValBinding::toWireType(val::array(vec), rvp::default_tag{}); + } +#else static WireType toWireType(const std::vector &vec) { return ValBinding::toWireType(val::array(vec)); } +#endif static std::vector fromWireType(WireType value) { return vecFromJSArray(ValBinding::fromWireType(value)); From 26983c694172201556a5592b90f8779dc93c8688 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 21 Aug 2024 15:02:18 +0200 Subject: [PATCH 05/52] chore(common): allow build agents to automatically select emsdk version The build agents will now automatically install and activate the Emscripten version found in minimum-versions.inc.sh when configuring WASM projects. For developer machines, this behaviour can be enabled by setting the environment variable `KEYMAN_USE_EMSDK` (recommended). Cherry-pick-of: #12243 --- resources/locate_emscripten.inc.sh | 66 ++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/resources/locate_emscripten.inc.sh b/resources/locate_emscripten.inc.sh index be66adfa32..36a78113f7 100644 --- a/resources/locate_emscripten.inc.sh +++ b/resources/locate_emscripten.inc.sh @@ -1,31 +1,73 @@ # shellcheck shell=bash # no hashbang for .inc.sh +KEYMAN_MIN_VERSION_EMSCRIPTEN=3.1.58 + # -# We don't want to rely on emcc.py being on the path, because Emscripten puts far +# We don't want to rely on emcc being on the path, because Emscripten puts far # too many things onto the path (in particular for us, node). # -# The following comment suggests that we don't need emcc.py on the path. +# The following comment suggests that we don't need emcc on the path. # https://github.com/emscripten-core/emscripten/issues/4848#issuecomment-1097357775 # -# So we try and locate emcc.py in common locations ourselves. The search pattern +# So we try and locate in common locations ourselves. The search pattern # is: # # 1. Look for $EMSCRIPTEN_BASE (our primary emscripten variable), which should -# point to the folder that emcc.py is located in -# 2. Look for $EMCC which should point to the emcc.py executable -# 3. Look for emcc.py on the path +# point to the folder that emcc is located in +# 2. Look for $EMCC which should point to the emcc executable +# 3. Look for emcc on the path # locate_emscripten() { + local EMCC_EXECUTABLE + if [[ "${BUILDER_OS}" == "win" ]]; then + EMCC_EXECUTABLE="emcc.py" + else + EMCC_EXECUTABLE="emcc" + fi if [[ -z ${EMSCRIPTEN_BASE+x} ]]; then if [[ -z ${EMCC+x} ]]; then - local EMCC=`which emcc.py` - [[ -z $EMCC ]] && builder_die "locate_emscripten: Could not locate emscripten (emcc.py) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" + local EMCC=`which ${EMCC_EXECUTABLE}` + [[ -z $EMCC ]] && builder_die "locate_emscripten: Could not locate emscripten (emcc) on the path or with \$EMCC or \$EMSCRIPTEN_BASE" fi - [[ -f $EMCC && ! -x $EMCC ]] && builder_die "locate_emscripten: Variable EMCC ($EMCC) points to emcc.py but it is not executable" - [[ -x $EMCC ]] || builder_die "locate_emscripten: Variable EMCC ($EMCC) does not point to a valid executable emcc.py" + [[ -f $EMCC && ! -x $EMCC ]] && builder_die "locate_emscripten: Variable EMCC ($EMCC) points to emcc but it is not executable" + [[ -x $EMCC ]] || builder_die "locate_emscripten: Variable EMCC ($EMCC) does not point to a valid executable emcc" EMSCRIPTEN_BASE="$(dirname "$EMCC")" fi - [[ -f ${EMSCRIPTEN_BASE}/emcc.py && ! -x ${EMSCRIPTEN_BASE}/emcc.py ]] && builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) contains emcc.py but it is not executable" - [[ -x ${EMSCRIPTEN_BASE}/emcc.py ]] || builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to emcc.py's folder" + [[ -f ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} && ! -x ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} ]] && builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) contains ${EMCC_EXECUTABLE} but it is not executable" + [[ -x ${EMSCRIPTEN_BASE}/${EMCC_EXECUTABLE} ]] || builder_die "locate_emscripten: Variable EMSCRIPTEN_BASE ($EMSCRIPTEN_BASE) does not point to ${EMCC_EXECUTABLE}'s folder" + + verify_emscripten_version +} + +# Ensure that we use correct version of emsdk on build agents. +# For developers, define KEYMAN_USE_SDK to do this on your +# build machine. +verify_emscripten_version() { + if [[ "$VERSION_ENVIRONMENT" != local || ! -z "${KEYMAN_USE_EMSDK+x}" ]]; then + _select_emscripten_version_with_emsdk + fi +} + +# Use emsdk to select the appropriate version of Emscripten +# according to minimum-versions.inc.sh +_select_emscripten_version_with_emsdk() { + if [[ -z "${EMSCRIPTEN_BASE+x}" ]]; then + builder_die "Variable EMSCRIPTEN_BASE must be set" + fi + + if [[ -z "${KEYMAN_MIN_VERSION_EMSCRIPTEN+x}" ]]; then + builder_die "Variable KEYMAN_MIN_VERSION_EMSCRIPTEN must be set" + fi + + pushd "${EMSCRIPTEN_BASE}/../.." > /dev/null + if [[ ! -f emsdk ]]; then + builder_die "emsdk[.bat] should be in $(pwd)" + fi + + export EMSDK_KEEP_DOWNLOADS=1 + git pull + ./emsdk install "$KEYMAN_MIN_VERSION_EMSCRIPTEN" + ./emsdk activate "$KEYMAN_MIN_VERSION_EMSCRIPTEN" + popd > /dev/null } From 952e7beb574e134a9708f58b10d6d9c0a74965fd Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 21 Aug 2024 16:05:29 +0200 Subject: [PATCH 06/52] chore: use emcc not emcc.py on mac/linux This is a manual cherry-pick of #12235, for 17.0-stable. Cherry-pick-of: #12235 --- core/wasm.build.linux.in | 6 +++--- core/wasm.build.mac.in | 6 +++--- core/wasm.defs.build | 6 +++--- developer/src/kmcmplib/wasm.build.linux.in | 6 +++--- developer/src/kmcmplib/wasm.build.mac.in | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/wasm.build.linux.in b/core/wasm.build.linux.in index d449dcf94a..78ce0b3030 100644 --- a/core/wasm.build.linux.in +++ b/core/wasm.build.linux.in @@ -1,4 +1,4 @@ [binaries] -c = ['$EMSCRIPTEN_BASE/emcc.py'] -cpp = ['$EMSCRIPTEN_BASE/em++.py'] -ar = ['$EMSCRIPTEN_BASE/emar.py'] \ No newline at end of file +c = ['$EMSCRIPTEN_BASE/emcc'] +cpp = ['$EMSCRIPTEN_BASE/em++'] +ar = ['$EMSCRIPTEN_BASE/emar'] \ No newline at end of file diff --git a/core/wasm.build.mac.in b/core/wasm.build.mac.in index d449dcf94a..78ce0b3030 100644 --- a/core/wasm.build.mac.in +++ b/core/wasm.build.mac.in @@ -1,4 +1,4 @@ [binaries] -c = ['$EMSCRIPTEN_BASE/emcc.py'] -cpp = ['$EMSCRIPTEN_BASE/em++.py'] -ar = ['$EMSCRIPTEN_BASE/emar.py'] \ No newline at end of file +c = ['$EMSCRIPTEN_BASE/emcc'] +cpp = ['$EMSCRIPTEN_BASE/em++'] +ar = ['$EMSCRIPTEN_BASE/emar'] \ No newline at end of file diff --git a/core/wasm.defs.build b/core/wasm.defs.build index 4a598a1e1c..f41af337a3 100644 --- a/core/wasm.defs.build +++ b/core/wasm.defs.build @@ -1,7 +1,7 @@ [binaries] -c = ['emcc.py'] -cpp = ['em++.py'] -ar = ['emar.py'] +c = ['emcc'] +cpp = ['em++'] +ar = ['emar'] exe_wrapper = 'node' [properties] diff --git a/developer/src/kmcmplib/wasm.build.linux.in b/developer/src/kmcmplib/wasm.build.linux.in index c5e61a9bda..27cb7ba68f 100644 --- a/developer/src/kmcmplib/wasm.build.linux.in +++ b/developer/src/kmcmplib/wasm.build.linux.in @@ -1,4 +1,4 @@ [binaries] -c = ['$EMSCRIPTEN_BASE/emcc.py'] -cpp = ['$EMSCRIPTEN_BASE/em++.py'] -ar = ['$EMSCRIPTEN_BASE/emar.py'] +c = ['$EMSCRIPTEN_BASE/emcc'] +cpp = ['$EMSCRIPTEN_BASE/em++'] +ar = ['$EMSCRIPTEN_BASE/emar'] diff --git a/developer/src/kmcmplib/wasm.build.mac.in b/developer/src/kmcmplib/wasm.build.mac.in index c5e61a9bda..27cb7ba68f 100644 --- a/developer/src/kmcmplib/wasm.build.mac.in +++ b/developer/src/kmcmplib/wasm.build.mac.in @@ -1,4 +1,4 @@ [binaries] -c = ['$EMSCRIPTEN_BASE/emcc.py'] -cpp = ['$EMSCRIPTEN_BASE/em++.py'] -ar = ['$EMSCRIPTEN_BASE/emar.py'] +c = ['$EMSCRIPTEN_BASE/emcc'] +cpp = ['$EMSCRIPTEN_BASE/em++'] +ar = ['$EMSCRIPTEN_BASE/emar'] From e20e2313253e88a534b00141b8188b0d3cfed7a4 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Mon, 19 Aug 2024 10:22:10 -0500 Subject: [PATCH 07/52] fix(core): set mac build version for meson cli build to 10.13 - add as option to compiler - Match version in #11302 Fixes: #11423 --- core/cross-mac-arm64.build | 6 +++--- core/cross-mac-x86_64.build | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/cross-mac-arm64.build b/core/cross-mac-arm64.build index 720e9f3100..faf3e6e9c1 100644 --- a/core/cross-mac-arm64.build +++ b/core/cross-mac-arm64.build @@ -5,9 +5,9 @@ cpu = 'arm64' endian = 'little' [binaries] -c = ['clang', '-arch', 'arm64'] -objc = ['clang', '-arch', 'arm64'] -cpp = ['clang++', '-arch', 'arm64'] +c = ['clang', '-arch', 'arm64', '-mmacosx-version-min=10.13'] +objc = ['clang', '-arch', 'arm64', '-mmacosx-version-min=10.13'] +cpp = ['clang++', '-arch', 'arm64', '-mmacosx-version-min=10.13'] ar = 'ar' ld = 'ld' strip = 'strip' diff --git a/core/cross-mac-x86_64.build b/core/cross-mac-x86_64.build index 2ab2c62a60..3378fe11a4 100644 --- a/core/cross-mac-x86_64.build +++ b/core/cross-mac-x86_64.build @@ -5,9 +5,9 @@ cpu = 'x86_64' endian = 'little' [binaries] -c = ['clang', '-arch', 'x86_64'] -objc = ['clang', '-arch', 'x86_64'] -cpp = ['clang++', '-arch', 'x86_64'] +c = ['clang', '-arch', 'x86_64', '-mmacosx-version-min=10.13'] +objc = ['clang', '-arch', 'x86_64', '-mmacosx-version-min=10.13'] +cpp = ['clang++', '-arch', 'x86_64', '-mmacosx-version-min=10.13'] ar = 'ar' ld = 'ld' strip = 'strip' From 6c9b335bc72dec807185b8bddfe5723cdf94c778 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Sat, 24 Aug 2024 00:15:33 +0200 Subject: [PATCH 08/52] fix(developer): find last matching key in LDML key bag when building KVK Fixes: #12056 Cherry-pick-of: #12278 --- .../src/compiler/visual-keyboard-compiler.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) 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 bbb2d83abf..d1a1d4e71a 100644 --- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts @@ -2,6 +2,23 @@ import { VisualKeyboard, LDMLKeyboard, CompilerCallbacks } from "@keymanapp/comm import { KeysCompiler } from "./keys.js"; import { CompilerMessages } from "./messages.js"; +// This is a partial polyfill for findLast, so not polluting Array.prototype +// +// TODO: remove and replace with Array.prototype.findLast when it is +// well-supported +function findLast(arr: any, callback: any) { + if (!arr) { + return undefined; + } + const len = arr.length >>> 0; + for (let i = len - 1; i >= 0; i--) { + if (callback(arr[i], i, arr)) { + return arr[i]; + } + } + return undefined; +} + export class LdmlKeyboardVisualKeyboardCompiler { public constructor(private callbacks: CompilerCallbacks) { } @@ -56,7 +73,8 @@ export class LdmlKeyboardVisualKeyboardCompiler { const keyId = key; x++; - let keydef = source.keyboard3.keys?.key?.find(x => x.id == key); + //@ts-ignore + let keydef = findLast(source.keyboard3.keys?.key, x => x.id == key); if (!keydef) { this.callbacks.reportMessage( From 85c944f2eb1ee277cae2f68c5655b702557c8c9e Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Sat, 24 Aug 2024 12:08:29 +0800 Subject: [PATCH 09/52] fix(core): properly support 'other' modifier state with `uint32_t` type While the modifier state property in core's API is 16-bit, internally ldml_processor supports the modifier flag LDML_KEYS_MOD_OTHER with a value of `0x10000`, which requires widening the value (we match the 32-bit size of the KMX_DWORD value from KMX+). Note: this is not yet well unit-tested. Relates-to: #11072 Fixes: #12057 Cherry-pick-of: #12281 --- core/src/ldml/ldml_processor.cpp | 2 +- core/src/ldml/ldml_vkeys.cpp | 2 +- core/src/ldml/ldml_vkeys.hpp | 13 ++++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/core/src/ldml/ldml_processor.cpp b/core/src/ldml/ldml_processor.cpp index f90fcfaa94..fcadda629c 100644 --- a/core/src/ldml/ldml_processor.cpp +++ b/core/src/ldml/ldml_processor.cpp @@ -85,7 +85,7 @@ ldml_processor::ldml_processor(path const & kb_path, const std::vector } else { str = keyEntry->get_to_string(); } - keys.add((km_core_virtual_key)kmapEntry->vkey, (uint16_t)kmapEntry->mod, str); + keys.add((km_core_virtual_key)kmapEntry->vkey, kmapEntry->mod, str); } } // else: no keys! but still valid. Just, no keys. diff --git a/core/src/ldml/ldml_vkeys.cpp b/core/src/ldml/ldml_vkeys.cpp index 07a2ff08ad..f79f82141f 100644 --- a/core/src/ldml/ldml_vkeys.cpp +++ b/core/src/ldml/ldml_vkeys.cpp @@ -17,7 +17,7 @@ vkeys::vkeys() : vkey_to_string() { } void -vkeys::add(km_core_virtual_key vk, uint16_t modifier_state, std::u16string output) { +vkeys::add(km_core_virtual_key vk, km_core_ldml_modifier_state modifier_state, std::u16string output) { // construct key const vkey_id id(vk, modifier_state); // assign the string diff --git a/core/src/ldml/ldml_vkeys.hpp b/core/src/ldml/ldml_vkeys.hpp index ed3368dc7e..6a54d77065 100644 --- a/core/src/ldml/ldml_vkeys.hpp +++ b/core/src/ldml/ldml_vkeys.hpp @@ -19,10 +19,17 @@ namespace km { namespace core { namespace ldml { +/** + * LDML keyboards have 32-bit modifier flags in order to support + * LDML_KEYS_MOD_OTHER (0x10000), unlike the Core APIs which have only 16 bit + * modifier flags. + */ +typedef uint32_t km_core_ldml_modifier_state; + /** * identifier for keybag lookup */ -typedef std::pair vkey_id; +typedef std::pair vkey_id; /** * LDML Class to manage all things key related: vkey remapping and vkey to string @@ -35,9 +42,9 @@ public: vkeys(); /** - * add a vkey to the bag + * add a vkey to the bag. */ - void add(km_core_virtual_key vk, uint16_t modifier_state, std::u16string output); + void add(km_core_virtual_key vk, km_core_ldml_modifier_state ldml_modifier_state, std::u16string output); /** * Lookup a vkey, returns an empty string if not found From c1b732391755e1655d08ac534a70020ff8adbf25 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 28 Aug 2024 06:56:21 +0700 Subject: [PATCH 10/52] chore(android,ios): Update FirstVoices keyboards to 12.15 * Keyboard version updates corresponding to fv_all.kmp version 12.15 --- oem/firstvoices/keyboards.csv | 71 ++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/oem/firstvoices/keyboards.csv b/oem/firstvoices/keyboards.csv index cbede23edc..22812ec14d 100644 --- a/oem/firstvoices/keyboards.csv +++ b/oem/firstvoices/keyboards.csv @@ -7,57 +7,58 @@ fv,fv_uummarmiutun,Uummarmiutun,Arctic,fv_uummarmiutun_kmw-9.0.js,9.1.1,ikt-Latn fv,fv_eastern_canadian_inuktitut,ᐃᓄᒃᑎᑐᑦ (Eastern Canadian Inuktitut),Arctic,fv_eastern_canadian_inuktitut_kmw-9.0.js,9.2.1,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics) fv,fv_migmaq,Mi'gmawi'simg / Mi'kmawi'simk,Atlantic,fv_migmaq_kmw-9.0.js,9.1.2,mic-Latn,Mi'kmaq (Latin) fv,fv_skicinuwatuwewakon,Skicinuwatuwewakon,Atlantic,fv_skicinuwatuwewakon_kmw-9.0.js,9.1.1,pqm-Latn,Malecite-Passamaquoddy (Latin) -fv,fv_uwikala,'Uwik̓ala,BC Coast,fv_uwikala_kmw-9.0.js,9.3,hei,Heiltsuk +fv,fv_uwikala,'Uwik̓ala,BC Coast,fv_uwikala_kmw-9.0.js,9.4,hei,Heiltsuk fv,fv_dexwlesucid,Dəxʷləšucid,BC Coast,fv_dexwlesucid_kmw-9.0.js,9.2.1,lut-Latn,Lushootseed (Latin) fv,fv_diitiidatx,Diidiitidq,BC Coast,fv_diitiidatx_kmw-9.0.js,9.2.1,nuk-Latn,Nuu-chah-nulth (Latin) -fv,fv_gitsenimx,Gitsenimx̱,BC Coast,fv_gitsenimx_kmw-9.0.js,10.1.1,git,Gitxsan (Latin) +fv,fv_gitsenimx,Gitsenimx̱,BC Coast,fv_gitsenimx_kmw-9.0.js,10.1.2,git,Gitxsan (Latin) fv,fv_hailzaqvla,Haiɫzaqvla,BC Coast,fv_hailzaqvla_kmw-9.0.js,9.5.2,hei,Heiltsuk (Latin) -fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1,has-Latn,Haisla (Latin) +fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1.2,has-Latn,Haisla (Latin) fv,fv_halqemeylem,Halq'eméylem,BC Coast,fv_halqemeylem_kmw-9.0.js,9.2,hur-Latn,Halkomelem (Latin) fv,fv_henqeminem,Hǝn̓q̓ǝmin̓ǝm,BC Coast,fv_henqeminem_kmw-9.0.js,10.1,hur-Latn,Halkomelem (Latin) fv,fv_klahoose,Homalco-Klahoose-Sliammon,BC Coast,fv_klahoose_kmw-9.0.js,10.1,coo,Comox fv,fv_hulquminum,Hul’q’umi’num’,BC Coast,fv_hulquminum_kmw-9.0.js,9.1,hur-Latn,Halkomelem (Latin) fv,fv_hulquminum_combine,Hul̓q̓umin̓um̓,BC Coast,fv_hulquminum_combine_kmw-9.0.js,2.0.1,hur-Latn,Halkomelem (Latin) -fv,fv_kwakwala_liqwala,Kʷak̓ʷala,BC Coast,fv_kwakwala_liqwala_kmw-9.0.js,9.2.5,kwk-Latn,Kwakiutl (Latin) -fv,fv_kwakwala,Kwak̕wala,BC Coast,fv_kwakwala_kmw-9.0.js,9.1.2,kwk-Latn,Kwakiutl (Latin) -fv,fv_nexwslayemucen,Nəxʷsƛ̓ay̓əmúcən,BC Coast,fv_nexwslayemucen_kmw-9.0.js,9.2.1,clm-Latn,Clallam (Latin) -fv,fv_nisgaa,Nisg̱a'a,BC Coast,fv_nisgaa_kmw-9.0.js,9.1.2,ncg-Latn,Nisga'a (Latin) -fv,fv_nuucaanul,Nuučaan̓uł,BC Coast,fv_nuucaanul_kmw-9.0.js,9.1.4,nuk-Latn,Nuu-chah-nulth (Latin) -fv,fv_nuxalk,Nuxalk,BC Coast,fv_nuxalk_kmw-9.0.js,10.0,blc-Latn,Bella Coola (Latin) +fv,fv_kwakwala_liqwala,Kʷak̓ʷala,BC Coast,fv_kwakwala_liqwala_kmw-9.0.js,9.3,kwk-Latn,Kwakiutl (Latin) +fv,fv_kwakwala,Kwak̕wala,BC Coast,fv_kwakwala_kmw-9.0.js,9.2,kwk-Latn,Kwakiutl (Latin) +fv,fv_lekwungen,Lək̓ʷəŋən,BC Coast,fv_lekwungen-9.0.js,1.0,str,Lekwungen +fv,fv_nexwslayemucen,Nəxʷsƛ̓ay̓əmúcən,BC Coast,fv_nexwslayemucen_kmw-9.0.js,10.0,clm-Latn,Clallam (Latin) +fv,fv_nisgaa,Nisg̱a'a,BC Coast,fv_nisgaa_kmw-9.0.js,9.2,ncg-Latn,Nisga'a (Latin) +fv,fv_nuucaanul,Nuučaan̓uł,BC Coast,fv_nuucaanul_kmw-9.0.js,9.2,nuk-Latn,Nuu-chah-nulth (Latin) +fv,fv_nuxalk,Nuxalk,BC Coast,fv_nuxalk_kmw-9.0.js,10.0.1,blc-Latn,Bella Coola (Latin) fv,fv_sencoten,SENĆOŦEN,BC Coast,fv_sencoten_kmw-9.0.js,9.2.2,str,Straits Salish -fv,fv_sguuxs,Sgüüx̱s,BC Coast,fv_sguuxs.js,1.0.1,tsi,Tsimshian +fv,fv_sguuxs,Sgüüx̱s,BC Coast,fv_sguuxs.js,1.1,tsi,Tsimshian fv,fv_shashishalhem,Shashishalhem,BC Coast,fv_shashishalhem_kmw-9.0.js,9.2,sec-Latn,Sechelt (Latin) -fv,fv_skwxwumesh_snichim,Sḵwx̱wúmesh sníchim,BC Coast,fv_skwxwumesh_snichim_kmw-9.0.js,9.3,squ-Latn,Squamish (Latin) +fv,fv_skwxwumesh_snichim,Sḵwx̱wúmesh sníchim,BC Coast,fv_skwxwumesh_snichim_kmw-9.0.js,10.0,squ-Latn,Squamish (Latin) fv,fv_smalgyax,Sm'algya̱x,BC Coast,fv_smalgyax_kmw-9.0.js,9.2,tsi-Latn,Tsimshian (Latin) -fv,fv_xaislakala,X̄a'ʼislak̓ala,BC Coast,fv_xaislakala_kmw-9.0.js,9.1.1,has-Latn,Haisla (Latin) -fv,fv_hlgaagilda_xaayda_kil,X̱aayda-X̱aad Kil,BC Coast,fv_hlgaagilda_xaayda_kil_kmw-9.0.js,9.3,hax,Southern Haida -fv,fv_dakelh,Dakelh,BC Interior,fv_dakelh_kmw-9.0.js,9.2,caf-Latn,Southern Carrier (Latin) +fv,fv_xaislakala,X̄a'ʼislak̓ala,BC Coast,fv_xaislakala_kmw-9.0.js,10.0,has-Latn,Haisla (Latin) +fv,fv_hlgaagilda_xaayda_kil,X̱aayda-X̱aad Kil,BC Coast,fv_hlgaagilda_xaayda_kil_kmw-9.0.js,9.4,hax,Southern Haida +fv,fv_dakelh,Dakelh,BC Interior,fv_dakelh_kmw-9.0.js,9.2.1,caf-Latn,Southern Carrier (Latin) fv,fv_ktunaxa,Ktunaxa,BC Interior,fv_ktunaxa_kmw-9.0.js,10.0,kut-Latn,Kutenai (Latin) -fv,fv_kwadacha_tsekene,Kwadacha Tsek’ene,BC Interior,fv_kwadacha_tsekene_kmw-9.0.js,1.0,sek-Latn,Sekani +fv,fv_kwadacha_tsekene,Kwadacha Tsek’ene,BC Interior,fv_kwadacha_tsekene_kmw-9.0.js,1.1,sek-Latn,Sekani fv,fv_natwits,Nedut’en-Witsuwit'en,BC Interior,fv_natwits_kmw-9.0.js,9.1.3,caf-Latn,Southern Carrier (Latin) -fv,fv_nlekepmxcin,Nłeʔkepmxcin,BC Interior,fv_nlekepmxcin_kmw-9.0.js,9.4,thp-Latn,Thompson (Latin) -fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.0,thp-Latn,Thompson (Latin) -fv,fv_nlakapamuxcheen,Nlakapamuxcheen,BC Interior,fv_nlakapamuxcheen_kmw-9.0.js,1.0.2,thp,Thompson -fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,9.3,oka,Okanagan +fv,fv_nlekepmxcin,Nłeʔkepmxcin,BC Interior,fv_nlekepmxcin_kmw-9.0.js,9.5.1,thp-Latn,Thompson (Latin) +fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.1.1,thp-Latn,Thompson (Latin) +fv,fv_nlakapamuxcheen,Nlakapamuxcheen,BC Interior,fv_nlakapamuxcheen_kmw-9.0.js,1.1,thp,Thompson +fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,10.0,oka,Okanagan fv,fv_secwepemctsin,Secwepemctsín,BC Interior,fv_secwepemctsin_kmw-9.0.js,9.2,shs-Latn,Shuswap (Latin) fv,fv_stlatlimxec,Sƛ̓aƛ̓imxəc,BC Interior,fv_stlatlimxec_kmw-9.0.js,9.3,lil-Latn,Lillooet (Latin) -fv,fv_statimcets,St̓át̓imcets,BC Interior,fv_statimcets_kmw-9.0.js,9.1.4,lil-Latn,Lillooet (Latin) -fv,fv_taltan,Tāłtān,BC Interior,fv_taltan_kmw-9.0.js,9.1.5,tht-Latn,Tahltan (Latin) -fv,fv_tsekehne,Tsek'ehne,BC Interior,fv_tsekehne_kmw-9.0.js,9.1.2,sek-Latn,Sekani (Latin) -fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.1.3,clc-Latn,Chilcotin (Latin) -fv,fv_southern_carrier,ᑐᑊᘁᗕᑋᗸ (Southern Carrier),BC Interior,fv_southern_carrier_kmw-9.0.js,10.0.1,caf-Cans,Southern Carrier (Unified Canadian Aboriginal Syllabics) +fv,fv_statimcets,St̓át̓imcets,BC Interior,fv_statimcets_kmw-9.0.js,9.2,lil-Latn,Lillooet (Latin) +fv,fv_taltan,Tāłtān,BC Interior,fv_taltan_kmw-9.0.js,9.2,tht-Latn,Tahltan (Latin) +fv,fv_tsekehne,Tsek'ehne,BC Interior,fv_tsekehne_kmw-9.0.js,9.2,sek-Latn,Sekani (Latin) +fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.2,clc-Latn,Chilcotin (Latin) +fv,fv_southern_carrier,ᑐᑊᘁᗕᑋᗸ (Southern Carrier),BC Interior,fv_southern_carrier_kmw-9.0.js,10.1,caf-Cans,Southern Carrier (Unified Canadian Aboriginal Syllabics) fv,fv_anicinapemi8in,Anicinapemi8in/Anishinàbemiwin,Eastern Subarctic,fv_anicinapemi8in_kmw-9.0.js,9.1.1,alq-Latn,Algonquin (Latin) fv,fv_atikamekw,Atikamekw,Eastern Subarctic,fv_atikamekw_kmw-9.0.js,9.1.1,atj-Latn,Atikamekw (Latin) fv,fv_ilnu_innu_aimun,Ilnu-Innu Aimun,Eastern Subarctic,fv_ilnu_innu_aimun_kmw-9.0.js,9.1.1,moe-Latn,Montagnais (Latin) fv,fv_swampy_cree,ᐃᓂᓂᒧᐎᐣ (Swampy Cree),Eastern Subarctic,fv_swampy_cree_kmw-9.0.js,9.2.1,csw-Cans,Swampy Cree (Unified Canadian Aboriginal Syllabics) fv,fv_moose_cree,ᐃᓕᓖᒧᐎᓐ (Moose Cree),Eastern Subarctic,fv_moose_cree_kmw-9.0.js,9.2.1,crm-Cans,Moose Cree (Unified Canadian Aboriginal Syllabics) fv,fv_northern_east_cree,ᐄᔨᔫ-ᐄᓅ ᐊᔨᒨᓐ (Northern East Cree),Eastern Subarctic,fv_northern_east_cree_kmw-9.0.js,9.2.1,crl-Cans,Northern East Cree (Unified Canadian Aboriginal Syllabics) -fv,fv_severn_ojibwa,ᐊᓂᔑᓂᓂᒧᐎᐣ (Severn Ojibwa),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,10.0.1,ojs-Cans,Severn Ojibwa (Unified Canadian Aboriginal Syllabics) -fv,fv_severn_ojibwa_rdot,ᐊᓂᔑᓂᓂᒧᐏᐣ (Severn Ojibwa right w-dot),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,1.0.1,ojs,Oji-Cree -fv,fv_ojibwa,ᐊᓂᔑᓇᐯᒧᐎᓐ (a-finals),Eastern Subarctic,fv_ojibwa_kmw-9.0.js,10.0.1,ojb-Cans,Northwestern Ojibwa (Unified Canadian Aboriginal Syllabics) -fv,fv_ojibwa_rdot,ᐁᓂᔑᓇᐯᒧᐏᓐ (a-finals right w-dot),Eastern Subarctic,fv_ojibwa_rdot_kmw-9.0.js,1.0.1,oj,Ojibwa -fv,fv_ojibwa_ifinal,ᐊᓂᔑᓇᐯᒧᐎᣙ (i-finals),Eastern Subarctic,fv_ojibwa_ifinal_kmw-9.0.js,1.0,oj,Ojibwa -fv,fv_ojibwa_ifinal_rdot,ᐊᓂᔑᓇᐯᒧᐏᣙ (i-finals right w-dot),Eastern Subarctic,fv_ojibwa_ifinal_rdot_kmw-9.0.js,1.0,oj,Ojibwa +fv,fv_severn_ojibwa,ᐊᓂᔑᓂᓂᒧᐎᐣ (Severn Ojibwa),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,10.1,ojs-Cans,Severn Ojibwa (Unified Canadian Aboriginal Syllabics) +fv,fv_severn_ojibwa_rdot,ᐊᓂᔑᓂᓂᒧᐏᐣ (Severn Ojibwa right w-dot),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,1.1,ojs,Oji-Cree +fv,fv_ojibwa,ᐊᓂᔑᓇᐯᒧᐎᓐ (a-finals),Eastern Subarctic,fv_ojibwa_kmw-9.0.js,10.1,ojb-Cans,Northwestern Ojibwa (Unified Canadian Aboriginal Syllabics) +fv,fv_ojibwa_rdot,ᐁᓂᔑᓇᐯᒧᐏᓐ (a-finals right w-dot),Eastern Subarctic,fv_ojibwa_rdot_kmw-9.0.js,1.0.2,oj,Ojibwa +fv,fv_ojibwa_ifinal,ᐊᓂᔑᓇᐯᒧᐎᣙ (i-finals),Eastern Subarctic,fv_ojibwa_ifinal_kmw-9.0.js,1.0.1,oj,Ojibwa +fv,fv_ojibwa_ifinal_rdot,ᐊᓂᔑᓇᐯᒧᐏᣙ (i-finals right w-dot),Eastern Subarctic,fv_ojibwa_ifinal_rdot_kmw-9.0.js,1.0.1,oj,Ojibwa fv,fv_naskapi,ᓇᔅᑲᐱ (Naskapi),Eastern Subarctic,fv_naskapi_kmw-9.0.js,9.3.1,nsk-Cans,Naskapi (Unified Canadian Aboriginal Syllabics) sil,sil_euro_latin,English,European,european2-1.6.js,3.0.2,en,English basic,basic_kbdcan,Français,European,canadian_french-1.0.js,1.1.1,fr-CA,French (Canada) @@ -82,23 +83,23 @@ fv,fv_isga_iabi,Isga Iʔabi,Prairies,fv_isga_iabi_kmw-9.0.js,9.1.1,sto-Latn,Ston fv,fv_lakota,Lak̇ot̄a,Prairies,fv_lakota-9.0.js,9.1.1,lkt-Latn,Lakota (Latin) fv,fv_nakoda,Nakoda,Prairies,fv_nakoda_kmw-9.0.js,9.1.1,asb-Latn,Assiniboine (Latin) fv,fv_tsuutina,Tsúùt'ínà,Prairies,fv_tsuutina_kmw-9.0.js,9.1.1,srs-Latn,Sarsi (Latin) -fv,fv_plains_cree,ᓀᐦᐃᔭᐍᐏᐣ (Plains Cree),Prairies,fv_plains_cree_kmw-9.0.js,11.0.2,crk-Cans,ᓀᐦᐃᔭᐍᐏᐣ (Cree syllabics) +fv,fv_plains_cree,ᓀᐦᐃᔭᐍᐏᐣ (Plains Cree),Prairies,fv_plains_cree_kmw-9.0.js,11.1,crk-Cans,ᓀᐦᐃᔭᐍᐏᐣ (Cree syllabics) fv,fv_dine_bizaad,Diné Bizaad,South West,fv_dine_bizaad_kmw-9.0.js,9.1.1,nv-Latn,Navajo (Latin) fv,fv_dane_zaa_zaage,Dane-Z̲aa Z̲áágéʔ,Western Subarctic,fv_dane_zaa_zaage_kmw-9.0.js,9.4,bea,Beaver fv,fv_dene_dzage,Dene Dzage,Western Subarctic,fv_dene_dzage_kmw-9.0.js,11.0.1,kkz-Latn,Kaska (Latin) -fv,fv_dene_zhatie,Dene Zhatié,Western Subarctic,fv_dene_zhatie_kmw-9.0.js,10.2,den,Dene Zhatıé +fv,fv_dene_zhatie,Dene Zhatié,Western Subarctic,fv_dene_zhatie_kmw-9.0.js,10.2.1,den,Dene Zhatıé fv,fv_denesuline_epsilon,Dënesųłıné,Western Subarctic,fv_denesuline_epsilon_kmw-9.0.js,10.0.1,chp,Chipewyan fv,fv_denesuline,Dɛnɛsųłiné,Western Subarctic,fv_denesuline_kmw-9.0.js,10.0.1,chp,Chipewyan (Latin) fv,fv_gwichin,Gwich'in,Western Subarctic,fv_gwichin_kmw-9.0.js,9.2.1,gwi-Latn,Gwichʼin (Latin) fv,fv_han,Hän,Western Subarctic,fv_han_kmw-9.0.js,9.2,haa-Latn,Han (Latin) -fv,fv_kashogotine_yati,K'áshogot'ı̨nę́ Yatı̨́,Western Subarctic,fv_kashogotine_yati_kmw-9.0.js,10.0,scs,North Slavey -fv,fv_tlingit,Łingít,Western Subarctic,fv_tlingit_kmw-9.0.js,10.0.1,tli,Tlingit (Latin) +fv,fv_kashogotine_yati,K'áshogot'ı̨nę́ Yatı̨́,Western Subarctic,fv_kashogotine_yati_kmw-9.0.js,10.1,scs,North Slavey +fv,fv_tlingit,Łingít,Western Subarctic,fv_tlingit_kmw-9.0.js,10.1,tli,Tlingit (Latin) fv,fv_neeaandeg,Nee'aanděg',Western Subarctic,fv_neeaandeg_kmw-9.0.js,9.1.1,tcb-Latn,Tanacross (Latin) fv,fv_neeaaneegn,Nee'aaneegn',Western Subarctic,fv_neeaaneegn_kmw-9.0.js,9.1,tau-Latn,Upper Tanana (Latin) fv,fv_northern_tutchone,Northern Tutchone,Western Subarctic,fv_northern_tutchone_kmw-9.0.js,9.2,ttm-Latn,Northern Tutchone (Latin) fv,fv_sahugotine_yati,Sahtúgot'ı̨nę́ Yatı̨́,Western Subarctic,fv_sahugotine_yati_kmw-9.0.js,9.1.1,scs-Latn,North Slavey (Latin) fv,fv_shihgotine_yati,Shıhgot'ı̨nę́ Yatı̨́,Western Subarctic,fv_shihgotine_yati_kmw-9.0.js,9.1.1,scs-Latn,North Slavey (Latin) -fv,fv_southern_tutchone,Southern Tutchone,Western Subarctic,fv_southern_tutchone_kmw-9.0.js,9.2.2,tce-Latn,Southern Tutchone (Latin) +fv,fv_southern_tutchone,Southern Tutchone,Western Subarctic,fv_southern_tutchone_kmw-9.0.js,9.3,tce-Latn,Southern Tutchone (Latin) fv,fv_tagizi_dene,Tāgizi Dene,Western Subarctic,fv_tagizi_dene_kmw-9.0.js,9.3,tgx-Latn,Tagish (Latin) fv,fv_tlicho_yatii,Tłı̨chǫ Yatıı̀,Western Subarctic,fv_tlicho_yatii_kmw-9.0.js,9.1.1,dgr-Latn,Dogrib (Latin) fv,fv_dene_mb,ᑌᓀ ᔭᕠᐁ (Dene MB),Western Subarctic,fv_dene_mb_kmw-9.0.js,9.2.1,chp-Cans,Chipewyan (Unified Canadian Aboriginal Syllabics) From 447b83a838fd436dda5c573b818ea4b362443c66 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 29 Aug 2024 15:21:31 +0700 Subject: [PATCH 11/52] fix(android): heck in material-stepper as internal Maven dependency --- android/KMAPro/build.gradle | 10 +- android/KMAPro/kMAPro/build.gradle | 1 - .../4.3.1/material-stepper-4.3.1-javadoc.jar | Bin 0 -> 219877 bytes .../4.3.1/material-stepper-4.3.1-sources.jar | Bin 0 -> 48791 bytes .../4.3.1/material-stepper-4.3.1.aar | Bin 0 -> 121509 bytes .../4.3.1/material-stepper-4.3.1.pom | 90 ++++++++++++++++++ 6 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1-javadoc.jar create mode 100644 android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1-sources.jar create mode 100644 android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1.aar create mode 100644 android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1.pom diff --git a/android/KMAPro/build.gradle b/android/KMAPro/build.gradle index 7e49d3dc01..4fbfd72881 100644 --- a/android/KMAPro/build.gradle +++ b/android/KMAPro/build.gradle @@ -2,8 +2,10 @@ buildscript { repositories { google() - jcenter() mavenCentral() + flatDir { + dirs "kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/" + } } dependencies { classpath 'com.android.tools.build:gradle:7.4.0' @@ -11,16 +13,16 @@ buildscript { classpath 'io.sentry:sentry-android-gradle-plugin:2.1.2' classpath 'name.remal:gradle-plugins:1.5.0' - // From jcenter() which could be sunset in future + // From jcenter() which was deprecated August 2024 // https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/ - classpath 'com.stepstone.stepper:material-stepper:4.3.1' + classpath 'com.stepstone.stepper:material-stepper:4.3.1@aar' } } allprojects { repositories { + maven { url uri("${projectDir}/libs") } google() - jcenter() mavenCentral() maven { url "https://jitpack.io" } } diff --git a/android/KMAPro/kMAPro/build.gradle b/android/KMAPro/kMAPro/build.gradle index 226e912fbe..01e2de32e3 100644 --- a/android/KMAPro/kMAPro/build.gradle +++ b/android/KMAPro/kMAPro/build.gradle @@ -145,7 +145,6 @@ repositories { dirs 'libs' } google() - jcenter() } dependencies { diff --git a/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1-javadoc.jar b/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1-javadoc.jar new file mode 100644 index 0000000000000000000000000000000000000000..895d772c3976617b65c3fb988fb60f6e132438c5 GIT binary patch literal 219877 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%0Aqz|3wIo{y6{Jwzh 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 literal 0 HcmV?d00001 diff --git a/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1-sources.jar b/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1-sources.jar new file mode 100644 index 0000000000000000000000000000000000000000..a3c414838713504399b6d6f14d80f2819f7730b0 GIT binary patch literal 48791 zcmbrmWprFyk}ND{W@ct)W@ct)X0#YAX0jxUnVHdImc?K(v&H=C-s$P-+w=9Cp6}IK zrBy%n-sh;+iO9^z$WoF81%m+sf`S495f_&Q0=z)}_yc%B1K#rDYQpr=3KEQO z{<7=Xg8MJK2>#_RV>4qXxBrjbFz=6Y8K6Kwlx z3b-fX|2Ub!#@NF+M_t}=oeQb^Ruj%IsgWUv9)q8Z3hAg&%UHFuZUcg!-pZN|HBpLQ zTAMlQ?GfSLcr-5A{S20W_vhrdOwPg^?9RENrBSzw?f2*JghVb{VhXgOP*W1aR@j}T zqS|tKYS1`NwxQC*COm83ko`nWi#4uuzl&}IhdkIYb(!hvi!ik0HHFNRa3^4Bu!#1R zV!=YH2v^;bB#R6|rMjK*NSy^YUR8s3y9L(;&w^`L3c!S#!X3AI)U;v6S61v6Sd2AG zk7$Q9?7dzeI^b+}la|Ezt7GfHLVVH|=Yyr|B7xsT4kfLa7l7Cc6+xU#ThBDI%uA=n z^_`|xh6<-ioyF*-In)Z_(~dVG=Al4?he(4Nvjv_>qe+lHATfO8`s?=%nhAWD!`#sa zYvkUTENR^#$(A2`0ZTsde4@<$6$ez#hX(c?X0IJp_(V1W+7fx!;5yY|bOpq;J&D=8 zXkMiVs{B`;ataihm5a6iEuFHg7KQ6cXypawi4%mS>2O(9{4ZGcSY4Eu`{44=L{0`2 zWiGb#7-VMqY){)JIj^cz(SxU0!S5RfJKglKj;{Gq)a>8{G@O*vUN9aNi%pXan)%;) zrI5fs&BU@$V^y8MhZX2em0vRw@SVt9zwqLIMc;z-Jl-?UG3@cbqI?V>60oR2owT{; zY!L8`CW)V!E^B5AD!wjUU<&3!EvmDj-(#POq=mO0cnwznR&}qsBdJ3}i+V2cdqkaL zaSxa8qzkhNW5czutUzymHb`r}C~~Dah_ZS$b*Xn1qcYd+lN3K+h7OPR6JZ|`47Z1$ z@VZbNOS9U^rjW^n6fZVTjU)sVUg$#vZG_J%qMqi3$NGCBaR*HYD7`|tD^=(7OA-~ zgxl?kZ#zcjZVCu95oDNT14H(`C%q}q!(%dIG7JS+Ds zYfH0C#Rd;G_e07!bKoJ03uc7hBFBtYCPF?cU#9q=$n$ob&boO|o; zs0$+xO@IRWvVVe%Ui5xJut}Y76!ure?4sAqz&l*6ji%)C%NMz9_nfI|{Xuff%+svr z4^Mb;^=tb2ViUXfr)k(?kK`Bq@t7V?;Zn0-cLH4OLCfr`hA_EaTL^JZx9}&y0*&AQ ziw0M|G{^|Lm_CmI0|D6rXp7_D#{55HJyo^eVSx#$`-t{1L!USuv=zo06A1;SDU#&U zz_+3PbR~^{HL&81ckc)Fi3e?}-tJe+U%srjC`BFVl3)kCiBO^>S57?OF(NkDPl3EElgzqM4e{O+E+cElx^FH^S|5fMe)2lA za7A9x@n6n}8(flOx)~Ird%hiDN^ZIQFxOnS2iIL06s8EBXQiT54bEq;2#Z{hOeZo0 z_CDsGX)|LBb_~=BjmTlY`~W}ge12E|xZ#f_Nq)DJr$O^$^3K9>9~Lk>#wa9?lLyrU zML6o5d?l1)!m@b=l1~|ldrYOc)WyJqOun81%jFt6Wq2@6cC%sQ(I_bEl*C!(HRxB&1Z+NLX#{F0&bNoT(+U5ncsoA$Gb^dxn zyhMT!pVl`rcU1q81xLez#PB~p9RK`KI;|@ZhPu4Zdtf+Q|D=TJ|f!SKYf?Zf+YGBcMTX>7?C>r8*(Uhpos_4k- zc&C}walWdnlD@sloAnp8Y45SDJQm+bdE@Mw4^JN2k>Lw-X3j+cwk0i>8AE<1mH_q^ z_-4)&qD1Theh6l_otbw-2Fzb1f3tqppyIPahU>1V22wfMN_>HK6MHO$_Z0aMHow)CkVrm`o5g@lih-vM;Y1gYAH6d z9jVU+Uid3IR>iVPe!us>8kKblF1F?G4ZzrDft}7MVe2c@steTP7q+U)Mh^jB&wC=L z1T5T}nppXd{6c&Vb9V38c^8FIE$^y!TF%*7WWc%qowh$Y{rg(+q{|%>NoJSfDRPeR zN9pB+e4%$8_a}Rq_6>tafK9)ve|p!6?>+*^70J0-;9HOgt~6B1x@}E8$a))5Iv8IV zLM2(~r%hGMysb-=G{QLV+r&)m%+scA>f3c{|Eg6NkLLXHU4CI_1e`|3FuX(Z>xi71_ZkJQD6!fe6{lsz{gj2gN zoZ8g06!t-M6TK$(C`m`Pp|H*(i>;z>#>rAHpy756$0xn3Se2R!+aagx3nP;5`n-hw z*osiKrID2)tv>6Gf4@ADeOcYNlBIDpxg3PE6-yy$u)Uvw#19$}^))hQJqx9pjVA|uoqnM6gQA=z7FT08hSeTO*^bieMCxUDYPO4s z?nN{sZJ1RFm)QtwYNo$E(0LBDjASlCetP2~@U1I{{(c8(D}l?AW63h7bYmW~Sk)2| zm`>}ZcSyT)cJb%WWVB4jrmwN?$Oy=ww~Xf2=$$wF`1k=FFA+=Rr4~VETs1!|ky zW2yb~9IB()(U}-(?VV-8E!=3Uc1oOB{0N~w3S4p27@({uvxxjdjO{b%G(s}6>*0A5 zI!)-Aur5hskQ5=z?c*dee1Q@~lo*S636M0H1na2%i=@6wl72NRV*JjUwGLFf`nZFs zrdNKAW_X%%#qP{~NlAXt5PbtB(=LjxtrFNeE-p&rJDHm{uhOwr%OAbO&EXGjzst?^ z)HoQ&u{aL7!2xyFW1g)B{Y!W-zYzgc$^D%K*LT0$805Fijvv(6z@#$Qg}EYd2B}mn zO=nXBV{>UOq1De|#p!xeKmVu<`+z=&;@F2X{Z9SmTM6#wuZl2t%dpomARb2D-|&gd z^fb1ee0iyOli0UQZyxa9uXpzk4>^lFlSZ+Awm9 zG7!C&v+g4XzI{$7fLhO3nka546XYU&NeGLW!~8280SNqi%|iGu;b`pus1zKG?f$Q& z2G#$(-NM}5%*5E#_P?Do=RI@H3}6LINFbm;>X$!CCszRW|D!DWQJL>J(+ibq=JFt!HWk?*`Cxg;y3Mi6EMwFsK8Y5+-1Pdy7}N5@1yHIaASS#E*+;U**G*vNsWd@0OtFVN^KT#ue3x@Jxji zPxNkI-PYXkG5N`tOENSdQ*#&wzImriZXr>d;;QF28(m*%;IOo9hFC?CqU#n^ib1Xg zQo+q<|IBSpR_WA0V12a+h$>^-RknMd#*6SBeS^jwT9XY7aakf=-5h#iioiOJ@}qIe z)jzNvzJw*6np;Jj7A92WYLbu2T&HTX7kBCOiGScdT zmI?#X*tt?cciVTl?&Osl#=E1h*XFV}=SR0=JKabNr8_v3|$~Bf@@y zuf#tXSvGmJZ-mA=;yX?xqZdcEjoV=a91q3Vy1R&dz}WYvjK}bYu;yJh+%6t}Perjq({-`E z&+H%tV8Lu4;*fd{DD%qxhUqa-sxAARv_lfSpQhsM2!C`Ms{Q>{u;FTl-apPTGWk_p z$#>fPEVzPt2+6VT)|Ir7lq4JdGh=1YO74r17s4o*Tgf(9vbXH=D--Te_F7R3qQU&c z$%CI>fXoY>T+n4`>vBx^&{hN;{mCe9=1%zt{yq7MiYIL$Y{2*IHJ0~xCON+XLS%kV zv5WIp1j)UTuX}^yGtLqp!Q%y;_VQaDh3Z{zq`8!1qDW!iK?2_SHyn09_L@CpUXBWL zJ_me#+&&;TuFehrN)XuZT%4oSc^}UWg-+j#YdOYCA`^uSJL2iePwEvMJ`5tJL)E#AwiVHAO+QOEg8=;TzRNT{vCTeY*&t7aF8;F7n*a?{Q#qg(KR8GY3P z*Zcw}><6wYh_H+Mn_8<^*J0^;ES^MA5Aqf(4S6zcN52jsjkxAlFrh%-D^XV`aNI#Z z(VJ{_l?NJ?-HDfs^yIVlbRcbwO3L5pIy!~>D z`ter=EO>Kt4sqsZXsaLg!l;dDinG4`x<2s%r5Wks63K*DBk%tGvt5T`CDoz(M?dDU z?8i??G9gwH!mHMo3QDveY6rjb58SZ7HF8vz-1X4tr>L#6-RH!%;o#wGtykg zZ8#l9nmWHMLWKo(hSzW3bH^2wEI7y^3ZIIj;j5iW!fNkuQ9qLBW~7gn9UdB3)uV?o zLDu>nR9%NKz76cfLhdpUTIHn84O-P zL6~(@y9t>9;7B^@{2{tYi#Bpa|moB^4{tN zIA31yIXk+gMRZf)qV*8g!xG8;u2J3;^Qp9Y_GF9SlN5v#czW0l=vo)s44Jqb%69R4 zHdN@PdD%}hTz*gW1N|$C+jIB*mH{=K9H53%{NJNk$;Hvq#oX2PU%@yP5M$Sb;6}Et zRJHuEi9FnVGuhb6g-$SH!)Wr={IlYIg#Hw{^zbAWSM7cEBZk9LUltEGI$sf7|CFsA zl#p?Zozy`1W!UoyR4$y1jA@o6Uw7|h053MRBJlAI zMMq$}z*)cP)vi)TE1Di{T-Z7hMG96nlXTlOcrA#INZB?=R+$VS@l|$6B?mV~Pz334 z3D*Y~uxn53Q6a@K=h+@)f2^FTs}G6GkEM?JJTr_xQ1n~j4ezyzjj!k@76Rg{B{e*I z+e+~4kHkpuxq|`_b0IT`v7?lusu;J1(GH`TU;!z})W?@w&(!9B<;`@ol(6k1}mOcz}nM_1(pic=Fl zHF2#&?@#o6!(ppwU@}F?{z3eo%uDCF+eLg+$WuFa#zcwj@?=BF= zs!HVyMrKS^Sbj@0#X!t~9vr*#u$i=3Q$WhoJL$?pnvy4{rYBDirL}-}SVLe8cv*87 zKb95@`-|>3#SC0Lc(_w-*vPbGGGG>YO1TJoOLShpCuAW!vaurW429dmG+bxDE?*)U zu%A`I+wV(oB^8pX_su~V`OC7fl=7B;UlD%CEp285qg-E^vA1mg3X^qKMdBB{l(;J3 zpMvUode622VNJW+G~4`sDf%%jdd2a$0Z$g*^^Rh-_&#Gy?IRh;8?^A{=QKfMdLtEE}_ z%`bJ3*B}KS8rDpOe9a(wAtW`rpphOt0hf>AfGV_xf!t}2Tb8<)GC{4Y+9WUya)|}n z!7+Wp7$U5{jEqP}Y91xLYPQ->mn)a-_7arA;z2LlgaP+a9-0rV>ARifW#%V-E@KeF z(gz#jc9?Rcjk^;{H{Dm!T-h$1274BxrG6=v2TGfD#}!1ji^5Zgw%Y`{r;Jl-c}`*Q z<(nbnjzyDJOp-aDym3$97+-r#`VC+HF^t3*yIqRJb;s_iDM&H6y* zUjm;>`}*SDM`AWDQ#1JSPvM1ky?R7(dv8YK#kXHr-57CJe5_XZP4Q#<2m79K@`$JtOo{2C+7hm()s@ZqQ4b<(ti}BfVR{B z4MzVJlf1g%ka#d2CV4 z(o#}sD7gtQ`3U~mc9O}V6+nzoS9excb+Jz}UJ_f~QD@4W9yoy{F+Z0ux1z^-QDb?UBkfYGR#}SUHam)l^uZ@CYhJlAp(l zKn%s}B!Cd&)OQ(tu>3rQaycA5V?!>WE3+Ue0qwu=uhldVUINX8%+a7<$|=?rhAg|)UTHKDpQ3;eXv zuvk5goCV;Bv~^)7(@;`7=GQ~S)Vs`VR7b!MfoAnFE@91HU)uT(3i3(T$oqsj=O?}* zafvVJ*^I-{zT?d2kJ83%c3~kc9BuZ(M}ebgMUZX6;t=*4{5CW1xjK1F z>XlF|%2^siowpW&mNQVBEne~H2T>S=1#+_*`ch}{LVVW0!FtLf`M%JuA~>Iny@8k* zn06h0Y~oEedi-cs#%f27(@;w)a>^s$|Ftou1IcOi3BI_Q8WKW$MP^?`P%rGuuNlTT z%TIKQ-!lZw^DupDkK~D&J)FHx=<&$of8*CP(sIU~!$xYlab+f23Cyv$*gW@DaQL;U zL?EqtkN2JGM4(LkQ6;FnqWGjn+~P(nIE6p}8Bc#8^LH&wr!j|p_x+{J8QckMWbAv# zN483~W!B*_rk~E$WAWTGS*o_(HT7zzei~(lVN~9iRHRNpG ze3gT;&e&0T%11L+P2+enW4bm13Id8qZA9yrl0t$i`2llc4>5+Lr7Z#puJ3c)7_7Zq z<`2upET)b%92O2EPs|D*53UFcOGHTD!eF(DH&qOxN@N!6vM+R)XC4+P$ZT)tB3-WY zE2ZzS%?uuxHp9gl?ae5j?)AR!El86pd zy_mhXQ~id_sfogdOdpcO4pvX!>n(mpdv%O(^}b4e3y78dH%SvLvrPJ_G#f1!E<`;W zu}Eq&#Cv=OXQpgj1}A6d$b>KBRK_q;rle=NF}M|+HP#Df_86KM6V{$DSR$IrSn-2i z%sJwmjW>Rxmv-qJk+x|mWbMU?Y~d8Ts1lv2P1Qnm=!Pw(Hw^~(8XRs%15@>;RPhwI zMqa!G^x?{QlAh5_ZQnP*ZpdJKe-j!IZ9y-`;mJO_fL|6W%1r3+b{h{Rz9iAoC>uxl znGeR=9cOJv&E9>Sc6^chDE3kJ_jjadnhdTiMgOuklp>ckKw8w|7FNoQmMqkS}dC%z=HSSKF6}G;OtWR84 zil&`s-O}B6>ihTn{&M+1)%2}8?^>P%_HpDD_OIZ8y<{Sg2Lz@7063)o-@qa2Xz%3c zYVGzn{ZUOm9-u$|;eg=4yc&=#ZbyquHbS=y!P#63J78NOrH>_VK`T#6K`$H)xJpQR zOWe%kR_m*gcRrl*Wp&KnsB5=I&`3*-&}0mF!DfkrrxnMHuLau34r z3rpZ2DUIK;fCkrTJy5PM+tPRO9tqV`zu}vI4-K3 zGB7!$Zu6S;qd@(udq74l21-?V$KeW{w^T^E%z351d%SbV^p~BHwOvdn#O{?DytO8; z(pTTFZSsKuv{HFixhw^))um%jzriXXadmifc$6 zRd2L>6bO^js`wBH(WBth%)?=ce9NG|SlewYfSFt2V`Q60Vh(whQ10PO9w;0ZNu^g)Ak^F!#J*G*LMqtlkOV+XeyB@ zLXiMMHU}6hAy3d;gH}Yt%uv7JJIxk+No2(EIKOou(;(*zS$Bw!fwa2T!Zik)hm+gD zH&4_T>{DV*Ge6nifZoV;?l58v%jVTmig6`{skw>eUK$)`?;IibXBO7Lbtw5aK1vcq zyY2h0OWqn@CP2Mqul6~s%saGapPvy?Q3eEaABtJ&eOo)|=_GtjSmMZ2gmdu>u)pF2 zKlfBZzo!W7)F5jtSmyiFkVh6^1t(GZoHz(rWGh}^=a{av_Y_(w2qmkIp6e|tUA+#| z&PisICQmHs-c>J_>X1Gy2mDh-#_DBFx(UE6790?e>5!ql@>S9fNL-|MV

t*JfXs2f@RLeVoFa$%GY`i~>3a^>S(y&1B}wP;XnFRAUMoZNjqHIo zi3@on5)~WPiM4cHoo}~{k@RWx>L|n#-N@89!xn5(A=qjxqVOJJ+v$A8`S0@)xC;_g z&{tiu$8CYp4?o2pqb}6IZF@k=>C_;gg|M`uKmaWREgd8jm1YLme)Fh0bPsh(Yhpf+ zb&#^K1GEY1j-t|oJ*w?AfTm$?|NLlFx9Pxd(0G?J4JnRl4$)}D2E8{%_#>r$ra{P5 zXfGgjmdvRh)Bq(ug)vgUzcr8TT94Gfar|b(#yD*9)o5YfpB~o#>hJCA$wZK;UtZEaL~#lrdV^9uagwLT<@+MC-L9Qrv5x z8i7pkmdr&Ps_>3XMCJ%U)!3I^OkgH2F`-sbA-jz_f@)vOOCtl5S+F(MyM~(M zaM2YMOx$BWhQ}&w_~K5rz&4X$9K$N-FKLyVkXGltLthS1HM&h=sA%lJtU~7mw-v`ffcLbMkC?k#@mH(LH+A|Y=MY6+FdTBs2kh2hV#DF{ccuQk~ z=q6AHF5zpIxgw(Ha_?8?Sscyb+|I+*!7=hA&nod)MjXw-Xq*_g5zZ|n7go0g);;`* zK|>rWI{Z3(RE&Y^aFaQzfO+{S?e*&z8Da12-|zuzk9cUFK|s z^CxHpyS7)*Jxh@f&JN9?MxihZIyF~6>8I&e7T2(RCd(4imxk?Uzz^qI@a?Ai#V6Hu*AK&l|Mf^vk&X_H_}DJq7LEh zfgL`19F$IEuv3oCR+u+QJ0x_ip9`Z}jYE989F~QD?ha#C>(4-0@kLy=h)!He&%H?U zacRSp%5*}?wx7wRDX&}b$?<;P@Jnq7@b-#E^fM=FiImTy&j;-cH3!vbUJAp zD70m|Zj4b#E7@u$F21b{@odB?oMo`9>q}|bPF}S)%}sW9&#wFAzWgc}GvgY-P(9LU z=ce@2IZXa(AiMu6yQSfE!tZ25n!?!S(VDpzvFKN`mfbpWO( zaex<7?0>-^YQ`r2QVg8}(8nGi;Gb#2xg>?8C_Jj<4TDtv_*J7+o1>!;oDHXgvo2QB}{8UVB^>Ru;i`*b+9x2Lozd!=EnOP@vy`@JUM9iAjw+bmTqQb{lx zEA|NfgaV!-VFHYO1zjZJCc|Oz8?Bd+eQ474SN)JH5QYj(%$(d-b?&NXjG~4FTrwbI zBVrXWzpu=VL}Wi~a*Bf|u#8F1E2LC}nXbw~lw2pM(^TCg3dLDr+V1)O;ExC2*3MNs zEJiJs;`Gg?7?w?AFJ3J15W~pwqs0KA7Dg34V9CJ%GRQK&+wwX9nL?i z_=?Lg)bRsq7fW?v!{qqbg62TuM71$ogk)LL(oU>FY@+1JM3%r^s8cKX*Uh7{H=)a# z*aQ3|7xnI~mqRQxiEd7KQqoRe^`s1W8#>BZ#&zTz;Rc> zy_e8aX9fmIQ`@!&1Z6~h4y-l^w8*s^Y2zwAvIsT_f9q{3{DN91@X8{w#$<{Y=Ukaur+y_Y1HwIp6 z3Ld-7I2ZM@nyB8L!+w90LP_b~e0D8XDPpLn;355>OA~(*>c~w|t2eB;Xke{>*m$jS zwBX}v&(@+svP~^nz;#GkccJ$+$6CrGi5;~`^FTh`7RIMN4_ z_?EO}c#svx*1H$(FD!eC^Ig#RtFMJEYvl!70KP5c^TNb6_S;K) z<48DPQro9vi?PUwHLR)w=C0VKi$ExJem%o4XQfH)pvE>-js;b%A^s4_T9erlDte__ENY z1aL+8-1=<=(8u$uWPVc{@8P^HZ}@7)2psJid&2UAXV2st!en8zsbJ+Ney1(S#*g|V)GT-bBXVR0S^jam^6s-;CJ^TW^ zUULvNedZSz7_Ju=<<|*ZbSras)oJNN-|HgQ(0Dap@f))jqdpNGc#hxW?P@rZn*%gI z_zD+C99EeTwaPw%>+BV5Jf=4hyrF8)ODygO|ItacB=%R6JK6utU2XtF#9w?Dl~&xc zW+XGjSpfc<17uKq|K=J0Y5D$}Ebw=uMe0BBo;Ib_ft}9XY*A2Zyhm)w!+=Z2XnEd2 zy}THOdQwy}!|yF#(YY2gK;Dm-hy}mZ<(-Y_p;&;c--W|%$i*f2`ovm<5WQd>mQdiG zhP_7BQ5w;}6{aFT7pO}_7B+f}+>bTXZ=BapH zzgnaIn$FbzaI>qSVe|E4YLlq@H7G-3E@XU8hv`X?8Xla>8(bMFUQRAjpFtxJKC)f- z<&f=G5BsDj>wEAbYby#wVR_T^sPqXANVT?dkvnLT6cv|@%5kZrQ%=$Q9ox%1VE~Rm z%#JJz4ta?4Cqvi{ltXyP`bV1}-s~x-6h!>BWPp<|jMVQ0R6lAsSIXd|;z4V?;z;-- zR{g|!a0?d-)+nhdS!T(MGfTE8kRXsL6&(RS*@Y5ihV*&pqvdL+T_}YPWw8bUW*B@O zJ8EM(%9sGsCM_Dt6_WT(+aOG3vAZT`IESX};TAeCd|2`4ZTulll9``L4+eN9Rj&3g zwq?wK(M6)QAZ!`5=8OA5gks7-xDo~*k1%1t9gZ&7c z!9AwJ{j95_t1fhNFDp_1xN8~B3G~K8KOnOdKz$)&fuY7s*_76T$Q(Z3u~k3H1^ram zR^;Dt7;rGI$btX7da(pTxS1w1r$BEAS>NFbGu$~pINuxkB*BoF@h_JT<%W8`wR(Cz zW|05vQIJTDxNV70TpJB&b}^yVTzrxW3h9bTKI{7&;dlxBwwU57PB`q%gtwt?B?#Vh zs!J+p+@4(HK4?E}*n)Cjv39aW->%$dW7l?y2U*wWIMeQ#rDo^vE+-AVGxC$%0fjui zMLHXPOQ*t_uz;dlhX@fn;K|hugYGcH`4wZyQ?%rJ>Tq6#*ALr3f+4cBx19HYC5;9! zdS9x6^c;USys3=v8$4^QO}a8|QauZwD9z~ z83@R&Z_>-vR}wmQ6<3))An>#SxKRC`T=E_yykTFLxaXzTMc>S(`!TElmHjM*Y~HkP}nzo$l3gfNnv zXO@7#*0`DKin7(B2fdy@(5!}wb>CYBY3Qrv-Je%4O6#T6{0yy_+>+k{w@^$wX{dV2 zr`SEDP?}g0b)UdmB4tZuJ(el-@ShDEaePbj!c{+2X#vlI)JJVSTvBOcFx*ztOhm$= z>0vaie(8O1DbLN?yov>{9=2M<5b3^{W0uo3d^)=%XyFiF+3?eW7U#s&1J71q)HBQD z7(a{qHIWx%^V2O0`Ed!eY`l1`=G2~!HmsS!({a&TaXpsG*>~d6%U9{)^}U(Hp0DTq zpJdS1PvS3Se^iYC2P)UU$$4UqZvUC@{hjZs)&DN+JdiQAxFvz`|FCNOu%TT@1fA&Y z&&6nBOZz%rB%`u~)Bo{^Kt7bVtiTa*Ocb?0xd)hSQTxn_b+6}SS?BV4JiKs3;-xbw zMHh*&phRtonX*#CP^D6jg4lpC)`|=b_c(&MoYN{t@7i-Dx`xoaSWxek^E?4jugO(74b{5haxE>YTZSLF)~J* z<)}zfQ%OWe?+{`Ogz|(MQzGJFTjv>@IK^Uc%H-1=REmcZVP$!(~7*S;dtc*`{y zVP!aN4A8Awdtb^$(wVq$P;BQ)8K$z4_`<6r(6%*^^6Z9CufZ$n#w9 zcAb$0@=S+EA07=kaBOI(+MEXu;m4e}Hfpv9uDx&KXk4k;1Iy1U)!ZoW?HHdY47+S9 z-d@lWNQPO&U0|oXQ5-Qu89~#`q?cGIrRRAi`!h8xk$30XR?1cyJMW7N6M3TGmu$t7 z_~hr`&V0SmY1h1OJY4R!=QAqc>$0nr__#fc84#4k;OjZ}ku*(+<~Z_B9sFG9xr8z? zA&o=7s0B)~R2XOG1mr@%OM@LQ3OTtS?Lyl8uv(8zCYkdO>ZhBb8`5FBuNv-wJQt=I zi3}L-JJ|Md6mI*A;TPFbFAEhC?RZyTAIh7!mWo~a!zw(f0&uqtbfmLV9SAp;F9?Qr ztT-;71R4+Z5#14=j&OQ5WW*m!$PmU{J6CE)*10#sBuZA$r{i$q9L`=mS1ib{UDUOn zn-$k&wgNfp=6NJLex8h2q}`EDC43>?Wy>pxd~RR&n$hXB+^1IAtcUGyseX7m0z+i_RwR~Tf10}Q+P(V^QI zLn5t#H_?I=-GEx#xX(3kMQsX)y?wY2cw_DQ9GmgTGjMBTkOd__XVK}$$O48qLXeWogZdWnQuAwL1)mW9_`^F)g$I>Z}V4E><$U{ZB5`-8cVY5pfM24-5|^5Wt^cCfEKX8N^< zgd}U}$TI8UxvpMx&RDC@cv1aGph7&|-5}BK$bv8F!!EUfs3_X3#Id%$`IdV|{U*NM z`StRUmBcOlUo~=^bYl2y0CRo-ynurLCUgF$bx6e6<)6Po0D=BlCUTtvkT7d%qV#VQJuA|<4(g4dg3@b}#7r0U znB`rG0;RezK1zU-g0$5p*%l2S4pB=usirPg!WJQaFY%bq+CJ}L&(kzWs3Ni!?R3|K z3AKbfUiESmK!Et8Nh>+lOb=mBdH~Vr#Uej{!W)%Rud80*YIO5GrzvIo6lg#RFH=j| zt+-4`7b#4f=a%P(w)ROe&CB-Pn&tq>MDeXgjmHOAo};pIi9T?!6jd8mF;Xce6G5@_ znx*0H0paaBxgRz?MxhzDqG|@C5sRY3t~sBg)gx|9lJ66%g2PK77$SE+q^amRS{~f2 z@w9f7*REgnH>2!+xf*i`>~a&zKfJkfG%{dtYt?S~UU4E5+SIM{u!dLPiwCjqAYzcK z0w8JC*e)ZP7?4UnNNn|J6kEi{-ut%`m|+xk31f8WT`xT-&fArKM64kzHpzIHbNhuH zgMema8lGCt`+i05EnJ>EdIrKAOrQB_kpoRq6Ckd!Kk%esx!~7Za08}Dehb3?{a9ta zuXRQPGr!2xI3Bw#!SjJb%uB{U$PXhPvv7!i73L%XD3X8b*-0xiHbI81Jf4yox~h^Ae-;;6{#Qc_ z0968S&kxyT$$m;7NfqF?O}BR^E1?DCRnsHkUKbFg#>`itEMdhK@h~V;=0j zoOTG9z-t94(E*&K0*xHoN^w-ard-?xa$UO&X)DJy$^D|NMEZ&N>%r~S%(EXf#ktBd zFX=>Vh$f>!Pxyjy4i5nFY^^Mk6Dz?6<0indG_!&0M4`>2C+t;nJG3~o&B2;);4%Jv zR$4eY`gJ)DMzkJ)Y2aZJU@2HzZQ|`(JX^pta80W_dDu9z&It$p7@!q41(c_$@JA~w z%i?VCPpe?PbBzFEaEpEWv6_qhc;0EDU0o!@kuy(#f(&-2209>N3gDPe=wCz-ljm`% zCvi`;62?U;7S?fHJF|;*Q%O~=^SRJ5PC%dMA=QlKm6^?H~J-9-o`vBQe zgk-+xUK-5sOYlh#RIKa)l&;#wg-w@H%)a#=U)x;6c1!ttHmvylEbkRZyjFWN&sHq#yK_p6<}N`2_5qtP7r)G@w< zwo*R)Mo39NRxyOcil&b{nRgG&0TrZhI$aOq3yBgz)o<}P&IyYj`N+IxyarX#W_V&1xI znFpfTEV~5%HA@wQKh0|lVkVrX8%0WO$lZNJUb zhrOLF!geA;%E;$M7TKA2k#{UQYP%g7Uf()nKf0Y=YdXWEgAudbk}XT)-&E_Eg|b`H z76Wgb))>A-8mRoeq@%1)f{el~v_IM#vB8T^EVy1|pU zwlicwM0$6^EnHWSRa4iBqQR?K>U!N%-oqBeze7Cx9&G0%H zx4KE!fpMW$2VVjc*lxdl7M|pKgQhw(Y0=U9@%27|i$q&nrHVl**NTS@-(FfJLYR)4 z#o(NyD3hA1AU?DgG zsa!n^ih(p#Z^fLrDA?$iDtMkn8Y(^IX^O`!54zKtx6s!7+MR0awUahkDKjRrHW?C^0Y+1VC3`^1d^U=8dm-D#YD+0ZGxT}BuyOM43R{jyQqCI(`;YUD(>DiUu z57;KVaZ8K5BHC0>?;KeTn&F~^Bfs0l3lD^sZ?)bhs{^H;DHGkCmy?OnNgwwcZA21V zmY$)~VrOFu)NLAJh#TA!15Xw@`8eaG{+S4;hQ|tE2@ODc4jZ0 zbn+R!pT%r=hLPBmeI814DW>kZVXLCZrfNJlbc>=BPEA=WXM&Aqsj$P4juNgPTD?BO z08%@wZpblPE-iG5BuU!=vg-;enH*6>eO(O~bWa-G<(Wq@$~?Qbrl`<-*=$j9s+Jz9 zqY@!>o-OPb?ZFt_(!4Dr?{~7p*<;jm3RLLT3t5{j`v`V)4&mN|vh9LJi$n<;_}*dDN0~TO$_$ob_G9l&f2fs=1|dwQ$Rva#X7$~rQ1pP$|6tXc7Yn=(bs2m7NwXo_ z>s0=G0GycJ22X~Qa3~^E>l)oHT%0V{rqbbBS6w-NFz6Tiq>ZaueJvZ@oLqxy^`q!J z??9JN?E9IGUeFq;r@BVx^4!1i)|5)JtA!!5BlfO?i{u{EmyPNfYA8Sk~ zTLH!f=4*8>WuLtm}QfI%fXOT4Y+GUixqrOAOYXJlCkB;FgMx8#YO^KZ!B(%FDp}prJ z*5iPm^-w*e>8cV5z$3}tI{OtHJU25e9CaHhirnb57Z3S!&L488wzh`G30yTBF_c*u zhH{MEIQu4@Z!hUIEE3HM7^dEYV@rsc2d=lKDe9C@Q?og#h!re^TNJ!)UzorG*pL=o z$o8V*wxOe9b$K&1<3q9{ui}-MAvs5+@eO-c zAbT|~RaXCpw0HgvG)mrmW81cECmq{H$F^;DY}>YN+qToO zla5Y$zO(MkoqNwZbJzU`-u=s4wRcrL&!-}_IfW0TE=l;P)ln-;#z#YYGliYxm^AFD z3FB${DiNiB0u|J2TuB!YuV~wx|MU>uTA#N>K(bMk4-t{zD8WOhpPd0j8RJf%1Z8W% zP2OD;EVMVW>j$O7j?#;A!%%t980a=M4#cerQi>~gJIJk;3pENpw|!-DMg@A(yfQu} z*=sL3$7+;hqJL0K)C^2R;5h7L(p(-YYe~5u5LysyeP(&ggo-?(p@AO8~u< z%w)~*T=3iY@b2K;Ec#7nYSW$Ho+T+&lOlKe%-MLa?=u~bhf54N<9VNvB4x_ zYzeEXEQvOk&|(ws5)^QqY+o6+I0OK1Ci?4nHZsp`THcLrJ{1?gSsO_)u9BreXd}DR z{``xu(8=wgFA+uS;|YxXYAX7x!)wdb^C_o(f)aZ!D85It^I*MM|{nDtwh+VTC6`EP?w&cMRh(8=+y(oWy$AHmk7{0#{B?#H}Qx581x6Uf&d z$b*c|Ue*e2=;1Qxv9FsTu{IxuIW$y0_Qb>&Ii0y=!G#&e$Hc@Ga#udJl9pOktSXIc zV};A%au!9Ao7O6HtxTyXoHjR11E;TRXj5Nx*r}OCKAtwQ{%*F#qQOQw8M0FCh3URx z5n3Xcs9~*KV_t>jsiM+CwhOHQgMe)OAt>czY8evctQQ=hKE>9n4&3aOJKhj~4%v$G z=?@I8S1^T#cY{c*?abZ|Z?}480lrT|hPwu6sf6gI?i=EI&AbieId-X6Rpokv3$OmQ zZdpeYUQLg!-6tA>R+b#(W4!^#%YzC!dY0)UEO#~#%e%Gh~s z4$uYIL(JcDsl}v-$p!RhPRhd8U*4i_f0rrLi5S?bR$n0WIM76K?L;#X9m3x-`aU)f zB}a`CDI^XK?w(l^Q-s7Rj&X^xVs}=q5=3eJzMtde1Da-lB-uBY(ywFEoo^W{M1aR4 z9@5HrR2?txgaejX8iA74d-2U0=8#e658t#RM)Pj_T=a)TgD@*};!X{h(<+dpyZNS$ z#yGmvsVFA9m~{Vj?zh~H9nL<$k(4~PZue{XS_zMg3*DG$yLikH@k{NwzBf9xCyzOw zMviWo9e>GtCab#f@>MCaD~xN~KnmT^OY@h#t8t>0P`;#O<9LprFn}GLZx{8wY*2!5 z8Uam8-`zV-_72U#L+=r3uH@>GlSh)OIfc)EnB>IbLdRf1ztI%%004~t=PLIfSzr14 z68OIo{*juL?S?2q_r035m$m}Y22isAoo|$0Gy1OMw}AlPVCw#KsG$^W>ZlTJ~mDDG=`gXMv7CK z3UozUfj%Yd51zJvr5}Tc7O+rX(!oT)ILh@zQY)aNB0M31&G6n|0M+Y0JGLIKAGaOn8H}4vVg*ljo7b;) zyaCgXwHx@)HNTvm(bfk%-FEO@GW-tl6a!+y>Nmr3YpVxh-TC%I?#d>|PC5-uITkW5@j~U>jHM7NRJ_hpTXH$!V=GgQ%QS%rP zvHQRMKvAL7yfLQ|#x$+*L`MFFAFB)oGh9sZ0CqC5E%?=BWJt)cal#;TQM%%44ijDO}L`y+aP*oB*@w$2HMJx-a{8{`3XuLHf zLnv6)qpQ}ohf21FKF=RQz8oRCbb5vdd5&9`uNN)bdUjuSOP28Xe37!tN$V=dcO!C5 zo|Lhu_)z*KH@=kRVigS?7-ew2l&WSX%BG{;LF(WzYmY){gho@sL_`Dxa z1*X_yEARK94EgVWd`@~s&%V@5JzuXsT?VL4R~!}d4;6!0v|ER3m)NLoe;fFEj%9>z ztp+HVDWZ1ZR&J~^!xn2%YPP)Bd$ldSk*XroO`uaL|5>rzYK{v3tbh)MwCF%rrsqhJ z1i4WaW?^Q*QAhp_8Q>jD$mF}2*WGa7(g77H)q8&(IigwcnIhN#f7=r}zud9g(J!23 z;E1Geo;g>m2x#RD#l6)x_yoRTRIaC#(B=T&!acFzk-ac)k;DarwLt!$AYdyZNr9c( zBQF8FhGQr>U*?TJdss`Ni4xlmI8QFfofFhMLr$2UMIK&(nwee4>@tb5A#a|Qd~Wn= zx;g}kGjK8kipUl>JR0oTemP;Cqh%`(J11Tsasx-Jc`ysMKLy$81M4|-C2V$Fw8#hQ zVtwa{cKXigH=q0gL3*Ga+I5}dFjqTX4;E!7!*SYL#!R0?1x$uv$BhR`wZhe|8V!V# zUx&}n7*Ye5O`w~&95KIC_mthe0n`wPY~O6WRC-Rknx1{3Y3nF*e8SdMn&f@^`EQr} zf07Kz{?ED9)!fL`*y;ZvS6O5i8Xx%1(Ah};)d1q3UlFpkvUT`t!Th&b#Q&f{)OH*< z*kF8Cbp0n1;+2jXTQ&yjul7l{i?u9HXiU3!j?BW6+s5-n6;(TRKA-&)jg)?5vROas zNsvK!eZvtKPbb@sUuA2Js&=RD;D1wx&G=z%|Huq^0SVD**$^e>*8KxzI zT0DjVd&*)XO>d@ufU7}gE=rM?pif7m*AjA%wgw0)D)*99s!RIwiLj{kGKId7$zhHW zL6It18WyVVal3cN7 zlHDdy9BG?Tq#}j*W7`M9)w&5dhA1YS97;z@Y6nPyh_ZsR!Xed%GJyn7qFWXZ@q193 zsxLX%0<=^hIC~ukgDAdlj3bDE$G^fJBPjcxQT?5>L$`P2){8HjEiI;FSJtJA-W&=czL{d-*3KB0V zk&tM9*`W}LES|7g19D^R;!vh*URN*hY0>CF{g1*Xy?L*&pty8~W5}jg8l}>VLZ7ky zpmOLD0l%LVRXTQPZzP7;hJ87-UwLs@8Lo76?E#2lD&MxK#}A3eWn_Un)`&uUXvN=& zuk4QlYN6ZlxTs=B#&PGagW;7`y*l@a5d`N07_nJOS@+_!FA8Uua@t?jbztJU-g)Z3 zV^pT{V)5cyk#P!YT)LKM3yM(hv9ab7q4Ldgk(2J77@kz_8kdFdFTz8Gh<@Gk^|-lv z&p-pa`qwAW_79?-1}3IQrNr{kD0#)$PySLbbjodl;5Ty zoI>}hr!CR4vrUh~o~&xpqFc(EiJKgZZZe{2!FI}yhU?GkrLx(v=X@~c1nnKTVR^a1 z6i1A`+qiJ+=mC4eW75W4INH-V3GATs=gviabmS5>aJAZ8ofvLOA}(~?-*=xeT7@e! zZixoVZpEuAP_M86OC;I67Q>4MBdFJb>zP34C$y9jy?bLNUVUN8##s2UM9!vzsozrd z*eSjs@{y&ZTNElY+n5jfA&wMjKeZ9mL8oE){7rv8AAkL9ofo8 ztIuEqcbhur%V|3Ww%ayrHRJn;%D8B*H?$iSBZyBC`fHbVKY*-BJx<0(|9LrV{e8@H zAawsj#;ru3<%0jqBto?gS-JEaC3(w67Laz1t*)_@w5)ZQ=*#<8qLEZRQVGA@gpg4% zeh=ofR-mITMMKtpMUy`}dd-*LXe|vBlQ9D0W3OQ`uWe+Eas$X6i$2t3xpb7g@a)(r4ZOT+q>z&@7_(nWKLLQPm<|M@_Bj?Qf1m7d(< zY<4-&1uT>|@)Icf)>XhM`IuBXd2WFg0@T?ggI3eRCC7@^y|Z$7O}eRMs$$PAO@qi@1F)=DAE#V{f%pC=c^Y5MG^Z^2jCzf*7|+ma5OS~%N&?M18jOx- z?xnfP!}HW*$VgJcg&{DP_uN35Z`2|UtTC(-C|jCxu?nvT5asui-N@+%cAQmlD&nZc zBaOJLlnvEkQ__54J}*^O*9byMcnc>X&`7ECONiW}Ja)~bhT&&={Z5n=>1EjWs9#Rk zvx&A)OJX!80hA<=Rb9+sUU#WAH-MP;i3%#Cd>n-vz6%p4&(ELE?Ad$gIKDXQO{_NW zObrPTN@;QSZmh7yuA__`KSnSD35JZM7~pSZ+5DLVT-h|OX@=VrPvJ%jkCWkkN+6^f zH6u(g*GhOxAVuEK+d`A}Az7{3BB;~EGsMv2br`S>U}7&rV5Uk4E?A;wPJNDjyO`KE{DLpL2=Z5#0F=As)%I8=i!e#au^`fZ&?ku_Oapl>GsYz&9^uK&c;&ku;8%if=}m@UD?en-k%(|25Itq zKF=7F#)Y)QuY1)elcFcgVnN;)f5-;sq*Ph|0$)G(412P|sbzm_Sn0k#w9&W@yi7ei z*$DFbHtPsx!Q8|n%=Iw2f%wsQaf&%ce%NgNX^^Jk@iP5&G{NW#D)ieZM;=wU4t5&F zAEDXZyyuvmJD9`diVBtQlP44W^S6q2ymm66RfmvQgLZsTJoe7(n)~YYV=ZnQudig# zfTk(2_YUROFH+R>rN+7lvaqB*EzG8>5uwV0pnRGabeZsZziOE^XSe}YI2Gv?t%TJ} zYg=0jEy6>M08O-7cLZrnydm$g&;y%iYE$F(``Zk9Kppz{HU1BGIL^tRCAfD?7hkJ{+Mo}0D$E`6O&K#}##Ii9s8!k4OD%XLshu+L z2OFq99@Qwv_KH11kBEXd8=J}?e95ieV_rLW65DuF$iMpUPybV?`R}d#|DrSa&vb65 z|6Mvb=-W7&*g9DMzW~muRUP5hztvyS-~C3F|GE_U&#(TKH^_gVr2Maw{$1t}rS$C~ z{M(LHyEz33bXYS#!2LWHwX#(O3I+*+%Jc^|1`p6QSs*q+*DkRV;h!TGFityGDI8;nV^4K9D|&|! zmKc&Ur3OFvJ!jGGmT=9$1Z_tDFfP@vFqt}H-QoT`v&25WvM8?UyJc3a;JsotZX(g} z|9#@U`Mk_G^Wy{eqQPcnxbBMeA{hVpoJLJP>nC}OIa?>0`n&clh3C&;N3bGLgZrW3 zPEs!%dm?Fh4Dgj$!5rEB+u~m(ZK2WmcQN22V_x{qdLAeb$m&)zQrMz-})IUx~J+@vcap+${zP|?my4$^T&5`pRfrvykjF{=y4xiUz$7tgv<^$ z#<6Ph_#hl)CnfNKd=-s~wpTxJy1=wip1^2afBYg>8omEVgFRlSD&{=2z+5IniZexJ zpr>(Q;En@zgDSazclGExlkmTSy`Sp;+`m0nlE3alJ z$K5cg2h4;$$g5Z=GGpg36gd>{TX}I0V3wdffQ*4xt7H{V0$ggvJ|Qw=Gh520K6nR4 zsED*2o@ZLu<-xT;6nAi^clvmLK0fDAup2pAR%kC!j|NM|w?x|EKkNFZ_IDT}g;@6h z;+_|^th%(XcvT7}Q|ejeW;NCdS(@m1*qjap3OZFRa@d(U_wO|>?_-!n3~1g> zg6(a_D^H$pdVu$tuI_;z?0S#R@$TeRq&$M*zsjwr&EM-{&bjPX^NbbV4up2=NCzi= zLCOteY%NUzup)n{Dw9<);)z8Z;hMEIIAcVY@!pw#VZ`vo5N4xu;T8W7o6FgLlE4=B z1^?k@8Z~?{@x<>gnH_KXf0vU*y#R4yd}rT`@9`@Ce;qW6=B8#&|H5YpI)CG|Z2o8V zqpBcxAo>rA#RE5J^ox} zi;sE^?)xcr=AB4PJTPJ<9`z(zUN5dcFVKT{5v$ly2nE^|Ale8&=kjoi<$t5lzK{y4 zj|N3QnEz{e~=1d_xu-YUMeBw#n7q=ER^8{+tM@2O|x`o6*95`TrNsrtG@(V%4eH>`gALx0IMZEeGKb5JbX7RxR z5m}a*J6Wkv!w8`-heBsOncQ5i#{+hP7YkFwDuo%lG@Rtkdj?|MfafRg!kdcwAu=a8yZZVMz zcXwHVH^|h3N+%ccTFHmz6Z1+`NT+y3w4YB)%(T&Hh)U~M83EU-s(ahrxFu76;QEl% zvu6#`op*XT8agDl_v}INPPTp6_}ur^ZM@;8ft}3yEWy8r7cB;;FNaqFti^r)iZ+2?^*#+@>?fHMHhbev?q#vmyJI> zV)e)2=(9FhW6f-LZmnV0!0|Ki?FrLy_7jI&*R;VOaXogH z%dqWiHW!(fGfB!zL8TtcCj;NzlH40)FRO-CKI+D`>aO!kKX{##OJ<6Q?naN4^@Jg? zSdv$oqU9s+3+_EOPp7)#8o1833%w7Ms5aP2p*q__pO-uMZ7tO6$L*8%PB-X3CB|(T zZ{3mXeLMfkI)7Wxi}g?#d9VNgqTgF>nEvam^Y@+iEt&gAp1H)fbX*s|0b{UN@YSiQv(O<`|dug`asHO<*6k_ko<0hAu=Br&FU`Fc~V z>T#G(mN|szZi9~q4VYb8M81`hwZTD5eVr_9FUch94{%^KEhu?Po>Q&VPqaT$;XK+o zT4FRYU$iP5SIdo$>i}I(;@NDDPF}o4ZLAXtnSDQRMdcvkp8G**z zf8gH!h_nugA&2aePy`BSUcFmL1`s+LF`D2nh4T!_iP;*xaqeYTY)fBVd^n)Tgc(^f zJxYp>?BKzO$E9>)0OOk#*Y`r~eiHeMS5Sbb7V@J}Hr7=yHt*C-&-JGybjFO~7>uq` z&Quyac{o~HORf>3tr=3Ez-T%d^{|3Fjyg0Kp;q0Z)X+}S!7A=uA7lP6N1 zqA`YynGF5n7E7*YuXPwil5Mm{b9kcWJH_`^Ah%LJWqw1O93vVSDrg?9gPmq{|2$~O z^%5P7c1(yOR6CsEFl3b@1>lOd4Eb#^ugqZmOMMGHf0ERS9N7c5*_B9U0xvXjrC#7b z3t@|SaMxriYKR>A_l+O-H4fQ0&bT>rPeVB#!15bLOj%o{P zV5BDk6`PCs-!|ByEl+LWd34VC?hqs8iiiv=H@Y9;l0e*{X{CkBMq}3_7see zA03*i(c}Diu3O;1BGZ!7`~qwq>Q)HefGr$?fiNTx7d#UMRoEvb z%qpuEHr0=BCbO?^j3=@y5oVfx2hK!k6z%Frj|od|Z02y3FMweUZUGZswq*Lz>{wPT zrJ;VYlzi7E5SEBLp#ZuX+Nm%D@O2mL@0O0<-3|S4Vd7&qo{Ejsl4~k%(bc*G^ zk4y@F{3tEl+@NdzT0VaV{kTDSnG15e_6H<%Nyc!MT}kE|yCB2;b4t#sc#!=cZ4N>G zWz`^kyw(A%u@2LHurGNhC3HYrkZL+Zkfea1zOZdor;pFK%DDon7M8CoGb90qT!=J* z_maSf)T(Ou$|ny2NrEWE71R_Zf)Kha2n^4}t-t&u?ADP~Q#G{M5;djmU~?@Q>#;`0 z#-UxCG=NtnaKK>sA30+yv9hJK7wM0G%L}Ln>q;%b52jpeLv#vv)r!_+SF3Lt}d42~$He z5*i9xx)dZsvs@m81Fh`ZXP%sAw(HO4Ab8I)QjWmW6+s3|LWSbcvI2nSCL@>s-3KhN zAKSxaoGOGE<5k1h9ix)4hSzN?*hmiRzegKNfcYPtrs5W6E=h^7(AAR%bn(t`op z5ObOpVkWy{h0+27GiVPQ<=sm8d;E2R3vYq`z#Jj3aJnwb;QU&Q0O4dV&Cm%kV2}qf zwH<9b;3AiQ>L&2*z=**ra%h6%|5T)6{YGsoft)&OYkF&!23?ItjT|{aBX%0aRq4^z z)P|y^Kt$hwko%`9D_Gdk+_v^4Y1T-}2@xfS(47(XhLLs#Q4Nklg9tU_r38vVA$I>F zdBBT=wlDy;=U_|-@~wI2$gPQ+tmuA$*vcW8zBB7E?u|aK9{g1!xsW9xUOyVI32hrD z%M~zz6@k=t!h3`h>4B0b0nRBx3s4__-YWr-j&_3TFFY|57`+B;lftr2IK*eyhkZ$p zY(ikUYRJnne<|IjmO|obp^-rWRq-yJ)hQ;;UCmi&zW%|->FDGB!$Tn2=M?{==TFq-)$-G+;&fWAloJMnrCa=eaO2(-B2pJjjhM_c< zxjBpaM0Q2SRKQ8&3g}IYq)G^oAOk%?QF+_TrxB+9a`ODa+34wBvkZ&VCPIaaE+}Cv zpsWZ1m@dXURres~&Dz7L@q*blguFTXUNi^bIwqTr=|x2(!1ZZ!(gh-sZKdS@+}vrAaWdWx{L{LtzR=OP0td-Idi z-t+TCateCsHf{R#_kSRNgJ#2nvxGuvr<3fU+C7UajYPji5hAIQ#gx@uaTnB2_Cu0p zh0CC91a49gH2_ku{qiVKgg4U1SGTdIny+M&)o>@7>nzY(yUyMkuhKowa`8@G9X6|> z@OvzYvmURJSw1`Iu4l#7o6k3~%zT3IjDE!?rIif(#(hUCIJ$5@UYviD@?#Ma7{ zGhG~*ur}M~5>haB5y+g`O&i4J)kP^^PSZos+aGktA>|eRMt?&g@3_aiP5LH05b=r= z4bCg$7c+I`RZKA>h()^_EAnl6kkZNCQA))|k~B*vjT0>GSr>45ID)tP-omja%0J~* zH$f9+S}vWz`^Bf;Vj$1R7DZYTGni`v&7u6=GGGymOwZZvqM9oV{l3J%4bD+&6L@Bu zkh?gF*MpeH?46`{oUG2r#ark3Y7+IZ0bFcuNRB1EI4czTJ4-n>L{t7sw)7vG(2UTU zS*R|o){F!TRayzowfU5rjB9=XS((PY&*>d6WjIMm5rmY04T_8w+xj%r%69T;kxt{l zI#g{MBv(K!x<}7hYzM?Yn^ij!yzgPlsxwUK8!Rfr2!%+`wv)(yqB0&zOs*bfL&}uJ zRB==Sj8leE1qvfN#$H)2xejeQm zdgXb5CYK%xL8J8zr+&r4MBY)sL982@P@18w$Raa;!&T#zea8f1P9qh^ix`p&cEyEShpQl{K;51V3<4%lQ?DFKo?zP@>#}?M2uh>Mud)$^ zE$%7k*u+5OO6K444-BB>O#EnaPvK>Z(4Jegc$Ga3IbE)f+3guhvdW$1Z{FzX(f2ib zhcU|%nd69&;>a=|MwBRt^<(8^g?mz4YpeBC*1pE-$SNBRd@sZpHLdfe4Ya=?V+L)m zVsoa7v)fou5EfG#ltb{7-qICAkR@so+Z_filvdFixJb~qW-+0aY7q)Fe#dP+UtB!z z7B_Qq2D500HM-akb}$DT;F>6z+u=Kmp+Uv-&EiZltZ`6t(JW(B$NFZJaKdR@`FW34 z_*Me)J(L^Akg{sGoTeCGc3Z9ud3UfaVo7L{(bE-C2TpQv3G2&s-_0obv;xL*Yxlb7@<}> zKL2*xN&RD&bTRc{jk52<=$tCpC08gC#{&0-PY`Po!zYXotlK67>W ztIfhw&64`2)5=R+@(Tv>dg2Fs1$;)rat?o13?k@&y`RvfzbBO%k5Zkfp!bHH6e=}pg? zwdP@XKd8Eb-!Qxq+dgzHEffF2((eLOKcL-W{dbidJ$6J{FDe zFNWB9MZgtW>htu3r1vXOus`h0dY>YZ$8(fft%>2){_rmH?Z%+$36Z-ecb&gu|Eu8p z+nb$QNU$#XR`D-<+m-(dcho<}2Y(AbRdZw4znxfzf0TXSI^gd~Fw8fQo!~AJtZtLq z2Gr#;yjUX~x;h2MzBwwi4($t)zOubQjx1A+R3QZIa(G@=bhPVxQUn1|PkdneAU88cV-f;HlI)+}#4AVrT+NIo?- zJ#s&$LO4gXqR^U5bQADl6$&FlP?174R$ao%NwBJ7{#?P1WIB`?#6})P2U_0e%TH|% zng9VLk;LT^z3(MLIEcfb{f*T1!-Y>q8Pv<8UcsMK;SjlXe5oy>$I=+{v)NGt&uJ*z zquScRya(wR3xfL4Fq|kp=00UzuUXb4Y!}#F-3VN7vJFp)b#d3>ar>S#RsKCPcARSn zgTPM-g2t$?kI9x|X}SqKPD;J?JegaLdr@0>G#v=}9JFr9NcVBP(${DOL&R(1V8B$6 zk){3l0=_1EMMkMC7JU;<;NAJ1F z4%RY_9E3i#v3g*wfA1&}3V0LK2Eo`Kxg~*|JdHJ}AZiv6%V97uKNEq(`~#*Sq!;7a zW-_<(v}lkG_vIVjetCHVv)jC%TtoO~3%zSCLq>BTklz-RxX;NRJxf2AO3zJatN-+?cO_5UUK z|C%HJBIfnYZT=bjRq9%f8_h^QCpG*F=u`@2g^tHO%FQF;m(na^Nlf{f(%C!+kP>DD z@u2*a79(FD7Xj#iovX4XJ`5sy*Q*~ceRG!AWK**7wyx>#f1b8{B}z5WezWM47~S;} z7xUPH#R%7>em@sT=D0=4Fr#)Au3*MY$x!8x?<{YUU&L?9H$7M}JWE)}Jw1pd$|b5X zAa=v8TJ?gwW7LZw<-`-OnET9;7#$8hOcN7{fUYem3A8Pt8c|A_-8NR0gDhrEL>tbgws<<8LXCWne+C4eBj;hRBF?d@lb^;F z#?Mw6)s`qV-cz(4kGY5|x6g@DrJ*|(k?NkTL&_VYx>+FehnflM$OtmQ>c%}M*kQqS z(Jw5G41I)qrO~7$yjpmm#}CDC(j2!eEIBd$YJoRm`jY%)&)R{547~9}dg4tmIha5!+R$pE^s9v-Z$q0u&P;KFp@(;Q=ik%HH*?E@QiCW7lKA1iR=$z?BUn!MTV^}gNWwYX5xL~VPHtY8k$HP5l93Q$q&T#@&OMR z?jC3Mf;R)gG?WHZj2kz}Cn50-t&L+baAUxh;$=TDjEa6Ds4J`Cjg*YRA zO_lsa=MWOX7*h@{8Ju$KFReUO5#G|M$NABPk2Vuxzt!l+m%4qNcvUEU#QcDf;*G_u z-Mih zk5NE&EgGvfFvGZ$t%Z%6ShjKq@sIS%Q9iZwO2Ef`j6)m_QeR!@Y%k&;)Wxu2F~#tB zfe}reg5431OI~&DZm<+ef2@g`q#O|o5cz@N?Z629 zq5P{KGzvH;&~g^iI_8M3)L;~jwue!-QCB`|3qLG$42BnnYqN|Frz+;@TlIy8{K8l z$5TyxN)IP;2h5L~4YkHT@9<6|^kR4jCTXQ<`i$lnK1Ruzu2!R4_|N-^t{S=gS6Pe4HkmQ}pNFZH5M-b&9!-HL}!yacke?2&ae zBh2p8d2JJ#K|*sqvD*&d5lYaery{&S9HC_NquwyS)NTFMAGkob8eRfu%6s>4RO%2m zY|B<(b5Zf}oMA)g?rCR^ndJnhL8eqLV6VFhvmGMTyxgU9gtczt7T5|6^&EhVzTtu% zSfOxFhnHZVS2(Fj=z#n^g|mUNmll@8*3<_Qpd0G2rs`*ZAux1lAEn^LqKWrs>LSls zl4tb zpq5Ah?b@K6d70L`v%9y2GqA#^Sw-Wzu*hL)y-6d&34tRis}jv-*~BgS^>VAubQIj+ z{-W6`HRVxhVdgea0-D8$JtRB-E?F?9oZoY~Wo<=637%ZW)I`!w98dM<1lYiW3Z8iL zFR7QpQrg}m$G!a*3)%F*$reMmpDe=Q;a@|3!8h!->47N9%+ig;`}TJr7=djF=?V%n zeE4j}fZ4BJdS}-S7_-o8UI^U6Yoi+ci{w1;H+@KVs|kSY-04;taUfHO?Bhj7>Wywb zZs21L7}E5i*Cj?WDz~t~=ecpvq|_d-W%1$2m9+K5-qMi$*5M|FL6$*23lx*aH7_9s z7iEzuGK?J$W`pn3iTPSCDZ3*DtBvaY>@Qs6^OnWzF(0 zr1co*$D56abTVOHq*w+{Hx6dUG$KnIvPV$68ocMan?JY+n{6umKs8PJG3w>MHg#Fs z0`wE_un6^}{_tm4QjdUhF~=C@c3z#YIwk&7b~H7D!wkJfI%75U`{ovKlbli)HQKI@ zPDY@}G#l2HPtOCK)QQ9z?H3w?vMVUC932CyeM?QKkRm%VdEZZf2JZ@o6ZvUw=WVB` zDHBx|WIO=1lZ!|XyX1zGlV}*6cv#eM4MYa~?eT43c{aI@z!>^M5Yl@xGmi| zSi?;rK#nvKG3b?D3Qll=RZNhM{dIWoD{eQ# z>PM;8Sm^6<~p`uNdc?{Ziq z7>h~I8tG76f;fypq@1Mbj_9VxG-N*Cl0%>iowjH%gZ-M9NjoeHH(Ity+YkQQ_YF7P zPYAJ6fMOO`Ianu@+XEwpHL_R~JWps9u0DU{?g)yn;C>wICARaI6kV%2pLS;lni#hr zeT<%!-yAU@1$@*z#EbGC0zYP{)ekdLnP7&p*&#A$VWMt2fM%F@3sM#MMvLhRelS8m zA8m*Md~+@tB_iU9!FIMK$0WJy`Ymgn%}+_`;1?qn4|urmU5N#N6U3wbZp!r}E}F7> zxTDL2-q6YJva+DY>(n>Rklz~$Esg?}jxcl}oD4(~ve9FO=X-~m{VH4iezb_F{tTmE z`@DXW^L(lIc3VAuyJ+@%17F=b!Ef+($yxYKzj~~@mqYXA1}c6hkL-no^G(zYFB;%N z1l^A~j>;N)0i<3k4JTu|q|gdl#+${&0s(XCy0gkAw`iIzR}%~}TZS1X2m>>g4_GBK0uM(&ky zfZ};)3)%r!AqHeMWd#CUl=;KTC9Ws9-o`y~NY+4&)@Qeitz4KQH}>I??=f{p509;92r{ zFFX;cz~2oan+`ue=EHVR+y7-2u(p_G;%i+#p5$I+ z==1$OrKi?@NbP`Xh6DS4pDyjj!S)*Gb4-%Y_}pq7T9uXqyLun;y&xNARZJ&QBD?N~ z*o+4J_gq&@?hm*p{A)Vx0eJEes#XdP0tsmbDW&QAL{JS?vXNChy_z|aDf0AHf(0R$ z0!4n;4obj#b2uOy*eR-4Mw&cL_0to^J8ikeqk-?&=Og3# z$&BB8R~Nj-_(VMFyX|=)0GKVldM6MU*)6Sn%J4G{y*dv)2Tz4V;eEGwIY|b*dfH6+ zTkEdpLSbe2p^LT#(7ZBW$@g@ZVtO@UFEwgdZgtL%2Mhj*FRFS+$EVdKCqzwcAmV)P zELB^l?qDJ!Veawt4yZe;Zg0r;qNX4s0q}qT?=;9)167aJL-HBc%SprpUzhgwUal~hPX9Kv-N0f%a zOaT%~DZf8d&hJvs79L_e0%{J`ohgdUUG=syJo@4OJ(G1PlX*Sr*-h#~LvkY%H7IyaTMrU94&Cmnwd=5 zyo_ZK>DKhe)bz>gY$w;+A$(B##4Mw#N6acIVG*WUBGi*80mr&fgqPexfgtY1vnA%h zuWOMo_=%vE%)!8X(qeGVp=D>5U7I<$_#e<@E4$y$qN;$(k6r%ZBgZ$SD5Z?i2&qN=rEk^fRAVqf zLPy$O1Y8U>TyjvT7Pq@xDT1{*z;^ZvL)V0)}ZDMCR2&a8h=Sz<9q1vY(0w;EfeX-{LarX3d>| zmT@w37^3>xfItY#?M9=O!nh@9kFc-6?_QWl`K!g6xR^1yIXJuQ=!AZmC&fTWglFFZQz0?$@ zyQ@4H9MVoTYW9fq=WO$M5Rs3iTfcYq!?#9ABc+*MXxwIWne?93`_4ugf}Jz``7oGf(m^5k_$T)`^fJp&xTEmFDjB87Xl0PnWwV?zm1EP?&@vI`!mPv#t!4pAfo1AV z0ozxtQxjcd#%LhR2_1iWM!&vbHB+pMZ&KXky{kKjkuILH#YbhKJ)xT$qUXvws;A@0 z+fx_2>0qN{7Wh!V{0Hs@W~s`7dRweT*DT&q(VbOvQI#O9h}cqN#s4bpE5NE;+OFx4 zZt3n2>CR1eBPA)_UD60ht8_QgDbgw3UD93BC?NmF_jpi_zQ^x>hl^`(xR|x>xu1Dv z&%?~D^}wg0)f-O#dNE1~hGtI{rMMLuA=w=wIl8`g7tGliQNiuWtnbC7o6=S}sXymn ziTy52{t1VPYW)MJJnB}w4f6}Pu9y#vBwz|b3q{m^UfrRmF`XmQPtMlI(_bE8Uv}&@ zqAUw0evrq%+LCiZvzb#mYbr9twF>T}&xC6?Tt5I`g zjtPmiZ7!Bw#fa9TSY-2t~kymNBIh^B^j0^P_Uni=&3lT3zg zh#rW5N||D2gi7#@0FJ5XAUAcHyygd8)G*eT=+h&xCKq`-n+@ot<-Qk&;4BZSxKGN~ zND}CEb{6Z#39t^=UKA>aKk0;8*=r7fGi||X@g%&038Z<7^A_YNp)JpN)T-b7&}zCg z>LdoiGTl9lUR@qtdH&TZ;=21Gb-XH^O`>lUICMu14P&U`Cl~sGaPhRjR7|2oC$LX! zgGvN#cnA!yiV%{@fNPJX%bCLH40=9R=D)u|x_O zQX;x>)4=OG4)Ep?v8|a^{3$c_88+`WJPQ^(@Lj4=b8pNvz8ccLjQ81SlsdIxT*6r_ zS!d7*j4SDvbgebMIgwKiXJgd3iCtbYl%UQryr-AmMgk(KGm!6=aT$-(!h+L^rp4X| z=EzVUxvqrm9;A{#1=!G2_p%y$UG&;xa}b0ZWkKWN^2yMUD#sW~jH9_g4Vk=7ZZ&|v z^y|H$bsx|vEr3ZCl^J>h-)p6g8?=;k6yF>?$o`nSG#yEt4+dEzZx4i~e2qb~#+$r^ z;UyrI`9$ZkGc)QCZ;gzjD{(;@>g@cO&a;_F?u~RB95_6<(KbtroMkxai=c>HwaLtt zB~EHP8Atr<5$5JmH+)cM6*i_^KdACrCa^7Q7nOXXTGN(s1B6oz5gnLFPqn8fzKk1h zzL;3D!AcX)2oy-7WEUFbZ^Ni2y)EoeEiP>9cPY(~eQLF$xc*`D!oF&oS6al@CSLbVj znA_G2NH_q)nxGB4^K9Ab%3Vs`S!=yx)lUy2IKyQJ8A@a!0SyiN733wDpV4*Stg*#` zZO>O+>+pxOBfTV+h1jz?oK86xI#XQ87Z>_+$7o-Gw zrboXe_A`F$y!JE1H4X>>nW1pIK4vcY!HZUsr>4VdMu@D8kU*YP7!@H0zEg9*EVVu48xTzkmupq-XqEk zm2gzK=*9|YSDW0h!1nsEun5ZY$l)pOXco!Ujid0TT2y?gXdBsF22Gk9ZC$*)sv4r> zt7zzGq}lh+0q$fiX#$J(9Lm!ymS46jK^j!H?CGf3)rfMO*m}cWsy~eLnT)a1vcX)0 z4aZ(gQ+v)0f!e;>t}3pjb44Ch6r2?q)F&W?42|ML6oq0#FI#|L^$v@&Icudsye)*0 zo&;HLuQw0b%QNRXWG+ClH52 zU$&~*MZ*<4eLtC^X{XF?W6&zFux-~gl^x$$+N9Vbj-0DHBYq#~@RYhvL~V-LJ(^@q z99!97xju1p)XcV{oM`1SkIWF-ZIZO zc7DaPu5MLi&QtbvJ+s%BlGgmz3hpnW+K@wvYfl=;1gKt-`l*Vz;W7J~wJkwa)bvO# znPoCRB{a{6fUQqKRKlO|r}5l0>;bAvX0{FGQ$$^2C!zPJ9BIY{Pmw>H!&Z6yY3zo& zl?UT|6Wm-_1o?6$tH2n6T9e)_1Yn*kTovdlR0S8-R#sn2H{GlolPBgqjy>^7P>tF5 zsbUg1GwJ5qf!G>BET;2^gD`irqfJqdXbQXvPH}6VkYD zd>t{!+E1I(Syo;(TU?sY&vG_Xh(1&18+^Ult0Fz0gai{~VumD1wq2|>;D#8!@J?ik zh<*g!A@W*lQ%rD$pV^-P3> z;C$5FILt3ZxuUCN>h#Opw!2=vGI%a#{+P@yn(DL)0z%4+JyOW=vg?!C5JsF;@?cd$ z`D~>$w8XNBjVGeG{lSf&{Vyq_cJq|n09bkw;KpBK(&9ZISxs@F*ThHhW3$80zZady z3M(AYT6OBl_rY=2Dz%>D5m}gUJwFNJf_7+R#Pm+f8I(G-)SDntwU9$%lWN*{>Jtz%HnvpVal43F!n#~znYd&l0QGCYq2E9rpD}Pn}M9wVI%3}25 zO`oPM38gM(<;6RAe-=fuHo|qsiDv(a&#$EFMYOS`awxQQ2m0p8%Sb6L(ngVmlN~8t!&a`Uj;Kb($otJR;GL)klZHkKp0d|}y zSuWZLakkbpcq+L1Rebd;^jdV(2^%KdhfX!+>8&lp25c`MH()&C2{u9*+s=Rc+1)Q9 z<%?g)yA1)(>Elg)<96FRu6J8*D%#ox80_OB)Kr(nT*)V!AeN|-_9FQ5uPq#eU`b*p zrvvO`OSb!Drr&%p2@zu@A|reK4ik-SWb&02t|X2eRJTpm#(dMeSHj>}pJx3<<|f$v z&)nb(aAYs!%JM9A&Qb&>bz5!paEqfUo%BE-ySEn^ZR?zvtL)aD`m$83QtA?3H{6En6vpG4DvGF~K>VW~3q#{V*V8PFe6;j_ddh< zTAtd3Y;yiK>b~ORQ^O_gXJK>Do)zJ-@{QF61#ZJVTY?{&WcLrF=uJ3RpVE)vIiBu9ZA7krPn;O!_dgtEvK6x zF(SEqZk}cw-KS@d-)l2WbcUvI6^3j#Dx}tC-L@U8j%Ff^?fCHhE~k;Zv|iwmoDp|j zbi{Nqy`y6FDclvuMEa5`i~A$Etg|i>N$><-za(U~x8)<=&uYP|<=_NO-j4N(1%i8{2(pQ3 zLjp83+eaL|mmhO?1}6JPAc)9v}!+5X|JPs{7`Z`4XyIhJ^M>z5Z-$(*m0 z6zN5=ttxsA?fi+1B1W*gBR}8BIK$VCmgC|yCQ1uC8PmomyuRF?Rme!Do`!@B!(QlU z(S=JXLLAZjqc8WV4eG#C}L(!h}Qqq4Jdr1kFO`ex>- zZXNvX{g*FCE>1V~SOO5_n8p+FKYNTShEF*JoG`xiU2sK&=G+VlFVvXvZ5WPbD7Xa9 zupB$>kHU(4qKl{!aRgj;J}R5cqY;Z9bYd!cs++$uCC%w6twtmb8!sMs;8H}Wfjncg zG(Cm+!Np?{A}8CsbBl_O@QF)U@1F+9IG}^O~g&zfNLOJ$5ZXQ!j5r+fb#;(Ufu656a9{X5s4dS)QjU41!Tgo)e z4i;~wBELlF22Vz=VkK1es#}JnAmCsz(1Y^xP=|D*L#!6!vtir|g^lacp0Y6mw`>WT zY-w(*W`5?P?Gm(}K`mVg363!06Rc+psOwEZnM*HH;%Lu`8~GZgu1qjqQCZIB#a;Ry z_X#P{yJsQr*q?WKViH4PNGzG!A~piIEo0}T!2}B#L_Z&D1-M=30iXuH1b z)PN4oeMLQE8B1JYs74GkqkCYrMVeP;>mL)>jNh<-t?=%%kW^?a^0BxlGvk{7L;KkuA1e3X^a8$fy<=km)M8G6CH1mXd-7_ zEcOSc;Ub1S1M41ipagk$ROd~$5C!0iO<_I)o`?A=+s>=Rs%3bEoX;ENZdFPjP8Zo- zMo+MpJle8N@py`+8JDJQ7xO(2eB&_M(>{qaDm?v?3CqhmW)goaZ$qO+n}>}JCnk$W zQU(1tx+E$Oth z7CWAQ?dgTb%|FHwsB@VFooYgg?ediuK6_NDk<55BsV(u8BK<5hvVytf3)ju6v0^Gi~%_&eACR zD!32lbN6|P8I^Ce=ws!K2s_LbeJhG!gH}I^g9tA}{;GzhFR3?%{Nt+tiD_@o*X-Br zxaZprcF7vWO#Mi7AqiCPL|#T$&W@V0d0L1$0cN&$bLUS~osFSwKYc_8OMw0Ckn@oI zC20OIwB`xM00ms|>g;6}^LFbD*7op|B3zN3@s(BK@wN#N*i@|>4}yhO=`Eys-bzKk zr`=)WaL&CG*$uJPrzCMLItDvQ7M8Y?K_7ZpFgWXLa;v=ixh9pMSsXsMo$~R*%@s4R zgDnJhn&>kuoD4jgtIm9>s5EQ}X*XVQc!W11!}Qf zyqF(ciN>}Dwp}?ANXPCOnt_EyCTYcL;rYZr!}^ufqCvXJl)f~4n{GpQxH_LqIGy0^ zi}or!b=?GNTKxho5NP_|PMxc11_^B<(k+tJOUHxzyA=(M$w4T9G7`|hQ}J}aUBXl~ zvNL^VYVb{ET*S`K`aj!~Jzss38VNl3f&q{u7kZ?H?;DDW;!Xgmyu>kWS3cpuC0pdp{lQyxFX<~@r{{tgkGyD)vMsav z^aZiDb-Bl}k2tpbYlK_-Ifqtx-wx~=ituPGz~m=_*PuGsS=_li#@7C5EQFHc*~e&OgTI!%l2UIw*`^)>ACv#2Dq(Pc<5@v zr6^nYeI6$*!MzA5tuAX_;u>{CuvuvxlsZ2vJLi3F%F7(1b^k%?_;w2l zu#5dIl27#8{^kVS25)I?X!Nr{{%w8p&Xf0}!0jt+H2>`^^h5xUcGoy$ zqF{#w=X!2}_pROR^+Z%lu4H6SV7sx0y^6$9im0bodB~?vO#sIjkH}i-=s9FE{h1}= zLaoLQyjH7jv|rPndii6o07Y}3oV;(w#WP-oLlJH!A8EIOv^=$V zhyWtGA9N?YmiI%Q(Et=$2J+1ebj`!)Y^oxlhWHcIKsJbMJRgZ6DCT^s5b^~o)}yYY z6d0kQx+_pBIo2x87%qZ(Dc)x4EMKa&h{Is(2`0MgaEzd6? z>88WSVn+Nn5!EZF``3j`^d9A^PK_Vg3ZWTg?71RGb3j4InDfDB@sqqKEc;ch(lKxg z+XgLXRG{on3v{ZE=6s;p*gwq@0p&>EO602>T|9v%Y~vL4*v}zCFqzQ6&k74LoX{e* z2-7UloIZThL+!nERK@ok_G1N?jt5Y2KGfP@Qr<%*#5V`Ptb_qA_*}_rK_I+0h|B;3 zp6xKdohnwDrClgOE1S1vnE4Sg50MYpl5bbJHvn-f($kQLi3y{XCMG|wKw_?+^(ZhT zTSzu0jvg-_{iz^Rv^Y_*)PtaS-b^?uaTv_WndThB@Lp+E{p}M5esxSmqfN=T2d^Na z@fGzg%}rh+bV!c*%B1d`YuH}cMnyRG7rm2?u!($desg`)`aJ#%=V9E0&z@?ZdpeWq z6yuniN2=j#&mFTjBycwjSaK|`k}-zbHfInl?<9>nc~U;eN?IytVAQ72c_qypG7v2k zh_~lJdMI?Tj*qGw(8{GBH5s~qx=_ocRRIqY_e(0A;m)#{s*$jG7{$=kkq^8&PA>C`p1_MkMKy@65@d|$^zZ8AlJ_erPI(ptBUhM~ zJau91gNKvXkwd_fX0O&7+vht)<|*mqfvBp2=JFSCFS82cj_pcWhOP_L{v7OE>y8}D zJDVoUSKG&#L^nJDmc|wynS3cfQ!PdytIa=VA8hpi3?1Sm#1+Wuh>OCI#oXHA9P? zk;drtBUyGH6D{2-Wpw?Z`38ycV%iQGr-hJt_jR-6iSrMVFVgO!ont79z zF7s=yEsdi@r8UgY%wb)j59>cZ#JgY(_&DXIIk1_EfBv2<$s}09lT}&u-d(-i zW7rRq7sU=9W-dexT&=KPZ&KQa7xN}oV;IeHs6{=k=`%d1 zszjK|g|?$=RyD!Sai0n8Hzi-tj`$vLx5Q4s_XgIMKXKl#f%v@w$Zd^;ziQY6x6j!F z1(%F|s(WAB8}p~SUH_OKpw!FXCCi5gsQP!?`n$G#kLNqqcW--9J3V7dBP$0bV7!9=;rTXe`7zT|&&wtG z?F>G515wR^X}(n`{9dwr7=bdhf5!FSIBs*JZsDB{2273!aK6RxodEcnMWBl(N z|Azf?sN{nrFjrrIxuX0DI}!MsUt^k`AF|ggnzzlxte1G9)`IP-1P;XC) z0XvDPp5b?UV9~z_|8~~9-yG~~4pI#uu^9{qi0t>)0AI6wq=1^m|B{=(oAVd3oRg8A zg`Vr}g#g}E|H}P7Wz}O6*pZ}x9ZBvdZWN6FGxvA7ft{X# zgQ>OEpT^O*K4#Sf%myE@{|WpQ2PW{2`O`T5lnrj5kw6C6YA+z0#7}I@B>xkeFwlR= z+TPT`=$GRFvx_O|JdpMw(4A83C)y42|B3cTq1F30SbIe`p$2d?76E>Y0e&K-20p9) zX=Z;g$^5Uk)vXEVEeY^aek){uy@GuE>|6s5*Z;!k;A->pC+h9fwIRtMaRRUn!@$Jx z{Ec`!NKileGsN$oV}JFK-wsFbZit`f-CiQ#Xn%V|{(H&t!Dsn1CZKq_{lBr?_gueY z!3C23Nrryqz<&SA-*+d!V^QP$GnVgT+AqAy?~~nkM7|@F=lwIXACmUF{`@P8*E^z3 zfj=Yqp)dckAKd?c(9eDNO5|Tzz8PWNPtbh}#k;r#ME?x&pN5J*a@t-UOz>{5eLJn})c#W@8=$DikJ{k( zIqqwN-?au`=l_@E_C~)I6Zwr&`27&>D@xymV5a-Ogz$TP>H87fm*>5UAl2YcBlx{o z?~iQ1lI6T(!!Y?%w%Zf~hq+(QLhh@;+~Gq3pN9Wskoc`8%#W?Oz31-BP2917yZtH4 zKgB2Rv)n&9ddHID`#YA~-25XkzdAN|2eu#Z-@tx8M0Y>L`zu*@sAU-yz?vK-@>Wzk=}{Fv~~p572ItdMgrix1J#{1qpnn00DUf{JI7{ L%J~=G{`CI<+YfEJ literal 0 HcmV?d00001 diff --git a/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1.aar b/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1.aar new file mode 100644 index 0000000000000000000000000000000000000000..9bc9a3f05cded90a5eb50afa9d58e61f9dea1bdd GIT binary patch literal 121509 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 iR2C)(9tunsvZS%+t}R%x7^ZIsnp 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ℑxqJ%n+D+cm27gpq`Ek#qHoKI`af7Fy|; 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 Tlw`yJVFMg6+#dvvlOX;dJX;_6 literal 0 HcmV?d00001 diff --git a/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1.pom b/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1.pom new file mode 100644 index 0000000000..5bd1fc5d39 --- /dev/null +++ b/android/KMAPro/kMAPro/libs/com/stepstone/stepper/material-stepper/4.3.1/material-stepper-4.3.1.pom @@ -0,0 +1,90 @@ + + + 4.0.0 + com.stepstone.stepper + material-stepper + 4.3.1 + aar + Android Material Stepper + This library allows to use Material steppers inside Android applications. + https://github.com/stepstone-tech/android-material-stepper + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + zawadz88 + Piotr Zawadzki + piotr.zawadzki@stepstone.com + + + + https://github.com/stepstone-tech/android-material-stepper.git + https://github.com/stepstone-tech/android-material-stepper.git + https://github.com/stepstone-tech/android-material-stepper + + + + com.android.support + appcompat-v7 + 25.4.0 + compile + + + junit + junit + 4.12 + test + + + org.mockito + mockito-core + 2.7.21 + test + + + com.squareup.assertj + assertj-android + 1.1.1 + test + + + org.robolectric + robolectric + 3.3.1 + test + + + httpclient + org.apache.httpcomponents + + + commons-logging + commons-logging + + + + + org.jetbrains.kotlin + kotlin-stdlib-jre7 + 1.1.4-3 + test + + + org.jetbrains.kotlin + kotlin-reflect + 1.1.4-3 + test + + + com.nhaarman + mockito-kotlin + 1.4.0 + test + + + From cc014e237d179c11c8c8dff249303093dde6d50e Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Fri, 23 Aug 2024 22:36:54 +0200 Subject: [PATCH 12/52] fix(linux): add `keymanFacename` to .ldml file This change adds the `keymanFacename` attribute based on the oskFont from `kmp.json` to the root element of the generated .ldml file so that onboard-keyman can display the proper font for the osk. Fixes: #12019 Cherry-pick-of: #12277 --- linux/debian/control | 2 + linux/keyman-config/keyman_config/__init__.py | 9 +++ .../keyman_config/install_kmp.py | 2 +- linux/keyman-config/keyman_config/kvk2ldml.py | 34 ++++++++++- linux/keyman-config/km-config | 17 +++++- linux/keyman-config/km-kvk2ldml | 11 +++- linux/keyman-config/tests/test_kvk2ldml.py | 57 +++++++++++++++++++ 7 files changed, 125 insertions(+), 7 deletions(-) create mode 100644 linux/keyman-config/tests/test_kvk2ldml.py diff --git a/linux/debian/control b/linux/debian/control index 611d586225..66a410f1e9 100644 --- a/linux/debian/control +++ b/linux/debian/control @@ -26,6 +26,7 @@ Build-Depends: pkgconf, python3-all (>= 3.5), python3-dbus, + python3-fonttools, python3-gi, python3-lxml, python3-magic, @@ -90,6 +91,7 @@ Depends: gir1.2-webkit2-4.1 | gir1.2-webkit2-4.0, keyman-engine, python3-bs4, + python3-fonttools, python3-gi, python3-packaging, python3-sentry-sdk (>= 1.1), diff --git a/linux/keyman-config/keyman_config/__init__.py b/linux/keyman-config/keyman_config/__init__.py index 2bb3cdbaa2..26fbeddf7d 100644 --- a/linux/keyman-config/keyman_config/__init__.py +++ b/linux/keyman-config/keyman_config/__init__.py @@ -1,5 +1,6 @@ import atexit import gettext +import importlib import logging import os import pathlib @@ -53,6 +54,14 @@ def initialize_sentry(): SentryErrorHandling().initialize_sentry() +def are_requirements_missing(): + try: + ttLib = importlib.import_module('fontTools.ttLib') + except ImportError: + return True + return False + + class FileCleanup(): """ Allow to register files that will be deleted when the process exits diff --git a/linux/keyman-config/keyman_config/install_kmp.py b/linux/keyman-config/keyman_config/install_kmp.py index 1ae05d905a..21520a10c2 100755 --- a/linux/keyman-config/keyman_config/install_kmp.py +++ b/linux/keyman-config/keyman_config/install_kmp.py @@ -177,8 +177,8 @@ class InstallKmp(): # Special handling to convert kvk into LDML logging.info("Converting %s to LDML and installing both as as keyman file", f['name']) - ldml = convert_kvk_to_ldml(fpath) name, ext = os.path.splitext(f['name']) + ldml = convert_kvk_to_ldml(name, fpath) ldmlfile = os.path.join(self.packageDir, f"{name}.ldml") output_ldml(ldmlfile, ldml) elif ftype == KMFileTypes.KM_ICON: diff --git a/linux/keyman-config/keyman_config/kvk2ldml.py b/linux/keyman-config/keyman_config/kvk2ldml.py index 5b3ab85ae8..875ab7b10c 100755 --- a/linux/keyman-config/keyman_config/kvk2ldml.py +++ b/linux/keyman-config/keyman_config/kvk2ldml.py @@ -1,11 +1,15 @@ #!/usr/bin/python3 import logging +import os import struct import sys +from fontTools import ttLib from lxml import etree +from keyman_config.kmpmetadata import parsemetadata + # .kvk file format # KVK files are variable length files with variable sized structures. @@ -311,7 +315,18 @@ def get_modifer(key): return modifier -def convert_ldml(kvkData): +def _fontFacename(fontFilename): + """Get the facename from fontFilename's TTF tables""" + # From https://github.com/mcfletch/ttfquery/blob/master/ttfquery/describe.py + FONT_SPECIFIER_NAME_ID = 4 + font = ttLib.TTFont(fontFilename) + for record in font['name'].names: + if record.nameID == FONT_SPECIFIER_NAME_ID: + return record.toUnicode() + return None + + +def convert_ldml(keyboardName, kvkData, kmpJsonFilename): keymaps = {} for key in kvkData.Keys: @@ -349,7 +364,19 @@ def convert_ldml(kvkData): else: keymaps["shift"] = (uskey,) + info, system, options, keyboards, files = parsemetadata(kmpJsonFilename) + ldml = etree.Element("keyboard", locale="zzz-keyman") + for keyboard in keyboards: + if keyboard['id'] != keyboardName: + continue + if 'oskFont' in keyboard: + fontFile = os.path.join(os.path.dirname(kmpJsonFilename), keyboard['oskFont']) + font = _fontFacename(fontFile) + if font: + ldml.set('keymanFacename', font) + break + etree.SubElement(ldml, "version", platform="11") names = etree.SubElement(ldml, "names") names.append(etree.Element("name", value="ZZZ")) @@ -402,6 +429,7 @@ def parse_kvk_file(kvkfile): return kvkData -def convert_kvk_to_ldml(kvkfile): +def convert_kvk_to_ldml(name, kvkfile): kvkData = parse_kvk_file(kvkfile) - return convert_ldml(kvkData) + kmpJsonFilename = os.path.join(os.path.dirname(kvkfile), 'kmp.json') + return convert_ldml(name, kvkData, kmpJsonFilename) diff --git a/linux/keyman-config/km-config b/linux/keyman-config/km-config index f40ebeebb4..641fb96470 100755 --- a/linux/keyman-config/km-config +++ b/linux/keyman-config/km-config @@ -9,7 +9,10 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk -from keyman_config import __versionwithtag__, __pkgversion__, add_standard_arguments, initialize_logging, initialize_sentry, verify_dbus_running +from keyman_config import ( + _, __versionwithtag__, __pkgversion__, add_standard_arguments, + are_requirements_missing, initialize_logging, initialize_sentry, + verify_dbus_running) from keyman_config.handle_install import download_and_install_package from keyman_config.ibus_util import verify_ibus_daemon from keyman_config.view_installed import ViewInstalledWindow @@ -42,6 +45,18 @@ if __name__ == '__main__': initialize_sentry() verify_dbus_running() + if are_requirements_missing(): + if args.install or args.url: + logging.error('Missing requirements. Please install python3-fonttools.') + else: + dialog = Gtk.MessageDialog( + None, 0, Gtk.MessageType.ERROR, + Gtk.ButtonsType.OK, _("Missing requirements. Please install python3-fonttools.")) + dialog.run() + dialog.destroy() + sys.exit(1) + + logging.info('Keyman version %s %s', __versionwithtag__, __pkgversion__) verify_ibus_daemon(False) diff --git a/linux/keyman-config/km-kvk2ldml b/linux/keyman-config/km-kvk2ldml index 8a9adbb322..6974ac7ebb 100755 --- a/linux/keyman-config/km-kvk2ldml +++ b/linux/keyman-config/km-kvk2ldml @@ -5,7 +5,9 @@ import logging import os import sys -from keyman_config import add_standard_arguments, initialize_logging, initialize_sentry, verify_dbus_running +from keyman_config import ( + are_requirements_missing, add_standard_arguments, initialize_logging, + initialize_sentry, verify_dbus_running) from keyman_config.kvk2ldml import parse_kvk_file, print_kvk, convert_ldml, output_ldml @@ -25,6 +27,10 @@ def main(): initialize_sentry() verify_dbus_running() + if are_requirements_missing(): + logging.error('km-kvk2ldml: Missing requirements. Please install python3-fonttools.') + sys.exit(1) + name, ext = os.path.splitext(args.kvkfile) # Check if input file extension is kvk if ext != ".kvk": @@ -54,7 +60,8 @@ def main(): try: with open(outputfile, 'wb') as ldmlfile: - ldml = convert_ldml(kvkData) + kmpJsonFilename = os.path.join(os.path.dirname(args.kvkfile), 'kmp.json') + ldml = convert_ldml(name, kvkData, kmpJsonFilename) output_ldml(ldmlfile, ldml) except PermissionError: logging.error(f'km-kvk2ldml: error, permission denied writing file `{outputfile}`') diff --git a/linux/keyman-config/tests/test_kvk2ldml.py b/linux/keyman-config/tests/test_kvk2ldml.py new file mode 100644 index 0000000000..9f4c072874 --- /dev/null +++ b/linux/keyman-config/tests/test_kvk2ldml.py @@ -0,0 +1,57 @@ +import os +import shutil +import sys +import tempfile +import unittest + +from keyman_config.kvk2ldml import KVKData, NFont, convert_ldml + +class Kvk2LdmlTests(unittest.TestCase): + def _createKmpJson(self, packagedir): + kmpJsonFilename = os.path.join(packagedir, 'kmp.json') + with open(kmpJsonFilename, 'w') as file: + file.write('''{ + "system": { + "keymanDeveloperVersion": "18.0", + "fileVersion": "7.0" + }, + "files": [ { + "name": "khmer_angkor.kmx", + "description": "Keyboard Khmer Angkor" + }, { + "name": "kmp.json", + "description": "Package information (JSON)" + } ], + "keyboards": [ { + "name": "Khmer Angkor", + "id": "khmer_angkor", + "version": "1.5", + "oskFont": "keymanweb-osk.ttf", + "languages": [ { + "name": "Central Khmer (Khmer, Cambodia)", + "id": "km" + } ]} + ]}''') + return kmpJsonFilename + + def test_convert_ldml__adds_keymanFacename(self): + # Setup + keyboardName = 'khmer_angkor' + kvkData = KVKData() + kvkData.AssociatedKeyboard = keyboardName + kvkData.UnicodeFont = NFont() + kvkData.UnicodeFont.name='DontUseThis!' + + workdir = tempfile.TemporaryDirectory() + kmpJsonFilename = self._createKmpJson(workdir.name) + shutil.copy2(os.path.join(sys.path[0], '../../../common/resources/fonts/keymanweb-osk.ttf'), + workdir.name) + + # Execute + ldml = convert_ldml(keyboardName, kvkData, kmpJsonFilename) + + # Verify + self.assertEqual(ldml.get('locale'), "zzz-keyman") + self.assertEqual(ldml.get('keymanFacename'), 'SymChar') + + workdir.cleanup() From 035c7f8e2339fc9f983145981abc9650c2bff7e6 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 23 Aug 2024 11:18:45 +0700 Subject: [PATCH 13/52] chore(oem/fv): Update to fv_all 13.0 --- oem/firstvoices/keyboards.csv | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/oem/firstvoices/keyboards.csv b/oem/firstvoices/keyboards.csv index 22812ec14d..d1f1b92180 100644 --- a/oem/firstvoices/keyboards.csv +++ b/oem/firstvoices/keyboards.csv @@ -12,40 +12,40 @@ fv,fv_dexwlesucid,Dəxʷləšucid,BC Coast,fv_dexwlesucid_kmw-9.0.js,9.2.1,lut-L fv,fv_diitiidatx,Diidiitidq,BC Coast,fv_diitiidatx_kmw-9.0.js,9.2.1,nuk-Latn,Nuu-chah-nulth (Latin) fv,fv_gitsenimx,Gitsenimx̱,BC Coast,fv_gitsenimx_kmw-9.0.js,10.1.2,git,Gitxsan (Latin) fv,fv_hailzaqvla,Haiɫzaqvla,BC Coast,fv_hailzaqvla_kmw-9.0.js,9.5.2,hei,Heiltsuk (Latin) -fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1.2,has-Latn,Haisla (Latin) -fv,fv_halqemeylem,Halq'eméylem,BC Coast,fv_halqemeylem_kmw-9.0.js,9.2,hur-Latn,Halkomelem (Latin) -fv,fv_henqeminem,Hǝn̓q̓ǝmin̓ǝm,BC Coast,fv_henqeminem_kmw-9.0.js,10.1,hur-Latn,Halkomelem (Latin) -fv,fv_klahoose,Homalco-Klahoose-Sliammon,BC Coast,fv_klahoose_kmw-9.0.js,10.1,coo,Comox -fv,fv_hulquminum,Hul’q’umi’num’,BC Coast,fv_hulquminum_kmw-9.0.js,9.1,hur-Latn,Halkomelem (Latin) +fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1.3,has-Latn,Haisla (Latin) +fv,fv_halqemeylem,Halq'eméylem,BC Coast,fv_halqemeylem_kmw-9.0.js,9.2.1,hur-Latn,Halkomelem (Latin) +fv,fv_henqeminem,Hǝn̓q̓ǝmin̓ǝm,BC Coast,fv_henqeminem_kmw-9.0.js,10.2.1,hur-Latn,Halkomelem (Latin) +fv,fv_klahoose,Homalco-Klahoose-Sliammon,BC Coast,fv_klahoose_kmw-9.0.js,10.2,coo,Comox +fv,fv_hulquminum,Hul’q’umi’num’,BC Coast,fv_hulquminum_kmw-9.0.js,9.1,hur,Halkomelem fv,fv_hulquminum_combine,Hul̓q̓umin̓um̓,BC Coast,fv_hulquminum_combine_kmw-9.0.js,2.0.1,hur-Latn,Halkomelem (Latin) fv,fv_kwakwala_liqwala,Kʷak̓ʷala,BC Coast,fv_kwakwala_liqwala_kmw-9.0.js,9.3,kwk-Latn,Kwakiutl (Latin) fv,fv_kwakwala,Kwak̕wala,BC Coast,fv_kwakwala_kmw-9.0.js,9.2,kwk-Latn,Kwakiutl (Latin) -fv,fv_lekwungen,Lək̓ʷəŋən,BC Coast,fv_lekwungen-9.0.js,1.0,str,Lekwungen -fv,fv_nexwslayemucen,Nəxʷsƛ̓ay̓əmúcən,BC Coast,fv_nexwslayemucen_kmw-9.0.js,10.0,clm-Latn,Clallam (Latin) -fv,fv_nisgaa,Nisg̱a'a,BC Coast,fv_nisgaa_kmw-9.0.js,9.2,ncg-Latn,Nisga'a (Latin) +fv,fv_lekwungen,Lekwungen (Lək̓ʷəŋən),BC Coast,fv_lekwungen_kmw-9.0.js,1.0.1,str,Straits Salish +fv,fv_nexwslayemucen,Nəxʷsƛ̓ay̓əmúcən,BC Coast,fv_nexwslayemucen_kmw-9.0.js,11.0,clm,Clallam +fv,fv_nisgaa,Nisg̱a'a,BC Coast,fv_nisgaa_kmw-9.0.js,9.2.1,ncg-Latn,Nisga'a (Latin) fv,fv_nuucaanul,Nuučaan̓uł,BC Coast,fv_nuucaanul_kmw-9.0.js,9.2,nuk-Latn,Nuu-chah-nulth (Latin) fv,fv_nuxalk,Nuxalk,BC Coast,fv_nuxalk_kmw-9.0.js,10.0.1,blc-Latn,Bella Coola (Latin) -fv,fv_sencoten,SENĆOŦEN,BC Coast,fv_sencoten_kmw-9.0.js,9.2.2,str,Straits Salish +fv,fv_sencoten,SENĆOŦEN,BC Coast,fv_sencoten_kmw-9.0.js,9.2.3,str,Straits Salish fv,fv_sguuxs,Sgüüx̱s,BC Coast,fv_sguuxs.js,1.1,tsi,Tsimshian -fv,fv_shashishalhem,Shashishalhem,BC Coast,fv_shashishalhem_kmw-9.0.js,9.2,sec-Latn,Sechelt (Latin) +fv,fv_shashishalhem,Shashishalhem,BC Coast,fv_shashishalhem_kmw-9.0.js,9.2.1,sec-Latn,Sechelt (Latin) fv,fv_skwxwumesh_snichim,Sḵwx̱wúmesh sníchim,BC Coast,fv_skwxwumesh_snichim_kmw-9.0.js,10.0,squ-Latn,Squamish (Latin) -fv,fv_smalgyax,Sm'algya̱x,BC Coast,fv_smalgyax_kmw-9.0.js,9.2,tsi-Latn,Tsimshian (Latin) +fv,fv_smalgyax,Sm'algya̱x,BC Coast,fv_smalgyax_kmw-9.0.js,9.3,tsi-Latn,Tsimshian (Latin) fv,fv_xaislakala,X̄a'ʼislak̓ala,BC Coast,fv_xaislakala_kmw-9.0.js,10.0,has-Latn,Haisla (Latin) fv,fv_hlgaagilda_xaayda_kil,X̱aayda-X̱aad Kil,BC Coast,fv_hlgaagilda_xaayda_kil_kmw-9.0.js,9.4,hax,Southern Haida fv,fv_dakelh,Dakelh,BC Interior,fv_dakelh_kmw-9.0.js,9.2.1,caf-Latn,Southern Carrier (Latin) fv,fv_ktunaxa,Ktunaxa,BC Interior,fv_ktunaxa_kmw-9.0.js,10.0,kut-Latn,Kutenai (Latin) fv,fv_kwadacha_tsekene,Kwadacha Tsek’ene,BC Interior,fv_kwadacha_tsekene_kmw-9.0.js,1.1,sek-Latn,Sekani -fv,fv_natwits,Nedut’en-Witsuwit'en,BC Interior,fv_natwits_kmw-9.0.js,9.1.3,caf-Latn,Southern Carrier (Latin) +fv,fv_natwits,Nedut’en-Witsuwit'en,BC Interior,fv_natwits_kmw-9.0.js,9.2,caf-Latn,Southern Carrier (Latin) fv,fv_nlekepmxcin,Nłeʔkepmxcin,BC Interior,fv_nlekepmxcin_kmw-9.0.js,9.5.1,thp-Latn,Thompson (Latin) -fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.1.1,thp-Latn,Thompson (Latin) +fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.1.2,thp,Thompson fv,fv_nlakapamuxcheen,Nlakapamuxcheen,BC Interior,fv_nlakapamuxcheen_kmw-9.0.js,1.1,thp,Thompson -fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,10.0,oka,Okanagan -fv,fv_secwepemctsin,Secwepemctsín,BC Interior,fv_secwepemctsin_kmw-9.0.js,9.2,shs-Latn,Shuswap (Latin) -fv,fv_stlatlimxec,Sƛ̓aƛ̓imxəc,BC Interior,fv_stlatlimxec_kmw-9.0.js,9.3,lil-Latn,Lillooet (Latin) +fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,10.0.1,oka,Okanagan +fv,fv_secwepemctsin,Secwepemctsín,BC Interior,fv_secwepemctsin_kmw-9.0.js,9.3,shs,Shuswap +fv,fv_stlatlimxec,Sƛ̓aƛ̓imxəc,BC Interior,fv_stlatlimxec_kmw-9.0.js,9.4,lil-Latn,Lillooet (Latin) fv,fv_statimcets,St̓át̓imcets,BC Interior,fv_statimcets_kmw-9.0.js,9.2,lil-Latn,Lillooet (Latin) fv,fv_taltan,Tāłtān,BC Interior,fv_taltan_kmw-9.0.js,9.2,tht-Latn,Tahltan (Latin) fv,fv_tsekehne,Tsek'ehne,BC Interior,fv_tsekehne_kmw-9.0.js,9.2,sek-Latn,Sekani (Latin) -fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.2,clc-Latn,Chilcotin (Latin) +fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.3,clc-Latn,Chilcotin (Latin) fv,fv_southern_carrier,ᑐᑊᘁᗕᑋᗸ (Southern Carrier),BC Interior,fv_southern_carrier_kmw-9.0.js,10.1,caf-Cans,Southern Carrier (Unified Canadian Aboriginal Syllabics) fv,fv_anicinapemi8in,Anicinapemi8in/Anishinàbemiwin,Eastern Subarctic,fv_anicinapemi8in_kmw-9.0.js,9.1.1,alq-Latn,Algonquin (Latin) fv,fv_atikamekw,Atikamekw,Eastern Subarctic,fv_atikamekw_kmw-9.0.js,9.1.1,atj-Latn,Atikamekw (Latin) @@ -53,16 +53,16 @@ fv,fv_ilnu_innu_aimun,Ilnu-Innu Aimun,Eastern Subarctic,fv_ilnu_innu_aimun_kmw-9 fv,fv_swampy_cree,ᐃᓂᓂᒧᐎᐣ (Swampy Cree),Eastern Subarctic,fv_swampy_cree_kmw-9.0.js,9.2.1,csw-Cans,Swampy Cree (Unified Canadian Aboriginal Syllabics) fv,fv_moose_cree,ᐃᓕᓖᒧᐎᓐ (Moose Cree),Eastern Subarctic,fv_moose_cree_kmw-9.0.js,9.2.1,crm-Cans,Moose Cree (Unified Canadian Aboriginal Syllabics) fv,fv_northern_east_cree,ᐄᔨᔫ-ᐄᓅ ᐊᔨᒨᓐ (Northern East Cree),Eastern Subarctic,fv_northern_east_cree_kmw-9.0.js,9.2.1,crl-Cans,Northern East Cree (Unified Canadian Aboriginal Syllabics) -fv,fv_severn_ojibwa,ᐊᓂᔑᓂᓂᒧᐎᐣ (Severn Ojibwa),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,10.1,ojs-Cans,Severn Ojibwa (Unified Canadian Aboriginal Syllabics) -fv,fv_severn_ojibwa_rdot,ᐊᓂᔑᓂᓂᒧᐏᐣ (Severn Ojibwa right w-dot),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,1.1,ojs,Oji-Cree +fv,fv_severn_ojibwa,ᐊᓂᔑᓂᓂᒧᐎᐣ (Severn Ojibwa),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,10.1.1,ojs-Cans,Severn Ojibwa (Unified Canadian Aboriginal Syllabics) +fv,fv_severn_ojibwa_rdot,ᐊᓂᔑᓂᓂᒧᐏᐣ (Severn Ojibwa right w-dot),Eastern Subarctic,fv_severn_ojibwa_kmw-9.0.js,1.1.1,ojs,Oji-Cree fv,fv_ojibwa,ᐊᓂᔑᓇᐯᒧᐎᓐ (a-finals),Eastern Subarctic,fv_ojibwa_kmw-9.0.js,10.1,ojb-Cans,Northwestern Ojibwa (Unified Canadian Aboriginal Syllabics) -fv,fv_ojibwa_rdot,ᐁᓂᔑᓇᐯᒧᐏᓐ (a-finals right w-dot),Eastern Subarctic,fv_ojibwa_rdot_kmw-9.0.js,1.0.2,oj,Ojibwa -fv,fv_ojibwa_ifinal,ᐊᓂᔑᓇᐯᒧᐎᣙ (i-finals),Eastern Subarctic,fv_ojibwa_ifinal_kmw-9.0.js,1.0.1,oj,Ojibwa -fv,fv_ojibwa_ifinal_rdot,ᐊᓂᔑᓇᐯᒧᐏᣙ (i-finals right w-dot),Eastern Subarctic,fv_ojibwa_ifinal_rdot_kmw-9.0.js,1.0.1,oj,Ojibwa +fv,fv_ojibwa_rdot,ᐁᓂᔑᓇᐯᒧᐏᓐ (a-finals right w-dot),Eastern Subarctic,fv_ojibwa_rdot_kmw-9.0.js,1.0.3,oj,Ojibwa +fv,fv_ojibwa_ifinal,ᐊᓂᔑᓇᐯᒧᐎᣙ (i-finals),Eastern Subarctic,fv_ojibwa_ifinal_kmw-9.0.js,1.0.2,oj,Ojibwa +fv,fv_ojibwa_ifinal_rdot,ᐊᓂᔑᓇᐯᒧᐏᣙ (i-finals right w-dot),Eastern Subarctic,fv_ojibwa_ifinal_rdot_kmw-9.0.js,1.0.2,oj,Ojibwa fv,fv_naskapi,ᓇᔅᑲᐱ (Naskapi),Eastern Subarctic,fv_naskapi_kmw-9.0.js,9.3.1,nsk-Cans,Naskapi (Unified Canadian Aboriginal Syllabics) sil,sil_euro_latin,English,European,european2-1.6.js,3.0.2,en,English basic,basic_kbdcan,Français,European,canadian_french-1.0.js,1.1.1,fr-CA,French (Canada) -fv,fv_anishinaabemowin,Anishinaabemowin,Great Lakes - St. Lawrence,fv_anishinaabemowin_kmw-9.0.js,10.1,oj,Ojibwa +fv,fv_anishinaabemowin,Anishinaabemowin,Great Lakes - St. Lawrence,fv_anishinaabemowin_kmw-9.0.js,10.2,oj,Ojibwa fv,fv_bodewadminwen,Bodéwadminwen-Nishnabémwen,Great Lakes - St. Lawrence,fv_bodewadminwen_kmw-9.0.js,9.1.1,pot-Latn,Potawatomi (Latin) fv,fv_goyogohono,Goyogo̱hó:nǫ',Great Lakes - St. Lawrence,fv_goyogohono_kmw-9.0.js,9.2.1,cay-Latn,Cayuga (Latin) fv,fv_kanienkeha_e,Kanien'kéha-Kanyen'kéha,Great Lakes - St. Lawrence,fv_kanienkeha_e_kmw-9.0.js,9.1.3,moh-Latn,Mohawk (Latin) @@ -85,7 +85,7 @@ fv,fv_nakoda,Nakoda,Prairies,fv_nakoda_kmw-9.0.js,9.1.1,asb-Latn,Assiniboine (La fv,fv_tsuutina,Tsúùt'ínà,Prairies,fv_tsuutina_kmw-9.0.js,9.1.1,srs-Latn,Sarsi (Latin) fv,fv_plains_cree,ᓀᐦᐃᔭᐍᐏᐣ (Plains Cree),Prairies,fv_plains_cree_kmw-9.0.js,11.1,crk-Cans,ᓀᐦᐃᔭᐍᐏᐣ (Cree syllabics) fv,fv_dine_bizaad,Diné Bizaad,South West,fv_dine_bizaad_kmw-9.0.js,9.1.1,nv-Latn,Navajo (Latin) -fv,fv_dane_zaa_zaage,Dane-Z̲aa Z̲áágéʔ,Western Subarctic,fv_dane_zaa_zaage_kmw-9.0.js,9.4,bea,Beaver +fv,fv_dane_zaa_zaage,Dane-Z̲aa Z̲áágéʔ,Western Subarctic,fv_dane_zaa_zaage_kmw-9.0.js,9.4.1,bea,Beaver fv,fv_dene_dzage,Dene Dzage,Western Subarctic,fv_dene_dzage_kmw-9.0.js,11.0.1,kkz-Latn,Kaska (Latin) fv,fv_dene_zhatie,Dene Zhatié,Western Subarctic,fv_dene_zhatie_kmw-9.0.js,10.2.1,den,Dene Zhatıé fv,fv_denesuline_epsilon,Dënesųłıné,Western Subarctic,fv_denesuline_epsilon_kmw-9.0.js,10.0.1,chp,Chipewyan @@ -100,7 +100,7 @@ fv,fv_northern_tutchone,Northern Tutchone,Western Subarctic,fv_northern_tutchone fv,fv_sahugotine_yati,Sahtúgot'ı̨nę́ Yatı̨́,Western Subarctic,fv_sahugotine_yati_kmw-9.0.js,9.1.1,scs-Latn,North Slavey (Latin) fv,fv_shihgotine_yati,Shıhgot'ı̨nę́ Yatı̨́,Western Subarctic,fv_shihgotine_yati_kmw-9.0.js,9.1.1,scs-Latn,North Slavey (Latin) fv,fv_southern_tutchone,Southern Tutchone,Western Subarctic,fv_southern_tutchone_kmw-9.0.js,9.3,tce-Latn,Southern Tutchone (Latin) -fv,fv_tagizi_dene,Tāgizi Dene,Western Subarctic,fv_tagizi_dene_kmw-9.0.js,9.3,tgx-Latn,Tagish (Latin) +fv,fv_tagizi_dene,Tāgizi Dene,Western Subarctic,fv_tagizi_dene_kmw-9.0.js,9.4,tgx-Latn,Tagish (Latin) fv,fv_tlicho_yatii,Tłı̨chǫ Yatıı̀,Western Subarctic,fv_tlicho_yatii_kmw-9.0.js,9.1.1,dgr-Latn,Dogrib (Latin) fv,fv_dene_mb,ᑌᓀ ᔭᕠᐁ (Dene MB),Western Subarctic,fv_dene_mb_kmw-9.0.js,9.2.1,chp-Cans,Chipewyan (Unified Canadian Aboriginal Syllabics) fv,fv_dene_nt,ᑌᓀ ᔭᕱᐁ (Dene NT),Western Subarctic,fv_dene_nt_kmw-9.0.js,9.2.1,chp-Cans,Chipewyan (Unified Canadian Aboriginal Syllabics) From 64c4601fd6cbfdc259d0af541c1ed905c11adddd Mon Sep 17 00:00:00 2001 From: sgschantz Date: Tue, 3 Sep 2024 13:07:25 +0700 Subject: [PATCH 14/52] fix(mac): check for macOS 11 for PostEvent access cherry-picked from f567778 CGPreflightPostEventAccess API should be available with macOS 10.15 (Catalina) but that does not appear to be true in experience. Changing to check for 11.0 (Big Sur) before using that API instead. Fixes: #12295 --- .../Keyman4MacIM/Privacy/PrivacyConsent.m | 59 ++++++++++--------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/mac/Keyman4MacIM/Keyman4MacIM/Privacy/PrivacyConsent.m b/mac/Keyman4MacIM/Keyman4MacIM/Privacy/PrivacyConsent.m index 7e3fffdb0a..992916862b 100644 --- a/mac/Keyman4MacIM/Keyman4MacIM/Privacy/PrivacyConsent.m +++ b/mac/Keyman4MacIM/Keyman4MacIM/Privacy/PrivacyConsent.m @@ -1,4 +1,4 @@ -/** +/* * Keyman is copyright (C) SIL International. MIT License. * * PrivacyConsent.m @@ -7,8 +7,8 @@ * Created by Shawn Schantz on 2022-09-22. * * Used to determine if the user has provided consent to the services it needs - * and, if not, to request that consent. For versions of macOS prior to 10.15, - * Keyman requires Accessibility access. For 10.15 and later, Keyman requires + * and, if not, to request that consent. For versions of macOS prior to 11.0, + * Keyman requires Accessibility access. For 11.0 and later, Keyman requires * PostEvent access. Both are presented to the user as a need for Accessibility * when prompted by the system and are listed under Accessibility in the Privacy * tab in System Preferences, Security & Privacy. Both Accessibility and @@ -16,7 +16,11 @@ * that access is not explicitly needed as long as one of the others is provided * first. * - * Access this functionality through the shared instance. Call + * Note that Apple's documentation states that the PostEvent access APIs are + * available with macOS 10.15 (Catalina) but testing showed that it was only + * available with macOS 11.0 (Big Sur). This is documented with issue #12295. + * + * To access this functionality, used the shared instance. Call * requestPrivacyAccess which will check whether access has been granted. If * not, then a dialog will be presented to the user to inform them that * Accessibility is required. Dismissing this dialog will trigger the API call @@ -24,7 +28,7 @@ * only happen once. If the user was prompted earlier and did not grant access, * they can still go to System Preferences and enable it there. So it is useful * to prompt with a dialog from Keyman at startup. Without Accessibility, the - * shift layer and the OSK do not work -- so Keyman is basically useless. + * shift layer and the OSK do not work. */ #import "PrivacyConsent.h" @@ -42,7 +46,7 @@ } /** - * For macOS earlier than 10.15: check for Accessibility access. + * For macOS earlier than 11.0: check for Accessibility access. */ - (BOOL)checkAccessibility { @@ -65,7 +69,7 @@ BOOL hasAccessibility = NO; // check if we already have accessibility - if (@available(macOS 10.15, *)) { + if (@available(macOS 11.0, *)) { hasAccessibility = [self checkPostEventAccess]; } else { hasAccessibility = [self checkAccessibility]; @@ -84,7 +88,7 @@ } /** - * For macOS earlier than 10.15: request Accessibility access. + * For macOS earlier than 11.0: request Accessibility access. */ - (void)requestAccessibility { @@ -111,19 +115,18 @@ * Initialize privacy alert appropriately as determined by macOS version. */ - (void)configureDialogForOsVersion { - - if (@available(macOS 10.15, *)) { - [self configureDialogForCatalinaAndLater]; + if (@available(macOS 11.0, *)) { + [self configureDialogForBigSurAndLater]; } else { - [self configureDialogForPreCatalina]; + [self configureDialogForPreBigSur]; } } /** - * Initialize privacy dialog for macOS versions prior to Catalina (10.15). + * Initialize privacy dialog for macOS versions prior to Big Sur (11.0). * In this case, request Accessibility access, not PostEvent. */ -- (void)configureDialogForPreCatalina { +- (void)configureDialogForPreBigSur { void (^consentPrompt)(void) = ^(void) { [self requestAccessibility]; @@ -135,10 +138,10 @@ } /** - * Initialize privacy dialog for macOS versions of Catalina (10.15) or later. + * Initialize privacy dialog for macOS versions of Big Sur (11.0) or later. * In this case, request PostEvent access, not Accessibility. */ -- (void)configureDialogForCatalinaAndLater { +- (void)configureDialogForBigSurAndLater { void (^consentPrompt)(void) = ^(void) { [self requestPostEventAccess]; @@ -159,7 +162,7 @@ /** * Check whether the user has allowed ListenEvent access. - * Only available with macOS Catalina (10.15) or later. + * Only available with macOS Big Sur (11.0) or later. * * If user has granted Accessibility or PostEvent access, then * ListenEvent access is also granted. @@ -169,18 +172,18 @@ BOOL hasAccess = NO; // below checks for ListenEvent access - if (@available(macOS 10.15, *)) { + if (@available(macOS 11.0, *)) { hasAccess = CGPreflightListenEventAccess(); NSLog(@"CGPreflightListenEventAccess() returned %@", hasAccess ? @"YES" : @"NO"); } else { - NSLog(@"CGPreflightListenEventAccess not available before macOS version 10.15"); + NSLog(@"CGPreflightListenEventAccess not available before macOS version 11.0"); } return hasAccess; } /** * Check whether the user has allowed PostEvent access. - * Only available with macOS Catalina (10.15) or later. + * Only available with macOS Big Sur (11.0) or later. * * If user has granted Accessibility, then PostEvent access is also granted. */ @@ -189,46 +192,46 @@ BOOL hasAccess = NO; // below checks for PostEvent access - if (@available(macOS 10.15, *)) { + if (@available(macOS 11.0, *)) { hasAccess = CGPreflightPostEventAccess(); NSLog(@"CGPreflightPostEventAccess() returned %@", hasAccess ? @"YES" : @"NO"); } else { - NSLog(@"CGPreflightPostEventAccess not available before macOS version 10.15"); + NSLog(@"CGPreflightPostEventAccess not available before macOS version 11.0"); } return hasAccess; } /** * Request ListenEvent access. - * Only available with macOS Catalina (10.15) or later. + * Only available with macOS Big Sur (11.0) or later. */ - (BOOL)requestListenEventAccess { BOOL granted = NO; - if (@available(macOS 10.15, *)) { + if (@available(macOS 11.0, *)) { granted = CGRequestListenEventAccess(); NSLog(@"CGRequestListenEventAccess() returned %@", granted ? @"YES" : @"NO"); } else { - NSLog(@"CGRequestListenEventAccess not available before macOS version 10.15"); + NSLog(@"CGRequestListenEventAccess not available before macOS version 11.0"); } return granted; } /** * Request PostEvent access. - * Only available with macOS Catalina (10.15) or later. + * Only available with macOS Big Sur (11.0) or later. */ - (BOOL)requestPostEventAccess { BOOL granted = NO; - if (@available(macOS 10.15, *)) { + if (@available(macOS 11.0, *)) { granted = CGRequestPostEventAccess(); NSLog(@"CGRequestPostEventAccess() returned %@", granted ? @"YES" : @"NO"); } else { - NSLog(@"CGRequestPostEventAccess not available before macOS version 10.15"); + NSLog(@"CGRequestPostEventAccess not available before macOS version 11.0"); } return granted; } From a9b3f089ad11f5d93005a038260cecc27c97d53b Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 6 Sep 2024 12:55:19 +0700 Subject: [PATCH 15/52] fix(android): skip language counts for lexical-model packages fix(android): Skip language counts for lexical-model packages --- .../src/main/java/com/tavultesoft/kmapro/PackageActivity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java index 5de23272f5..17203b9ada 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/PackageActivity.java @@ -112,7 +112,8 @@ public class PackageActivity extends AppCompatActivity implements // Number of languages associated with the first keyboard in a keyboard package. // lexical-model packages will be 0 - final int languageCount = kmpProcessor.getLanguageCount(pkgInfo, PackageProcessor.PP_KEYBOARDS_KEY, 0); + final int languageCount = (keyboardCount > 0) ? + kmpProcessor.getLanguageCount(pkgInfo, PackageProcessor.PP_KEYBOARDS_KEY, 0) : 0; // Sanity check for keyboard packages if (pkgTarget.equals(PackageProcessor.PP_TARGET_KEYBOARDS)) { From 68ca0980499e85b748ed7655fd6e934459df10c0 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Sun, 8 Sep 2024 22:08:43 -0400 Subject: [PATCH 16/52] auto: increment stable-17.0 version to 17.0.330 --- HISTORY.md | 23 +++++++++++++++++++++++ VERSION.md | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 76c681d539..a145231142 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,28 @@ # Keyman Version History +## 17.0.329 stable 2024-09-09 + +* chore(android,ios): Add ojibwa ifinal/rdot keyboards to FirstVoices (#12020) +* change(web): revert #11174, which loads keyboards before initializing the OSK (#12040) +* fix(web): unrevert #11258, leaving OSK hidden before instructed to display (#12058) +* chore(common): use `nvm` to select version of node for builds (#12074) +* fix(developer): ignore scan code if zero in debugger (#12182) +* fix(developer): enforce presence of Version field when FollowKeyboardVersion is not set, in package compiler (#12206) +* fix(developer): enforce presence of kps Info.Description field in info compilers (#12207) +* fix(web): disable fat-finger data use when mayCorrect = false (#12226) +* chore(common): allow build agents to automatically select emsdk version, and enable support for 3.1.60+ (#12245) +* fix(web): fix documentation-keyboard spacebar-text scaling (#12240) +* fix(core): set mac build version for meson cli build to 10.13 (#12246) +* change(ios): defer registration of fonts past initialization (#12241) +* chore(android,ios): Update FirstVoices keyboards to 12.15 (#12301) +* fix(core): properly support 'other' modifier state with `uint32_t` type (#12285) +* fix(developer): find last matching key in LDML key bag when building KVK (#12284) +* fix(android): check in material-stepper as internal Maven dependency (#12324) +* fix(linux): add `keymanFacename` to .ldml file (#12283) +* chore(oem/fv): Update to fv_all 13.0 (#12363) +* fix(mac): avoid crash on startup with macOS 10.15 (Catalina) (#12364) +* fix(android): skip language counts for lexical-model packages (#12368) + ## 17.0.328 stable 2024-07-27 * fix(web): add nullish test in setOsk (#12041) diff --git a/VERSION.md b/VERSION.md index 3e94a1aa9f..ad53a2c5b0 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.329 \ No newline at end of file +17.0.330 \ No newline at end of file From 040c9e44ff08030ae786803861536f2e8010f115 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 11 Sep 2024 09:03:34 +0700 Subject: [PATCH 17/52] refactor(android): Move Sentry and Apk to publish task --- android/KMAPro/build.sh | 13 ++++ android/KMAPro/kMAPro/build.gradle | 15 ++-- android/build-publish.sh | 87 ------------------------ android/build.sh | 2 +- oem/firstvoices/android/app/build.gradle | 15 ++-- oem/firstvoices/android/build.sh | 10 ++- 6 files changed, 38 insertions(+), 104 deletions(-) delete mode 100755 android/build-publish.sh diff --git a/android/KMAPro/build.sh b/android/KMAPro/build.sh index 192e321118..c348a91be7 100755 --- a/android/KMAPro/build.sh +++ b/android/KMAPro/build.sh @@ -14,6 +14,8 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "$KEYMAN_ROOT/resources/build/build-help.inc.sh" . "$KEYMAN_ROOT/resources/build/build-download-resources.sh" +. "$KEYMAN_ROOT/android/KMAPro/build-play-store-notes.inc.sh" + # This script runs from its own folder cd "$THIS_SCRIPT_PATH" @@ -32,6 +34,7 @@ builder_describe "Builds Keyman for Android app." \ "configure" \ "build" \ "test Runs lint and unit tests." \ + "publish Publishes symbols to Sentry and the APK to the Play Store." \ "--ci Don't start the Gradle daemon. For CI" \ "--upload-sentry Upload to sentry" @@ -116,3 +119,13 @@ if builder_start_action test; then builder_finish_action success test fi + +if builder_start_action publish; then + # Copy Release Notes + generateReleaseNotes + + # Publish symbols and Keyman for Android to Play Store + ./gradlew $DAEMON_FLAG publishSentry publishReleaseApk + + builder_finish_action success publish +fi diff --git a/android/KMAPro/kMAPro/build.gradle b/android/KMAPro/kMAPro/build.gradle index 01e2de32e3..f431f09ea9 100644 --- a/android/KMAPro/kMAPro/build.gradle +++ b/android/KMAPro/kMAPro/build.gradle @@ -105,12 +105,17 @@ android { } // how to configure the sentry android gradle plugin -sentry { - // Disables or enables the automatic configuration of Native symbols - uploadNativeSymbols = true +task publishSentry { + doLast { + println 'Publishing Keyman symbols to Sentry' + sentry { + // Disables or enables the automatic configuration of Native symbols + uploadNativeSymbols = true - // Does or doesn't include the source code of native code for Sentry - includeNativeSources = true + // Does or doesn't include the source code of native code for Sentry + includeNativeSources = true + } + } } String env_keys_json_file = System.getenv("keys_json_file") diff --git a/android/build-publish.sh b/android/build-publish.sh deleted file mode 100755 index 29c152c993..0000000000 --- a/android/build-publish.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env bash -# CI script to publish specified app APKs to the Play Store. -# The APKs should already have been built from a separate script - -# set -x: Debugging use, print each statement -# set -x - -## 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/android/KMAPro/build-play-store-notes.inc.sh" - -echo Publishing APKs to Play Store - -# -# Prevents 'clear' on exit of mingw64 bash shell -# -SHLVL=0 - -display_usage ( ) { - echo "build-publish.sh [-no-daemon] [-kmapro] [-fv]" - echo - echo "Publish app to the Play Store" - echo " -no-daemon Don't start the Gradle daemon. Use for CI" - echo " -kmapro Keyman for Android" - echo " -fv First Voices" - exit 1 -} - -NO_DAEMON=false -DO_KMAPRO=false -DO_FV=false - -# Parse args -while [[ $# -gt 0 ]] ; do - key="$1" - case $key in - -no-daemon) - NO_DAEMON=true - ;; - -kmapro) - DO_KMAPRO=true - ;; - -fv) - DO_FV=true - ;; - -h|-\?) - display_usage - ;; - esac - shift # past argument -done - -# Override JAVA_HOME to OpenJDK 11 -set_java_home - -echo -echo "NO_DAEMON: $NO_DAEMON" -echo "DO_KMAPRO: $DO_KMAPRO" -echo "DO_FV: $DO_FV" -echo - -if [ "$NO_DAEMON" = true ]; then - DAEMON_FLAG=--no-daemon -else - DAEMON_FLAG= -fi - -BUILD_FLAGS="publishReleaseApk" -echo "BUILD_FLAGS $BUILD_FLAGS" - -# Publish Keyman for Android -if [ "$DO_KMAPRO" = true ]; then - # Copy Release Notes - generateReleaseNotes - cd "$KEYMAN_ROOT/android/KMAPro/" - ./gradlew $DAEMON_FLAG $BUILD_FLAGS -fi - -# Publish FV app -if [ "$DO_FV" = true ]; then - cd "$KEYMAN_ROOT/oem/firstvoices/android/" - ./gradlew $DAEMON_FLAG $BUILD_FLAGS -fi diff --git a/android/build.sh b/android/build.sh index b22d8887f1..ad650c067e 100755 --- a/android/build.sh +++ b/android/build.sh @@ -25,7 +25,7 @@ builder_describe \ configure \ build \ test \ - "publish Publishes the APKs to the Play Store." \ + "publish Publishes symbols to Sentry and the APKs to the Play Store." \ --ci+ \ --upload-sentry+ \ ":engine=KMEA Keyman Engine for Android" \ diff --git a/oem/firstvoices/android/app/build.gradle b/oem/firstvoices/android/app/build.gradle index 43adc17265..62064f3899 100644 --- a/oem/firstvoices/android/app/build.gradle +++ b/oem/firstvoices/android/app/build.gradle @@ -73,12 +73,17 @@ java { } // how to configure the sentry android gradle plugin -sentry { - // Disables or enables the automatic configuration of Native symbols - uploadNativeSymbols = true +task publishSentry { + doLast { + println 'Publishing FirstVoices symbols to Sentry' + sentry { + // Disables or enables the automatic configuration of Native symbols + uploadNativeSymbols = true - // Does or doesn't include the source code of native code for Sentry - includeNativeSources = true + // Does or doesn't include the source code of native code for Sentry + includeNativeSources = true + } + } } String env_keys_json_file = System.getenv("oem_firstvoices_keys_json_file") diff --git a/oem/firstvoices/android/build.sh b/oem/firstvoices/android/build.sh index 75bcfc672a..5500555acd 100755 --- a/oem/firstvoices/android/build.sh +++ b/oem/firstvoices/android/build.sh @@ -32,6 +32,7 @@ builder_describe "Builds FirstVoices for Android app." \ "configure" \ "build" \ "test Runs lint and tests." \ + "publish Publishes symbols to Sentry and the APK to the Play Store." \ "--ci Don't start the Gradle daemon. For CI" \ "--upload-sentry Upload to sentry" @@ -61,15 +62,10 @@ fi #### Build action definitions #### -function makeLocalSentryRelease() { - echo "Placeholder for uploading symbols to Sentry" -} - -#### Build action definitions #### - # Check about cleaning artifact paths if builder_start_action clean; then rm -rf "$KEYMAN_ROOT/oem/firstvoices/android/app/build/outputs" + rm -rf "$KEYMAN_ROOT/oem/firstvoices/android/app/build/tmp" builder_finish_action success clean fi @@ -102,3 +98,5 @@ if builder_start_action test; then builder_finish_action success test fi + +builder_run_action publish ./gradlew $DAEMON_FLAG publishSentry publishReleaseApk From 91cd73602a5102c8ab04c4042f6d8aa983ffd47a Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 12 Sep 2024 10:02:18 +0700 Subject: [PATCH 18/52] fix(developer): rwrite ldml visual keyboard compiler The visual keyboard compiler was never finished in 17.0. This rewrites it to: 1. Use the kmxplus data rather than reading from xml directly 2. Fill in `visualkeyboard.header.kbdname` 3. Support modifiers 4. Handle encoded characters like `\u{1234}` 5. Handle string variables like `${one}`* Additional unit tests have been added to verify the behavior of the visual keyboard compiler in more detail. * String variable tests will be enabled in next commit (which is a cherry-pick of #12404). Other fixes: 1. The LDML XML reader was relying on its input being a Node.js `Buffer` even though it was declared `Uint8Array`, as it implicitly used `Buffer.toString()` to do text conversion. (`Buffer` subclasses from `Uint8Array`). This breaks when using `Uint8Array` directly and means we had an implicit dependency on Node.js. See also #12331. 2. XML errors were not captured in the LDML XML reader. See also #12331. 3. The unused and unfinished touch-layout-compiler.ts and keymanweb-compiler.ts have been removed along with corresponding unit tests and fixtures. These will be replaced by Core implementations; see #12291. Fixes: #12395 Cherry-pick-of: #12402 --- .../src/consts/modifier-key-constants.ts | 33 +++ .../ldml-keyboard/ldml-keyboard-xml-reader.ts | 26 +- common/web/types/src/main.ts | 1 + common/web/types/src/util/common-events.ts | 7 + developer/src/kmc-ldml/package.json | 2 + .../src/kmc-ldml/src/compiler/compiler.ts | 5 +- .../src/compiler/keymanweb-compiler.ts | 113 --------- .../src/compiler/touch-layout-compiler.ts | 112 --------- .../src/compiler/visual-keyboard-compiler.ts | 111 ++++++--- .../src/kmc-ldml/test/fixtures/basic-kvk.txt | 6 +- .../kmc-ldml/test/fixtures/basic-no-debug.js | 1 - developer/src/kmc-ldml/test/fixtures/basic.js | 48 ---- .../src/kmc-ldml/test/fixtures/basic.txt | 6 +- .../src/kmc-ldml/test/fixtures/basic.xml | 4 +- developer/src/kmc-ldml/test/helpers/index.ts | 31 +-- .../kmc-ldml/test/test-keymanweb-compiler.ts | 50 ---- .../test/test-visual-keyboard-compiler-e2e.ts | 31 --- .../test/test-visual-keyboard-compiler.ts | 227 ++++++++++++++++++ package-lock.json | 19 ++ 19 files changed, 401 insertions(+), 432 deletions(-) create mode 100644 common/web/types/src/consts/modifier-key-constants.ts delete mode 100644 developer/src/kmc-ldml/src/compiler/keymanweb-compiler.ts delete mode 100644 developer/src/kmc-ldml/src/compiler/touch-layout-compiler.ts delete mode 100644 developer/src/kmc-ldml/test/fixtures/basic-no-debug.js delete mode 100644 developer/src/kmc-ldml/test/fixtures/basic.js delete mode 100644 developer/src/kmc-ldml/test/test-keymanweb-compiler.ts delete mode 100644 developer/src/kmc-ldml/test/test-visual-keyboard-compiler-e2e.ts create mode 100644 developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts diff --git a/common/web/types/src/consts/modifier-key-constants.ts b/common/web/types/src/consts/modifier-key-constants.ts new file mode 100644 index 0000000000..245cbf70f3 --- /dev/null +++ b/common/web/types/src/consts/modifier-key-constants.ts @@ -0,0 +1,33 @@ +/* + * Keyman is copyright (C) SIL International. MIT License. + * + * Modifier key bit-flags + */ + +export const ModifierKeyConstants = { + // Define Keyman Developer modifier bit-flags (exposed for use by other modules) + // Compare against /common/include/kmx_file.h. CTRL+F "#define LCTRLFLAG" to find the secton. + LCTRLFLAG: 0x0001, // Left Control flag + RCTRLFLAG: 0x0002, // Right Control flag + LALTFLAG: 0x0004, // Left Alt flag + RALTFLAG: 0x0008, // Right Alt flag + K_SHIFTFLAG: 0x0010, // Either shift flag + K_CTRLFLAG: 0x0020, // Either ctrl flag + K_ALTFLAG: 0x0040, // Either alt flag + K_METAFLAG: 0x0080, // Either Meta-key flag (tentative). Not usable in keyboard rules; + // Used internally (currently, only by KMW) to ensure Meta-key + // shortcuts safely bypass rules + // Meta key = Command key on macOS, Windows key on Windows/Linux + CAPITALFLAG: 0x0100, // Caps lock on + NOTCAPITALFLAG: 0x0200, // Caps lock NOT on + NUMLOCKFLAG: 0x0400, // Num lock on + NOTNUMLOCKFLAG: 0x0800, // Num lock NOT on + SCROLLFLAG: 0x1000, // Scroll lock on + NOTSCROLLFLAG: 0x2000, // Scroll lock NOT on + ISVIRTUALKEY: 0x4000, // It is a Virtual Key Sequence + VIRTUALCHARKEY: 0x8000, // Keyman 6.0: Virtual Key Cap Sequence NOT YET + + // Note: OTHER_MODIFIER = 0x10000, used by KMX+ for the + // other modifier flag in layers, > 16 bit so not available here. + // See keys_mod_other in keyman_core_ldml.ts +} 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 4f5c30bb1a..efe3984ff0 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 @@ -113,6 +113,7 @@ export class LDMLKeyboardXMLSourceFileReader { for (const sub of obj) { // retain the same subtag if (!this.boxImportsAndSpecials(sub, subtag)) { + // resolveImports has already logged a message return false; } } @@ -125,6 +126,7 @@ export class LDMLKeyboardXMLSourceFileReader { boxXmlArray(obj, key); // Now, resolve the import if (!this.resolveImports(obj, subtag)) { + // resolveImports has already logged a message return false; } // now delete the import array we so carefully constructed, the caller does not @@ -132,6 +134,7 @@ export class LDMLKeyboardXMLSourceFileReader { delete obj['import']; } else { if (!this.boxImportsAndSpecials(obj[key], key)) { + // resolveImports has already logged a message return false; } } @@ -151,6 +154,7 @@ export class LDMLKeyboardXMLSourceFileReader { // first, the explicit imports for (const asImport of ([...obj['import'] as LKImport[]].reverse())) { if (!this.resolveOneImport(obj, subtag, asImport)) { + // resolveOneImport has already logged a message return false; } } @@ -161,6 +165,7 @@ export class LDMLKeyboardXMLSourceFileReader { base: constants.cldr_import_base, path: constants.cldr_implied_keys_import }, true)) { + // resolveOneImport has already logged a message return false; } } else if (subtag === 'forms') { @@ -169,6 +174,7 @@ export class LDMLKeyboardXMLSourceFileReader { base: constants.cldr_import_base, path: constants.cldr_implied_forms_import }, true)) { + // resolveOneImport has already logged a message return false; } } @@ -266,7 +272,8 @@ export class LDMLKeyboardXMLSourceFileReader { // An alternative fix would be to pull xml2js directly from github // rather than using the version tagged on npmjs.com. }); - parser.parseString(file, (e: unknown, r: unknown) => { a = r as LDMLKeyboardXMLSourceFile }); // TODO-LDML: isn't 'e' the error? + const data = new TextDecoder().decode(file); + parser.parseString(data, (e: unknown, r: unknown) => { if(e) throw e; a = r as LDMLKeyboardXMLSourceFile }); // TODO-LDML: isn't 'e' the error? return a; })(); return source; @@ -278,14 +285,23 @@ export class LDMLKeyboardXMLSourceFileReader { */ public load(file: Uint8Array): LDMLKeyboardXMLSourceFile | null { if (!file) { + throw new Error(`file parameter must not be null`); + } + + let source: LDMLKeyboardXMLSourceFile = null; + try { + source = this.loadUnboxed(file); + } catch(e) { + this.callbacks.reportMessage(CommonTypesMessages.Error_InvalidXml({e})); return null; } - const source = this.loadUnboxed(file); - if(this.boxArrays(source)) { + + if (this.boxArrays(source)) { return source; - } else { - return null; } + + // boxArrays ... resolveImports has already logged a message + return null; } loadTestDataUnboxed(file: Uint8Array): any { diff --git a/common/web/types/src/main.ts b/common/web/types/src/main.ts index 5c79ed6761..53200dec80 100644 --- a/common/web/types/src/main.ts +++ b/common/web/types/src/main.ts @@ -20,6 +20,7 @@ export { VariableParser, MarkerParser } from './ldml-keyboard/pattern-parser.js' export { LDMLKeyboardXMLSourceFileReader, LDMLKeyboardXMLSourceFileReaderOptions } from './ldml-keyboard/ldml-keyboard-xml-reader.js'; export * as Constants from './consts/virtual-key-constants.js'; +export { ModifierKeyConstants } from './consts/modifier-key-constants.js'; export { defaultCompilerOptions, CompilerBaseOptions, CompilerCallbacks, CompilerOptions, CompilerEvent, CompilerErrorNamespace, CompilerErrorSeverity, CompilerPathCallbacks, CompilerFileSystemCallbacks, CompilerCallbackOptions, diff --git a/common/web/types/src/util/common-events.ts b/common/web/types/src/util/common-events.ts index eee8a6c84c..5b3fd7d507 100644 --- a/common/web/types/src/util/common-events.ts +++ b/common/web/types/src/util/common-events.ts @@ -1,3 +1,6 @@ +/* + * Keyman is copyright (C) SIL International. MIT License. + */ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageDef as def, CompilerMessageSpec as m } from './compiler-interfaces.js'; import { constants } from '@keymanapp/ldml-keyboard-constants'; @@ -43,4 +46,8 @@ export class CommonTypesMessages { static Error_TestDataUnexpectedArray = (o: {subtag: string}) => m(this.ERROR_TestDataUnexpectedArray, `Problem reading test data: expected single ${def(o.subtag)} element, found multiple`); + + static ERROR_InvalidXml = SevError | 0x0008; + static Error_InvalidXml = (o:{e: any}) => + m(this.ERROR_InvalidXml, `The XML file could not be read: ${(o.e ?? '').toString()}`); }; diff --git a/developer/src/kmc-ldml/package.json b/developer/src/kmc-ldml/package.json index ffb495ac7b..a2b56a24f3 100644 --- a/developer/src/kmc-ldml/package.json +++ b/developer/src/kmc-ldml/package.json @@ -35,12 +35,14 @@ "@keymanapp/developer-test-helpers": "*", "@keymanapp/resources-gosh": "*", "@types/chai": "^4.1.7", + "@types/common-tags": "^1.8.4", "@types/mocha": "^5.2.7", "@types/node": "^20.4.1", "@types/semver": "^7.3.12", "c8": "^7.12.0", "chai": "^4.3.4", "chalk": "^2.4.2", + "common-tags": "^1.8.2", "mocha": "^8.4.0", "ts-node": "^9.1.1", "typescript": "^4.9.5" diff --git a/developer/src/kmc-ldml/src/compiler/compiler.ts b/developer/src/kmc-ldml/src/compiler/compiler.ts index b972baf750..85aa79c37b 100644 --- a/developer/src/kmc-ldml/src/compiler/compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/compiler.ts @@ -125,6 +125,8 @@ export class LdmlKeyboardCompiler implements KeymanCompiler { return null; } + outputFilename = outputFilename ?? inputFilename.replace(/\.xml$/, '.kmx'); + // In order for the KMX file to be loaded by non-KMXPlus components, it is helpful // to duplicate some of the metadata KMXPlusMetadataCompiler.addKmxMetadata(kmx.kmxplus, kmx.keyboard, compilerOptions); @@ -134,7 +136,7 @@ export class LdmlKeyboardCompiler implements KeymanCompiler { const kmx_binary = builder.compile(); const vkcompiler = new LdmlKeyboardVisualKeyboardCompiler(this.callbacks); - const vk = vkcompiler.compile(source); + const vk = vkcompiler.compile(kmx.kmxplus, this.callbacks.path.basename(outputFilename, '.kmx')); const writer = new KvkFileWriter(); const kvk_binary = writer.write(vk); @@ -149,7 +151,6 @@ export class LdmlKeyboardCompiler implements KeymanCompiler { //KMW17.0: const encoder = new TextEncoder(); //KMW17.0: const kmw_binary = encoder.encode(kmw_string); - outputFilename = outputFilename ?? inputFilename.replace(/\.xml$/, '.kmx'); return { artifacts: { diff --git a/developer/src/kmc-ldml/src/compiler/keymanweb-compiler.ts b/developer/src/kmc-ldml/src/compiler/keymanweb-compiler.ts deleted file mode 100644 index a35739247b..0000000000 --- a/developer/src/kmc-ldml/src/compiler/keymanweb-compiler.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { CompilerCallbacks, VisualKeyboard, LDMLKeyboard, TouchLayoutFileWriter, KeymanFileTypes } from "@keymanapp/common-types"; -import { LdmlCompilerOptions } from "./ldml-compiler-options.js"; -import { TouchLayoutCompiler } from "./touch-layout-compiler.js"; -import { LdmlKeyboardVisualKeyboardCompiler } from "./visual-keyboard-compiler.js"; - -const MINIMUM_KMW_VERSION = '16.0'; - -export class LdmlKeyboardKeymanWebCompiler { - private readonly options: LdmlCompilerOptions; - private readonly nl: string; - private readonly tab: string; - constructor(private callbacks: CompilerCallbacks, options?: LdmlCompilerOptions) { - this.options = { ...options }; - this.nl = this.options.saveDebug ? "\n" : ''; - this.tab = this.options.saveDebug ? " " : ''; - } - - public compileVisualKeyboard(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile) { - const nl = this.nl, tab = this.tab; - const vkc = new LdmlKeyboardVisualKeyboardCompiler(this.callbacks); - const vk: VisualKeyboard.VisualKeyboard = vkc.compile(source); - - let result = - `{F: ' 1em ${JSON.stringify(vk.header.unicodeFont.name)}', `+ - `K102: ${vk.header.flags & VisualKeyboard.VisualKeyboardHeaderFlags.kvkh102 ? 1 : 0}};${nl}` + // TODO-LDML: escape ' and " in font name correctly - `${tab}this.KV.KLS={${nl}` + - `${tab}${tab}TODO_LDML: ${vk.keys.length}${nl}` + - // TODO-LDML: fill in KLS - `${tab}}`; - - return result; - } - - public compileTouchLayout(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile) { - const tlcompiler = new TouchLayoutCompiler(); - const layout = tlcompiler.compileToJavascript(source); - const writer = new TouchLayoutFileWriter({formatted: this.options.saveDebug}); - return writer.compile(layout); - } - - private cleanName(name: string): string { - let result = this.callbacks.path.basename(name, KeymanFileTypes.Source.LdmlKeyboard); - if(!result) { - throw new Error(`Invalid file name ${name}`); - } - - result = result.replaceAll(/[^a-z0-9]/g, '_'); - if(result.match(/^[0-9]/)) { - // Can't have a digit as initial - result = '_' + result; - } - return result; - } - - public compile(name: string, source: LDMLKeyboard.LDMLKeyboardXMLSourceFile): string { - const nl = this.nl, tab = this.tab; - - const sName = 'Keyboard_'+this.cleanName(name); - const displayUnderlying = true; // TODO-LDML - const modifierBitmask = 0; // TODO-LDML: define the modifiers used by this keyboard - const vkDictionary = ''; // TODO-LDML: vk dictionary for touch keys - const hasSupplementaryPlaneChars = false; // TODO-LDML - const isRTL = false; // TODO-LDML - - let result = - `if(typeof keyman === 'undefined') {${nl}` + - `${tab}console.error('Keyboard requires KeymanWeb ${MINIMUM_KMW_VERSION} or later');${nl}` + - `} else {${nl}` + - `${tab}KeymanWeb.KR(new ${sName}());${nl}` + - `}${nl}` + - `function ${sName}() {${nl}` + - // `${tab}${this.setupDebug()}${nl}` + ? we may use this for modifierBitmask in future - // `${tab}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` + ? we probably don't need this, it's for back-compat - `${tab}this.KI="${sName}";${nl}` + - `${tab}this.KN=${JSON.stringify(source.keyboard3.info.name)};${nl}` + - `${tab}this.KMINVER=${JSON.stringify(MINIMUM_KMW_VERSION)};${nl}` + - `${tab}this.KV=${this.compileVisualKeyboard(source)};${nl}` + - `${tab}this.KDU=${displayUnderlying ? '1' : '0'};${nl}` + - `${tab}this.KH="";${nl}` + // TODO-LDML: help text not supported - `${tab}this.KM=0;${nl}` + // TODO-LDML: mnemonic layout not supported for LDML keyboards - `${tab}this.KBVER=${JSON.stringify(source.keyboard3.version?.number || '0.0')};${nl}` + - `${tab}this.KMBM=${modifierBitmask};${nl}`; - - if(isRTL) { - result += `${tab}this.KRTL=1;${nl}`; - } - - if(hasSupplementaryPlaneChars) { - result += `${tab}this.KS=1;${nl}`; - } - - if(vkDictionary != '') { - result += `${tab}this.KVKD=${JSON.stringify(vkDictionary)};${nl}`; - } - - let layoutFile = this.compileTouchLayout(source); - if(layoutFile != '') { - result += `${tab}this.KVKL=${layoutFile};${nl}`; - } - // TODO-LDML: KCSS not supported - - // TODO-LDML: embed binary keyboard for loading into Core - - // A LDML keyboard has a no-op for its gs() (begin Unicode) function, - // because the functionality is embedded in Keyman Core - result += `${tab}this.gs=function(t,e){${nl}`+ - `${tab}${tab}return 0;${nl}`+ // TODO-LDML: we will start by embedding call into Keyman Core here - `${tab}};${nl}`; - - result += `}${nl}`; - return result; - } -} diff --git a/developer/src/kmc-ldml/src/compiler/touch-layout-compiler.ts b/developer/src/kmc-ldml/src/compiler/touch-layout-compiler.ts deleted file mode 100644 index 5c5c7eb194..0000000000 --- a/developer/src/kmc-ldml/src/compiler/touch-layout-compiler.ts +++ /dev/null @@ -1,112 +0,0 @@ -import { TouchLayout, LDMLKeyboard } from "@keymanapp/common-types"; - -export class TouchLayoutCompiler { - public compileToJavascript(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile): TouchLayout.TouchLayoutFile { - let result: TouchLayout.TouchLayoutFile = {}; - - // start with desktop to mimic vk emit - result.desktop = { - defaultHint: "none", // TODO-LDML this should be optional - layer: [] - }; - - for(let layers of source.keyboard3.layers) { - for(let layer of layers.layer) { - const resultLayer = this.compileHardwareLayer(source, result, layer); - result.desktop.layer.push(resultLayer); - } - } - return result; - } - - private compileHardwareLayer( - source: LDMLKeyboard.LDMLKeyboardXMLSourceFile, - file: TouchLayout.TouchLayoutFile, - layer: LDMLKeyboard.LKLayer - ) { - // TODO-LDML: consider consolidation with keys.ts? - - let fileLayer: TouchLayout.TouchLayoutLayer = { - id: this.translateLayerIdToTouchLayoutLayerId(layer.id, layer.modifiers), - row: [] - }; - - let y = -1; - - for(let row of layer.row) { - y++; - - let fileRow: TouchLayout.TouchLayoutRow = {id: y, key: []}; - fileLayer.row.push(fileRow); - - const keys = row.keys.split(' '); - for(let key of keys) { - const keydef = source.keyboard3.keys?.key?.find(x => x.id == key); - if(keydef) { - const fileKey: TouchLayout.TouchLayoutKey = { - id: this.translateKeyIdentifierToTouch(keydef.id) as TouchLayout.TouchLayoutKeyId, - text: keydef.output || '', - // TODO-LDML: additional properties - }; - fileRow.key.push(fileKey); - } else { - // TODO-LDML: consider logging missing keys - } - } - } - - return fileLayer; - } - - private translateLayerIdToTouchLayoutLayerId(id: string, modifier: string): string { - // Touch layout layers have a set of reserved names that correspond to - // hardware modifiers. We want to map these identifiers first before falling - // back to the layer ids - - // The set of recognized layer identifiers is: - // - // touch | LDML - // ---------------+------------- - // default | none - // shift | shift - // caps | caps - // rightalt | altR - // rightalt-shift | altR shift - // - const map = { - none: 'default', - shift: 'shift', - caps: 'caps', - altR: 'rightalt', - "altR shift": 'rightalt-shift' - }; - - // canonicalize modifier string, alphabetical - // TODO-LDML: need to support multiple here - if (modifier && modifier.indexOf(',') !== -1) { - throw Error(`Internal error: TODO-LDML: multiple modifiers ${modifier} not yet supported.`); - } - modifier = (modifier||'').split(/\b/).sort().join(' ').trim(); - - if(Object.hasOwn(map, modifier)) { - return (map as any)[modifier]; - } - - // TODO-LDML: Other layer names will be used unmodified, is this sufficient? - return id; - } - - private translateKeyIdentifierToTouch(id: string): string { - // Note: keys identifiers in kmx were traditionally case-insensitive, but we - // are going to use them as case-insensitive for LDML keyboards. The set of - // standard key identifiers a-z, A-Z, 0-9 will be used, where possible, and - // all other keys will be mapped to `T_key`. - - if(id.match(/^[0-9a-zA-Z]$/)) { - return 'K_'+id; - } - - // Not a standard key - return 'T_'+id; - } -} 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 d1a1d4e71a..812e57ef82 100644 --- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts @@ -1,5 +1,12 @@ -import { VisualKeyboard, LDMLKeyboard, CompilerCallbacks } from "@keymanapp/common-types"; -import { KeysCompiler } from "./keys.js"; +/* + * Keyman is copyright (C) SIL International. MIT License. + * + * Export LDML data (https://www.unicode.org/reports/tr35/tr35-keyboards.html) + * to .kvk format. This is an interim solution until Keyman Core supports + * interrogation of the KMX+ data for OSK. + */ +import { ModifierKeyConstants, KMXPlus } from "@keymanapp/common-types"; +import { VisualKeyboard, CompilerCallbacks } from "@keymanapp/common-types"; import { CompilerMessages } from "./messages.js"; // This is a partial polyfill for findLast, so not polluting Array.prototype @@ -19,25 +26,37 @@ function findLast(arr: any, callback: any) { return undefined; } + +const LDML_MODIFIER_TO_KVK_MODIFIER = new Map(); +LDML_MODIFIER_TO_KVK_MODIFIER.set(ModifierKeyConstants.LCTRLFLAG, VisualKeyboard.VisualKeyboardShiftState.KVKS_LCTRL); +LDML_MODIFIER_TO_KVK_MODIFIER.set(ModifierKeyConstants.RCTRLFLAG, VisualKeyboard.VisualKeyboardShiftState.KVKS_RCTRL); +LDML_MODIFIER_TO_KVK_MODIFIER.set(ModifierKeyConstants.LALTFLAG, VisualKeyboard.VisualKeyboardShiftState.KVKS_LALT); +LDML_MODIFIER_TO_KVK_MODIFIER.set(ModifierKeyConstants.RALTFLAG, VisualKeyboard.VisualKeyboardShiftState.KVKS_RALT); +LDML_MODIFIER_TO_KVK_MODIFIER.set(ModifierKeyConstants.K_SHIFTFLAG, VisualKeyboard.VisualKeyboardShiftState.KVKS_SHIFT); +LDML_MODIFIER_TO_KVK_MODIFIER.set(ModifierKeyConstants.K_CTRLFLAG, VisualKeyboard.VisualKeyboardShiftState.KVKS_CTRL); +LDML_MODIFIER_TO_KVK_MODIFIER.set(ModifierKeyConstants.K_ALTFLAG, VisualKeyboard.VisualKeyboardShiftState.KVKS_ALT); + export class LdmlKeyboardVisualKeyboardCompiler { public constructor(private callbacks: CompilerCallbacks) { } - public compile(source: LDMLKeyboard.LDMLKeyboardXMLSourceFile): VisualKeyboard.VisualKeyboard { + public compile(source: KMXPlus.KMXPlusData, keyboardId: string): VisualKeyboard.VisualKeyboard { let result = new VisualKeyboard.VisualKeyboard(); /* TODO-LDML: consider VisualKeyboardHeaderFlags.kvkhUseUnderlying kvkhDisplayUnderlying kvkhAltGr kvkh102 */ result.header.flags = 0; result.header.version = 0x0600; - - /* TODO-LDML: consider associatedKeyboard: this _must_ be set to id (aka basename sans ext) of keyboard .kmx file */ - result.header.associatedKeyboard = ''; + result.header.associatedKeyboard = keyboardId; result.header.ansiFont = {...VisualKeyboard.DEFAULT_KVK_FONT}; result.header.unicodeFont = {...VisualKeyboard.DEFAULT_KVK_FONT}; - for(let layers of source.keyboard3.layers) { - const { formId } = layers; - for(let layer of layers.layer) { + for(let layersList of source.layr.lists) { + const formId = layersList.hardware.value; + if(formId == 'touch') { + continue; + } + + for(let layer of layersList.layers) { this.compileHardwareLayer(source, result, layer, formId); } } @@ -45,58 +64,74 @@ export class LdmlKeyboardVisualKeyboardCompiler { } private compileHardwareLayer( - source: LDMLKeyboard.LDMLKeyboardXMLSourceFile, + source: KMXPlus.KMXPlusData, vk: VisualKeyboard.VisualKeyboard, - layer: LDMLKeyboard.LKLayer, + layer: KMXPlus.LayrEntry, hardware: string, ) { - const layerId = layer.id; - if (hardware === 'touch') { - hardware = 'us'; // TODO-LDML: US Only. Do something different here? - } - const keymap = KeysCompiler.getKeymapFromForms(source.keyboard3?.forms?.form, hardware); - if (!keymap) { - this.callbacks.reportMessage( - CompilerMessages.Error_InvalidHardware({ formId: hardware }) - ); + const layerId = layer.id.value; + + hardware = 'us'; // TODO-LDML: US Only. We need to clean this up for other hardware forms + + const shift = this.translateLayerModifiersToVisualKeyboardShift(layer.mod); + if(shift === null) { + // Caps (num, scroll) is not a supported shift state in .kvk return; } - const shift = this.translateLayerIdToVisualKeyboardShift(layer.id); let y = -1; - for(let row of layer.row) { + for(let row of layer.rows) { y++; - - const keys = row.keys.split(' '); let x = -1; - for(let key of keys) { - const keyId = key; + for(let key of row.keys) { x++; - //@ts-ignore - let keydef = findLast(source.keyboard3.keys?.key, x => x.id == key); + const keydef: KMXPlus.KeysKeys = findLast(source.keys?.keys, (kd: KMXPlus.KeysKeys) => kd.id.value == key.value); + const kmap = source.keys.kmap.find(k => k.key == keydef.id.value && k.mod == layer.mod); + const text = this.getDisplayFromKey(keydef, source) ?? null; - if (!keydef) { + if (!keydef || !kmap || text === null) { this.callbacks.reportMessage( - CompilerMessages.Error_KeyNotFoundInKeyBag({ keyId, layer: layerId, row: y, col: x, form: hardware }) + CompilerMessages.Error_KeyNotFoundInKeyBag({ keyId: key.value, layer: layerId, row: y, col: x, form: hardware }) ); } else { vk.keys.push({ flags: VisualKeyboard.VisualKeyboardKeyFlags.kvkkUnicode, - shift: shift, - text: keydef.output, // TODO-LDML: displays - vkey: keymap[y][x], + shift, + text, + vkey: kmap.vkey }); } } } } - private translateLayerIdToVisualKeyboardShift(id: string) { - if(id == 'base') { - return 0; + private getDisplayFromKey(keydef: KMXPlus.KeysKeys, source: KMXPlus.KMXPlusData) { + const display = source.disp?.disps?.find(d => d.id.value == keydef.id.value || d.to.value == keydef.to.value); + return display?.display.value ?? keydef.to.value; + } + + private translateLayerModifiersToVisualKeyboardShift(modifiers: number): VisualKeyboard.VisualKeyboardShiftState { + + if(modifiers == 0) { + return VisualKeyboard.VisualKeyboardShiftState.KVKS_NORMAL; } - // TODO-LDML: other modifiers - return 0; + + if(modifiers & + (ModifierKeyConstants.CAPITALFLAG | ModifierKeyConstants.NUMLOCKFLAG | ModifierKeyConstants.SCROLLFLAG) + ) { + // Caps/Num/Scroll are not supported in .kvk, in combination or alone + return null; + } + + let shift: VisualKeyboard.VisualKeyboardShiftState = 0; + + for(const mod of LDML_MODIFIER_TO_KVK_MODIFIER.keys()) { + if(modifiers & mod) { + shift |= LDML_MODIFIER_TO_KVK_MODIFIER.get(mod); + } + } + + return shift; } } diff --git a/developer/src/kmc-ldml/test/fixtures/basic-kvk.txt b/developer/src/kmc-ldml/test/fixtures/basic-kvk.txt index 68666feacf..da8f5e6011 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic-kvk.txt +++ b/developer/src/kmc-ldml/test/fixtures/basic-kvk.txt @@ -1,4 +1,6 @@ # +# Keyman is copyright (C) SIL International. MIT License. +# # basic-kvk.txt describes the expected output of running kmc against basic.xml to generate # a .kvk file. It is used in the end-to-end test test-visual-keyboard-compiler-e2e.ts. # @@ -10,8 +12,8 @@ block(kvkheader) 00 06 00 00 # version 0x0600 00 # flags block(associated_keyboard) - 01 00 # string len in UTF-16 code units incl zterm - 00 00 # '\0' + 06 00 # string len in UTF-16 code units incl zterm + 62 00 61 00 73 00 69 00 63 00 00 00 # 'basic\0' block(ansi_font) 06 00 # string len in UTF-16 code units incl zterm diff --git a/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js b/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js deleted file mode 100644 index 84168414cf..0000000000 --- a/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js +++ /dev/null @@ -1 +0,0 @@ -if(typeof keyman === 'undefined') {console.error('Keyboard requires KeymanWeb 16.0 or later');} else {KeymanWeb.KR(new Keyboard_basic());}function Keyboard_basic() {this.KI="Keyboard_basic";this.KN="TestKbd";this.KMINVER="16.0";this.KV={F: ' 1em "Arial"', K102: 0};this.KV.KLS={TODO_LDML: 2};this.KDU=1;this.KH="";this.KM=0;this.KBVER="1.0.0";this.KMBM=0;this.KVKL={"desktop":{"defaultHint":"none","layer":[{"id":"base","row":[{"id":"0","key":[{"id":"T_hmaqtugha","text":"ħ"},{"id":"T_that","text":"ថា"}]}]}],"displayUnderlying":false}};this.gs=function(t,e){return 0;};} diff --git a/developer/src/kmc-ldml/test/fixtures/basic.js b/developer/src/kmc-ldml/test/fixtures/basic.js deleted file mode 100644 index c74798cfac..0000000000 --- a/developer/src/kmc-ldml/test/fixtures/basic.js +++ /dev/null @@ -1,48 +0,0 @@ -if(typeof keyman === 'undefined') { - console.error('Keyboard requires KeymanWeb 16.0 or later'); -} else { - KeymanWeb.KR(new Keyboard_basic()); -} -function Keyboard_basic() { - this.KI="Keyboard_basic"; - this.KN="TestKbd"; - this.KMINVER="16.0"; - this.KV={F: ' 1em "Arial"', K102: 0}; - this.KV.KLS={ - TODO_LDML: 2 - }; - this.KDU=1; - this.KH=""; - this.KM=0; - this.KBVER="1.0.0"; - this.KMBM=0; - this.KVKL={ - "desktop": { - "defaultHint": "none", - "layer": [ - { - "id": "base", - "row": [ - { - "id": "0", - "key": [ - { - "id": "T_hmaqtugha", - "text": "ħ" - }, - { - "id": "T_that", - "text": "ថា" - } - ] - } - ] - } - ], - "displayUnderlying": false - } -}; - this.gs=function(t,e){ - return 0; - }; -} diff --git a/developer/src/kmc-ldml/test/fixtures/basic.txt b/developer/src/kmc-ldml/test/fixtures/basic.txt index b471228a52..6302a5eb27 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic.txt +++ b/developer/src/kmc-ldml/test/fixtures/basic.txt @@ -1,4 +1,6 @@ # +# Keyman is copyright (C) SIL International. MIT License. +# # basic.txt describes the expected output of running kmc against basic.xml. It is used in # the end-to-end test test-compiler-e2e.ts. # @@ -402,7 +404,7 @@ block(layr) # struct COMP_KMXPLUS_LAYR { 01 00 00 00 # count 7B 00 00 00 # KMX_DWORD minDeviceWidth; // 123 # layers 0 - index(strNull,strBase,2) # KMXPLUS_STR id; + 00 00 00 00 # KMXPLUS_STR id; 00 00 00 00 # KMX_DWORD mod 00 00 00 00 # KMX_DWORD row index 01 00 00 00 # KMX_DWORD count @@ -502,7 +504,6 @@ block(strs) # struct COMP_KMXPLUS_STRS { diff(strs,strSet) sizeof(strSet,2) diff(strs,strSet2) sizeof(strSet2,2) diff(strs,strTranTo) sizeof(strTranTo,2) - diff(strs,strBase) sizeof(strBase,2) diff(strs,strElemBkspFrom2) sizeof(strElemBkspFrom2,2) diff(strs,strGapReserved) sizeof(strGapReserved,2) diff(strs,strHmaqtugha) sizeof(strHmaqtugha,2) @@ -538,7 +539,6 @@ block(strs) # struct COMP_KMXPLUS_STRS { #str #0A block(strSet2) 61 00 62 00 63 00 block(x) 00 00 # 'abc' block(strTranTo) 61 00 02 03 block(x) 00 00 # 'â' (U+0061 U+0302) - block(strBase) 62 00 61 00 73 00 65 00 block(x) 00 00 # 'base' block(strElemBkspFrom2) 65 00 block(x) 00 00 # 'e' block(strGapReserved) 67 00 61 00 70 00 20 00 28 00 72 00 65 00 73 00 65 00 72 00 76 00 65 00 64 00 29 00 block(x) 00 00 # 'gap (reserved)' block(strHmaqtugha) 68 00 6d 00 61 00 71 00 74 00 75 00 67 00 68 00 61 00 block(x) 00 00 # 'hmaqtugha' diff --git a/developer/src/kmc-ldml/test/fixtures/basic.xml b/developer/src/kmc-ldml/test/fixtures/basic.xml index c8565271ed..168ee0ef9a 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic.xml +++ b/developer/src/kmc-ldml/test/fixtures/basic.xml @@ -1,4 +1,5 @@ + + diff --git a/developer/src/kmc-ldml/test/helpers/index.ts b/developer/src/kmc-ldml/test/helpers/index.ts index 2e9e16ff6a..0fd659fd1b 100644 --- a/developer/src/kmc-ldml/test/helpers/index.ts +++ b/developer/src/kmc-ldml/test/helpers/index.ts @@ -1,16 +1,17 @@ -/** +/* + * Keyman is copyright (C) SIL International. MIT License. + * * Helpers and utilities for the Mocha tests. */ import 'mocha'; import * as path from 'path'; import { fileURLToPath } from 'url'; import { SectionCompiler, SectionCompilerNew } from '../../src/compiler/section-compiler.js'; -import { util, KMXPlus, LDMLKeyboardXMLSourceFileReader, VisualKeyboard, CompilerEvent, LDMLKeyboardTestDataXMLSourceFile, compilerEventFormat, LDMLKeyboard, UnicodeSetParser, CompilerCallbacks } from '@keymanapp/common-types'; +import { util, KMXPlus, LDMLKeyboardXMLSourceFileReader, CompilerEvent, LDMLKeyboardTestDataXMLSourceFile, compilerEventFormat, LDMLKeyboard, UnicodeSetParser, CompilerCallbacks } from '@keymanapp/common-types'; import { LdmlKeyboardCompiler } from '../../src/main.js'; // make sure main.js compiles import { assert } from 'chai'; import { KMXPlusMetadataCompiler } from '../../src/compiler/metadata-compiler.js'; import { LdmlCompilerOptions } from '../../src/compiler/ldml-compiler-options.js'; -import { LdmlKeyboardVisualKeyboardCompiler } from '../../src/compiler/visual-keyboard-compiler.js'; import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; import KMXPlusFile = KMXPlus.KMXPlusFile; @@ -20,7 +21,6 @@ import Section = KMXPlus.Section; import { ElemCompiler, ListCompiler, StrsCompiler } from '../../src/compiler/empty-compiler.js'; import { KmnCompiler } from '@keymanapp/kmc-kmn'; import { VarsCompiler } from '../../src/compiler/vars.js'; -// import Vars = KMXPlus.Vars; /** * Builds a path to the fixture with the given path components. @@ -47,7 +47,7 @@ beforeEach(function() { afterEach(function() { if (this.currentTest.state !== 'passed') { - compilerTestCallbacks.messages.forEach(message => console.log(message.message)); + compilerTestCallbacks.printMessages(); } }); @@ -160,28 +160,7 @@ export async function compileKeyboard(inputFilename: string, options: LdmlCompil return kmx; } -export async function compileVisualKeyboard(inputFilename: string, options: LdmlCompilerOptions): Promise { - const k = new LdmlKeyboardCompiler(); - assert.isTrue(await k.init(compilerTestCallbacks, options)); - const source = k.load(inputFilename); - checkMessages(); - assert.isNotNull(source, 'k.load should not have returned null'); - - const valid = await k.validate(source); - checkMessages(); - assert.isTrue(valid, 'k.validate should not have failed'); - - const vk = (new LdmlKeyboardVisualKeyboardCompiler(compilerTestCallbacks)).compile(source); - checkMessages(); - assert.isNotNull(vk, 'LdmlKeyboardVisualKeyboardCompiler.compile should not have returned null'); - - return vk; -} - export function checkMessages() { - if(compilerTestCallbacks.messages.length > 0) { - console.log(compilerTestCallbacks.messages); - } assert.isEmpty(compilerTestCallbacks.messages, compilerEventFormat(compilerTestCallbacks.messages)); } diff --git a/developer/src/kmc-ldml/test/test-keymanweb-compiler.ts b/developer/src/kmc-ldml/test/test-keymanweb-compiler.ts deleted file mode 100644 index 9a14b38c33..0000000000 --- a/developer/src/kmc-ldml/test/test-keymanweb-compiler.ts +++ /dev/null @@ -1,50 +0,0 @@ -import 'mocha'; -import { assert } from 'chai'; -import { checkMessages, compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; -import { LdmlKeyboardKeymanWebCompiler } from '../src/compiler/keymanweb-compiler.js'; -import { LdmlKeyboardCompiler } from '../src/compiler/compiler.js'; -import * as fs from 'fs'; - -describe('LdmlKeyboardKeymanWebCompiler', function() { - - it('should build a .js file', async function() { - // Let's build basic.xml - // It should generate content identical to basic.js - const inputFilename = makePathToFixture('basic.xml'); - const outputFilename = makePathToFixture('basic.js'); - const outputFilenameNoDebug = makePathToFixture('basic-no-debug.js'); - - // Load input data; we'll use the LDML keyboard compiler loader to save us - // effort here - const k = new LdmlKeyboardCompiler(); - await k.init(compilerTestCallbacks, {...compilerTestOptions, saveDebug: true, shouldAddCompilerVersion: false}); - const source = k.load(inputFilename); - checkMessages(); - assert.isNotNull(source, 'k.load should not have returned null'); - - // Sanity check ... this is also checked in other tests - const valid = await k.validate(source); - checkMessages(); - assert.isTrue(valid, 'k.validate should not have failed'); - - // Actual test: compile to javascript - const jsCompiler = new LdmlKeyboardKeymanWebCompiler(compilerTestCallbacks, {...compilerTestOptions, saveDebug: true}); - const output = jsCompiler.compile('basic.xml', source); - assert.isNotNull(output); - - // Does the emitted js match? - const outputFixture = fs.readFileSync(outputFilename, 'utf-8').replaceAll(/\r\n/g, '\n'); - assert.strictEqual(output, outputFixture); - - // Second test: compile to javascript without debug formatting - const jsCompilerNoDebug = new LdmlKeyboardKeymanWebCompiler(compilerTestCallbacks, {...compilerTestOptions, saveDebug: false}); - const outputNoDebug = jsCompilerNoDebug.compile('basic.xml', source); - assert.isNotNull(outputNoDebug); - - // Does the emitted js match? The nodebug has no newline at end, but allow one in the fixture - const outputFixtureNoDebug = fs.readFileSync(outputFilenameNoDebug, 'utf-8').replaceAll(/\r\n/g, '\n').trim(); - assert.strictEqual(outputNoDebug, outputFixtureNoDebug); - - // TODO(lowpri): consider using Typescript parser to generate AST for further validation - }); -}); 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 deleted file mode 100644 index df0aea0391..0000000000 --- a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler-e2e.ts +++ /dev/null @@ -1,31 +0,0 @@ -import 'mocha'; -import {assert} from 'chai'; -import hextobin from '@keymanapp/hextobin'; -import { KvkFileWriter } from '@keymanapp/common-types'; -import {checkMessages, compilerTestOptions, compileVisualKeyboard, makePathToFixture} from './helpers/index.js'; - -describe('visual-keyboard-compiler', function() { - this.slow(500); // 0.5 sec -- json schema validation takes a while - - it('should build fixtures', async function() { - // Let's build basic.xml - // It should match basic.kvk (built from basic-kvk.txt) - - const inputFilename = makePathToFixture('basic.xml'); - const binaryFilename = makePathToFixture('basic-kvk.txt'); - - // Compile the visual keyboard - const vk = await compileVisualKeyboard(inputFilename, {...compilerTestOptions, saveDebug: true, shouldAddCompilerVersion: false}); - assert.isNotNull(vk); - - // Use the builder to generate the binary output file - const writer = new KvkFileWriter(); - const code = writer.write(vk); - checkMessages(); - assert.isNotNull(code); - - // Compare output - let expected = await hextobin(binaryFilename, undefined, {silent:true}); - assert.deepEqual(code, expected); - }); -}); diff --git a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts new file mode 100644 index 0000000000..cc44286909 --- /dev/null +++ b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts @@ -0,0 +1,227 @@ +/* + * Keyman is copyright (C) SIL International. MIT License. + */ +import 'mocha'; +import * as path from 'path'; +import {assert} from 'chai'; +import { stripIndent } from 'common-tags'; + +import { KvkFileWriter, LDMLKeyboardXMLSourceFileReader, VisualKeyboard } from '@keymanapp/common-types'; +import hextobin from '@keymanapp/hextobin'; + +import { checkMessages, compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; + +import { LdmlKeyboardVisualKeyboardCompiler } from '../src/compiler/visual-keyboard-compiler.js'; +import { LdmlKeyboardCompiler } from '../src/main.js'; + +describe('visual-keyboard-compiler', function() { + this.slow(500); // 0.5 sec -- json schema validation takes a while + + it('should build fixtures', async function() { + // Let's build basic.xml + + // It should match basic.kvk (built from basic-kvk.txt) + const inputFilename = makePathToFixture('basic.xml'); + const binaryFilename = makePathToFixture('basic-kvk.txt'); + + // Compile the visual keyboard + const k = new LdmlKeyboardCompiler(); + assert.isTrue(await k.init(compilerTestCallbacks, {...compilerTestOptions, saveDebug: true, shouldAddCompilerVersion: false})); + const source = k.load(inputFilename); + checkMessages(); + assert.isNotNull(source, 'k.load should not have returned null'); + + const valid = await k.validate(source); + checkMessages(); + assert.isTrue(valid, 'k.validate should not have failed'); + + let kmx = await k.compile(source); + assert(kmx, 'k.compile should not have failed'); + + const vk = (new LdmlKeyboardVisualKeyboardCompiler(compilerTestCallbacks)).compile(kmx.kmxplus, path.basename(inputFilename, '.xml')); + checkMessages(); + assert.isNotNull(vk, 'LdmlKeyboardVisualKeyboardCompiler.compile should not have returned null'); + + // Use the builder to generate the binary output file + const writer = new KvkFileWriter(); + const code = writer.write(vk); + assert.isEmpty(compilerTestCallbacks.messages); + assert.isNotNull(code); + + // Compare output + let expected = await hextobin(binaryFilename, undefined, {silent:true}); + + assert.deepEqual(code, expected); + }); + + it('should support various modifiers', async function() { + const xml = stripIndent` + + + + + + + + + + + + + + + `; + + const vk = await loadVisualKeyboardFromXml(xml, 'test'); + + assert.equal(vk.keys.length, 5); + assert.equal(vk.keys[0].shift, VisualKeyboard.VisualKeyboardShiftState.KVKS_NORMAL); + assert.equal(vk.keys[1].shift, VisualKeyboard.VisualKeyboardShiftState.KVKS_SHIFT); + assert.equal(vk.keys[2].shift, VisualKeyboard.VisualKeyboardShiftState.KVKS_RALT); + assert.equal(vk.keys[3].shift, VisualKeyboard.VisualKeyboardShiftState.KVKS_RCTRL | VisualKeyboard.VisualKeyboardShiftState.KVKS_RALT); + assert.equal(vk.keys[4].shift, VisualKeyboard.VisualKeyboardShiftState.KVKS_SHIFT | VisualKeyboard.VisualKeyboardShiftState.KVKS_RALT); + }); + + it('should emit the correct associated keyboard id', async function() { + const xml = stripIndent` + + + + + + + + + + + `; + + const vk = await loadVisualKeyboardFromXml(xml, 'test'); + + assert.equal(vk.header.associatedKeyboard, 'test'); + }); + + it('should support ', async function() { + const xml = stripIndent` + + + + + + + + + + + + + + + + `; + + const vk = await loadVisualKeyboardFromXml(xml, 'test'); + + assert.equal(vk.keys.length, 2); + assert.equal(vk.keys[0].text, 'C'); + assert.equal(vk.keys[1].text, 'D'); + }); + + it('should correctly decode \\u{xxxx}', async function() { + const xml = stripIndent` + + + + + + + + + + + + + + + `; + + const vk = await loadVisualKeyboardFromXml(xml, 'test'); + + assert.equal(vk.keys.length, 2); + assert.equal(vk.keys[0].text, '\u{0e80}'); + assert.equal(vk.keys[1].text, '\u{0e81}'); + }); + + it.skip('should read string variables in key.output', async function() { + const xml = stripIndent` + + + + + + + + + + + + + + + `; + + const vk = await loadVisualKeyboardFromXml(xml, 'test'); + + assert.equal(vk.keys.length, 1); + assert.equal(vk.keys[0].text, '2'); + }); + + it.skip('should read string variables in display.display', async function() { + const xml = stripIndent` + + + + + + + + + + + + + + + + + + `; + + const vk = await loadVisualKeyboardFromXml(xml, 'test'); + + assert.equal(vk.keys.length, 1); + assert.equal(vk.keys[0].text, '2'); + }); +}); + +async function loadVisualKeyboardFromXml(xml: string, id: string) { + const data = new TextEncoder().encode(xml); + assert.isOk(data); + + const reader = new LDMLKeyboardXMLSourceFileReader(compilerTestOptions.readerOptions, compilerTestCallbacks); + const source = reader.load(data); + assert.isEmpty(compilerTestCallbacks.messages); + assert.isOk(source); + + const k = new LdmlKeyboardCompiler(); + assert.isTrue(await k.init(compilerTestCallbacks, compilerTestOptions)); + + const kmx = await k.compile(source); + assert(kmx, 'k.compile should not have failed'); + + const vk = (new LdmlKeyboardVisualKeyboardCompiler(compilerTestCallbacks)).compile(kmx.kmxplus, id); + assert.isEmpty(compilerTestCallbacks.messages); + assert.isOk(vk); + + return vk; +} diff --git a/package-lock.json b/package-lock.json index 3125817985..7706d512c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1794,12 +1794,14 @@ "@keymanapp/developer-test-helpers": "*", "@keymanapp/resources-gosh": "*", "@types/chai": "^4.1.7", + "@types/common-tags": "^1.8.4", "@types/mocha": "^5.2.7", "@types/node": "^20.4.1", "@types/semver": "^7.3.12", "c8": "^7.12.0", "chai": "^4.3.4", "chalk": "^2.4.2", + "common-tags": "^1.8.2", "mocha": "^8.4.0", "ts-node": "^9.1.1", "typescript": "^4.9.5" @@ -4196,6 +4198,13 @@ "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, + "node_modules/@types/common-tags": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/@types/common-tags/-/common-tags-1.8.4.tgz", + "integrity": "sha512-S+1hLDJPjWNDhcGxsxEbepzaxWqURP/o+3cP4aa2w7yBXgdcmKGQtZzP8JbyfOd0m+33nh+8+kvxYE2UJtBDkg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/component-emitter": { "version": "1.2.11", "dev": true, @@ -5611,6 +5620,16 @@ "node": ">=14" } }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/component-emitter": { "version": "1.3.0", "dev": true, From 44e28e21a6a424a3590be6dcb9b9cecf925a9692 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 12 Sep 2024 09:18:06 +0700 Subject: [PATCH 19/52] fix(developer): check vars string usage before definition Validation of vars was not properly checking for forward references to string variables. This, coupled with a null vs undefined bug in subsequent use, meant that forward reference variables were ending up with a literal string value of 'undefined'. This also fixes the test for visual-keyboard-compiler, where the fixture was actually buggy and was the trigger for investigating this problem. Fixes: #12403 Relates-to: #12395 --- common/web/types/src/kmx/kmx-plus.ts | 2 +- developer/src/kmc-ldml/src/compiler/vars.ts | 9 ++++++++- .../test/fixtures/sections/vars/fail-badref-7.xml | 15 +++++++++++++++ developer/src/kmc-ldml/test/test-vars.ts | 9 ++++++++- .../test/test-visual-keyboard-compiler.ts | 8 ++++---- 5 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml diff --git a/common/web/types/src/kmx/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus.ts index 6e3c73d33c..42dc7305a7 100644 --- a/common/web/types/src/kmx/kmx-plus.ts +++ b/common/web/types/src/kmx/kmx-plus.ts @@ -285,7 +285,7 @@ export class Vars extends Section { }); } findStringVariableValue(id: string): string { - return Vars.findVariable(this.strings, id)?.value?.value; // Unwrap: Variable, StrsItem + return Vars.findVariable(this.strings, id)?.value?.value ?? null; // Unwrap: Variable, StrsItem } substituteSetRegex(str: string, sections: DependencySections): string { return str.replaceAll(VariableParser.SET_REFERENCE, (_entire, id) => { diff --git a/developer/src/kmc-ldml/src/compiler/vars.ts b/developer/src/kmc-ldml/src/compiler/vars.ts index 34fa99831b..be2ffb85b7 100644 --- a/developer/src/kmc-ldml/src/compiler/vars.ts +++ b/developer/src/kmc-ldml/src/compiler/vars.ts @@ -68,9 +68,16 @@ export class VarsCompiler extends SectionCompiler { // Strings for (const { id, value } of variables.string) { addId(id); - allStrings.add(id); const stringrefs = VariableParser.allStringReferences(value); + for(const ref of stringrefs) { + if(!allStrings.has(ref)) { + valid = false; + this.callbacks.reportMessage(LdmlCompilerMessages.Error_MissingStringVariable({id: ref})); + allStrings.add(ref); // avoids multiple reports of same missing variable + } + } st.string.add(SubstitutionUse.variable, stringrefs); + allStrings.add(id); } // Sets for (const { id, value } of variables.set) { diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml new file mode 100644 index 0000000000..25e7c46a1d --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-badref-7.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/test-vars.ts b/developer/src/kmc-ldml/test/test-vars.ts index e3ac53c4a9..f22499f179 100644 --- a/developer/src/kmc-ldml/test/test-vars.ts +++ b/developer/src/kmc-ldml/test/test-vars.ts @@ -187,7 +187,14 @@ describe('vars', function () { CompilerMessages.Error_MissingStringVariable({id: 'missingStringInSet'}) ], }, - ], varsDependencies); + { + subpath: 'sections/vars/fail-badref-7.xml', + errors: [ + LdmlCompilerMessages.Error_MissingStringVariable({id: 'usedBeforeDefinition'}) + ], + strictErrors: true + }, +], varsDependencies); describe('should match some marker constants', () => { // neither of these live here, but, common/web/types does not import ldml-keyboard-constants otherwise. diff --git a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts index cc44286909..c051dcd0be 100644 --- a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts @@ -152,7 +152,7 @@ describe('visual-keyboard-compiler', function() { assert.equal(vk.keys[1].text, '\u{0e81}'); }); - it.skip('should read string variables in key.output', async function() { + it('should read string variables in key.output', async function() { const xml = stripIndent` @@ -164,8 +164,8 @@ describe('visual-keyboard-compiler', function() { - + `; @@ -176,7 +176,7 @@ describe('visual-keyboard-compiler', function() { assert.equal(vk.keys[0].text, '2'); }); - it.skip('should read string variables in display.display', async function() { + it('should read string variables in display.display', async function() { const xml = stripIndent` @@ -191,8 +191,8 @@ describe('visual-keyboard-compiler', function() { - + `; From 62af49a46a8229fb12a50a39ad81dc807ce40464 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 12 Sep 2024 10:24:43 +0700 Subject: [PATCH 20/52] chore(developer): rename CompilerMessages back for 17.0 --- developer/src/kmc-ldml/src/compiler/vars.ts | 2 +- developer/src/kmc-ldml/test/test-vars.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-ldml/src/compiler/vars.ts b/developer/src/kmc-ldml/src/compiler/vars.ts index be2ffb85b7..d640dbf1a3 100644 --- a/developer/src/kmc-ldml/src/compiler/vars.ts +++ b/developer/src/kmc-ldml/src/compiler/vars.ts @@ -72,7 +72,7 @@ export class VarsCompiler extends SectionCompiler { for(const ref of stringrefs) { if(!allStrings.has(ref)) { valid = false; - this.callbacks.reportMessage(LdmlCompilerMessages.Error_MissingStringVariable({id: ref})); + this.callbacks.reportMessage(CompilerMessages.Error_MissingStringVariable({id: ref})); allStrings.add(ref); // avoids multiple reports of same missing variable } } diff --git a/developer/src/kmc-ldml/test/test-vars.ts b/developer/src/kmc-ldml/test/test-vars.ts index f22499f179..b1fadd0e44 100644 --- a/developer/src/kmc-ldml/test/test-vars.ts +++ b/developer/src/kmc-ldml/test/test-vars.ts @@ -190,7 +190,7 @@ describe('vars', function () { { subpath: 'sections/vars/fail-badref-7.xml', errors: [ - LdmlCompilerMessages.Error_MissingStringVariable({id: 'usedBeforeDefinition'}) + CompilerMessages.Error_MissingStringVariable({id: 'usedBeforeDefinition'}) ], strictErrors: true }, From 94a4ac4eaeee754b5bb404b66f21f5f6f846294e Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 16 Sep 2024 14:00:39 +0700 Subject: [PATCH 21/52] fix(developer): LDML compiler, add TSS_VISUALKEYBOARD store when compiling visual keyboard Fixes: #12395 Cherry-pick-of: #12402 --- .../src/kmc-ldml/src/compiler/compiler.ts | 33 +++++++++++++------ .../kmc-ldml/src/compiler/empty-compiler.ts | 2 +- .../src/compiler/visual-keyboard-compiler.ts | 33 +++++++++++++++++-- .../test/test-visual-keyboard-compiler.ts | 12 +++++-- 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/developer/src/kmc-ldml/src/compiler/compiler.ts b/developer/src/kmc-ldml/src/compiler/compiler.ts index 85aa79c37b..6e923f9855 100644 --- a/developer/src/kmc-ldml/src/compiler/compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/compiler.ts @@ -1,4 +1,4 @@ -import { LDMLKeyboardXMLSourceFileReader, LDMLKeyboard, KMXPlus, CompilerCallbacks, LDMLKeyboardTestDataXMLSourceFile, UnicodeSetParser, KeymanCompiler, KeymanCompilerResult, KeymanCompilerArtifacts, defaultCompilerOptions, KMXBuilder, KvkFileWriter, KeymanCompilerArtifactOptional } from '@keymanapp/common-types'; +import { KMX, LDMLKeyboardXMLSourceFileReader, LDMLKeyboard, KMXPlus, CompilerCallbacks, LDMLKeyboardTestDataXMLSourceFile, UnicodeSetParser, KeymanCompiler, KeymanCompilerResult, KeymanCompilerArtifacts, defaultCompilerOptions, KMXBuilder, KvkFileWriter, KeymanCompilerArtifactOptional } from '@keymanapp/common-types'; import { LdmlCompilerOptions } from './ldml-compiler-options.js'; import { CompilerMessages } from './messages.js'; import { BkspCompiler, TranCompiler } from './tran.js'; @@ -132,13 +132,27 @@ export class LdmlKeyboardCompiler implements KeymanCompiler { KMXPlusMetadataCompiler.addKmxMetadata(kmx.kmxplus, kmx.keyboard, compilerOptions); // Use the builder to generate the binary output file - const builder = new KMXBuilder(kmx, compilerOptions.saveDebug); - const kmx_binary = builder.compile(); + const kmxBuilder = new KMXBuilder(kmx, compilerOptions.saveDebug); + const keyboardId = this.callbacks.path.basename(outputFilename, '.kmx'); + const vkCompiler = new LdmlKeyboardVisualKeyboardCompiler(this.callbacks); + const vkCompilerResult = vkCompiler.compile(kmx.kmxplus, keyboardId); + if(vkCompilerResult === null) { + return null; + } + const vkData = typeof vkCompilerResult == 'object' ? vkCompilerResult : null; - const vkcompiler = new LdmlKeyboardVisualKeyboardCompiler(this.callbacks); - const vk = vkcompiler.compile(kmx.kmxplus, this.callbacks.path.basename(outputFilename, '.kmx')); - const writer = new KvkFileWriter(); - const kvk_binary = writer.write(vk); + if(vkData) { + kmx.keyboard.stores.push({ + dpName: '', + dpString: keyboardId + '.kvk', + dwSystemID: KMX.KMXFile.TSS_VISUALKEYBOARD + }); + } + + const kmxBinary = kmxBuilder.compile(); + + const kvkWriter = new KvkFileWriter(); + const kvkBinary = vkData ? kvkWriter.write(vkData) : null; // Note: we could have a step of generating source files here // KvksFileWriter()... @@ -151,11 +165,10 @@ export class LdmlKeyboardCompiler implements KeymanCompiler { //KMW17.0: const encoder = new TextEncoder(); //KMW17.0: const kmw_binary = encoder.encode(kmw_string); - return { artifacts: { - kmx: { data: kmx_binary, filename: outputFilename }, - kvk: { data: kvk_binary, filename: outputFilename.replace(/\.kmx$/, '.kvk') }, + kmx: { data: kmxBinary, filename: outputFilename }, + kvk: kvkBinary ? { data: kvkBinary, filename: outputFilename.replace(/\.kmx$/, '.kvk') } : null, //KMW17.0: js: { data: kmw_binary, filename: outputFilename.replace(/\.kmx$/, '.js') }, } }; diff --git a/developer/src/kmc-ldml/src/compiler/empty-compiler.ts b/developer/src/kmc-ldml/src/compiler/empty-compiler.ts index 911e56d896..514024fedd 100644 --- a/developer/src/kmc-ldml/src/compiler/empty-compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/empty-compiler.ts @@ -5,7 +5,7 @@ import { VarsCompiler } from './vars.js'; import { CompilerMessages } from './messages.js'; /** - * Compiler for typrs that don't actually consume input XML + * Compiler for types that don't actually consume input XML */ export abstract class EmptyCompiler extends SectionCompiler { private _id: SectionIdent; 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 812e57ef82..cf027043ba 100644 --- a/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/src/compiler/visual-keyboard-compiler.ts @@ -40,7 +40,15 @@ export class LdmlKeyboardVisualKeyboardCompiler { public constructor(private callbacks: CompilerCallbacks) { } - public compile(source: KMXPlus.KMXPlusData, keyboardId: string): VisualKeyboard.VisualKeyboard { + /** + * Generate a visual keyboard + * @param source Compiled KMX+ data; note that this is modified to add + * &VISUALKEYBOARD system store on success + * @param keyboardId Basename of keyboard, without file extension + * @returns Visual keyboard data on success, null on failure, or + * false if no VK was generated for this keyboard + */ + public compile(source: KMXPlus.KMXPlusData, keyboardId: string): VisualKeyboard.VisualKeyboard | boolean | null { let result = new VisualKeyboard.VisualKeyboard(); /* TODO-LDML: consider VisualKeyboardHeaderFlags.kvkhUseUnderlying kvkhDisplayUnderlying kvkhAltGr kvkh102 */ @@ -50,6 +58,8 @@ export class LdmlKeyboardVisualKeyboardCompiler { result.header.ansiFont = {...VisualKeyboard.DEFAULT_KVK_FONT}; result.header.unicodeFont = {...VisualKeyboard.DEFAULT_KVK_FONT}; + let hasVisualKeyboard = false; + for(let layersList of source.layr.lists) { const formId = layersList.hardware.value; if(formId == 'touch') { @@ -57,9 +67,23 @@ export class LdmlKeyboardVisualKeyboardCompiler { } for(let layer of layersList.layers) { - this.compileHardwareLayer(source, result, layer, formId); + const res = this.compileHardwareLayer(source, result, layer, formId); + if(res === false) { + // failed to compile the layer + return null; + } + if(res === null) { + // not a supported layer type, but not an error + continue; + } + hasVisualKeyboard = true; } } + + if(!hasVisualKeyboard) { + return false; + } + return result; } @@ -76,9 +100,10 @@ export class LdmlKeyboardVisualKeyboardCompiler { const shift = this.translateLayerModifiersToVisualKeyboardShift(layer.mod); if(shift === null) { // Caps (num, scroll) is not a supported shift state in .kvk - return; + return null; } + let result = true; let y = -1; for(let row of layer.rows) { y++; @@ -94,6 +119,7 @@ export class LdmlKeyboardVisualKeyboardCompiler { this.callbacks.reportMessage( CompilerMessages.Error_KeyNotFoundInKeyBag({ keyId: key.value, layer: layerId, row: y, col: x, form: hardware }) ); + result = false; } else { vk.keys.push({ flags: VisualKeyboard.VisualKeyboardKeyFlags.kvkkUnicode, @@ -104,6 +130,7 @@ export class LdmlKeyboardVisualKeyboardCompiler { } } } + return result; } private getDisplayFromKey(keydef: KMXPlus.KeysKeys, source: KMXPlus.KMXPlusData) { diff --git a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts index cc44286909..dee096cb22 100644 --- a/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts +++ b/developer/src/kmc-ldml/test/test-visual-keyboard-compiler.ts @@ -6,7 +6,7 @@ import * as path from 'path'; import {assert} from 'chai'; import { stripIndent } from 'common-tags'; -import { KvkFileWriter, LDMLKeyboardXMLSourceFileReader, VisualKeyboard } from '@keymanapp/common-types'; +import { KMX, KvkFileWriter, LDMLKeyboardXMLSourceFileReader, VisualKeyboard } from '@keymanapp/common-types'; import hextobin from '@keymanapp/hextobin'; import { checkMessages, compilerTestCallbacks, compilerTestOptions, makePathToFixture } from './helpers/index.js'; @@ -38,9 +38,16 @@ describe('visual-keyboard-compiler', function() { let kmx = await k.compile(source); assert(kmx, 'k.compile should not have failed'); - const vk = (new LdmlKeyboardVisualKeyboardCompiler(compilerTestCallbacks)).compile(kmx.kmxplus, path.basename(inputFilename, '.xml')); + const keyboardId = path.basename(inputFilename, '.xml'); + + const vk = (new LdmlKeyboardVisualKeyboardCompiler(compilerTestCallbacks)).compile(kmx.kmxplus, keyboardId); checkMessages(); assert.isNotNull(vk, 'LdmlKeyboardVisualKeyboardCompiler.compile should not have returned null'); + assert.isNotNull(kmx.keyboard.stores.find(store => + store.dwSystemID == KMX.KMXFile.TSS_VISUALKEYBOARD && + store.dpString == keyboardId + '.kvk' + )); + assert(typeof vk == 'object'); // Use the builder to generate the binary output file const writer = new KvkFileWriter(); @@ -220,6 +227,7 @@ async function loadVisualKeyboardFromXml(xml: string, id: string) { assert(kmx, 'k.compile should not have failed'); const vk = (new LdmlKeyboardVisualKeyboardCompiler(compilerTestCallbacks)).compile(kmx.kmxplus, id); + assert(typeof vk == 'object'); assert.isEmpty(compilerTestCallbacks.messages); assert.isOk(vk); From 6b77800ee129e3441664bfff7c5271edbbe16978 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Mon, 16 Sep 2024 18:48:40 -0400 Subject: [PATCH 22/52] auto: increment stable-17.0 version to 17.0.331 --- HISTORY.md | 6 ++++++ VERSION.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index a145231142..6e68c94094 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,11 @@ # Keyman Version History +## 17.0.330 stable 2024-09-16 + +* refactor(android): Move Sentry and APK to publish task (#12392) +* fix(developer): rewrite ldml visual keyboard compiler (#12406) +* fix(developer): check vars string usage before definition (#12407) + ## 17.0.329 stable 2024-09-09 * chore(android,ios): Add ojibwa ifinal/rdot keyboards to FirstVoices (#12020) diff --git a/VERSION.md b/VERSION.md index ad53a2c5b0..0371049d55 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.330 \ No newline at end of file +17.0.331 \ No newline at end of file From c264c0e502421dd74aa32b706db850aaf0dfb5cd Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Wed, 25 Sep 2024 09:44:31 +0700 Subject: [PATCH 23/52] fix(android): Hide suggestion banner on password fields --- .../main/java/com/keyman/engine/KMKeyboardWebViewClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardWebViewClient.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardWebViewClient.java index b80f6766a3..1e28e4af0b 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardWebViewClient.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboardWebViewClient.java @@ -164,7 +164,7 @@ public final class KMKeyboardWebViewClient extends WebViewClient { // appContext instead of context? SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); boolean modelPredictionPref = false; - if (KMManager.currentLexicalModel != null) { + if (!KMManager.getMayPredictOverride() && KMManager.currentLexicalModel != null) { modelPredictionPref = prefs.getBoolean(KMManager.getLanguagePredictionPreferenceKey(KMManager.currentLexicalModel.get(KMManager.KMKey_LanguageID)), true); } KMManager.setBannerOptions(modelPredictionPref); From 055aa37925977e8b10552267bcbe8d7c683ff165 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 26 Sep 2024 09:37:49 -0700 Subject: [PATCH 24/52] fix(common): declare dep on @keymanapp/ldml-keyboard-constants Fixes: #12470 --- common/web/types/package.json | 1 + package-lock.json | 1 + 2 files changed, 2 insertions(+) diff --git a/common/web/types/package.json b/common/web/types/package.json index 529624bc64..fb65261c7b 100644 --- a/common/web/types/package.json +++ b/common/web/types/package.json @@ -30,6 +30,7 @@ }, "dependencies": { "@keymanapp/keyman-version": "*", + "@keymanapp/ldml-keyboard-constants": "*", "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", "semver": "^7.5.2", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" diff --git a/package-lock.json b/package-lock.json index 7706d512c6..8b2b1c816d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -510,6 +510,7 @@ "license": "MIT", "dependencies": { "@keymanapp/keyman-version": "*", + "@keymanapp/ldml-keyboard-constants": "*", "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#7a188a1e26f8f36a175d95b67ffece8702363dfc", "semver": "^7.5.2", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" From 9534d7e05626725de4b53a7fbf7152d241e715e0 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 4 Oct 2024 13:06:18 +0700 Subject: [PATCH 25/52] cherrypick(oem/fv): Update keyboard versions and names for fv_all.kmp --- oem/firstvoices/keyboards.csv | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/oem/firstvoices/keyboards.csv b/oem/firstvoices/keyboards.csv index d1f1b92180..ed13eb5aaa 100644 --- a/oem/firstvoices/keyboards.csv +++ b/oem/firstvoices/keyboards.csv @@ -7,16 +7,16 @@ fv,fv_uummarmiutun,Uummarmiutun,Arctic,fv_uummarmiutun_kmw-9.0.js,9.1.1,ikt-Latn fv,fv_eastern_canadian_inuktitut,ᐃᓄᒃᑎᑐᑦ (Eastern Canadian Inuktitut),Arctic,fv_eastern_canadian_inuktitut_kmw-9.0.js,9.2.1,ike-Cans,Eastern Canadian Inuktitut (Unified Canadian Aboriginal Syllabics) fv,fv_migmaq,Mi'gmawi'simg / Mi'kmawi'simk,Atlantic,fv_migmaq_kmw-9.0.js,9.1.2,mic-Latn,Mi'kmaq (Latin) fv,fv_skicinuwatuwewakon,Skicinuwatuwewakon,Atlantic,fv_skicinuwatuwewakon_kmw-9.0.js,9.1.1,pqm-Latn,Malecite-Passamaquoddy (Latin) -fv,fv_uwikala,'Uwik̓ala,BC Coast,fv_uwikala_kmw-9.0.js,9.4,hei,Heiltsuk +fv,fv_uwikala,’Wuìk̓ala,BC Coast,fv_uwikala_kmw-9.0.js,9.4,hei,Heiltsuk fv,fv_dexwlesucid,Dəxʷləšucid,BC Coast,fv_dexwlesucid_kmw-9.0.js,9.2.1,lut-Latn,Lushootseed (Latin) fv,fv_diitiidatx,Diidiitidq,BC Coast,fv_diitiidatx_kmw-9.0.js,9.2.1,nuk-Latn,Nuu-chah-nulth (Latin) fv,fv_gitsenimx,Gitsenimx̱,BC Coast,fv_gitsenimx_kmw-9.0.js,10.1.2,git,Gitxsan (Latin) -fv,fv_hailzaqvla,Haiɫzaqvla,BC Coast,fv_hailzaqvla_kmw-9.0.js,9.5.2,hei,Heiltsuk (Latin) +fv,fv_hailzaqvla,Haíɫzaqvḷa,BC Coast,fv_hailzaqvla_kmw-9.0.js,10.0,hei,Heiltsuk (Latin) fv,fv_haisla,Haisla,BC Coast,fv_haisla.js,2.1.3,has-Latn,Haisla (Latin) fv,fv_halqemeylem,Halq'eméylem,BC Coast,fv_halqemeylem_kmw-9.0.js,9.2.1,hur-Latn,Halkomelem (Latin) -fv,fv_henqeminem,Hǝn̓q̓ǝmin̓ǝm,BC Coast,fv_henqeminem_kmw-9.0.js,10.2.1,hur-Latn,Halkomelem (Latin) -fv,fv_klahoose,Homalco-Klahoose-Sliammon,BC Coast,fv_klahoose_kmw-9.0.js,10.2,coo,Comox -fv,fv_hulquminum,Hul’q’umi’num’,BC Coast,fv_hulquminum_kmw-9.0.js,9.1,hur,Halkomelem +fv,fv_henqeminem,hǝn̓q̓ǝmin̓ǝm̓,BC Coast,fv_henqeminem_kmw-9.0.js,10.2.1,hur-Latn,Halkomelem (Latin) +fv,fv_klahoose,Éy7á7juuthem,BC Coast,fv_klahoose_kmw-9.0.js,10.2,coo,Comox +fv,fv_hulquminum,Hul’q’umi’num’,BC Coast,fv_hulquminum_kmw-9.0.js,9.2,hur,Halkomelem fv,fv_hulquminum_combine,Hul̓q̓umin̓um̓,BC Coast,fv_hulquminum_combine_kmw-9.0.js,2.0.1,hur-Latn,Halkomelem (Latin) fv,fv_kwakwala_liqwala,Kʷak̓ʷala,BC Coast,fv_kwakwala_liqwala_kmw-9.0.js,9.3,kwk-Latn,Kwakiutl (Latin) fv,fv_kwakwala,Kwak̕wala,BC Coast,fv_kwakwala_kmw-9.0.js,9.2,kwk-Latn,Kwakiutl (Latin) @@ -28,9 +28,9 @@ fv,fv_nuxalk,Nuxalk,BC Coast,fv_nuxalk_kmw-9.0.js,10.0.1,blc-Latn,Bella Coola (L fv,fv_sencoten,SENĆOŦEN,BC Coast,fv_sencoten_kmw-9.0.js,9.2.3,str,Straits Salish fv,fv_sguuxs,Sgüüx̱s,BC Coast,fv_sguuxs.js,1.1,tsi,Tsimshian fv,fv_shashishalhem,Shashishalhem,BC Coast,fv_shashishalhem_kmw-9.0.js,9.2.1,sec-Latn,Sechelt (Latin) -fv,fv_skwxwumesh_snichim,Sḵwx̱wúmesh sníchim,BC Coast,fv_skwxwumesh_snichim_kmw-9.0.js,10.0,squ-Latn,Squamish (Latin) +fv,fv_skwxwumesh_snichim,Sḵwx̱wú7mesh sníchim,BC Coast,fv_skwxwumesh_snichim_kmw-9.0.js,10.0,squ-Latn,Squamish (Latin) fv,fv_smalgyax,Sm'algya̱x,BC Coast,fv_smalgyax_kmw-9.0.js,9.3,tsi-Latn,Tsimshian (Latin) -fv,fv_xaislakala,X̄a'ʼislak̓ala,BC Coast,fv_xaislakala_kmw-9.0.js,10.0,has-Latn,Haisla (Latin) +fv,fv_xaislakala,X̄aʼislak̓ala,BC Coast,fv_xaislakala_kmw-9.0.js,10.0,has-Latn,Haisla (Latin) fv,fv_hlgaagilda_xaayda_kil,X̱aayda-X̱aad Kil,BC Coast,fv_hlgaagilda_xaayda_kil_kmw-9.0.js,9.4,hax,Southern Haida fv,fv_dakelh,Dakelh,BC Interior,fv_dakelh_kmw-9.0.js,9.2.1,caf-Latn,Southern Carrier (Latin) fv,fv_ktunaxa,Ktunaxa,BC Interior,fv_ktunaxa_kmw-9.0.js,10.0,kut-Latn,Kutenai (Latin) @@ -39,13 +39,13 @@ fv,fv_natwits,Nedut’en-Witsuwit'en,BC Interior,fv_natwits_kmw-9.0.js,9.2,caf-L fv,fv_nlekepmxcin,Nłeʔkepmxcin,BC Interior,fv_nlekepmxcin_kmw-9.0.js,9.5.1,thp-Latn,Thompson (Latin) fv,fv_nlha7kapmxtsin,Nlha7kapmxtsin,BC Interior,fv_nlha7kapmxtsin_kmw-9.0.js,10.1.2,thp,Thompson fv,fv_nlakapamuxcheen,Nlakapamuxcheen,BC Interior,fv_nlakapamuxcheen_kmw-9.0.js,1.1,thp,Thompson -fv,fv_nsilxcen,Nsilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,10.0.1,oka,Okanagan +fv,fv_nsilxcen,Nsyilxcən,BC Interior,fv_nsilxcen_kmw-9.0.js,10.0.1,oka,Okanagan fv,fv_secwepemctsin,Secwepemctsín,BC Interior,fv_secwepemctsin_kmw-9.0.js,9.3,shs,Shuswap fv,fv_stlatlimxec,Sƛ̓aƛ̓imxəc,BC Interior,fv_stlatlimxec_kmw-9.0.js,9.4,lil-Latn,Lillooet (Latin) fv,fv_statimcets,St̓át̓imcets,BC Interior,fv_statimcets_kmw-9.0.js,9.2,lil-Latn,Lillooet (Latin) -fv,fv_taltan,Tāłtān,BC Interior,fv_taltan_kmw-9.0.js,9.2,tht-Latn,Tahltan (Latin) +fv,fv_taltan,Tāłtān,BC Interior,fv_taltan_kmw-9.0.js,9.2,tht-Latn,Tahltan (Latin) fv,fv_tsekehne,Tsek'ehne,BC Interior,fv_tsekehne_kmw-9.0.js,9.2,sek-Latn,Sekani (Latin) -fv,fv_tsilhqotin,Tŝilhqot'in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.3,clc-Latn,Chilcotin (Latin) +fv,fv_tsilhqotin,Tŝilhqot’in,BC Interior,fv_tsilhqotin_kmw-9.0.js,9.3,clc-Latn,Chilcotin (Latin) fv,fv_southern_carrier,ᑐᑊᘁᗕᑋᗸ (Southern Carrier),BC Interior,fv_southern_carrier_kmw-9.0.js,10.1,caf-Cans,Southern Carrier (Unified Canadian Aboriginal Syllabics) fv,fv_anicinapemi8in,Anicinapemi8in/Anishinàbemiwin,Eastern Subarctic,fv_anicinapemi8in_kmw-9.0.js,9.1.1,alq-Latn,Algonquin (Latin) fv,fv_atikamekw,Atikamekw,Eastern Subarctic,fv_atikamekw_kmw-9.0.js,9.1.1,atj-Latn,Atikamekw (Latin) @@ -86,10 +86,10 @@ fv,fv_tsuutina,Tsúùt'ínà,Prairies,fv_tsuutina_kmw-9.0.js,9.1.1,srs-Latn,Sars fv,fv_plains_cree,ᓀᐦᐃᔭᐍᐏᐣ (Plains Cree),Prairies,fv_plains_cree_kmw-9.0.js,11.1,crk-Cans,ᓀᐦᐃᔭᐍᐏᐣ (Cree syllabics) fv,fv_dine_bizaad,Diné Bizaad,South West,fv_dine_bizaad_kmw-9.0.js,9.1.1,nv-Latn,Navajo (Latin) fv,fv_dane_zaa_zaage,Dane-Z̲aa Z̲áágéʔ,Western Subarctic,fv_dane_zaa_zaage_kmw-9.0.js,9.4.1,bea,Beaver -fv,fv_dene_dzage,Dene Dzage,Western Subarctic,fv_dene_dzage_kmw-9.0.js,11.0.1,kkz-Latn,Kaska (Latin) -fv,fv_dene_zhatie,Dene Zhatié,Western Subarctic,fv_dene_zhatie_kmw-9.0.js,10.2.1,den,Dene Zhatıé -fv,fv_denesuline_epsilon,Dënesųłıné,Western Subarctic,fv_denesuline_epsilon_kmw-9.0.js,10.0.1,chp,Chipewyan -fv,fv_denesuline,Dɛnɛsųłiné,Western Subarctic,fv_denesuline_kmw-9.0.js,10.0.1,chp,Chipewyan (Latin) +fv,fv_dene_dzage,Danezāgéʼ,Western Subarctic,fv_dene_dzage_kmw-9.0.js,11.0.1,kkz-Latn,Kaska (Latin) +fv,fv_dene_zhatie,Dene Zhatıé,Western Subarctic,fv_dene_zhatie_kmw-9.0.js,10.2.1,den,Dene Zhatıé +fv,fv_denesuline_epsilon,Dɛnɛsųłįnɛ,Western Subarctic,fv_denesuline_epsilon_kmw-9.0.js,10.0.2,chp,Chipewyan +fv,fv_denesuline,Dënesųłıné,Western Subarctic,fv_denesuline_kmw-9.0.js,10.0.1,chp,Chipewyan (Latin) fv,fv_gwichin,Gwich'in,Western Subarctic,fv_gwichin_kmw-9.0.js,9.2.1,gwi-Latn,Gwichʼin (Latin) fv,fv_han,Hän,Western Subarctic,fv_han_kmw-9.0.js,9.2,haa-Latn,Han (Latin) fv,fv_kashogotine_yati,K'áshogot'ı̨nę́ Yatı̨́,Western Subarctic,fv_kashogotine_yati_kmw-9.0.js,10.1,scs,North Slavey From 4a99cb93261ad60c040824689c7cb749e14e11d1 Mon Sep 17 00:00:00 2001 From: sgschantz Date: Tue, 8 Oct 2024 14:41:31 +0700 Subject: [PATCH 26/52] chore(ios): renew certificate --- ios/exportAppStore.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/exportAppStore.plist b/ios/exportAppStore.plist index 48ef58f532..bb7315750e 100644 --- a/ios/exportAppStore.plist +++ b/ios/exportAppStore.plist @@ -7,9 +7,9 @@ teamID 3YE4W86L3G signingCertificate - BB842A0081298BBA6D034C85451750B08FC9EE8A + 683E4A3CDF5277C13004E84D63E31D2F720AB063 installerSigningCertificate - BB842A0081298BBA6D034C85451750B08FC9EE8A + 683E4A3CDF5277C13004E84D63E31D2F720AB063 provisioningProfiles Tavultesoft.Keyman From df1ec2fe9490f2949ad2a94677e7132ff4e5b49e Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 25 Sep 2024 07:33:42 -0700 Subject: [PATCH 27/52] fix(developer): ignore excess whitespace in `` attribute Cherry-pick-of: #12468 Fixes: #12449 --- developer/src/kmc-ldml/src/compiler/layr.ts | 2 +- .../sections/layr/row-keys-whitespace.xml | 18 +++++++++++++ developer/src/kmc-ldml/test/test-layr.ts | 25 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 developer/src/kmc-ldml/test/fixtures/sections/layr/row-keys-whitespace.xml diff --git a/developer/src/kmc-ldml/src/compiler/layr.ts b/developer/src/kmc-ldml/src/compiler/layr.ts index 8056144b25..bc7ee38e1e 100644 --- a/developer/src/kmc-ldml/src/compiler/layr.ts +++ b/developer/src/kmc-ldml/src/compiler/layr.ts @@ -63,7 +63,7 @@ export class LayrCompiler extends SectionCompiler { for (const layer of layers.layer) { const rows = layer.row.map((row) => { const erow: LayrRow = { - keys: row.keys.split(' ').map((id) => sections.strs.allocString(id)), + keys: row.keys.trim().split(/[ \t]+/).map((id) => sections.strs.allocString(id)), }; return erow; }); diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/row-keys-whitespace.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/row-keys-whitespace.xml new file mode 100644 index 0000000000..f8d1a629d5 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/row-keys-whitespace.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/test-layr.ts b/developer/src/kmc-ldml/test/test-layr.ts index 32d212a009..bc275d0ea1 100644 --- a/developer/src/kmc-ldml/test/test-layr.ts +++ b/developer/src/kmc-ldml/test/test-layr.ts @@ -129,5 +129,30 @@ describe('layr', function () { ]); }, }, + { + subpath: 'sections/layr/row-keys-whitespace.xml', + callback(sect) { + const layr = sect; + 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.value, 'us'); + const layer0 = list0.layers[0]; + assert.ok(layer0); + assert.equal(layer0.rows.length, 2); + assert.equal(layer0.id.value, 'base'); + assert.equal(layer0.mod, constants.keys_mod_none); + for(const row of layer0.rows) { + assert.ok(row); + assert.equal(row.keys.length, 2); + assert.equal(row.keys[0]?.value, 'grave'); + assert.equal(row.keys[1]?.value, 'mistake'); + } + }, + }, ]); }); From 0c9f272cbc3a655dbd6f3bae1bac00d2b86d49e7 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 10 Oct 2024 11:54:45 +0700 Subject: [PATCH 28/52] fix(developer): prevent invalid string ids Adds checks for invalid string IDs and corresponding unit tests. Fixes: #12451 Cherry-pick-of: #12645 --- .../src/kmc-ldml/src/compiler/messages.ts | 17 ++++++++++++---- developer/src/kmc-ldml/src/compiler/vars.ts | 20 +++++++++++++++++++ .../vars/fail-invalid-identifiers.xml | 17 ++++++++++++++++ developer/src/kmc-ldml/test/test-vars.ts | 10 ++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 developer/src/kmc-ldml/test/fixtures/sections/vars/fail-invalid-identifiers.xml diff --git a/developer/src/kmc-ldml/src/compiler/messages.ts b/developer/src/kmc-ldml/src/compiler/messages.ts index 7ebf6bddc7..a87c4d7927 100644 --- a/developer/src/kmc-ldml/src/compiler/messages.ts +++ b/developer/src/kmc-ldml/src/compiler/messages.ts @@ -174,7 +174,13 @@ export class CompilerMessages { static Error_UnparseableReorderSet = (o: { from: string, set: string }) => m(this.ERROR_UnparseableReorderSet, `Illegal UnicodeSet "${def(o.set)}" in reorder "${def(o.from)}`); - // Available: 0x029 + static ERROR_InvalidVariableIdentifer = SevError | 0x0029; + static Error_InvalidVariableIdentifer = (o: { id: string }) => m( + this.ERROR_InvalidVariableIdentifer, + `Invalid variable identifier "\\u${def(o.id)}". Identifiers must be between 1 and 32 characters, and can use A-Z, a-z, 0-9, and _.`, + ); + + // Available: 0x02A-0x2F static ERROR_InvalidQuadEscape = SevError | 0x0030; static Error_InvalidQuadEscape = (o: { cp: number }) => @@ -189,9 +195,12 @@ export class CompilerMessages { m(this.ERROR_UnparseableTransformFrom, `Invalid transform from="${def(o.from)}": "${def(o.message)}"`); static ERROR_IllegalTransformDollarsign = SevErrorTransform | 0x01; - static Error_IllegalTransformDollarsign = (o: { from: string }) => - m(this.ERROR_IllegalTransformDollarsign, `Invalid transform from="${def(o.from)}": Unescaped dollar-sign ($) is not valid transform syntax.`, - '**Hint**: Use `\\$` to match a literal dollar-sign.'); + static Error_IllegalTransformDollarsign = (o: { from: string }) => m( + this.ERROR_IllegalTransformDollarsign, + `Invalid transform from="${def(o.from)}": Unescaped dollar-sign ($) is not valid transform syntax.`, + `**Hint**: Use \`\\$\` to match a literal dollar-sign. If this precedes a variable name, `+ + `the variable name may not be valid (A-Z, a-z, 0-9, _, 32 character maximum).` + ); static ERROR_TransformFromMatchesNothing = SevErrorTransform | 0x02; static Error_TransformFromMatchesNothing = (o: { from: string }) => diff --git a/developer/src/kmc-ldml/src/compiler/vars.ts b/developer/src/kmc-ldml/src/compiler/vars.ts index d640dbf1a3..669aefe62f 100644 --- a/developer/src/kmc-ldml/src/compiler/vars.ts +++ b/developer/src/kmc-ldml/src/compiler/vars.ts @@ -40,6 +40,14 @@ export class VarsCompiler extends SectionCompiler { return valid; } + private validateIdentifier(id: string) { + if(!id.match(VariableParser.ID)) { // From DTD + this.callbacks.reportMessage(CompilerMessages.Error_InvalidVariableIdentifer({id})); + return false; + } + return true; + } + private validateVars(st: Substitutions): boolean { let valid = true; const variables = this.keyboard3?.variables; @@ -67,6 +75,10 @@ export class VarsCompiler extends SectionCompiler { if (variables) { // Strings for (const { id, value } of variables.string) { + if(!this.validateIdentifier(id)) { + valid = false; + continue; + } addId(id); const stringrefs = VariableParser.allStringReferences(value); for(const ref of stringrefs) { @@ -81,6 +93,10 @@ export class VarsCompiler extends SectionCompiler { } // Sets for (const { id, value } of variables.set) { + if(!this.validateIdentifier(id)) { + valid = false; + continue; + } addId(id); allSets.add(id); // check for illegal references, here. @@ -103,6 +119,10 @@ export class VarsCompiler extends SectionCompiler { } // UnicodeSets for (const { id, value } of variables.uset) { + if(!this.validateIdentifier(id)) { + valid = false; + continue; + } addId(id); allUnicodeSets.add(id); const stringrefs = VariableParser.allStringReferences(value); diff --git a/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-invalid-identifiers.xml b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-invalid-identifiers.xml new file mode 100644 index 0000000000..880864fd4e --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/vars/fail-invalid-identifiers.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/test-vars.ts b/developer/src/kmc-ldml/test/test-vars.ts index b1fadd0e44..05fb6d0b4a 100644 --- a/developer/src/kmc-ldml/test/test-vars.ts +++ b/developer/src/kmc-ldml/test/test-vars.ts @@ -121,6 +121,16 @@ describe('vars', function () { CompilerMessages.Error_DuplicateVariable({ids: 'upper, y'}) ], }, + { + subpath: 'sections/vars/fail-invalid-identifiers.xml', + errors: [ + CompilerMessages.Error_InvalidVariableIdentifer({id: 'invalid-string'}), + CompilerMessages.Error_InvalidVariableIdentifer({id: 'invalid-set'}), + CompilerMessages.Error_InvalidVariableIdentifer({id: 'invalid-uset'}), + CompilerMessages.Error_InvalidVariableIdentifer({id: 'a_marker_name_more_than_32_chars_long'}), + CompilerMessages.Error_InvalidVariableIdentifer({id: '😡'}), + ], + }, { subpath: 'sections/vars/fail-uset-props1.xml', errors: [ From bac04ee20eca34aa0364fc8782a902672e60d9a9 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Wed, 30 Oct 2024 02:29:33 -0400 Subject: [PATCH 29/52] auto: increment stable-17.0 version to 17.0.332 --- HISTORY.md | 9 +++++++++ VERSION.md | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 6e68c94094..71fdfd83ea 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,14 @@ # Keyman Version History +## 17.0.331 stable 2024-10-30 + +* fix(android): Hide suggestion banner on password fields (#12466) +* fix(common): declare dep on @keymanapp/ldml-keyboard-constants (#12475) +* fix(oem/fv): Update keyboard versions and names for fv_all.kmp (#12504) +* chore(ios): renew certificate (#12513) +* fix(developer): prevent invalid string ids (#12524) +* fix(developer): ignore excess whitespace in `` attribute (#12523) + ## 17.0.330 stable 2024-09-16 * refactor(android): Move Sentry and APK to publish task (#12392) diff --git a/VERSION.md b/VERSION.md index 0371049d55..4700eeddbd 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.331 \ No newline at end of file +17.0.332 \ No newline at end of file From 3cd28d4f9f35bd6374847a629c7b0321375c06a2 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 4 Nov 2024 08:04:43 +0700 Subject: [PATCH 30/52] fix(developer): create Server config directory before options save Also use back-off logic for saving in case config file is locked by another process. Cherry-pick-of: #12608 Fixes: #12607 Fixes: KEYMAN-DEVELOPER-1Z1 --- .../src/tike/main/KeymanDeveloperOptions.pas | 67 ++++++++++--------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/developer/src/tike/main/KeymanDeveloperOptions.pas b/developer/src/tike/main/KeymanDeveloperOptions.pas index 6eb0573096..5f8613499f 100644 --- a/developer/src/tike/main/KeymanDeveloperOptions.pas +++ b/developer/src/tike/main/KeymanDeveloperOptions.pas @@ -83,6 +83,7 @@ type procedure optWriteInt(const nm: string; value: Integer); procedure WriteServerConfigurationJson; class function Default_DefaultProjectPath: string; static; + function BackOffAndSaveJson(const Filename: string; const JSON: TJSONObject): Boolean; public procedure Read; procedure Write; @@ -406,8 +407,6 @@ begin end; procedure TKeymanDeveloperOptions.Write; -var - count: Integer; begin // If the output file does not exist, this creates it. Note that we load // from the existing file before writing out our set of options, which is @@ -464,33 +463,7 @@ begin ForceDirectories(TKeymanDeveloperPaths.OptionsPath); try - count := 0; - repeat - try - SaveJSONToFile(TKeymanDeveloperPaths.OptionsPath + TKeymanDeveloperPaths.S_OptionsJson, json); - Break; - except - on E:EOSError do - begin - if E.ErrorCode = ERROR_ACCESS_DENIED then - begin - // Back off and retry 0.5 sec later, it's probably another - // instance happening to read or write the settings file - Inc(count); - Sleep(500); - end - else - raise; - end - else - raise; - end; - until count >= Max_Retries; - if count >= Max_Retries then - begin - if TKeymanSentryClient.Instance <> nil then - TKeymanSentryClient.Instance.ReportMessage('TKeymanDeveloperOptions: Failed to write settings after 5 tries'); - end; + BackOffAndSaveJson(TKeymanDeveloperPaths.OptionsPath + TKeymanDeveloperPaths.S_OptionsJson, json); except on E:Exception do begin @@ -507,6 +480,39 @@ begin WriteServerConfigurationJson; end; +function TKeymanDeveloperOptions.BackOffAndSaveJson(const Filename: string; const JSON: TJSONObject): Boolean; +var + count: Integer; +begin + count := 0; + repeat + try + SaveJSONToFile(Filename, JSON); + Exit(True); + except + on E:EOSError do + begin + if E.ErrorCode = ERROR_ACCESS_DENIED then + begin + // Back off and retry 0.5 sec later, it's probably another + // instance happening to read or write the settings file + Inc(count); + Sleep(500); + end + else + raise; + end + else + raise; + end; + until count >= Max_Retries; + + if TKeymanSentryClient.Instance <> nil then + TKeymanSentryClient.Instance.ReportMessage('TKeymanDeveloperOptions: Failed to write '+Filename+' after 5 tries'); + + Result := False; +end; + procedure TKeymanDeveloperOptions.WriteServerConfigurationJson; var o: TJSONObject; @@ -517,7 +523,8 @@ begin o.AddPair('ngrokToken', FServerNgrokToken); o.AddPair('useNgrok', TJSONBool.Create(FServerUseNgrok)); o.AddPair('ngrokVisible', TJSONBool.Create(FServerServerShowConsoleWindow)); - SaveJSONToFile(TKeymanDeveloperPaths.ServerDataPath + TKeymanDeveloperPaths.S_ServerConfigJson, o); + ForceDirectories(TKeymanDeveloperPaths.ServerDataPath); + BackOffAndSaveJSON(TKeymanDeveloperPaths.ServerDataPath + TKeymanDeveloperPaths.S_ServerConfigJson, o); finally o.Free; end; From 8bff156a682dbbff76aa49f8a682c5c4814aa5bf Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 4 Nov 2024 17:44:22 +0100 Subject: [PATCH 31/52] fix(linux): set environment variable for rendering of downloads dialog This works around a problem in webkit2gtk where the download dialog sometimes only renders a blank screen. Setting the environment variable seems to help, not only in the cases that the issue describes (with a NVidia graphics card), but also in my testing in a VM. Fixes: #12587 Cherry-pick-of: #12616 --- linux/keyman-config/km-config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux/keyman-config/km-config b/linux/keyman-config/km-config index 641fb96470..e099c59eda 100755 --- a/linux/keyman-config/km-config +++ b/linux/keyman-config/km-config @@ -2,6 +2,7 @@ import argparse import logging +import os import sys import gi @@ -66,6 +67,10 @@ if __name__ == '__main__': elif args.url: download_and_install_package(args.url) else: + # Workaround for bug in webkit2gtk (#12587) + if not 'WEBKIT_DISABLE_DMABUF_RENDERER' in os.environ: + os.environ['WEBKIT_DISABLE_DMABUF_RENDERER'] = '1' + w = ViewInstalledWindow() try: w.run() From 3da2c2895658b54c88baa79907b5b41a4120d8b2 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 6 Nov 2024 06:11:38 +0700 Subject: [PATCH 32/52] fix(developer): handle merge commits when checking git log date Relates-to: keymanapp/keyboards#3143 Fixes: #12626 Fixes: KEYMAN-DEVELOPER-2AY Cherry-pick-of: #12627 --- .../src/kmc/src/util/getLastGitCommitDate.ts | 47 +++++++++++++++---- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/developer/src/kmc/src/util/getLastGitCommitDate.ts b/developer/src/kmc/src/util/getLastGitCommitDate.ts index bc85edacce..955927c20d 100644 --- a/developer/src/kmc/src/util/getLastGitCommitDate.ts +++ b/developer/src/kmc/src/util/getLastGitCommitDate.ts @@ -10,21 +10,53 @@ export const expectedGitDateFormat = /^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d\d\ */ export function getLastGitCommitDate(path: string): string { // TZ=UTC0 git log -1 --no-merges --date=format:%Y-%m-%dT%H:%M:%SZ --format=%ad - let result = null; + let result = callGitLog([ + 'log', // git log + '-1', // one commit only + '--no-merges', // we're only interested in 'real' commits + '--format=%at', // emit only the commit date as a UNIX timestamp + '--', + path + ]); - try { - result = execFileSync('git', [ + if(typeof result != 'string') { + return null; + } + + if(result == '') { + // #12626: no history was found, but not an error. We may have only a merge + // commit in history for that file, allow merges in the log + result = callGitLog([ 'log', // git log '-1', // one commit only - '--no-merges', // we're only interested in 'real' commits '--format=%at', // emit only the commit date as a UNIX timestamp '--', path - ], { + ]); + + if(typeof result != 'string') { + return null; + } + } + + const sec = Number.parseInt(result); + if(Number.isNaN(sec)) { + // We received invalid data, perhaps a git error string so just ignore + return null; + } + + // We receive a timestamp in seconds but we need milliseconds + return new Date(sec * 1000).toISOString(); +} + +function callGitLog(params: string[]) { + try { + const result = execFileSync('git', params, { encoding: 'utf-8', // force a string result rather than Buffer windowsHide: true, // on windows, we may need this to suppress a console window popup stdio: ['pipe', 'pipe', 'pipe'] // all output via pipe, so we don't get git errors on console }); + return result.trim(); } catch (e) { // If git is not available, or the file is not in-repo, then it is probably // fine to just silently return null, as the only machines where this is @@ -34,9 +66,4 @@ export function getLastGitCommitDate(path: string): string { // seems low. return null; } - - // We receive a timestamp in seconds but we need milliseconds - const msec = Number.parseInt(result.trim()) * 1000; - - return new Date(msec).toISOString(); } From a75d888aa5af097472b7f1d28d8bc8262cf29cff Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Wed, 6 Nov 2024 01:24:14 -0500 Subject: [PATCH 33/52] auto: increment stable-17.0 version to 17.0.333 --- HISTORY.md | 6 ++++++ VERSION.md | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 71fdfd83ea..061ac40119 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,11 @@ # Keyman Version History +## 17.0.332 stable 2024-11-06 + +* fix(developer): create Server config directory before options save (#12609) +* fix(developer): handle merge commits when checking git log date (#12628) +* fix(linux): set environment variable for rendering of downloads dialog (#12617) + ## 17.0.331 stable 2024-10-30 * fix(android): Hide suggestion banner on password fields (#12466) diff --git a/VERSION.md b/VERSION.md index 4700eeddbd..794e84bf25 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.332 \ No newline at end of file +17.0.333 \ No newline at end of file From 1c94d721ef5bd8a37256f74eca24d6f834443c1f Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 14 Nov 2024 16:37:55 +0100 Subject: [PATCH 34/52] fix(core): permanently disable logging This change disables logging at compile time to work around #12661. Logging can be enabled in the debugger, or by re-compiling with `g_debug_KeymanLog` set to TRUE. Related: #12661 --- core/src/kmx/kmx_processevent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/kmx/kmx_processevent.cpp b/core/src/kmx/kmx_processevent.cpp index 604c6f6fe2..80e0f39c04 100644 --- a/core/src/kmx/kmx_processevent.cpp +++ b/core/src/kmx/kmx_processevent.cpp @@ -12,7 +12,7 @@ using namespace kmx; /* Globals */ KMX_BOOL km::core::kmx::g_debug_ToConsole = FALSE; -KMX_BOOL km::core::kmx::g_debug_KeymanLog = TRUE; +KMX_BOOL km::core::kmx::g_debug_KeymanLog = FALSE; // workaround for #12661 KMX_BOOL km::core::kmx::g_silent = FALSE; /* From a3986e7574d5046ff40304268749503993d86280 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Wed, 6 Nov 2024 09:30:18 -0600 Subject: [PATCH 35/52] =?UTF-8?q?fix(core):=20implement=20ldml=5Fprocessor?= =?UTF-8?q?::get=5Fkey=5Flist()=20=20=F0=9F=8D=92=20=F0=9F=99=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Cherry pick of https://github.com/keymanapp/keyman/pull/12644 - Cherry pick of https://github.com/keymanapp/keyman/commit/de3397b47668dd3082e9df095a10d007a3731b98 Fixes: #12298 --- core/include/keyman/keyman_core_api_vkeys.h | 1 + core/src/kmx/kmx_plus.h | 6 + core/src/ldml/ldml_processor.cpp | 3 +- core/src/ldml/ldml_vkeys.cpp | 110 +++++++++++++ core/src/ldml/ldml_vkeys.hpp | 7 + .../unit/ldml/keyboards/k_004_tinyshift.xml | 11 +- core/tests/unit/ldml/ldml.cpp | 71 +++++++- core/tests/unit/ldml/ldml_test_source.cpp | 155 ++++++++++++------ core/tests/unit/ldml/ldml_test_source.hpp | 75 ++++++++- 9 files changed, 374 insertions(+), 65 deletions(-) diff --git a/core/include/keyman/keyman_core_api_vkeys.h b/core/include/keyman/keyman_core_api_vkeys.h index 7e4a6d181a..7e65d8ad91 100644 --- a/core/include/keyman/keyman_core_api_vkeys.h +++ b/core/include/keyman/keyman_core_api_vkeys.h @@ -16,6 +16,7 @@ #pragma once enum km_core_modifier_state { + KM_CORE_MODIFIER_NONE = 0, KM_CORE_MODIFIER_LCTRL = 1 << 0, KM_CORE_MODIFIER_RCTRL = 1 << 1, KM_CORE_MODIFIER_LALT = 1 << 2, diff --git a/core/src/kmx/kmx_plus.h b/core/src/kmx/kmx_plus.h index a8e5c1f0e4..e3a510b76d 100644 --- a/core/src/kmx/kmx_plus.h +++ b/core/src/kmx/kmx_plus.h @@ -455,7 +455,13 @@ public: bool setLayr(const COMP_KMXPLUS_LAYR *newLayr); bool valid() const; + /** + * @param list index from 0 to layr->listCount + */ const COMP_KMXPLUS_LAYR_LIST *getList(KMX_DWORD list) const; + /** + * @param entry index value: COMP_KMXPLUS_LAYR_LIST.layer but less than COMP_KMXPLUS_LAYR_LIST.layer+COMP_KMXPLUS_LAYR_LIST.count + */ const COMP_KMXPLUS_LAYR_ENTRY *getEntry(KMX_DWORD entry) const; const COMP_KMXPLUS_LAYR_ROW *getRow(KMX_DWORD row) const; const COMP_KMXPLUS_LAYR_KEY *getKey(KMX_DWORD key) const; diff --git a/core/src/ldml/ldml_processor.cpp b/core/src/ldml/ldml_processor.cpp index fcadda629c..4e42c3acea 100644 --- a/core/src/ldml/ldml_processor.cpp +++ b/core/src/ldml/ldml_processor.cpp @@ -348,8 +348,7 @@ km_core_attr const & ldml_processor::attributes() const { } km_core_keyboard_key * ldml_processor::get_key_list() const { - km_core_keyboard_key* key_list = new km_core_keyboard_key(KM_CORE_KEYBOARD_KEY_LIST_END); - return key_list; + return keys.get_key_list(); } km_core_keyboard_imx * ldml_processor::get_imx_list() const { diff --git a/core/src/ldml/ldml_vkeys.cpp b/core/src/ldml/ldml_vkeys.cpp index f79f82141f..dc3f22f18b 100644 --- a/core/src/ldml/ldml_vkeys.cpp +++ b/core/src/ldml/ldml_vkeys.cpp @@ -8,6 +8,8 @@ #include "ldml_vkeys.hpp" #include "kmx_file.h" #include +#include +#include namespace km { namespace core { @@ -22,6 +24,114 @@ vkeys::add(km_core_virtual_key vk, km_core_ldml_modifier_state modifier_state, s const vkey_id id(vk, modifier_state); // assign the string vkey_to_string[id] = output; + // includes all keys - including gaps. + all_vkeys.insert(id); +} + +km_core_keyboard_key * +vkeys::get_key_list() const { + // prescan to find out which modifier flags are used + + std::size_t other_key_count = 0; // number of 'OTHER' keys, which will need to expand to all of the other_state set ( so other_state.size()) + + std::set all_modifiers; + for (const auto &k : all_vkeys) { + const auto mod = k.second; + if (mod == LDML_KEYS_MOD_OTHER) { + other_key_count++; + } + all_modifiers.insert(mod); + } + std::set other_state; + + // Alt + if (all_modifiers.count(LDML_KEYS_MOD_ALT) == 0 && all_modifiers.count(LDML_KEYS_MOD_ALTL) == 0 && all_modifiers.count(LDML_KEYS_MOD_ALTR) == 0) { + // no ALT keys were seen, so OTHER includes ALT + other_state.insert(KM_CORE_MODIFIER_ALT); + } else if(all_modifiers.count(LDML_KEYS_MOD_ALTL) == 0) { + other_state.insert(KM_CORE_MODIFIER_RALT); + } else if(all_modifiers.count(LDML_KEYS_MOD_ALTR) == 0) { + other_state.insert(KM_CORE_MODIFIER_LALT); + } + + // ctrl + if (all_modifiers.count(LDML_KEYS_MOD_CTRL) == 0 && all_modifiers.count(LDML_KEYS_MOD_CTRLL) == 0 && all_modifiers.count(LDML_KEYS_MOD_CTRLR) == 0) { + // no CTRL keys were seen, so OTHER includes CTRL + other_state.insert(KM_CORE_MODIFIER_CTRL); + } else if(all_modifiers.count(LDML_KEYS_MOD_CTRLL) == 0) { + other_state.insert(KM_CORE_MODIFIER_RCTRL); + } else if(all_modifiers.count(LDML_KEYS_MOD_CTRLR) == 0) { + other_state.insert(KM_CORE_MODIFIER_LCTRL); + } + + // shift + if (all_modifiers.count(LDML_KEYS_MOD_SHIFT) == 0) { + other_state.insert(KM_CORE_MODIFIER_SHIFT); + } + + // caps + if (all_modifiers.count(LDML_KEYS_MOD_CAPS) == 0) { + other_state.insert(KM_CORE_MODIFIER_CAPS); + } + + // none- it's possible there is no 'none' layer + if (all_modifiers.count(LDML_KEYS_MOD_NONE) == 0) { + other_state.insert(KM_CORE_MODIFIER_NONE); + } + + // We need ALL combinations of the other_state, except for 'all off'. + // The number of additions will be (2**(other_state.size())-1 + // Also, since the LDML_KEYS_MOD_OTHER modifier is excluded, we + // will need to subtract 1 when calculating new_list_size + const std::size_t other_expanded_count = (1 << other_state.size()) - 1; + + std::vector other_expanded_mods(other_expanded_count); + + // populate the expanded list. + // we start at 1 because 0 is "all bits off" (00000b) + for (std::size_t expansion = 1; expansion <= other_expanded_count; expansion++) { + uint32_t &expanded_mod = other_expanded_mods.at(expansion-1) = KM_CORE_MODIFIER_NONE; + std::size_t bit_mask = 1; + for (const auto mod : other_state) { + // Check if this modifier is on in this iteration of the expansion + // bit_mask will be 2^0 … 2^(other_state().size()-1) + if (bit_mask & expansion) { + // do we include this entry? check if this bit is on + expanded_mod |= mod; + } + // shift the bitmask over + assert(expanded_mod <= KM_CORE_MODIFIER_MASK_CAPS); + bit_mask <<= 1; + } + } + + const std::size_t new_list_size = all_vkeys.size() // original size + + (other_key_count * (other_expanded_count - 1))// number of additional entries needed + + 1; // terminator + km_core_keyboard_key *list = new km_core_keyboard_key[new_list_size]; + std::size_t n = 0; + for (const auto &k : all_vkeys) { + const auto vkey = k.first; + const auto mod = k.second; + + if (mod == LDML_KEYS_MOD_OTHER) { + // expand to all of other_state + for (const auto expanded_mod : other_expanded_mods) { + list[n].key = vkey; + list[n++].modifier_flag = expanded_mod; + assert(n <= new_list_size); + } + } else { + assert(mod <= KM_CORE_MODIFIER_MASK_CAPS); // that no LDMLisms escape + list[n].key = vkey; + list[n++].modifier_flag = mod; + assert(n <= new_list_size); + } + } + // add the list terminator + list[n++] = KM_CORE_KEYBOARD_KEY_LIST_END; + assert(n == new_list_size); + return list; } static const uint16_t BOTH_ALT = LALTFLAG | RALTFLAG; diff --git a/core/src/ldml/ldml_vkeys.hpp b/core/src/ldml/ldml_vkeys.hpp index 6a54d77065..916d805e2c 100644 --- a/core/src/ldml/ldml_vkeys.hpp +++ b/core/src/ldml/ldml_vkeys.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "keyman_core.h" @@ -37,6 +38,7 @@ typedef std::pair vkey_id; class vkeys { private: std::map vkey_to_string; + std::set all_vkeys; public: vkeys(); @@ -53,6 +55,11 @@ public: std::u16string lookup(km_core_virtual_key vk, uint16_t modifier_state, bool &found) const; + /** + * For implementing ldml_processor::get_key_list() + */ + km_core_keyboard_key* get_key_list() const; + private: /** * Non-recursive internal lookup of a specific ID diff --git a/core/tests/unit/ldml/keyboards/k_004_tinyshift.xml b/core/tests/unit/ldml/keyboards/k_004_tinyshift.xml index 4346fa801b..2d152867a7 100644 --- a/core/tests/unit/ldml/keyboards/k_004_tinyshift.xml +++ b/core/tests/unit/ldml/keyboards/k_004_tinyshift.xml @@ -2,8 +2,9 @@ @@ -23,5 +24,11 @@ + + + + + + diff --git a/core/tests/unit/ldml/ldml.cpp b/core/tests/unit/ldml/ldml.cpp index 3c27046b23..cb4fd45e15 100644 --- a/core/tests/unit/ldml/ldml.cpp +++ b/core/tests/unit/ldml/ldml.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include "path.hpp" #include "state.hpp" @@ -266,6 +267,63 @@ verify_context(std::u16string &text_store, km_core_state *&test_state, std::vect delete[] buf; } + +/** + * @param actual the list from get_key_list() + * @param expected optional list with keys to check, can be empty - not exhaistive + * @returns true if passing + */ +bool +verify_key_list(std::set &actual, std::set &expected) { + bool equals = true; + // error if any bad modifier keys + for(const auto &akey : actual) { + if (akey.modifier_state > KM_CORE_MODIFIER_MASK_CAPS) { + equals = false; + std::u16string dump = convert(akey.dump()); // akey.dump() + std::wcout << console_color::fg(console_color::BRIGHT_RED) << "- FAIL - key_map had key with bad modifier " << akey.modifier_state << ": " << dump << console_color::reset() << std::endl; + } + } + // error if any expected keys missing (note expected may be empty) + for(const auto &ekey : expected) { + if (actual.count(ekey) == 0) { + equals = false; + std::u16string dump = convert(ekey.dump()); // akey.dump() + std::wcout << console_color::fg(console_color::BRIGHT_RED) << "- FAIL - key_map had missing key " << dump << console_color::reset() << std::endl; + } + } + if (equals) { + std::wcout << console_color::fg(console_color::GREEN) << " " << actual.size() << " vkeys OK, verified " << expected.size() << console_color::reset() << std::endl; + } + return equals; +} + +/** + * @param actual_list the list from get_key_list() + * @param keylist optional string with keys to check, can be empty + * @param test the LDML test source, for additional data + * @returns true if passing + */ +bool +verify_key_list(const km_core_keyboard_key *actual_list, const std::u16string &expected_list, const km::tests::LdmlTestSource &test) { + std::set actual, expected; + // convert actual list + while (actual_list != nullptr && !(actual_list->key == 0 && actual_list->modifier_flag == 0)) { + km::tests::key_event k(actual_list->key, (uint16_t)actual_list->modifier_flag); + actual.insert(k); + actual_list++; // advance pointer + } + // parse the expected list + std::string keylist = convert(expected_list); + while (!keylist.empty() && keylist[0] == '[') { + const km::tests::key_event k = km::tests::LdmlEmbeddedTestSource::parse_next_key(keylist); + if (!k.empty()) { + expected.emplace(k); + } + } + return verify_key_list(actual, expected); +} + int run_test(const km::core::path &source, const km::core::path &compiled, km::tests::LdmlTestSource& test_source) { km_core_keyboard * test_kb = nullptr; @@ -371,6 +429,17 @@ run_test(const km::core::path &source, const km::core::path &compiled, km::tests errorLine = __LINE__; } } break; + case km::tests::LDML_ACTION_CHECK_KEYLIST: { + std::cout << "- checking keylist" << std::endl; + // get keylist from kbd + const km_core_keyboard_key* actual_list = test_kb->get_key_list(); + if (!verify_key_list(actual_list, action.string, test_source)) { + errorLine = __LINE__; + } else { + std::cout << " .. passes." << std::endl; + } + delete [] actual_list; + } break; case km::tests::LDML_ACTION_FAIL: { // test requested failure std::wcout << console_color::fg(console_color::BRIGHT_RED) << "- FAIL: " << action.string << console_color::reset() @@ -421,7 +490,7 @@ int run_all_tests(const km::core::path &source, const km::core::path &compiled, std::vector failures; // track failures for summary - int embedded_result = embedded_test_source.load_source(source); + int embedded_result = embedded_test_source.load_source(source, compiled); if (!filter.empty()) { // Always skip the embedded test if there's a filter. diff --git a/core/tests/unit/ldml/ldml_test_source.cpp b/core/tests/unit/ldml/ldml_test_source.cpp index 2db7efe6e3..ba724aec03 100644 --- a/core/tests/unit/ldml/ldml_test_source.cpp +++ b/core/tests/unit/ldml/ldml_test_source.cpp @@ -122,6 +122,50 @@ bool LdmlTestSource::get_expected_beep() const { return false; } +int LdmlTestSource::load_kmx_plus(const km::core::path &compiled) { + // check and load the KMX (yes, once again) + rawdata = km::tests::load_kmx_file(compiled); + if(!km::core::ldml_processor::is_handled(rawdata)) { + std::cerr << "Reading KMX for test purposes failed: " << compiled << std::endl; + return __LINE__; + } + + auto comp_keyboard = (const km::core::kmx::COMP_KEYBOARD*)rawdata.data(); + // initialize the kmxplus object with our copy + kmxplus.reset(new km::core::kmx::kmx_plus(comp_keyboard, rawdata.size())); + + if (!kmxplus->is_valid()) { + std::cerr << "kmx_plus invalid" << std::endl; + return __LINE__; + } + + if (!kmxplus->key2Helper.valid()) { + std::cerr << "kmx_plus invalid" << std::endl; + return __LINE__; + } + + return 0; // success +} + +bool LdmlTestSource::get_vkey_table(std::set &fillin) const { + if (!kmxplus || !kmxplus->is_valid()) { + return false; // fail + } + + // just dump the kmap table + for (KMX_DWORD kmapIdx = 0; kmapIdx < kmxplus->key2->kmapCount; kmapIdx++) { + const km::core::kmx::COMP_KMXPLUS_KEYS_KMAP *kmap = kmxplus->key2Helper.getKmap(kmapIdx); + if (kmap == nullptr) { + return false; + } + if (kmap->vkey > 0xFF) { + continue; // synthetic key- skip + } + fillin.insert(key_event(kmap->vkey, kmap->mod)); + } + return true; +} + // String trim functions from https://stackoverflow.com/a/217605/1836776 // trim from start (in place) static inline void @@ -259,12 +303,13 @@ LdmlEmbeddedTestSource::is_token(const std::string token, std::string &line) { } int -LdmlEmbeddedTestSource::load_source( const km::core::path &path ) { +LdmlEmbeddedTestSource::load_source( const km::core::path &path, const km::core::path &compiled ) { const std::string s_keys = "@@keys: "; const std::string s_expected = "@@expected: "; const std::string s_context = "@@context: "; const std::string s_capsLock = "@@capsLock: "; const std::string s_expecterror = "@@expect-error: "; + const std::string s_keylist = "@@keylist: "; // Parse out the header statements in file.kmn that tell us (a) environment, (b) key sequence, (c) start context, (d) expected // result @@ -296,6 +341,10 @@ LdmlEmbeddedTestSource::load_source( const km::core::path &path ) { context = parse_source_string(line); } else if (is_token(s_capsLock, line)) { set_caps_lock_on(parse_source_string(line).compare(u"1") == 0); + } else if (is_token(s_keylist, line)) { + set_keylist(line); + } else if (line[0] == '@') { + std::cerr << path << " warning, unknown @-command " << line << std::endl; } } @@ -311,7 +360,13 @@ LdmlEmbeddedTestSource::load_source( const km::core::path &path ) { return __LINE__; } - return 0; + // and load KMX+ for keylist + if (!expected_error) { + // don't attempt to load KMX+ on expected error + return load_kmx_plus(compiled); + } else { + return 0; + } } km_core_status @@ -352,7 +407,7 @@ LdmlTestSource::char_to_event(char ch) { } uint16_t -LdmlTestSource::get_modifier(std::string const m) { +LdmlTestSource::get_modifier(std::string const &m) { for (int i = 0; km::core::kmx::s_modifier_names[i].name; i++) { if (m == km::core::kmx::s_modifier_names[i].name) { return km::core::kmx::s_modifier_names[i].modifier; @@ -361,6 +416,12 @@ LdmlTestSource::get_modifier(std::string const m) { return 0; } +std::string key_event::dump() const { + std::stringstream f; + f << "Key: {" << km::core::kmx::Debug_VirtualKey(vk) << ", " << km::core::kmx::Debug_ModifierName(modifier_state) << "}"; + return f.str(); +} + key_event LdmlEmbeddedTestSource::vkey_to_event(std::string const &vk_event) { // vkey format is MODIFIER MODIFIER K_NAME @@ -396,34 +457,37 @@ LdmlEmbeddedTestSource::vkey_to_event(std::string const &vk_event) { void LdmlEmbeddedTestSource::next_action(ldml_action &fillin) { - if (is_done || keys.empty()) { - // We were already done. return done. - fillin.type = LDML_ACTION_DONE; - return; + if (keys.empty()) { + // #3 we are almost done, let's run the key check + if (check_keylist) { + fillin.type = LDML_ACTION_CHECK_KEYLIST; + fillin.string = expected_keylist; // could be empty + check_keylist = false; + } else { + fillin.type = LDML_ACTION_DONE; + } } else if(keys[0].empty()) { + // #2. Then, when we finish a key set, we check the 'expected' at the end of it. // Got to the end of a key set. time to check fillin.type = LDML_ACTION_CHECK_EXPECTED; fillin.string = expected[0]; // copy expected expected.pop_front(); keys.pop_front(); - if (keys.empty()) { - is_done = true; // so we get DONE next time - } } else { + // #1 First, we process each key fillin.type = LDML_ACTION_KEY_EVENT; fillin.k = next_key(); } } - key_event LdmlEmbeddedTestSource::next_key() { // mutate this->keys - return next_key(keys[0]); + return parse_next_key(keys[0]); } key_event -LdmlEmbeddedTestSource::next_key(std::string &keys) { +LdmlEmbeddedTestSource::parse_next_key(std::string &keys) { // Parse the next element of the string, chop it off, and return it // mutates keys if (keys.length() == 0) @@ -448,10 +512,10 @@ LdmlEmbeddedTestSource::next_key(std::string &keys) { class LdmlJsonTestSource : public LdmlTestSource { public: - LdmlJsonTestSource(const std::string &path, km::core::kmx::kmx_plus *kmxplus); + LdmlJsonTestSource(const std::string &path); virtual ~LdmlJsonTestSource(); virtual const std::u16string &get_context(); - int load(const nlohmann::json &test); + int load(const nlohmann::json &test, const km::core::path &compiled); virtual void next_action(ldml_action &fillin); private: std::string path; @@ -462,14 +526,14 @@ private: * Which action are we on? */ std::size_t action_index = -1; - const km::core::kmx::kmx_plus *kmxplus; /** @return false if not found */ bool set_key_from_id(key_event& k, const std::u16string& id); bool loaded_context = false; + bool check_keys = true; }; -LdmlJsonTestSource::LdmlJsonTestSource(const std::string &path, km::core::kmx::kmx_plus *k) -:path(path), kmxplus(k) { +LdmlJsonTestSource::LdmlJsonTestSource(const std::string &path) +:path(path) { } @@ -514,6 +578,13 @@ bool LdmlJsonTestSource::set_key_from_id(key_event& k, const std::u16string& id) void LdmlJsonTestSource::next_action(ldml_action &fillin) { if ((action_index+1) >= data["/actions"_json_pointer].size()) { + // add check keylist + if (check_keys) { + fillin.type = LDML_ACTION_CHECK_KEYLIST; + fillin.string.clear(); + check_keys = false; + return; + } // at end, done fillin.type = LDML_ACTION_DONE; return; @@ -581,19 +652,21 @@ LdmlJsonTestSource::get_context() { return context; } -int LdmlJsonTestSource::load(const nlohmann::json &data) { +int LdmlJsonTestSource::load(const nlohmann::json &data, const km::core::path &compiled) { this->data = data; - // TODO-LDML: validate here? - return 0; + // TODO-LDML: validate JSON here? + + // load up the kmx_plus + return load_kmx_plus(compiled); } #if defined(HAVE_ICU4C) class LdmlJsonRepertoireTestSource : public LdmlTestSource { public: - LdmlJsonRepertoireTestSource(const std::string &path, km::core::kmx::kmx_plus *kmxplus); + LdmlJsonRepertoireTestSource(const std::string &path ); virtual ~LdmlJsonRepertoireTestSource(); virtual const std::u16string &get_context(); - int load(const nlohmann::json &test); + int load(const nlohmann::json &test, const km::core::path &compiled); virtual void next_action(ldml_action &fillin); private: std::string path; @@ -605,11 +678,10 @@ private: std::unique_ptr uset; std::unique_ptr iterator; bool need_check = false; // set this after each char - const km::core::kmx::kmx_plus *kmxplus; }; -LdmlJsonRepertoireTestSource::LdmlJsonRepertoireTestSource(const std::string &path, km::core::kmx::kmx_plus *k) -:path(path), kmxplus(k){ +LdmlJsonRepertoireTestSource::LdmlJsonRepertoireTestSource(const std::string &path) +:path(path) { } @@ -697,7 +769,7 @@ LdmlJsonRepertoireTestSource::get_context() { return context; // no context needed } -int LdmlJsonRepertoireTestSource::load(const nlohmann::json &data) { +int LdmlJsonRepertoireTestSource::load(const nlohmann::json &data, const km::core::path &compiled) { this->data = data; // TODO-LDML // Need an update to json.hpp to use contains() // if (data.contains("/type"_json_pointer)) { @@ -728,7 +800,7 @@ int LdmlJsonRepertoireTestSource::load(const nlohmann::json &data) { // } // #endif iterator = std::unique_ptr(new icu::UnicodeSetIterator(*uset)); - return 0; + return load_kmx_plus(compiled); } #endif // HAVE_ICU4C @@ -752,25 +824,6 @@ int LdmlJsonTestSourceFactory::load(const km::core::path &compiled, const km::co return __LINE__; // empty } - // check and load the KMX (yes, once again) - if(!km::core::ldml_processor::is_kmxplus_file(compiled, rawdata)) { - std::cerr << "Reading KMX for test purposes failed: " << compiled << std::endl; - return __LINE__; - } - - auto comp_keyboard = (const km::core::kmx::COMP_KEYBOARD*)rawdata.data(); - // initialize the kmxplus object with our copy - kmxplus.reset(new km::core::kmx::kmx_plus(comp_keyboard, rawdata.size())); - - if (!kmxplus->is_valid()) { - std::cerr << "kmx_plus invalid" << std::endl; - return __LINE__; - } - - if (!kmxplus->key2Helper.valid()) { - std::cerr << "kmx_plus invalid" << std::endl; - return __LINE__; - } auto conformsTo = data["/keyboardTest3/conformsTo"_json_pointer].get(); assert_or_return(std::string(LDML_CLDR_TEST_VERSION_LATEST) == conformsTo); @@ -793,8 +846,8 @@ int LdmlJsonTestSourceFactory::load(const km::core::path &compiled, const km::co test_path.append(info_name).append("/tests/").append(tests_name).append("/").append(test_name); // std::cout << "JSON: reading " << info_name << "/" << test_path << std::endl; - std::unique_ptr subtest(new LdmlJsonTestSource(test_path, kmxplus.get())); - assert_or_return(subtest->load(test) == 0); + std::unique_ptr subtest(new LdmlJsonTestSource(test_path)); + assert_or_return(subtest->load(test, compiled) == 0); test_map[test_path] = std::unique_ptr(subtest.release()); } } @@ -809,8 +862,8 @@ int LdmlJsonTestSourceFactory::load(const km::core::path &compiled, const km::co std::string test_path; test_path.append(info_name).append("/repertoire/").append(rep_name); - std::unique_ptr reptest(new LdmlJsonRepertoireTestSource(test_path, kmxplus.get())); - assert_or_return(reptest->load(rep) == 0); + std::unique_ptr reptest(new LdmlJsonRepertoireTestSource(test_path)); + assert_or_return(reptest->load(rep, compiled) == 0); test_map[test_path] = std::unique_ptr(reptest.release()); } diff --git a/core/tests/unit/ldml/ldml_test_source.hpp b/core/tests/unit/ldml/ldml_test_source.hpp index 4637af9bd4..c8e7061ed6 100644 --- a/core/tests/unit/ldml/ldml_test_source.hpp +++ b/core/tests/unit/ldml/ldml_test_source.hpp @@ -4,6 +4,7 @@ #include "path.hpp" #include +#include #include #include "kmx/kmx_plus.h" @@ -14,6 +15,34 @@ namespace tests { struct key_event { km_core_virtual_key vk; uint16_t modifier_state; + public: + key_event() : vk(0), modifier_state(0) { + } + key_event(km_core_virtual_key k, uint16_t m) :vk(k), modifier_state(m) { + } + std::string dump() const; + int compare(const key_event &other) const { + if (vk < other.vk) return -1; + if (vk > other.vk) return 1; + if (modifier_state < other.modifier_state) return -1; + if (modifier_state > other.modifier_state) return 1; + return 0; + } + + bool operator<(const key_event &other) const { + return compare(other) < 0; + } + bool operator>(const key_event &other) const { + return compare(other) > 0; + } + bool operator==(const key_event &other) const { + return compare(other) == 0; + } + /** true if unset (null) key */ + bool empty() const { + return vk == 0 && modifier_state == 0; + } + }; enum ldml_action_type { @@ -37,6 +66,10 @@ enum ldml_action_type { * expected text */ LDML_ACTION_CHECK_EXPECTED, + /** + * string - keylist to check + */ + LDML_ACTION_CHECK_KEYLIST, // TODO-LDML: gestures, etc? Depends on touch. /** @@ -77,10 +110,17 @@ public: virtual km_core_status get_expected_load_status(); virtual const std::u16string &get_context() = 0; virtual bool get_expected_beep() const; + /** + * fillin a list + * @param fillin key list to be filled in with all vkeys in the hardware map. + * @param modifier modifier to load key list for + * @returns false on load fail, true on OK + */ + bool get_vkey_table(std::set &fillin) const; // helper functions static key_event char_to_event(char ch); - static uint16_t get_modifier(std::string const m); + static uint16_t get_modifier(std::string const &m); static std::u16string parse_source_string(std::string const &s); static std::u16string parse_u8_source_string(std::string const &s); @@ -102,6 +142,12 @@ private: private: bool _caps_lock_on = false; +protected: + /** populate rawdata and kmxplus */ + int load_kmx_plus(const km::core::path &compiled); + // copy of the kbd data, for lookups + std::vector rawdata; + std::unique_ptr kmxplus; }; typedef std::map> JsonTestMap; @@ -120,9 +166,6 @@ class LdmlJsonTestSourceFactory { const JsonTestMap& get_tests() const; private: JsonTestMap test_map; - // copy of the kbd data, for lookups - std::vector rawdata; - std::unique_ptr kmxplus; }; @@ -134,7 +177,7 @@ public: /** * Load the test_source from comments in the .xml source */ - int load_source(const km::core::path &path); + int load_source(const km::core::path &path, const km::core::path &compiled); virtual km_core_status get_expected_load_status(); virtual const std::u16string &get_context(); @@ -143,10 +186,6 @@ public: virtual void next_action(ldml_action &fillin); private: - - bool is_token(const std::string token, std::string &line); - key_event vkey_to_event(std::string const &vk_event); - key_event next_key(std::string &keys); key_event next_key(); std::deque keys; @@ -155,6 +194,24 @@ private: bool expected_beep = false; bool expected_error = false; bool is_done = false; + /** did we check the keylist yet? */ + bool check_keylist = true; + /** set the expected keys in the keylist */ + void set_keylist(std::string const& s) { + expected_keylist = parse_source_string(s); + } + + std::u16string expected_keylist; + + /** returns false on fail and updates the message */ + bool handle_check_keylist(std::string &message) const; + +// utility + static key_event vkey_to_event(std::string const &vk_event); + static bool is_token(const std::string token, std::string &line); + +public: + static key_event parse_next_key(std::string &keys); }; } // namespace tests From 109e81869dd13e3f3853756550790d767e3a84d2 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 9 Dec 2024 18:21:35 +0100 Subject: [PATCH 36/52] fix(linux): update AppStream metadata --- linux/debian/com.keyman.config.appdata.xml | 7 ++++++- linux/debian/com.keyman.ibus_keyman.metainfo.xml | 6 ++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/linux/debian/com.keyman.config.appdata.xml b/linux/debian/com.keyman.config.appdata.xml index 9df49a37dc..e7f7152422 100644 --- a/linux/debian/com.keyman.config.appdata.xml +++ b/linux/debian/com.keyman.config.appdata.xml @@ -5,10 +5,15 @@ MIT MIT Keyman - SIL International + + SIL Global + https://keyman.com/cdn/dev/img/keyman-logo.png Keyman for Linux

Keyman makes it possible for you to type in over 2,000 languages + + mild +

diff --git a/linux/debian/com.keyman.ibus_keyman.metainfo.xml b/linux/debian/com.keyman.ibus_keyman.metainfo.xml index 1f021d2fce..7b109278a1 100644 --- a/linux/debian/com.keyman.ibus_keyman.metainfo.xml +++ b/linux/debian/com.keyman.ibus_keyman.metainfo.xml @@ -2,9 +2,11 @@ com.keyman.ibus_keyman MIT - GPL-2+ + GPL-2.0+ Keyman - SIL International + + SIL Global + https://keyman.com/cdn/dev/img/keyman-logo.png ibus-keyman From a998e29bb5b1a1c06923f5faa44460bd307c1ab2 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 10 Dec 2024 16:36:56 +0100 Subject: [PATCH 37/52] fix(linux): work around Lintian errors We only use a C API, so we can safely ignore all C++ symbols that show up in the symbols file. Those come from std template instantiations. Fixes: #12051 --- linux/debian/libkeymancore1.symbols | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux/debian/libkeymancore1.symbols b/linux/debian/libkeymancore1.symbols index 99a3be74a4..236801261b 100644 --- a/linux/debian/libkeymancore1.symbols +++ b/linux/debian/libkeymancore1.symbols @@ -1,7 +1,8 @@ libkeymancore.so.1 libkeymancore1 #MINVER# * Build-Depends-Package: libkeymancore-dev - (c++|optional)"typeinfo name for std::codecvt_utf8_utf16@Base" 17.0.244 +# We only use a C API, so ignore all C++ symbols in the std namespace that bleed through + (c++|regex|optional)"std::" 17.0.332 km_core_context_clear@Base 17.0.195 km_core_context_get@Base 17.0.195 km_core_context_item_list_size@Base 17.0.195 From e2dc02c54236b03dcaaf041b5bbb3e510e231ad7 Mon Sep 17 00:00:00 2001 From: "Steven R. Loomis" Date: Tue, 10 Dec 2024 09:54:01 -0600 Subject: [PATCH 38/52] =?UTF-8?q?chore(core):=20ldml=20test=20updates=20fo?= =?UTF-8?q?r=2017.x=20=F0=9F=8D=92=20=F0=9F=99=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - reapply 17.x core API from 18.x Fixes: #12298 --- core/tests/unit/ldml/ldml_test_source.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/tests/unit/ldml/ldml_test_source.cpp b/core/tests/unit/ldml/ldml_test_source.cpp index ba724aec03..bc01151056 100644 --- a/core/tests/unit/ldml/ldml_test_source.cpp +++ b/core/tests/unit/ldml/ldml_test_source.cpp @@ -123,9 +123,9 @@ bool LdmlTestSource::get_expected_beep() const { } int LdmlTestSource::load_kmx_plus(const km::core::path &compiled) { - // check and load the KMX (yes, once again) - rawdata = km::tests::load_kmx_file(compiled); - if(!km::core::ldml_processor::is_handled(rawdata)) { + + // check and load the KMX (yes, once again) + if(!km::core::ldml_processor::is_kmxplus_file(compiled, rawdata)) { std::cerr << "Reading KMX for test purposes failed: " << compiled << std::endl; return __LINE__; } From 29298e496af4b3d9171cf72f046e4e3879253d62 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 10 Dec 2024 17:23:43 +0100 Subject: [PATCH 39/52] =?UTF-8?q?fix(linux):=20pushing=20of=20updated=20ch?= =?UTF-8?q?angelog=20branch=20=F0=9F=8D=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the `upload-to-debian.sh` script if the `chore/linux/changelog` branch was created a while back while the base branch moved in the meantime. In this case we have to use `--force` instead of `--force-with-lease` otherwise `git` gets confused. This is save to do since the intention is that we replace the previous commit and we know that there is (should be) only one commit on the `chore/linux/changelog` branch. (cherry picked from commit bbf8acbda9c0d5105888756fdfef1002d99f280f) --- linux/scripts/upload-to-debian.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/scripts/upload-to-debian.sh b/linux/scripts/upload-to-debian.sh index 0d6d3252b8..2d61078945 100755 --- a/linux/scripts/upload-to-debian.sh +++ b/linux/scripts/upload-to-debian.sh @@ -100,7 +100,7 @@ function push_to_github_and_create_pr() { local pr_number if [[ -n "${PUSH}" ]]; then - ${NOOP} git push --force-with-lease origin "${BRANCH}" + ${NOOP} git push --force origin "${BRANCH}" pr_number=$(gh pr list --draft --search "${COMMIT_MSG}" --base "${BASE}" --json number --jq '.[].number') if [[ -n ${pr_number} ]]; then builder_echo "PR #${pr_number} already exists" From 3869580b779ff8663e466d1392fd2ae5187d60a6 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 10 Dec 2024 10:26:28 +0100 Subject: [PATCH 40/52] chore(linux): change SIL International to SIL Global --- linux/Dockerfile | 4 ++-- linux/debian/copyright | 12 ++++++------ linux/ibus-keyman/src/engine.c | 2 +- linux/ibus-keyman/src/engine.h | 2 +- linux/ibus-keyman/src/keyman-service.c | 2 +- linux/ibus-keyman/src/keyman-service.h | 2 +- linux/ibus-keyman/src/keymanutil.c | 2 +- linux/ibus-keyman/src/keymanutil.h | 2 +- linux/ibus-keyman/src/kmpdetails.c | 2 +- linux/ibus-keyman/src/main.c | 2 +- linux/ibus-keyman/src/test/testdata/kmp.json | 2 +- linux/ibus-keyman/src/test/testdata/kmp1.json | 2 +- linux/ibus-keyman/src/test/testdata/kmp2.json | 2 +- linux/ibus-keyman/tests/ibusimcontext.c | 2 +- linux/ibus-keyman/tests/ibusimcontext.h | 2 +- linux/keyman-config/COPYING | 2 +- linux/keyman-config/Makefile | 2 +- linux/keyman-config/buildtools/help2md | 4 ++-- linux/keyman-config/keyman_config/sentry_handling.py | 5 +++++ linux/keyman-config/locale/keyman-config.pot | 2 +- 20 files changed, 31 insertions(+), 26 deletions(-) diff --git a/linux/Dockerfile b/linux/Dockerfile index ea07ec699a..fac302b474 100644 --- a/linux/Dockerfile +++ b/linux/Dockerfile @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2023 SIL International. All rights reserved. +# Copyright (c) 2022-2023 SIL Global. All rights reserved. # # builder image for a linux build # see ../docs/build/linux-ubuntu.md @@ -7,7 +7,7 @@ ARG OS_VERSION=latest ARG OS_PLATFORM=amd64 FROM --platform=${OS_PLATFORM} ubuntu:${OS_VERSION} -LABEL org.opencontainers.image.authors="SIL International." +LABEL org.opencontainers.image.authors="SIL Global." LABEL org.opencontainers.image.url="https://github.com/keymanapp/keyman.git" LABEL org.opencontainers.image.title="Keyman Linux Build Image" diff --git a/linux/debian/copyright b/linux/debian/copyright index ee6603bded..3956e1463d 100644 --- a/linux/debian/copyright +++ b/linux/debian/copyright @@ -4,24 +4,24 @@ Upstream-Contact: Keyman team Source: https://github.com/keymanapp/keyman Files: * -Copyright: 2018-2024 SIL International +Copyright: 2018-2024 SIL Global License: MIT Files: linux/ibus-keyman/* -Copyright: 2004-2024 SIL International +Copyright: 2004-2024 SIL Global License: GPL-2+ Files: linux/ibus-keyman/src/keymanutil.c linux/ibus-keyman/src/keymanutil.h linux/ibus-keyman/src/kmpdetails.c linux/ibus-keyman/src/kmpdetails.h -Copyright: 2009-2024 SIL International +Copyright: 2009-2024 SIL Global License: GPL-2+ or MIT Files: linux/ibus-keyman/src/keyman-service.c linux/ibus-keyman/src/keyman-service.h linux/keyman-config/buildtools/help2md -Copyright: 2018-2024 SIL International +Copyright: 2018-2024 SIL Global License: GPL-3+ Files: linux/ibus-keyman/tests/ibusimcontext.c @@ -31,7 +31,7 @@ Copyright: 2008-2010, Peng Huang 2008-2013, Peng Huang 2008-2021, Red Hat, Inc. 2015-2021, Takao Fujiwara - 2021-2024, SIL International + 2021-2024, SIL Global License: LGPL-2.1+ Files: linux/keyman-config/buildtools/help2man @@ -41,7 +41,7 @@ License: GPL-3+ Files: debian/com.keyman.config.appdata.xml debian/com.keyman.ibus_keyman.metainfo.xml Copyright: 2019 Daniel Glassey - 2022-2024 SIL International + 2022-2024 SIL Global License: MIT License: MIT diff --git a/linux/ibus-keyman/src/engine.c b/linux/ibus-keyman/src/engine.c index edd6db0720..d35f49c7e1 100644 --- a/linux/ibus-keyman/src/engine.c +++ b/linux/ibus-keyman/src/engine.c @@ -3,7 +3,7 @@ /* * Keyman Input Method for IBUS (The Input Bus) * - * Copyright (C) 2009-2023 SIL International + * Copyright (C) 2009-2023 SIL Global * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public diff --git a/linux/ibus-keyman/src/engine.h b/linux/ibus-keyman/src/engine.h index 5aaa6303a7..21a99314fb 100644 --- a/linux/ibus-keyman/src/engine.h +++ b/linux/ibus-keyman/src/engine.h @@ -3,7 +3,7 @@ /* * Keyman Input Method for IBUS (The Input Bus) * - * Copyright (C) 2018 SIL International + * Copyright (C) 2018 SIL Global * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public diff --git a/linux/ibus-keyman/src/keyman-service.c b/linux/ibus-keyman/src/keyman-service.c index b5c4afc75f..fa2bdb702b 100644 --- a/linux/ibus-keyman/src/keyman-service.c +++ b/linux/ibus-keyman/src/keyman-service.c @@ -3,7 +3,7 @@ /* * Keyman Input Method for IBUS (The Input Bus) * - * Copyright (C) 2018-2023 SIL International + * Copyright (C) 2018-2023 SIL Global * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public diff --git a/linux/ibus-keyman/src/keyman-service.h b/linux/ibus-keyman/src/keyman-service.h index 0f7221478a..a989d6b513 100644 --- a/linux/ibus-keyman/src/keyman-service.h +++ b/linux/ibus-keyman/src/keyman-service.h @@ -3,7 +3,7 @@ /* * Keyman Input Method for IBUS (The Input Bus) * - * Copyright (C) 2018-2023 SIL International + * Copyright (C) 2018-2023 SIL Global * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public diff --git a/linux/ibus-keyman/src/keymanutil.c b/linux/ibus-keyman/src/keymanutil.c index 26bfcf1d55..be4c66c56d 100644 --- a/linux/ibus-keyman/src/keymanutil.c +++ b/linux/ibus-keyman/src/keymanutil.c @@ -3,7 +3,7 @@ /* * Keyman Input Method for IBUS (The Input Bus) * - * Copyright (C) 2018 SIL International + * Copyright (C) 2018 SIL Global * * keymanutil is dual licensed under the MIT or GPL licenses as described below. * diff --git a/linux/ibus-keyman/src/keymanutil.h b/linux/ibus-keyman/src/keymanutil.h index 8a3f4506fa..c4a10687f5 100644 --- a/linux/ibus-keyman/src/keymanutil.h +++ b/linux/ibus-keyman/src/keymanutil.h @@ -3,7 +3,7 @@ /* * Keyman Input Method for IBUS (The Input Bus) * - * Copyright (C) 2018-2023 SIL International + * Copyright (C) 2018-2023 SIL Global * * keymanutil is dual licensed under the MIT or GPL licenses as described below. * diff --git a/linux/ibus-keyman/src/kmpdetails.c b/linux/ibus-keyman/src/kmpdetails.c index ba6e26faea..5d98c3bf34 100644 --- a/linux/ibus-keyman/src/kmpdetails.c +++ b/linux/ibus-keyman/src/kmpdetails.c @@ -3,7 +3,7 @@ /* * Keyman Input Method for IBUS (The Input Bus) * - * Copyright (C) 2018 SIL International + * Copyright (C) 2018 SIL Global * * kmpdetails is dual licensed under the MIT or GPL licenses as described below. * diff --git a/linux/ibus-keyman/src/main.c b/linux/ibus-keyman/src/main.c index 477d744d9b..b7da28e97d 100644 --- a/linux/ibus-keyman/src/main.c +++ b/linux/ibus-keyman/src/main.c @@ -3,7 +3,7 @@ /* * Keyman Input Method for IBUS (The Input Bus) * - * Copyright (C) 2018 SIL International + * Copyright (C) 2018 SIL Global * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public diff --git a/linux/ibus-keyman/src/test/testdata/kmp.json b/linux/ibus-keyman/src/test/testdata/kmp.json index d2ee4fa9e1..4320826b2f 100644 --- a/linux/ibus-keyman/src/test/testdata/kmp.json +++ b/linux/ibus-keyman/src/test/testdata/kmp.json @@ -14,7 +14,7 @@ "description": "LIBTRALO" }, "copyright": { - "description": "\u00A9 2008-2018 SIL International" + "description": "\u00A9 2008-2018 SIL Global" }, "author": { "description": "support@keyman.com", diff --git a/linux/ibus-keyman/src/test/testdata/kmp1.json b/linux/ibus-keyman/src/test/testdata/kmp1.json index 5d9954c330..5ca7bd87d0 100644 --- a/linux/ibus-keyman/src/test/testdata/kmp1.json +++ b/linux/ibus-keyman/src/test/testdata/kmp1.json @@ -14,7 +14,7 @@ "description": "LIBTRALO" }, "copyright": { - "description": "\u00A9 2008-2018 SIL International" + "description": "\u00A9 2008-2018 SIL Global" }, "author": { "description": "support@keyman.com", diff --git a/linux/ibus-keyman/src/test/testdata/kmp2.json b/linux/ibus-keyman/src/test/testdata/kmp2.json index 5e889091f7..187f2dbbb6 100644 --- a/linux/ibus-keyman/src/test/testdata/kmp2.json +++ b/linux/ibus-keyman/src/test/testdata/kmp2.json @@ -14,7 +14,7 @@ "description": "LIBTRALO" }, "copyright": { - "description": "\u00A9 2008-2018 SIL International" + "description": "\u00A9 2008-2018 SIL Global" }, "author": { "description": "support@keyman.com", diff --git a/linux/ibus-keyman/tests/ibusimcontext.c b/linux/ibus-keyman/tests/ibusimcontext.c index 8cf389d749..c6d7af1e98 100644 --- a/linux/ibus-keyman/tests/ibusimcontext.c +++ b/linux/ibus-keyman/tests/ibusimcontext.c @@ -4,7 +4,7 @@ * Copyright (C) 2008-2013 Peng Huang * Copyright (C) 2015-2022 Takao Fujiwara * Copyright (C) 2008-2022 Red Hat, Inc. - * Copyright (C) 2021-2022 SIL International + * Copyright (C) 2021-2022 SIL Global * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/linux/ibus-keyman/tests/ibusimcontext.h b/linux/ibus-keyman/tests/ibusimcontext.h index f45b404a26..94e8687bde 100644 --- a/linux/ibus-keyman/tests/ibusimcontext.h +++ b/linux/ibus-keyman/tests/ibusimcontext.h @@ -3,7 +3,7 @@ /* ibus - The Input Bus * Copyright (C) 2008-2010 Peng Huang * Copyright (C) 2008-2010 Red Hat, Inc. - * Copyright (C) 2021-2022 SIL International + * Copyright (C) 2021-2022 SIL Global * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/linux/keyman-config/COPYING b/linux/keyman-config/COPYING index 5260aa6d9e..485c2c057c 100644 --- a/linux/keyman-config/COPYING +++ b/linux/keyman-config/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 2018 SIL International +Copyright (c) 2018 SIL Global Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/linux/keyman-config/Makefile b/linux/keyman-config/Makefile index f057dcad0c..d36bf16a0f 100644 --- a/linux/keyman-config/Makefile +++ b/linux/keyman-config/Makefile @@ -48,7 +48,7 @@ MOFILES := $(POFILES:.po=/LC_MESSAGES/keyman-config.mo) update-template: version xgettext --package-name "keyman" --package-version "$(VERSION)" \ - --msgid-bugs-address "" --copyright-holder "SIL International" \ + --msgid-bugs-address "" --copyright-holder "SIL Global" \ --language=Python --directory=. --output-dir=locale --output=keyman-config.pot \ --add-comments=i18n: --sort-by-file --width=98 \ keyman_config/*.py km-* diff --git a/linux/keyman-config/buildtools/help2md b/linux/keyman-config/buildtools/help2md index 23a3f5b26b..a32685d1de 100755 --- a/linux/keyman-config/buildtools/help2md +++ b/linux/keyman-config/buildtools/help2md @@ -5,7 +5,7 @@ # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, # 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2020, 2021 Free Software # Foundation, Inc. -# Copyright (C) 2021 SIL International +# Copyright (C) 2021 SIL Global # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -76,7 +76,7 @@ my $version_info = enc_user sprintf _(<<'EOT'), $this_program, $this_version; Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2020, 2021 Free Software Foundation, Inc. -Copyright (C) 2021 SIL International +Copyright (C) 2021 SIL Global This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/linux/keyman-config/keyman_config/sentry_handling.py b/linux/keyman-config/keyman_config/sentry_handling.py index 7585f88e43..7d76843a22 100644 --- a/linux/keyman-config/keyman_config/sentry_handling.py +++ b/linux/keyman-config/keyman_config/sentry_handling.py @@ -1,4 +1,9 @@ #!/usr/bin/python3 +''' +Keyman is copyright (C) SIL Global. MIT License. + +Implements the Sentry error handling +''' import getpass import hashlib import importlib diff --git a/linux/keyman-config/locale/keyman-config.pot b/linux/keyman-config/locale/keyman-config.pot index 50b0d4d8ea..ed377151f7 100644 --- a/linux/keyman-config/locale/keyman-config.pot +++ b/linux/keyman-config/locale/keyman-config.pot @@ -1,5 +1,5 @@ # SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR SIL International +# Copyright (C) YEAR SIL Global # This file is distributed under the same license as the keyman package. # FIRST AUTHOR , YEAR. # From d67589dcfacb8f4b8361ec3dc74294496550dc94 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Tue, 10 Dec 2024 16:53:46 +0100 Subject: [PATCH 41/52] chore(linux): update changelog --- linux/debian/changelog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/linux/debian/changelog b/linux/debian/changelog index ddd4d3611d..18629dd4e3 100644 --- a/linux/debian/changelog +++ b/linux/debian/changelog @@ -1,3 +1,11 @@ +keyman (17.0.331-1) UNRELEASED; urgency=medium + + * set environment variable for rendering of downloads dialog (#12617) + * add `keymanFacename` to .ldml file (#12283) + * ignore exceptions trying to install cache (#11885) + + -- Eberhard Beilharz Tue, 10 Dec 2024 16:48:59 +0100 + keyman (17.0.326-1) unstable; urgency=medium * New upstream release From 1fd7406c7d6f28c193bc64f9b26f7882c03b3f6f Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 11 Dec 2024 09:00:06 +0100 Subject: [PATCH 42/52] chore(linux): remove unnecessary line from changelog According to a comment on the latest upload to mentors.debian.org we don't have to add the line "Re-release to Debian", so this change removes this. --- linux/scripts/debian.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/scripts/debian.sh b/linux/scripts/debian.sh index 66cc7ba157..3a896c10b2 100755 --- a/linux/scripts/debian.sh +++ b/linux/scripts/debian.sh @@ -36,7 +36,7 @@ for proj in ${projects}; do EXTRA_ARGS="--distribution ${DIST} --force-distribution" fi # shellcheck disable=SC2086 - dch --newversion "${version}-${DEBREVISION-1}" ${EXTRA_ARGS} "Re-release to Debian" + dch --newversion "${version}-${DEBREVISION-1}" ${EXTRA_ARGS} "" debuild -d -S -sa -Zxz cd "${BASEDIR}" done From ab9cfe1bf3faa8850e5a3c65a4e8e128815cda10 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 11 Dec 2024 09:19:08 +0100 Subject: [PATCH 43/52] chore(linux): update `upload-to-debian.sh` script This copies the `upload-to-debian.sh` script from `master` to the `stable-17.0` branch. --- linux/scripts/upload-to-debian.sh | 37 +++++++++++++++++++------------ 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/linux/scripts/upload-to-debian.sh b/linux/scripts/upload-to-debian.sh index 2d61078945..ead2943983 100755 --- a/linux/scripts/upload-to-debian.sh +++ b/linux/scripts/upload-to-debian.sh @@ -92,21 +92,28 @@ function get_latest_stable_branch_name() { echo "${stable_branch##* }" } +# Push the changelog changes to GitHub and create a PR. Returns the PR# +# in the environment variable PR_NUMBER. function push_to_github_and_create_pr() { - local BRANCH=$1 - local BASE=$2 - local COMMIT_MSG=$3 - local PR_MSG=$4 - local pr_number + local BRANCH=$1 # `chore/linux/changelog` or `chore/linux/cherry-pick/changelog` + local BASE=$2 # stable branch, `beta` or `master` + local PR_TITLE=$3 # `Update debian changelog` + local PR_BODY=$4 # `@keymanapp-test-bot skip` if [[ -n "${PUSH}" ]]; then - ${NOOP} git push --force origin "${BRANCH}" - pr_number=$(gh pr list --draft --search "${COMMIT_MSG}" --base "${BASE}" --json number --jq '.[].number') - if [[ -n ${pr_number} ]]; then - builder_echo "PR #${pr_number} already exists" - else - ${NOOP} gh pr create --draft --base "${BASE}" --title "${PR_MSG}" --body "@keymanapp-test-bot skip" - fi + # Push to origin. We force push to reset the branch the commit we just made. + # There shouldn't be any other commits on ${BRANCH} except the one we want to replace + # (if any). + ${NOOP} git push --force origin "${BRANCH}" + PR_NUMBER=$(gh pr list --draft --search "${PR_TITLE}" --base "${BASE}" --json number --jq '.[].number') + if [[ -n ${PR_NUMBER} ]]; then + builder_echo "PR #${PR_NUMBER} already exists" + else + ${NOOP} gh pr create --draft --base "${BASE}" --title "${PR_TITLE}" --body "${PR_BODY}" + PR_NUMBER=$(gh pr list --draft --search "${PR_TITLE}" --base "${BASE}" --json number --jq '.[].number') + fi + else + PR_NUMBER="" fi } @@ -142,12 +149,14 @@ cp debianpackage/keyman-*/debian/changelog debian/ git add debian/changelog COMMIT_MESSAGE="chore(linux): Update debian changelog" git commit -m "${COMMIT_MESSAGE}" -push_to_github_and_create_pr chore/linux/changelog "${DEPLOY_BRANCH#origin/}" "${COMMIT_MESSAGE}" "${COMMIT_MESSAGE}" +push_to_github_and_create_pr chore/linux/changelog "${DEPLOY_BRANCH#origin/}" "${COMMIT_MESSAGE}" "@keymanapp-test-bot skip" # Create cherry-pick on master branch git checkout -B chore/linux/cherry-pick/changelog origin/master git cherry-pick -x chore/linux/changelog -push_to_github_and_create_pr chore/linux/cherry-pick/changelog master "${COMMIT_MESSAGE}" "${COMMIT_MESSAGE} 🍒" +push_to_github_and_create_pr chore/linux/cherry-pick/changelog master "${COMMIT_MESSAGE} 🍒" \ +"Cherry-pick-of: #${PR_NUMBER} +@keymanapp-test-bot skip" builder_heading "Finishing" git checkout "${CURRENT_BRANCH}" From ed9269ef30da328b3cddfa9130ac2a7eed9e73ab Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Wed, 11 Dec 2024 15:54:09 +0100 Subject: [PATCH 44/52] chore(linux): Update debian changelog --- linux/debian/changelog | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/linux/debian/changelog b/linux/debian/changelog index 18629dd4e3..3a2dae55f3 100644 --- a/linux/debian/changelog +++ b/linux/debian/changelog @@ -1,10 +1,11 @@ -keyman (17.0.331-1) UNRELEASED; urgency=medium +keyman (17.0.332-1) unstable; urgency=medium * set environment variable for rendering of downloads dialog (#12617) * add `keymanFacename` to .ldml file (#12283) * ignore exceptions trying to install cache (#11885) + * New upstream release. - -- Eberhard Beilharz Tue, 10 Dec 2024 16:48:59 +0100 + -- Eberhard Beilharz Wed, 11 Dec 2024 15:53:59 +0100 keyman (17.0.326-1) unstable; urgency=medium From bce5327c8c8f7b811f6fb4f2e56e15542653910a Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Mon, 13 Jan 2025 07:04:03 +0700 Subject: [PATCH 45/52] fix(android): Process hardware keystrokes when OSK is hidden --- .../app/src/main/java/com/keyman/engine/KMKeyboard.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java index ac86b11c28..39e81bac64 100644 --- a/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java +++ b/android/KMEA/app/src/main/java/com/keyman/engine/KMKeyboard.java @@ -31,6 +31,7 @@ import android.content.pm.ApplicationInfo; import android.content.res.Configuration; import android.net.Uri; import android.os.Handler; +import android.os.Looper; import android.util.DisplayMetrics; import android.util.Log; import android.view.GestureDetector; @@ -70,6 +71,10 @@ final class KMKeyboard extends WebView { protected KeyboardType keyboardType = KeyboardType.KEYBOARD_TYPE_UNDEFINED; protected ArrayList javascriptAfterLoad = new ArrayList<>(); + // .getMainLooper() returns the looper associated with the main UI thread. + // https://stackoverflow.com/questions/13974661/runonuithread-vs-looper-getmainlooper-post-in-android + private Handler jsQueuer = new Handler(Looper.getMainLooper()); + private static String currentKeyboard = null; /** @@ -368,7 +373,7 @@ final class KMKeyboard extends WebView { if(this.javascriptAfterLoad.size() > 0) { // Don't call this WebView method on just ANY thread - run it on the main UI thread. // https://stackoverflow.com/a/22611010 - this.postDelayed(new Runnable() { + jsQueuer.postDelayed(new Runnable() { @Override public void run() { StringBuilder allCalls = new StringBuilder(); From a07d6a4b8281c805415faab9e0cfbf5d4ff92939 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 16 Jan 2025 09:14:21 +0700 Subject: [PATCH 46/52] chore: use GitHub PR titles when writing HISTORY.md --- resources/build/increment-version.sh | 6 +++--- resources/build/version/src/fixupHistory.ts | 4 ++-- resources/build/version/src/index.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/build/increment-version.sh b/resources/build/increment-version.sh index 1a577b480f..da459776eb 100755 --- a/resources/build/increment-version.sh +++ b/resources/build/increment-version.sh @@ -104,9 +104,9 @@ echo "increment-version.sh: running resources/build/version" pushd "$KEYMAN_ROOT" ABORT=0 if [[ -z "$fromversion" ]]; then - node resources/build/version/build/src/index.js history version -t "$GITHUB_TOKEN" -b "$base" $HISTORY_FORCE || ABORT=$? + node resources/build/version/build/src/index.js history version -t "$GITHUB_TOKEN" -b "$base" $HISTORY_FORCE --github-pr || ABORT=$? else - node resources/build/version/build/src/index.js history version -t "$GITHUB_TOKEN" -b "$base" $HISTORY_FORCE --from "$fromversion" --to "$toversion" || ABORT=$? + node resources/build/version/build/src/index.js history version -t "$GITHUB_TOKEN" -b "$base" $HISTORY_FORCE --github-pr --from "$fromversion" --to "$toversion" || ABORT=$? fi if [[ $ABORT = 50 ]]; then @@ -179,7 +179,7 @@ if [ "$action" == "commit" ]; then # In order to avoid potential git conflicts, we run the history collater # again on the master HISTORY.md. Note that the script always exits 1 to # indicate it hasn't updated VERSION.md. We could tweak that in the future. - node resources/build/version/lib/index.js history --no-write-github-comment -t "$GITHUB_TOKEN" -b "$base" || true + node resources/build/version/lib/index.js history --no-write-github-comment --github-pr -t "$GITHUB_TOKEN" -b "$base" || true # If HISTORY.md has been updated, then we want to create a branch and push # it for review diff --git a/resources/build/version/src/fixupHistory.ts b/resources/build/version/src/fixupHistory.ts index 2183b11f70..a8ceda3c50 100644 --- a/resources/build/version/src/fixupHistory.ts +++ b/resources/build/version/src/fixupHistory.ts @@ -184,7 +184,7 @@ export const sendCommentToPullRequestAndRelatedIssues = async ( */ export const fixupHistory = async ( - octokit: GitHub, base: string, force: boolean, writeGithubComment: boolean, from?: string, to?: string + octokit: GitHub, base: string, force: boolean, writeGithubComment: boolean, useGitHubPRInfo: boolean, from?: string, to?: string ): Promise => { // @@ -194,7 +194,7 @@ export const fixupHistory = async ( let pulls: PRInformation[] = []; try { - pulls = await reportHistory(octokit, base, force, false, from, to); + pulls = await reportHistory(octokit, base, force, useGitHubPRInfo, from, to); } catch(e) { logWarning(String(e)); return -1; diff --git a/resources/build/version/src/index.ts b/resources/build/version/src/index.ts index 16f1583e39..ea0b12e7e7 100644 --- a/resources/build/version/src/index.ts +++ b/resources/build/version/src/index.ts @@ -108,7 +108,7 @@ const main = async (): Promise => { if(argv._.includes('history')) { logInfo(`# Validating history for ${version}`); - changeCount = await fixupHistory(octokit, argv.base, argv.force, argv['write-github-comment'], argv.from, argv.to); + changeCount = await fixupHistory(octokit, argv.base, argv.force, argv['write-github-comment'], argv['github-pr'], argv.from, argv.to); logInfo(`# ${changeCount} change(s) found for ${version}\n`); } From 1e2ad40c19c43d4a00a530edeaf14ff04ba011b2 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 16 Jan 2025 11:04:22 +0700 Subject: [PATCH 47/52] fix(developer): filter incorrect fonts out of .keyboard_info The font collection code was somewhat wrong in kmc-keyboard-info. It collected all fonts referenced in the package, even for multi-keyboard packages, which meant that the .keyboard_info file listed all fonts for all languages. Furthermore, if a font was referenced in multiple language entries in the .kps, then it would be repeated for each language in the .keyboard_info. This patch addresses both of these bugs. The good news is that this makes some of the .keyboard_info files smaller. In particular, fv_all.keyboard_info goes from 4675 lines down to 695 lines! Fixes: #12852 Cherry-pick-of: #12909 --- .../src/keyboard-info-compiler.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts index ed704c6e8c..3605b81f8d 100644 --- a/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts +++ b/developer/src/kmc-keyboard-info/src/keyboard-info-compiler.ts @@ -493,9 +493,6 @@ export class KeyboardInfoCompiler implements KeymanCompiler { keyboard_info.languages[language] = {}; } - const fontSource = [].concat(...kmpJsonData.keyboards.map(e => e.displayFont ? [e.displayFont] : []), ...kmpJsonData.keyboards.map(e => e.webDisplayFonts ?? [])); - const oskFontSource = [].concat(...kmpJsonData.keyboards.map(e => e.oskFont ? [e.oskFont] : []), ...kmpJsonData.keyboards.map(e => e.webOskFonts ?? [])); - for(const bcp47 of Object.keys(keyboard_info.languages)) { const language = keyboard_info.languages[bcp47]; @@ -520,6 +517,20 @@ export class KeyboardInfoCompiler implements KeymanCompiler { // do it right now. // + // The code below: + // 1. Only includes fonts associated with keyboards which support the current bcp47 (filter) + // 2. Joins the displayFont and webDisplayFonts data, and removes duplicates (...new Set()) + + const supportedKeyboards = kmpJsonData.keyboards.filter(k => k.languages.find(lang => lang.id == bcp47)); + const fontSource = [...new Set([].concat( + ...supportedKeyboards.map(e => e.displayFont ? [e.displayFont] : []), + ...supportedKeyboards.map(e => e.webDisplayFonts ?? []) + ))]; + const oskFontSource = [...new Set([].concat( + ...supportedKeyboards.map(e => e.oskFont ? [e.oskFont] : []), + ...supportedKeyboards.map(e => e.webOskFonts ?? []) + ))]; + if(fontSource.length) { language.font = await this.fontSourceToKeyboardInfoFont(kpsFilename, kmpJsonData, fontSource); if(language.font == null) { From f45a1899cb3dd251456392881f3521a46e7ea4b4 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Thu, 16 Jan 2025 04:05:07 -0500 Subject: [PATCH 48/52] auto: increment stable-17.0 version to 17.0.334 --- HISTORY.md | 11 +++++++++++ VERSION.md | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 061ac40119..fefc4911e7 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,16 @@ # Keyman Version History +## 17.0.333 stable 2025-01-16 + +* fix(core): permanently disable logging (#12674) +* fix(linux): pushing of updated changelog branch (#12819) +* fix(linux): work around Lintian errors (#12817) +* fix(core): implement ldml_processor::get_key_list() (#12816) +* chore(linux): Update debian changelog (#12022) +* fix(android): use main looper to dispatch key events when OSK is hidden (#12875) +* chore: use GitHub PR titles when writing HISTORY.md (#12908) +* fix(developer): filter incorrect fonts out of .keyboard_info (#12913) + ## 17.0.332 stable 2024-11-06 * fix(developer): create Server config directory before options save (#12609) diff --git a/VERSION.md b/VERSION.md index 794e84bf25..19627ad9a5 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -17.0.333 \ No newline at end of file +17.0.334 \ No newline at end of file From fdafd5879ec926b1f71a768f61fe17e71749602b Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 16 Jan 2025 16:29:53 +0100 Subject: [PATCH 49/52] chore(linux): Update debian changelog --- linux/debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/debian/changelog b/linux/debian/changelog index 3a2dae55f3..22fd40caad 100644 --- a/linux/debian/changelog +++ b/linux/debian/changelog @@ -1,3 +1,9 @@ +keyman (17.0.333-1) unstable; urgency=medium + + * New upstream release. + + -- Eberhard Beilharz Thu, 16 Jan 2025 16:29:44 +0100 + keyman (17.0.332-1) unstable; urgency=medium * set environment variable for rendering of downloads dialog (#12617) From 4baf10bde0e1021993d725eef2939a97eb2edc16 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 16 Jan 2025 16:46:12 +0100 Subject: [PATCH 50/52] =?UTF-8?q?chore(linux):=20update=20copyright=20year?= =?UTF-8?q?=20=F0=9F=8D=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick-of: #12918 --- linux/debian/copyright | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linux/debian/copyright b/linux/debian/copyright index 3956e1463d..46f156e19b 100644 --- a/linux/debian/copyright +++ b/linux/debian/copyright @@ -4,24 +4,24 @@ Upstream-Contact: Keyman team Source: https://github.com/keymanapp/keyman Files: * -Copyright: 2018-2024 SIL Global +Copyright: 2018-2025 SIL Global License: MIT Files: linux/ibus-keyman/* -Copyright: 2004-2024 SIL Global +Copyright: 2004-2025 SIL Global License: GPL-2+ Files: linux/ibus-keyman/src/keymanutil.c linux/ibus-keyman/src/keymanutil.h linux/ibus-keyman/src/kmpdetails.c linux/ibus-keyman/src/kmpdetails.h -Copyright: 2009-2024 SIL Global +Copyright: 2009-2025 SIL Global License: GPL-2+ or MIT Files: linux/ibus-keyman/src/keyman-service.c linux/ibus-keyman/src/keyman-service.h linux/keyman-config/buildtools/help2md -Copyright: 2018-2024 SIL Global +Copyright: 2018-2025 SIL Global License: GPL-3+ Files: linux/ibus-keyman/tests/ibusimcontext.c @@ -31,7 +31,7 @@ Copyright: 2008-2010, Peng Huang 2008-2013, Peng Huang 2008-2021, Red Hat, Inc. 2015-2021, Takao Fujiwara - 2021-2024, SIL Global + 2021-2025, SIL Global License: LGPL-2.1+ Files: linux/keyman-config/buildtools/help2man @@ -41,7 +41,7 @@ License: GPL-3+ Files: debian/com.keyman.config.appdata.xml debian/com.keyman.ibus_keyman.metainfo.xml Copyright: 2019 Daniel Glassey - 2022-2024 SIL Global + 2022-2025 SIL Global License: MIT License: MIT From 4124900b1146a313ec53c509f6d877d3a720d5a5 Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 23 Jan 2025 09:25:56 +0700 Subject: [PATCH 51/52] fix(android): Remove READ_MEDIA_IMAGES and READ_MEDIA_VIDEO permissions --- android/KMAPro/kMAPro/src/main/AndroidManifest.xml | 4 ---- .../main/java/com/tavultesoft/kmapro/CheckPermissions.java | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml index 7196abdb22..d4028e8a70 100644 --- a/android/KMAPro/kMAPro/src/main/AndroidManifest.xml +++ b/android/KMAPro/kMAPro/src/main/AndroidManifest.xml @@ -7,10 +7,6 @@ - - - - diff --git a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/CheckPermissions.java b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/CheckPermissions.java index 888d430b0b..431d97e353 100644 --- a/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/CheckPermissions.java +++ b/android/KMAPro/kMAPro/src/main/java/com/tavultesoft/kmapro/CheckPermissions.java @@ -35,8 +35,8 @@ public class CheckPermissions { checkPermission(activity, Manifest.permission.READ_EXTERNAL_STORAGE); } else { // API 33+ - //https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions - // Manifest.permission.READ_MEDIA_AUDIO doesn't seem to be needed + // We had to remove these MEDIA permissions from AndroidManifest.xml so these will end up failing + // https://support.google.com/googleplay/android-developer/answer/14115180?hl=en permissionsOK = permissionsOK && checkPermission(activity, Manifest.permission.READ_MEDIA_IMAGES); permissionsOK = permissionsOK && checkPermission(activity, Manifest.permission.READ_MEDIA_VIDEO); } From 6651ca3c448f86ec2c220905a89b67cdacb0a18d Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Thu, 23 Jan 2025 09:36:21 +0700 Subject: [PATCH 52/52] docs(android): Update storage permission help Reference: https://support.google.com/googleplay/android-developer/answer/14115180?hl=en --- .../help/troubleshooting/grant-storage-permission.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/android/help/troubleshooting/grant-storage-permission.md b/android/help/troubleshooting/grant-storage-permission.md index 1b8554d7f0..7b47cdf4ea 100644 --- a/android/help/troubleshooting/grant-storage-permission.md +++ b/android/help/troubleshooting/grant-storage-permission.md @@ -19,13 +19,7 @@ permission to access storage / "file and media". The screenshot below is from An ### Android 13.0+ Devices -Step 1) -Go to Android Settings. +Due to Google Play Store's "Photo and Video Permissions policy", +Keyman for Android must use a system picker to browse for .kmp files from within the Keyman app. -Step 2) -Depending on your device, click "Apps" and grant Keyman permission to the following: - * Photos and videos --> Always allow all - -The screenshot below is from Android 14.0. - -![](../android_images/keyman-storage-permission-34b.png) +Follow the steps in [Installing Custom Keyboards/Dictionaries](../basic/installing-custom-packages).