diff --git a/.editorconfig b/.editorconfig index a17a535817..99552fac20 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,7 +9,7 @@ insert_final_newline = true trim_trailing_whitespace = true [*.md] -max_line_length = off +max_line_length = 160 [{Makefile,rules}] indent_style = tab diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7354c987f5..15924ad455 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -115,7 +115,8 @@ Include details about your configuration and environment: This section guides you through submitting an enhancement suggestion for Keyman, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion :pencil: and find related suggestions :mag_right:. -Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](https://github.com/keymanapp/keyman/issues/new?assignees=&labels=feat&template=feature_request.md&title=feat%3A+), including the steps that you imagine you would take if the feature you're requesting existed. +Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). +Fill in [the template](https://github.com/keymanapp/keyman/issues/new?assignees=&labels=feat&template=feature_request.md&title=feat%3A+), including the steps that you imagine you would take if the feature you're requesting existed. #### Before Submitting An Enhancement Suggestion diff --git a/HISTORY.md b/HISTORY.md index 0a5860a7e1..df57d7815d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,36 @@ # Keyman Version History +## 15.0.215 beta 2022-03-17 + +* fix(web): crash on focus before init (#6393) + +## 15.0.214 beta 2022-03-16 + +* feat(web): `&newLayer` and `&oldLayer` (#6366) + +## 15.0.213 beta 2022-03-15 + +* feat(common): zip and index keyboard artifacts (#6367) +* fix(android/engine): Activate menu on globe longpress before release (#6356) +* fix(web): subkey touch position after scroll (#6340) +* fix(developer): warn on ncaps usage inconsistency (#6347) +* fix(web): caps state tracking for touch (#6351) +* chore(windows): Update license date (#6374) +* chore(android): Separate CI step to generate Play Store notes (#6375) +* chore(linux): Update changelog and copyright (#6372) +* fix(oem/fv/android): Consolidate dictionary and keyboard settings (#6369) +* fix(linux): Don't start ibus-daemon multiple times (#6283) + +## 15.0.212 beta 2022-03-11 + +* chore(linux): Fix lintian warnings (#6360) +* fix(common): allow custom keyboard builds (#6358) + +## 15.0.211 beta 2022-03-10 + +* fix(oem/fv/android): Check keyboard exists before registering a model (#6346) +* chore(common): cleanup sh global color variables (#6353) + ## 15.0.210 beta 2022-03-10 * feat(common): build test keyboards via script (#6352) diff --git a/LICENSE.md b/LICENSE.md index 24c907d61f..e031c6cc13 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ # License -Copyright (c) 2017-2021 SIL International. All rights reserved. +Copyright (c) 2017-2022 SIL International. All rights reserved. Licensed under the MIT License. @@ -10,7 +10,7 @@ Licensed under the MIT License. The MIT License -Copyright (c) 2017-2021 SIL International +Copyright (c) 2017-2022 SIL International Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/VERSION.md b/VERSION.md index d7162a38bf..8b01078ed3 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -15.0.211 \ No newline at end of file +15.0.216 \ No newline at end of file diff --git a/android/KMAPro/build-play-store-notes.sh b/android/KMAPro/build-play-store-notes.sh new file mode 100755 index 0000000000..6ca9ca0e4b --- /dev/null +++ b/android/KMAPro/build-play-store-notes.sh @@ -0,0 +1,48 @@ +# Set sensible script defaults: +# set -e: Terminate script if a command returns an error +set -e +# set -u: Terminate script if an unset variable is used +set -u + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../resources/build/build-utils.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +QUIET=0 + +. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" + +THIS_DIR="$(dirname "$THIS_SCRIPT")" + +# +# Copy release notes for Gradle Play Publisher to upload +# Reference: https://github.com/Triple-T/gradle-play-publisher#uploading-release-notes +# +PLAY_RELEASE_NOTES="$KEYMAN_ROOT/android/KMAPro/kMAPro/src/main/play/release-notes/en-US/$TIER.txt" +if [ $TIER = "stable" ]; then + PLAY_RELEASE_NOTES="$KEYMAN_ROOT/android/KMAPro/kMAPro/src/main/play/release-notes/en-US/default.txt" +fi +echo "Generating Play Store release notes to $PLAY_RELEASE_NOTES" +echo "" > "$PLAY_RELEASE_NOTES" + +# Copy whatsnew.md to release notes 1 line at a time, +# filtering for lines that start with "*". +# Play Store release notes have a limit of 500 characters +FILTERED_LINES=`grep '^\s*\*.*$' "$KEYMAN_ROOT/android/help/about/whatsnew.md"` +IFS=$'\n' # Change IFS to new line +for line in $FILTERED_LINES +do + CHARS_IN_RELEASE_NOTES=$( wc -m < $PLAY_RELEASE_NOTES ) + CHARS_IN_CURRENT_LINE=$( wc -m <<< $line ) + if (( CHARS_IN_RELEASE_NOTES + CHARS_IN_CURRENT_LINE + 1 < 450 )); then + # Copy line to Play Store release notes + echo "$line" >> $PLAY_RELEASE_NOTES + else + # 450 chars reached + warn "Warning: Play Store release notes approaching 500 character limit" + echo '* Additional bug fixes and improvements' >> $PLAY_RELEASE_NOTES + break + fi +done 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 d18075ce42..1ae612a93a 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 @@ -105,6 +105,13 @@ public class PackageActivity extends AppCompatActivity implements return; } + // Check minimum keyboard version to ensure current version of Keyman supports the features + String pkgMinimumKeyboardVersion = kmpProcessor.getPackageMinimumKeyboardVersion(pkgInfo); + if (FileUtils.compareVersions(pkgMinimumKeyboardVersion, KMManager.getMajorVersion()) == FileUtils.VERSION_GREATER) { + showErrorToast(context, getString(R.string.minimum_keyboard_version_not_supported)); + return; + } + pkgName = kmpProcessor.getPackageName(pkgInfo); final int keyboardCount = kmpProcessor.getKeyboardCount(pkgInfo); diff --git a/android/KMAPro/kMAPro/src/main/res/values/strings.xml b/android/KMAPro/kMAPro/src/main/res/values/strings.xml index 8dda950bd0..e248b971ab 100644 --- a/android/KMAPro/kMAPro/src/main/res/values/strings.xml +++ b/android/KMAPro/kMAPro/src/main/res/values/strings.xml @@ -241,4 +241,7 @@ Invalid/Missing metadata in package + + + Keyboard requires a newer version of Keyman diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboard.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboard.java index d40da0d67c..f5cf3f5137 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboard.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMKeyboard.java @@ -190,6 +190,7 @@ final class KMKeyboard extends WebView { return; } else if (KMManager.getGlobeKeyState() == KMManager.GlobeKeyState.GLOBE_KEY_STATE_DOWN) { KMManager.setGlobeKeyState(KMManager.GlobeKeyState.GLOBE_KEY_STATE_LONGPRESS); + KMManager.handleGlobeKeyAction(context, true, keyboardType); return; /* For future implementation else if(suggestionJSON != null) { diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java index 963c74d9a7..d27860ed57 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/KMManager.java @@ -1325,7 +1325,17 @@ public final class KMManager { return true; } - public static boolean setBannerOptions(boolean mayPredict) { + /** + * deleteLexicalModel - Remove lexical model from the installed list + * and deregister the model with KMW + * @param context + * @param position - int position in the models list + */ + public static void deleteLexicalModel(Context context, int position, boolean silenceNotification) { + KeyboardPickerActivity.deleteLexicalModel(context, position, silenceNotification); + } + + public static boolean setBannerOptions(boolean mayPredict) { String url = KMString.format("setBannerOptions(%s)", mayPredict); if (InAppKeyboard != null) { InAppKeyboard.loadJavascript(url); @@ -2099,21 +2109,30 @@ public final class KMManager { globeKeyState = state; } + /** + * Return if the lock screen is locked (prevents keyboard picker menu from being displayed) + * @return boolean + */ + private static boolean isLocked() { + KeyguardManager keyguardManager = (KeyguardManager) appContext.getSystemService(Context.KEYGUARD_SERVICE); + // inKeyguardRestrictedInputMode() deprecated, so check isKeyguardLocked() to determine if screen is locked + return keyguardManager.isKeyguardLocked(); + } + /** * Handle the globe key action * @param globeKeyDown boolean if the globe key state is GLOBE_KEY_STATE_DOWN * @param keyboardType KeyboardType KEYBOARD_TYPE_INAPP or KEYBOARD_TYPE_SYSTEM */ - private static void handleGlobeKeyAction(Context context, boolean globeKeyDown, KeyboardType keyboardType) { + public static void handleGlobeKeyAction(Context context, boolean globeKeyDown, KeyboardType keyboardType) { // Update globeKeyState if (globeKeyState != GlobeKeyState.GLOBE_KEY_STATE_LONGPRESS) { globeKeyState = globeKeyDown ? GlobeKeyState.GLOBE_KEY_STATE_DOWN : GlobeKeyState.GLOBE_KEY_STATE_UP; } if (KMManager.shouldAllowSetKeyboard()) { - KeyguardManager keyguardManager = (KeyguardManager) appContext.getSystemService(Context.KEYGUARD_SERVICE); // inKeyguardRestrictedInputMode() deprecated, so check isKeyguardLocked() to determine if screen is locked - if (keyguardManager.isKeyguardLocked()) { + if (isLocked()) { if (keyboardType == KeyboardType.KEYBOARD_TYPE_SYSTEM && globeKeyState == GlobeKeyState.GLOBE_KEY_STATE_UP) { doGlobeKeyLockscreenAction(context); } diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelPickerActivity.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelPickerActivity.java index 819c2b71a0..b43e403190 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelPickerActivity.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/ModelPickerActivity.java @@ -275,7 +275,7 @@ public final class ModelPickerActivity extends BaseActivity { // Uses the repo dataset's master lexical model list to create a filtered adapter for use here. // As this one is specific to this class, we can implement Activity-specific functionality within it. - static private class FilteredLexicalModelAdapter extends NestedAdapter { + static public class FilteredLexicalModelAdapter extends NestedAdapter { static final int RESOURCE = R.layout.models_list_row_layout; private final Context context; diff --git a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java index b4b935fac2..9a06a1255f 100644 --- a/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java +++ b/android/KMEA/app/src/main/java/com/tavultesoft/kmea/packages/PackageProcessor.java @@ -394,6 +394,22 @@ public class PackageProcessor { } } + /** + * Parse a kmp.json JSON object and return the package's minimum keyboard version (system.fileVersion). + * This is to avoid issues with app crashing if keyboard functionality is not supported. + * If undefined, return default version "7.0". + * @param json kmp.json as a JSON object. + * @return String of the package's minimum keyboard version + */ + public static String getPackageMinimumKeyboardVersion(JSONObject json) { + try { + return json.getJSONObject("system").getString("fileVersion"); + } catch (Exception e) { + KMLog.LogException(TAG, "", e); + return "7.0"; + } + } + /** * Parse a kmp.json JSON object and return the package's target (keyboards vs lexical models). * Only one can be valid. Otherwise, return "invalid" diff --git a/android/KMEA/app/src/main/res/values/strings.xml b/android/KMEA/app/src/main/res/values/strings.xml index 2b59b03306..27ef7195f0 100644 --- a/android/KMEA/app/src/main/res/values/strings.xml +++ b/android/KMEA/app/src/main/res/values/strings.xml @@ -97,7 +97,6 @@ Updates available for dictionary %1$s: %2$s - Keyboard version @@ -133,6 +132,9 @@ Checking for associated dictionary to download + + Cannot connect to Keyman server to check for associated dictionary to download + Would you like to download the latest version of this dictionary? @@ -210,10 +212,14 @@ Dictionary + + Dictionary + Dictionaries + Check for available dictionary - + Check for dictionaries online Dictionary: %1$s diff --git a/android/build-help.sh b/android/build-help.sh index 2053c5fdcc..0b47159633 100755 --- a/android/build-help.sh +++ b/android/build-help.sh @@ -107,34 +107,3 @@ if $DO_HTM; then cp android_images/* "$DESTHTM/android_images/" fi - -# -# Copy release notes for Gradle Play Publisher to upload -# Reference: https://github.com/Triple-T/gradle-play-publisher#uploading-release-notes -# -PLAY_RELEASE_NOTES="$KEYMAN_ROOT/android/KMAPro/kMAPro/src/main/play/release-notes/en-US/$TIER.txt" -if [ $TIER = "stable" ]; then - PLAY_RELEASE_NOTES="$KEYMAN_ROOT/android/KMAPro/kMAPro/src/main/play/release-notes/en-US/default.txt" -fi -echo "Generating Play Store release notes to $PLAY_RELEASE_NOTES" -echo "" > "$PLAY_RELEASE_NOTES" - -# Copy whatsnew.md to release notes 1 line at a time, -# filtering for lines that start with "*". -# Play Store release notes have a limit of 500 characters -FILTERED_LINES=`grep '^\s*\*.*$' "$KEYMAN_ROOT/android/help/about/whatsnew.md"` -IFS=$'\n' # Change IFS to new line -for line in $FILTERED_LINES -do - CHARS_IN_RELEASE_NOTES=$( wc -m < $PLAY_RELEASE_NOTES ) - CHARS_IN_CURRENT_LINE=$( wc -m <<< $line ) - if (( CHARS_IN_RELEASE_NOTES + CHARS_IN_CURRENT_LINE + 1 < 450 )); then - # Copy line to Play Store release notes - echo "$line" >> $PLAY_RELEASE_NOTES - else - # 450 chars reached - warn "Warning: Play Store release notes approaching 500 character limit" - echo '* Additional bug fixes and improvements' >> $PLAY_RELEASE_NOTES - break - fi -done diff --git a/android/build-publish.sh b/android/build-publish.sh old mode 100644 new mode 100755 index 53dcd3a334..3cce36b910 --- a/android/build-publish.sh +++ b/android/build-publish.sh @@ -75,6 +75,9 @@ echo "BUILD_FLAGS $BUILD_FLAGS" # Publish Keyman for Android if [ "$DO_KMAPRO" = true ]; then cd "$KEYMAN_ROOT/android/KMAPro/" + # Copy Release Notes + ./build-play-store-notes.sh + ./gradlew $DAEMON_FLAG $BUILD_FLAGS fi diff --git a/android/help/about/whatsnew.md b/android/help/about/whatsnew.md index 17331a0c77..9fe22293e9 100644 --- a/android/help/about/whatsnew.md +++ b/android/help/about/whatsnew.md @@ -15,6 +15,6 @@ Here are some of the new features we have added to Keyman 15.0 for Android: | System | 1 | Quickly switch to previous system keyboard | | System | 2+ | Quickly switch to next Keyman keyboard | - * Long press and release the globe key to bring up the keyboard picker menu. On a Keyman system keyboard, the bottom of this menu will also display other enabled system keyboards that can be selected. + * Long press the globe key to bring up the keyboard picker menu. On a Keyman system keyboard, the bottom of this menu will also display other enabled system keyboards that can be selected. Note: On the lock screen, the keyboard picker menu is not displayed. diff --git a/common/core/web/input-processor/package-lock.json b/common/core/web/input-processor/package-lock.json index 0823023b26..53ee499c90 100644 --- a/common/core/web/input-processor/package-lock.json +++ b/common/core/web/input-processor/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/input-processor", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/common/core/web/input-processor/package.json b/common/core/web/input-processor/package.json index f8bfed33d2..d75de9055b 100644 --- a/common/core/web/input-processor/package.json +++ b/common/core/web/input-processor/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/input-processor", - "version": "15.0.211", + "version": "15.0.216", "description": "The core text and prediction processing engine for KeymanWeb", "repository": { "type": "git", @@ -18,8 +18,8 @@ }, "homepage": "https://github.com/keymanapp/keyman#readme", "devDependencies": { - "@keymanapp/lexical-model-compiler": "^15.0.211", - "@keymanapp/resources-gosh": "^15.0.211", + "@keymanapp/lexical-model-compiler": "^15.0.216", + "@keymanapp/resources-gosh": "^15.0.216", "@types/node": "^11.9.4", "chai": "^4.3.4", "mocha": "^8.4.0", @@ -34,11 +34,11 @@ "mocha": "mocha" }, "dependencies": { - "@keymanapp/keyboard-processor": "^15.0.211", - "@keymanapp/lexical-model-layer": "^15.0.211", - "@keymanapp/models-types": "^15.0.211", - "@keymanapp/web-environment": "^15.0.211", - "@keymanapp/web-utils": "^15.0.211", + "@keymanapp/keyboard-processor": "^15.0.216", + "@keymanapp/lexical-model-layer": "^15.0.216", + "@keymanapp/models-types": "^15.0.216", + "@keymanapp/web-environment": "^15.0.216", + "@keymanapp/web-utils": "^15.0.216", "eventemitter3": "^4.0.0" } } diff --git a/common/core/web/input-processor/test.sh b/common/core/web/input-processor/test.sh index d24fb3df27..a3c46c65cf 100755 --- a/common/core/web/input-processor/test.sh +++ b/common/core/web/input-processor/test.sh @@ -54,7 +54,7 @@ if [ $FETCH_DEPS = true ]; then fi # Ensures that the lexical model compiler has been built locally. -echo "${TERM_HEADING}Preparing Lexical Model Compiler for test use${NORMAL}" +echo_heading "Preparing Lexical Model Compiler for test use" pushd $WORKING_DIRECTORY/node_modules/@keymanapp/lexical-model-compiler npm run build popd @@ -75,5 +75,5 @@ if [ $FETCH_DEPS = true ]; then fi # Now we run our local tests. -echo "${TERM_HEADING}Running Input Processor test suite${NORMAL}" +echo_heading "Running Input Processor test suite" test-headless || fail "Input Processor tests failed!" diff --git a/common/core/web/keyboard-processor/package-lock.json b/common/core/web/keyboard-processor/package-lock.json index fd7533149c..fe44fb7853 100644 --- a/common/core/web/keyboard-processor/package-lock.json +++ b/common/core/web/keyboard-processor/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/keyboard-processor", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/common/core/web/keyboard-processor/package.json b/common/core/web/keyboard-processor/package.json index d5b462478e..347f838f6b 100644 --- a/common/core/web/keyboard-processor/package.json +++ b/common/core/web/keyboard-processor/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/keyboard-processor", - "version": "15.0.211", + "version": "15.0.216", "description": "Core module for Keyman keyboard support in KeymanWeb.", "repository": { "type": "git", @@ -18,7 +18,7 @@ }, "homepage": "https://github.com/keymanapp/keyman#readme", "devDependencies": { - "@keymanapp/resources-gosh": "^15.0.211", + "@keymanapp/resources-gosh": "^15.0.216", "chai": "^4.3.4", "mocha": "^8.4.0", "mocha-teamcity-reporter": "^4.0.0", @@ -32,9 +32,9 @@ "mocha": "mocha" }, "dependencies": { - "@keymanapp/models-types": "^15.0.211", - "@keymanapp/web-environment": "^15.0.211", - "@keymanapp/web-utils": "^15.0.211", + "@keymanapp/models-types": "^15.0.216", + "@keymanapp/web-environment": "^15.0.216", + "@keymanapp/web-utils": "^15.0.216", "@types/node": "^11.9.4" } } diff --git a/common/core/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/core/web/keyboard-processor/src/text/keyboardProcessor.ts index f36bbb6124..75439369bc 100644 --- a/common/core/web/keyboard-processor/src/text/keyboardProcessor.ts +++ b/common/core/web/keyboard-processor/src/text/keyboardProcessor.ts @@ -421,16 +421,14 @@ namespace com.keyman.text { * Function _UpdateVKShift * Scope Private * @param {Object} e OSK event - * @param {number} v keyboard shift state - * @param {(boolean|number)} d set (1) or clear(0) shift state bits * @return {boolean} Always true * Description Updates the current shift state within KMW, updating the OSK's visualization thereof. */ - _UpdateVKShift(e: KeyEvent, v: number, d: boolean|number): boolean { - var keyShiftState=0, lockStates=0, i; + _UpdateVKShift(e: KeyEvent): boolean { + let keyShiftState=0; - var lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK']; - var lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL']; + const lockNames = ['CAPS', 'NUM_LOCK', 'SCROLL_LOCK']; + const lockKeys = ['K_CAPS', 'K_NUMLOCK', 'K_SCROLL']; if(!this.activeKeyboard) { return true; @@ -439,7 +437,6 @@ namespace com.keyman.text { if(e) { // read shift states from Pevent keyShiftState = e.Lmodifiers; - lockStates = e.Lstates; // Are we simulating AltGr? If it's a simulation and not real, time to un-simulate for the OSK. if(this.activeKeyboard.isChiral && (this.activeKeyboard.emulatesAltGr) && @@ -448,25 +445,10 @@ namespace com.keyman.text { keyShiftState &= ~Codes.modifierCodes['RALT']; } - for(i=0; i < lockNames.length; i++) { - if(lockStates & Codes.stateBitmasks[lockNames[i]]) { - this.stateKeys[lockKeys[i]] = !!(lockStates & Codes.modifierCodes[lockNames[i]]); - } - } - } else if(d) { - keyShiftState |= v; - - for(i=0; i < lockNames.length; i++) { - if(v & Codes.stateBitmasks[lockNames[i]]) { - this.stateKeys[lockKeys[i]] = true; - } - } - } else { - keyShiftState &= ~v; - - for(i=0; i < lockNames.length; i++) { - if(v & Codes.stateBitmasks[lockNames[i]]) { - this.stateKeys[lockKeys[i]] = false; + // Set stateKeys where corresponding value is passed in e.Lstates + for(let i=0; i < lockNames.length; i++) { + if(e.Lstates & Codes.stateBitmasks[lockNames[i]]) { + this.stateKeys[lockKeys[i]] = !!(e.Lstates & Codes.modifierCodes[lockNames[i]]); } } } @@ -700,6 +682,13 @@ namespace com.keyman.text { this.layerId = 'default'; } + if(keyEvent.device.formFactor != utils.FormFactor.Desktop) { + // The caps layer works slightly differently on touch than on desktop. + // It's a single layer with no ability to mix with other modifiers + // We need to make sure that the state is kept in sync with the layer. + this.stateKeys['K_CAPS'] = this.layerId == 'caps'; + } + let baseModifierState = text.KeyboardProcessor.getModifierState(this.layerId); this.modStateFlags = baseModifierState | keyEvent.Lstates; } @@ -729,10 +718,10 @@ namespace com.keyman.text { // I3318 (always clear deadkeys after backspace) outputTarget.deadkeys().clear(); } else if(KeyboardProcessor.isModifier(Levent)) { - // For eventual integration - we bypass an OSK update for physical keystrokes when in touch mode. this.activeKeyboard.notify(Levent.Lcode, outputTarget, isKeyDown ? 1 : 0); + // For eventual integration - we bypass an OSK update for physical keystrokes when in touch mode. if(!Levent.device.touchable) { - return this._UpdateVKShift(Levent, Levent.Lcode-15, 1); // I2187 + return this._UpdateVKShift(Levent); // I2187 } else { return true; } @@ -740,7 +729,7 @@ namespace com.keyman.text { if(Levent.LmodifierChange) { this.activeKeyboard.notify(0, outputTarget, 1); - this._UpdateVKShift(Levent, 0, 1); + this._UpdateVKShift(Levent); } // No modifier keypresses detected. @@ -751,7 +740,7 @@ namespace com.keyman.text { this.layerId = 'default'; this.keyboardInterface.resetContextCache(); - this._UpdateVKShift(null, 15, 0); + this._UpdateVKShift(null); }; setNumericLayer(device: utils.DeviceSpec) { diff --git a/common/core/web/keyboard-processor/test.sh b/common/core/web/keyboard-processor/test.sh index b66fb3cb56..ae82949fad 100755 --- a/common/core/web/keyboard-processor/test.sh +++ b/common/core/web/keyboard-processor/test.sh @@ -64,6 +64,6 @@ pushd "$KEYMAN_ROOT/common/core/web/tools/recorder/src" popd # Run headless (browserless) tests. -echo "${TERM_HEADING}Running Keyboard Processor test suite${NORMAL}" +echo_heading "Running Keyboard Processor test suite" test-headless || fail "Keyboard Processor tests failed!" diff --git a/common/core/web/tools/recorder/package-lock.json b/common/core/web/tools/recorder/package-lock.json index c6aa597b93..c44727da9a 100644 --- a/common/core/web/tools/recorder/package-lock.json +++ b/common/core/web/tools/recorder/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/recorder-core", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/common/core/web/tools/recorder/package.json b/common/core/web/tools/recorder/package.json index c29bc0cad9..b12e1b6284 100644 --- a/common/core/web/tools/recorder/package.json +++ b/common/core/web/tools/recorder/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/recorder-core", - "version": "15.0.211", + "version": "15.0.216", "description": "Core classes used to develop KeymanWeb test cases based on keystrokes", "main": "index.js", "scripts": { @@ -17,10 +17,10 @@ }, "homepage": "https://github.com/keymanapp/keyman#readme", "dependencies": { - "@keymanapp/keyboard-processor": "^15.0.211", - "@keymanapp/models-types": "^15.0.211", - "@keymanapp/web-environment": "^15.0.211", - "@keymanapp/web-utils": "^15.0.211", + "@keymanapp/keyboard-processor": "^15.0.216", + "@keymanapp/models-types": "^15.0.216", + "@keymanapp/web-environment": "^15.0.216", + "@keymanapp/web-utils": "^15.0.216", "@types/node": "^11.9.4" }, "devDependencies": { diff --git a/common/core/web/tools/sentry-manager/package-lock.json b/common/core/web/tools/sentry-manager/package-lock.json index e72110017c..a932f2a8d8 100644 --- a/common/core/web/tools/sentry-manager/package-lock.json +++ b/common/core/web/tools/sentry-manager/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/web-sentry-manager", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/common/core/web/tools/sentry-manager/package.json b/common/core/web/tools/sentry-manager/package.json index 680a0b372f..4f432b8ffc 100644 --- a/common/core/web/tools/sentry-manager/package.json +++ b/common/core/web/tools/sentry-manager/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/web-sentry-manager", - "version": "15.0.211", + "version": "15.0.216", "description": "Common setup for KeymanWeb's Sentry-based error reporting", "main": "dist/index.js", "scripts": { @@ -20,7 +20,7 @@ "typescript": "^3.8.3" }, "dependencies": { - "@keymanapp/web-environment": "^15.0.211", + "@keymanapp/web-environment": "^15.0.216", "@sentry/browser": "^5.27.4" } } diff --git a/common/core/web/utils/package-lock.json b/common/core/web/utils/package-lock.json index d99d453960..f90dd640fe 100644 --- a/common/core/web/utils/package-lock.json +++ b/common/core/web/utils/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/web-utils", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/common/core/web/utils/package.json b/common/core/web/utils/package.json index f9d801aea5..016e57bdb7 100644 --- a/common/core/web/utils/package.json +++ b/common/core/web/utils/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/web-utils", - "version": "15.0.211", + "version": "15.0.216", "description": "Common utility functions used throughout other Keyman packages", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -20,8 +20,8 @@ }, "homepage": "https://github.com/keymanapp/keyman#readme", "devDependencies": { - "@keymanapp/resources-gosh": "^15.0.211", - "@keymanapp/web-environment": "^15.0.211", + "@keymanapp/resources-gosh": "^15.0.216", + "@keymanapp/web-environment": "^15.0.216", "@types/node": "^14.0.5", "typescript": "^3.8.3" } diff --git a/common/models/templates/package-lock.json b/common/models/templates/package-lock.json index 61fbd18da0..aed3769f2c 100644 --- a/common/models/templates/package-lock.json +++ b/common/models/templates/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/models-templates", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/common/models/templates/package.json b/common/models/templates/package.json index 8e5896f921..f7fc5c69be 100644 --- a/common/models/templates/package.json +++ b/common/models/templates/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/models-templates", - "version": "15.0.211", + "version": "15.0.216", "description": "Backing model implementations (templates) for Keyman's modelling layer", "keywords": [ "lm", @@ -42,8 +42,8 @@ "url": "https://github.com/keymanapp/keyman/issues" }, "devDependencies": { - "@keymanapp/models-types": "^15.0.211", - "@keymanapp/web-utils": "^15.0.211", + "@keymanapp/models-types": "^15.0.216", + "@keymanapp/web-utils": "^15.0.216", "@types/chai": "^4.2.11", "@types/mocha": "^7.0.2", "@types/node": "^14.0.4", @@ -52,6 +52,6 @@ "typescript": "^3.8.3" }, "dependencies": { - "@keymanapp/models-wordbreakers": "^15.0.211" + "@keymanapp/models-wordbreakers": "^15.0.216" } } diff --git a/common/models/types/package-lock.json b/common/models/types/package-lock.json index aa2235ae9e..8a5baf0b92 100644 --- a/common/models/types/package-lock.json +++ b/common/models/types/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/models-types", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/common/models/types/package.json b/common/models/types/package.json index 502b8c151e..78762c80d3 100644 --- a/common/models/types/package.json +++ b/common/models/types/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/models-types", - "version": "15.0.211", + "version": "15.0.216", "description": "Type definitions in used in the modeling (lexical model/predictive text) component of Keyman.", "types": "./index.d.ts", "scripts": { diff --git a/common/models/wordbreakers/package-lock.json b/common/models/wordbreakers/package-lock.json index 009f524959..745b40eeed 100644 --- a/common/models/wordbreakers/package-lock.json +++ b/common/models/wordbreakers/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/models-wordbreakers", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/common/models/wordbreakers/package.json b/common/models/wordbreakers/package.json index ce17181344..f90fb38d59 100644 --- a/common/models/wordbreakers/package.json +++ b/common/models/wordbreakers/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/models-wordbreakers", - "version": "15.0.211", + "version": "15.0.216", "description": "Word breakers bundled in the modeling layer", "keywords": [ "lexical model", @@ -40,7 +40,7 @@ "url": "https://github.com/keymanapp/keyman/issues" }, "devDependencies": { - "@keymanapp/models-types": "^15.0.211", + "@keymanapp/models-types": "^15.0.216", "@types/chai": "^4.2.11", "@types/mocha": "^7.0.2", "chai": "^4.3.4", diff --git a/common/predictive-text/package-lock.json b/common/predictive-text/package-lock.json index 4708764a1b..08ec16035f 100644 --- a/common/predictive-text/package-lock.json +++ b/common/predictive-text/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/lexical-model-layer", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/common/predictive-text/package.json b/common/predictive-text/package.json index 441f84922a..b2b0df0192 100644 --- a/common/predictive-text/package.json +++ b/common/predictive-text/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/lexical-model-layer", - "version": "15.0.211", + "version": "15.0.216", "description": "Keyman/Predictive Text integration layer", "main": "build/index.js", "scripts": { @@ -21,8 +21,8 @@ }, "homepage": "https://github.com/keymanapp/keyman#readme", "devDependencies": { - "@keymanapp/models-types": "^15.0.211", - "@keymanapp/resources-gosh": "^15.0.211", + "@keymanapp/models-types": "^15.0.216", + "@keymanapp/resources-gosh": "^15.0.216", "@types/node": "^10.17.21", "chai": "^4.3.4", "karma": "^6.3.4", @@ -46,10 +46,10 @@ "typescript": "^3.8.3" }, "dependencies": { - "@keymanapp/models-templates": "^15.0.211", - "@keymanapp/models-wordbreakers": "^15.0.211", - "@keymanapp/web-environment": "^15.0.211", - "@keymanapp/web-utils": "^15.0.211", + "@keymanapp/models-templates": "^15.0.216", + "@keymanapp/models-wordbreakers": "^15.0.216", + "@keymanapp/web-environment": "^15.0.216", + "@keymanapp/web-utils": "^15.0.216", "es6-shim": "^0.35.5", "string.prototype.codepointat": "^0.2.1", "string.prototype.startswith": "^0.2.0" diff --git a/common/predictive-text/testing/one-stage-embedded-webworker/build.sh b/common/predictive-text/testing/one-stage-embedded-webworker/build.sh index 64e1628d7e..f319ad2c4c 100644 --- a/common/predictive-text/testing/one-stage-embedded-webworker/build.sh +++ b/common/predictive-text/testing/one-stage-embedded-webworker/build.sh @@ -1,33 +1,22 @@ -#! /bin/bash +#!/usr/bin/env bash # # Compiles the Language Modeling Layer for common use in predictive text and autocorrective applications. # Designed for optimal compatibility with the Keyman Suite. # +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../../resources/build/build-utils.sh" +. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +## END STANDARD BUILD SCRIPT INCLUDE + display_usage ( ) { echo "build.sh [-clean]" echo echo " -clean to erase pre-existing build products before a re-build" } -# Fails the build if a specified file does not exist. -assert ( ) { - if ! [ -f $1 ]; then - fail "Build failed." - exit 1 - fi -} - -# Prints a nice, common error message. -fail ( ) { - FAILURE_MSG="$1" - if [[ "$FAILURE_MSG" == "" ]]; then - FAILURE_MSG="Unknown failure." - fi - echo "${ERROR_RED}$FAILURE_MSG${NORMAL}" - exit 1 -} - SOURCE="testing/one-stage-embedded-webworker" echo "Node.js + dependencies check" diff --git a/common/predictive-text/testing/two-stage-embedded-webworker/build.sh b/common/predictive-text/testing/two-stage-embedded-webworker/build.sh index 0e1c9eae4b..1a1c5eb347 100644 --- a/common/predictive-text/testing/two-stage-embedded-webworker/build.sh +++ b/common/predictive-text/testing/two-stage-embedded-webworker/build.sh @@ -1,33 +1,22 @@ -#! /bin/bash +#!/usr/bin/env bash # # Compiles the Language Modeling Layer for common use in predictive text and autocorrective applications. # Designed for optimal compatibility with the Keyman Suite. # +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../../resources/build/build-utils.sh" +. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +## END STANDARD BUILD SCRIPT INCLUDE + display_usage ( ) { echo "build.sh [-clean]" echo echo " -clean to erase pre-existing build products before a re-build" } -# Fails the build if a specified file does not exist. -assert ( ) { - if ! [ -f $1 ]; then - fail "Build failed." - exit 1 - fi -} - -# Prints a nice, common error message. -fail ( ) { - FAILURE_MSG="$1" - if [[ "$FAILURE_MSG" == "" ]]; then - FAILURE_MSG="Unknown failure." - fi - echo "${ERROR_RED}$FAILURE_MSG${NORMAL}" - exit 1 -} - SOURCE="testing/two-stage-embedded-webworker" COMPILED_WORKER="worker.js" diff --git a/common/test/keyboards/.gitignore b/common/test/keyboards/.gitignore index ef4be49c85..eab8a63166 100644 --- a/common/test/keyboards/.gitignore +++ b/common/test/keyboards/.gitignore @@ -1 +1,3 @@ -*/build/ \ No newline at end of file +*/build/ +*/*_source.zip +index.html diff --git a/common/test/keyboards/build.sh b/common/test/keyboards/build.sh old mode 100644 new mode 100755 index 176b79cd50..f3a3c69f06 --- a/common/test/keyboards/build.sh +++ b/common/test/keyboards/build.sh @@ -21,6 +21,9 @@ display_usage() { echo " --keyboard, -k Build only keyboards (not packages)" echo " --kmcomp path Specify path to kmcomp.exe, defaults" echo " to windows/bin/developer/kmcomp.exe" + echo " --zip-source Create zip file for source of each" + echo " keyboard for artifact tests" + echo " --index Build index.html for artifact tests" echo echo "Targets (all unless specified):" @@ -37,6 +40,9 @@ QUIET=false DEBUG=false CLEAN=false KEYBOARDS_ONLY=false +CUSTOM_KMCOMP= +INDEX=false +ZIPSOURCE=false KMCOMP="$KEYMAN_ROOT/windows/bin/developer/kmcomp.exe" TARGETS=() @@ -61,9 +67,16 @@ while [[ $# -gt 0 ]] ; do --keyboard|-k) KEYBOARDS_ONLY=true ;; + --zip-source) + ZIPSOURCE=true + ;; + --index) + INDEX=true + ;; --kmcomp) shift KMCOMP="$1" + CUSTOM_KMCOMP=true ;; *) TARGETS+=("$key") @@ -75,35 +88,35 @@ done # don't currently have a binary version of kmcomp available # during Linux and macOS builds, so that will need to be # manually sourced. +KMCOMP_LAUNCHER= -case "${OSTYPE}" in - "cygwin") - KMCOMP_LAUNCHER= - ;; - "msys") - KMCOMP_LAUNCHER= - ;; - "darwin"*) - # For Catalina (10.15) onwards, must use wine64 - base_macos_ver=10.15 - macos_ver=$(sw_vers -productVersion) - if verlt "$macos_ver" "$base_macos_ver"; then +if ! $CUSTOM_KMCOMP; then + case "${OSTYPE}" in + "cygwin") + ;; + "msys") + ;; + "darwin"*) + # For Catalina (10.15) onwards, must use wine64 + base_macos_ver=10.15 + macos_ver=$(sw_vers -productVersion) + if verlt "$macos_ver" "$base_macos_ver"; then + KMCOMP_LAUNCHER=wine + else + # On Catalina, and later versions: + # wine-4.12.1 works; wine-5.0, wine-5.7 do not. + # retrieve these from: + # `brew tap gcenx/wine && brew install --cask --no-quarantine wine-crossover` + # may also need to `sudo spctl --master-disable` + KMCOMP_LAUNCHER=wine64 + KMCOMP="$(dirname $KMCOMP)/kmcomp.x64.exe" + fi + ;; + *) KMCOMP_LAUNCHER=wine - else - # On Catalina, and later versions: - # wine-4.12.1 works; wine-5.0, wine-5.7 do not. - # retrieve these from: - # `brew tap gcenx/wine && brew install --cask --no-quarantine wine-crossover` - # may also need to `sudo spctl --master-disable` - KMCOMP_LAUNCHER=wine64 - KMCOMP="$(dirname $KMCOMP)/kmcomp.x64.exe" - fi - ;; - *) - KMCOMP_LAUNCHER=wine - ;; -esac - + ;; + esac +fi # Build list of available targets from subfolders, if none specified if [ ${#TARGETS[@]} == 0 ]; then @@ -120,22 +133,30 @@ if ! $QUIET; then "QUIET: $QUIET" \ "KEYBOARDS_ONLY: $KEYBOARDS_ONLY" \ "TARGETS: ${TARGETS[@]}" \ + "ZIPSOURCE: $ZIPSOURCE" \ + "INDEX: $INDEX" \ "" fi clean() { - local kpj="$1.kpj" ss= + local kpj="$1.kpj" ss= s= if $QUIET; then ss=-ss + s=-s fi pushd "$1" > /dev/null - $KMCOMP_LAUNCHER "$KMCOMP" -c $ss "$kpj" + if [ -f build.sh ]; then + ./build.sh -c $s + else + $KMCOMP_LAUNCHER "$KMCOMP" -c $ss "$kpj" + fi popd > /dev/null } build() { - local kpj="$1.kpj" d= t= ss= target= + local kpj="$1.kpj" d= t= ss= target= s= k= if $KEYBOARDS_ONLY; then + k=-k t=-t target="$1.kmn" fi @@ -143,12 +164,24 @@ build() { d=-d fi if $QUIET; then + s=-s ss=-ss fi # -w - treat warnings as errors, we'll force this # -cfc - check filename conventions pushd "$1" > /dev/null - $KMCOMP_LAUNCHER "$KMCOMP" $d $ss -w -cfc "$kpj" $t "$target" + if [ -f build.sh ]; then + ./build.sh $d $k $s + else + $KMCOMP_LAUNCHER "$KMCOMP" $d $ss -w -cfc "$kpj" $t "$target" + fi + popd > /dev/null +} + +zipsource() { + local target="$1" + pushd "$1" > /dev/null + 7z a -r -x!build -x"!$target.kpj.user" "${target}_source.zip" . popd > /dev/null } @@ -156,16 +189,57 @@ build() { for TARGET in "${TARGETS[@]}"; do if $CLEAN; then - echo - echo_heading "Cleaning target $TARGET" - echo + if ! $QUIET; then + echo + echo_heading "Cleaning target $TARGET" + echo + fi clean "$TARGET" else - echo - echo_heading "Building target $TARGET" - echo + if ! $QUIET; then + echo + echo_heading "Building target $TARGET" + echo + fi build "$TARGET" + + if $ZIPSOURCE; then + zipsource "$TARGET" + fi fi done +### + +if $INDEX; then + if $CLEAN; then + rm -f "$THIS_DIR/index.html" + else + cat << EOF > "$THIS_DIR/index.html" + + + + + Test Keyboards - $VERSION_WITH_TAG + + +

Test Keyboards - $VERSION_WITH_TAG

+ + + +EOF + fi +fi exit 0 diff --git a/common/test/keyboards/full_caps_3620_3621/source/full_caps_3620_3621.kmn b/common/test/keyboards/full_caps_3620_3621/source/full_caps_3620_3621.kmn index aa7c9aa40a..ad51b8f95b 100644 --- a/common/test/keyboards/full_caps_3620_3621/source/full_caps_3620_3621.kmn +++ b/common/test/keyboards/full_caps_3620_3621/source/full_caps_3620_3621.kmn @@ -1,6 +1,6 @@ c full_caps_3620_3621 generated from template at 2021-12-01 08:45:15 c with name "full_caps_3620_3621" -store(&VERSION) '10.0' +store(&VERSION) '15.0' store(&NAME) 'full_caps_3620_3621' store(©RIGHT) '©' store(&KEYBOARDVERSION) '1.0' diff --git a/common/test/keyboards/obolo_chwerty_6347/HISTORY.md b/common/test/keyboards/obolo_chwerty_6347/HISTORY.md new file mode 100644 index 0000000000..e4b8b51ee0 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/HISTORY.md @@ -0,0 +1,36 @@ +Obolo Chwerty Keyboard Change History +==================== + +1.2.1 (2021-11-23) +---------------- +* Removed accent key from numbers row on default layer, and from symbols row on shift layer. + +1.2.0 (2021-07-05) +---------------- +* Updated keycap for key 6 to match output on mobile shift layer, and added longpress for ^ +* Activated spacebar on layer alt for mobile/tablet layout +* Updated documentation +* Miscellaneous minor updates + +1.1.2 (2021-02-04) +---------------- +* Updated output for keys CH and SH on SHIFT layer to match key cap on touchscreen and desktop. +* Resolved capslock issue for keys CH, SH, Ọ and N̄ on desktop. +* Added long press on touchscreen for frequently used accented letters. +* Added the Naira sign (₦) and Ñ (an alternative where software cannot render N̄ well, though Ñ is not part of the Obolo orthography.) + +1.1.1 (2020-10-27) +---------------- +* Increment version number to force recompile of touch layout + +1.1 (2020-07-07) +---------------- +* Moved the high tone (which is not required, except in primers) to long press on low tone button (for touchscreen). +* Changed backspace behavior for ch, sh, n̄. +* Added long press for Q, H, X and C keys on touchscreen. +* Added hyphen-dash (a frequently used mark) to default and shift layers for touchscreen. +* Fixed typo and omissions in documentation. + +1.0 (2019-07-20) +---------------- +* Created by Rogers Katelem Edeh diff --git a/common/test/keyboards/obolo_chwerty_6347/LICENSE.md b/common/test/keyboards/obolo_chwerty_6347/LICENSE.md new file mode 100644 index 0000000000..eee2ba508b --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +© 2019 - 2021 Rogers Katelem Edeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/common/test/keyboards/obolo_chwerty_6347/README.md b/common/test/keyboards/obolo_chwerty_6347/README.md new file mode 100644 index 0000000000..18cf57b117 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/README.md @@ -0,0 +1,36 @@ +Obolo Chwerty keyboard +============== + +© 2019 - 2021 Rogers Katelem Edeh + +Version 1.2.0 + +Description +----------- + +NOTE: This keyboard has been modified from the original for the purposes of testing https://github.com/keymanapp/keyman/issues/6347. It is not intended to be used for general purposes, and is not the final release version. Changes made: + +* Files renamed +* Font and PHP help have been removed (reduce distribution size) + +Obolo Chwerty Keyboard is a keyboard layout for the Obolo language of Nigeria. This layout covers the need of every dialect in that language. +On this keyboard, accents are typed after the base letters. So, to type Obolo language, simply tap the given latters and tap the appropriate accent key to place the accent on the letter. + +Links +----- +https://keyman.com/keyboards/obolo_chwerty + +Supported Platforms +------------------- + * Windows + * macOS + * Linux + * Web + * iPhone + * iPad + * Android phone + * Android tablet + * Mobile devices + * Desktop devices + * Tablet devices + diff --git a/common/test/keyboards/obolo_chwerty_6347/obolo_chwerty_6347.keyboard_info b/common/test/keyboards/obolo_chwerty_6347/obolo_chwerty_6347.keyboard_info new file mode 100644 index 0000000000..1513b8bb47 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/obolo_chwerty_6347.keyboard_info @@ -0,0 +1,7 @@ +{ + "license": "mit", + "languages": [ + "ann-Latn" + ], + "description": "Obolo Chwerty Keyboard: A keyboard layout for the Obolo language of Nigeria. It covers the need of every dialect in that language" +} diff --git a/common/test/keyboards/obolo_chwerty_6347/obolo_chwerty_6347.kpj b/common/test/keyboards/obolo_chwerty_6347/obolo_chwerty_6347.kpj new file mode 100644 index 0000000000..69cff5096f --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/obolo_chwerty_6347.kpj @@ -0,0 +1,183 @@ + + + + $PROJECTPATH\build + True + True + True + keyboard + + + + id_e2041c991cdc20c570b342a5803447b0 + obolo_chwerty_6347.kmn + source\obolo_chwerty_6347.kmn + 1.2.1 + .kmn +
+ Obolo Chwerty + © 2019-2022 Rogers Katelem Edeh + A keyboard layout (chwerty) for the Obolo language of Nigeria. The keyboard covers the need of every dialect in that language. +
+
+ + id_4ed7acb803d5177bff445780f774fdb3 + obolo_chwerty_6347.kps + source\obolo_chwerty_6347.kps + + .kps +
+ Obolo Chwerty + © 2019-2022 Rogers Katelem Edeh +
+
+ + id_ede98e4633e239f933cbfd1f4e1b766c + HISTORY.md + HISTORY.md + + .md + + + id_53e892b8b41cc4caece1cfd5ef21d6e7 + LICENSE.md + LICENSE.md + + .md + + + id_0730bb7c2e8f9ea2438b52e419dd86c9 + README.md + README.md + + .md + + + id_fa9ac62e52c7671ac61602e3583305fd + obolo_chwerty_6347.keyboard_info + obolo_chwerty_6347.keyboard_info + + .keyboard_info + + + id_ef2a383b75a0364689701ecbf2f6fefa + obolo_chwerty_6347.ico + source\obolo_chwerty_6347.ico + + .ico + id_e2041c991cdc20c570b342a5803447b0 + + + id_fa2b1b4a5977c1283d061d23611709ef + obolo_chwerty_6347.kvk + source\..\build\obolo_chwerty_6347.kvk + + .kvk + id_4ed7acb803d5177bff445780f774fdb3 + + + id_13adcc1b6b8e23edd35cfc6ab7c245b0 + obolo_chwerty_6347.kmx + source\..\build\obolo_chwerty_6347.kmx + + .kmx + id_4ed7acb803d5177bff445780f774fdb3 + + + id_3ec4dad3d83c69fc4b33eb86d401d8cb + obolo_chwerty_6347.js + source\..\build\obolo_chwerty_6347.js + + .js + id_4ed7acb803d5177bff445780f774fdb3 + + + id_f6212220adf6c5eb0ae25c33cb973c64 + chwerty_default.png + source\welcome\chwerty_default.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_cd62e578000692c9966c069950904d06 + chwerty_keycombi.png + source\welcome\chwerty_keycombi.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_2d29737f21e65a75ca98a9c3ab1f4a6f + chwerty_mobi_alt.png + source\welcome\chwerty_mobi_alt.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_2d856489cc6083c4b74a1b8c2b528785 + chwerty_mobi_default.png + source\welcome\chwerty_mobi_default.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_ee5bdb44f34cd08e1c6012f91790c302 + chwerty_mobi_shift.png + source\welcome\chwerty_mobi_shift.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_743e9cd02f1d4004a5320b9faa355587 + chwerty_shift.png + source\welcome\chwerty_shift.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_a81a3f903e8ce052259e09e4a6fbabb0 + chwertyftkey1.png + source\welcome\chwertyftkey1.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_cb8167846a4ac07edd78e5a39a7cc587 + chwertyftkey2.png + source\welcome\chwertyftkey2.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_7325a11eaf4f66357aa7185056091802 + chwertyftkey3.png + source\welcome\chwertyftkey3.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_724e5b4c63f10bc0abf7077f7c3172fc + welcome.htm + source\welcome\welcome.htm + + .htm + id_4ed7acb803d5177bff445780f774fdb3 + + + id_8da344c4cea6f467013357fe099006f5 + readme.htm + source\readme.htm + + .htm + id_4ed7acb803d5177bff445780f774fdb3 + +
+
diff --git a/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.css b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.css new file mode 100644 index 0000000000..3fe38a2f20 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.css @@ -0,0 +1,7 @@ +/* tone keys colour */ +.android .kmw-keyboard-obolo_chwerty_6347 #default-T_GRV {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6347 #default-T_CCM {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6347 #shift-T_GRV {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6347 #shift-T_CCM {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6347 #caps-T_GRV {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6347 #caps-T_CCM {color: #02ff02;} diff --git a/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.ico b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.ico new file mode 100644 index 0000000000..4d329aaf90 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.ico differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.keyman-touch-layout b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.keyman-touch-layout new file mode 100644 index 0000000000..c9e7ea336e --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.keyman-touch-layout @@ -0,0 +1,2053 @@ +{ + "tablet": { + "font": "Tahoma", + "layer": [ + { + "id": "default", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "1", + "width": "111", + "sk": [ + { + "text": "¹", + "id": "U_00B9" + }, + { + "text": "₁", + "id": "U_2081" + } + ] + }, + { + "id": "K_2", + "text": "2", + "width": "111", + "sk": [ + { + "text": "²", + "id": "U_00B2" + }, + { + "id": "U_2082" + } + ] + }, + { + "id": "K_3", + "text": "3", + "width": "111", + "sk": [ + { + "text": "³", + "id": "U_00B3" + }, + { + "id": "U_2083" + } + ] + }, + { + "id": "K_4", + "text": "4", + "width": "111", + "sk": [ + { + "text": "⁴", + "id": "U_2074" + }, + { + "text": "₄", + "id": "U_2084" + } + ] + }, + { + "id": "K_5", + "text": "5", + "width": "111", + "sk": [ + { + "text": "⁵", + "id": "U_2075" + }, + { + "id": "U_2085" + } + ] + }, + { + "id": "K_6", + "text": "6", + "width": "111", + "sk": [ + { + "text": "⁶", + "id": "U_2076" + }, + { + "id": "U_2086" + } + ] + }, + { + "id": "K_7", + "text": "7", + "width": "111", + "sk": [ + { + "text": "⁷", + "id": "U_2077" + }, + { + "id": "U_2087" + } + ] + }, + { + "id": "K_8", + "text": "8", + "width": "111", + "sk": [ + { + "text": "⁸", + "id": "U_2078" + }, + { + "text": "₈", + "id": "U_2088" + } + ] + }, + { + "id": "K_9", + "text": "9", + "width": "111", + "sk": [ + { + "text": "⁹", + "id": "U_2079" + }, + { + "id": "U_2089" + } + ] + }, + { + "id": "K_0", + "text": "0", + "width": "111", + "sk": [ + { + "text": "⁰", + "id": "U_2070" + }, + { + "id": "U_2080" + } + ] + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "T_Q", + "text": "ch", + "pad": "", + "width": "", + "sk": [ + { + "text": "q", + "id": "U_0071" + } + ] + }, + { + "id": "K_W", + "text": "w" + }, + { + "id": "K_E", + "text": "e", + "sk": [ + { + "text": "è", + "id": "U_00E8" + }, + { + "text": "ê", + "id": "U_00EA" + } + ] + }, + { + "id": "K_R", + "text": "r" + }, + { + "id": "K_T", + "text": "t" + }, + { + "id": "K_Y", + "text": "y" + }, + { + "id": "K_U", + "text": "u", + "sk": [ + { + "text": "ù", + "id": "U_00F9" + }, + { + "text": "û", + "id": "U_00FB" + } + ] + }, + { + "id": "K_I", + "text": "i", + "sk": [ + { + "text": "ì", + "id": "U_00EC" + }, + { + "text": "î", + "id": "U_00EE" + } + ] + }, + { + "id": "K_O", + "text": "o", + "sk": [ + { + "text": "ò", + "id": "U_00F2" + }, + { + "text": "ô", + "id": "U_00F4" + } + ] + }, + { + "id": "K_P", + "text": "p" + }, + { + "id": "T_GRV", + "text": "ˋ", + "sk": [ + { + "text": "´", + "id": "T_ACU" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_A", + "text": "a", + "pad": "70", + "sk": [ + { + "text": "à", + "id": "U_00E0" + }, + { + "text": "â", + "id": "U_00E2" + } + ] + }, + { + "id": "K_S", + "text": "s" + }, + { + "id": "K_D", + "text": "d" + }, + { + "id": "K_F", + "text": "f" + }, + { + "id": "K_G", + "text": "g" + }, + { + "id": "T_H", + "text": "sh", + "sk": [ + { + "text": "h", + "id": "U_0068" + }, + { + "text": "ṣ", + "id": "U_1E63" + } + ] + }, + { + "id": "K_J", + "text": "j" + }, + { + "id": "K_K", + "text": "k" + }, + { + "id": "K_L", + "text": "l" + }, + { + "id": "T_CCM", + "text": "ˆ", + "sk": [ + { + "text": "ˇ", + "id": "T_CRN" + } + ] + }, + { + "id": "T_SPA", + "text": "", + "width": "40", + "sp": "10" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "pad": "50", + "width": "120", + "sp": "1", + "nextlayer": "shift" + }, + { + "id": "K_Z", + "text": "z" + }, + { + "id": "T_X", + "text": "ọ", + "sk": [ + { + "text": "ọ̀", + "id": "U_1ECD_0300" + }, + { + "text": "ộ", + "id": "U_1ED9" + }, + { + "text": "x", + "id": "U_0078" + } + ] + }, + { + "id": "T_C", + "text": "n̄", + "sk": [ + { + "text": "ñ", + "id": "U_00F1" + }, + { + "text": "c", + "id": "U_0063" + } + ] + }, + { + "id": "K_V", + "text": "v" + }, + { + "id": "K_B", + "text": "b" + }, + { + "id": "K_N", + "text": "n", + "sk": [ + { + "text": "ǹ", + "id": "U_01F9" + } + ] + }, + { + "id": "K_M", + "text": "m", + "sk": [ + { + "text": "m̀", + "id": "U_006D_0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "text": "!", + "id": "U_0021" + }, + { + "text": "/", + "id": "U_002F" + }, + { + "text": "'", + "id": "U_0027" + }, + { + "text": "\"", + "id": "U_0022" + }, + { + "text": "(", + "id": "U_0028" + }, + { + "text": ")", + "id": "U_0029" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "120", + "sp": "1" + }, + { + "id": "T_SPB", + "text": "", + "width": "20", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_ALT", + "text": "*Symbol*", + "width": "120", + "sp": "1", + "nextlayer": "alt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "", + "sp": "1" + }, + { + "id": "K_COMMA", + "text": ",", + "sk": [ + { + "text": ";", + "id": "U_003B" + } + ] + }, + { + "id": "K_SPACE", + "text": "", + "width": "520", + "sp": "0" + }, + { + "id": "K_PERIOD", + "text": ".", + "sk": [ + { + "text": ":", + "id": "U_003A" + } + ] + }, + { + "id": "T_ENG", + "text": "⨷", + "sp": "1", + "sk": [ + { + "text": "–", + "id": "U_2013" + }, + { + "text": "—", + "id": "U_2014" + }, + { + "text": "_", + "id": "U_005F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "120", + "sp": "1" + } + ] + } + ] + }, + { + "id": "shift", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "!", + "width": "111" + }, + { + "id": "K_2", + "text": "@", + "width": "111" + }, + { + "id": "K_3", + "text": "#", + "width": "111" + }, + { + "id": "K_4", + "text": "$", + "width": "111" + }, + { + "id": "K_5", + "text": "%", + "width": "111", + "sk": [ + { + "text": "‰", + "id": "U_2030" + }, + { + "text": "‱", + "id": "U_2031" + } + ] + }, + { + "id": "U_20A6", + "text": "₦", + "width": "111", + "sk": [ + { + "text": "^", + "id": "U_005E" + } + ] + }, + { + "id": "K_7", + "text": "&", + "width": "111" + }, + { + "id": "K_8", + "text": "*", + "width": "111" + }, + { + "id": "K_9", + "text": "(", + "width": "111" + }, + { + "id": "K_0", + "text": ")", + "width": "111" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "T_Q", + "text": "Ch", + "pad": "", + "sk": [ + { + "text": "Q", + "id": "U_0051" + } + ] + }, + { + "id": "K_W", + "text": "W" + }, + { + "id": "K_E", + "text": "E", + "sk": [ + { + "text": "È", + "id": "U_00C8" + }, + { + "text": "Ê", + "id": "U_00CA" + } + ] + }, + { + "id": "K_R", + "text": "R" + }, + { + "id": "K_T", + "text": "T" + }, + { + "id": "K_Y", + "text": "Y" + }, + { + "id": "K_U", + "text": "U", + "sk": [ + { + "text": "Ù", + "id": "U_00D9" + }, + { + "text": "Û", + "id": "U_00DB" + } + ] + }, + { + "id": "K_I", + "text": "I", + "sk": [ + { + "text": "Ì", + "id": "U_00CC" + }, + { + "text": "Î", + "id": "U_00CE" + } + ] + }, + { + "id": "K_O", + "text": "O", + "sk": [ + { + "text": "Ò", + "id": "U_00D2" + }, + { + "text": "Ô", + "id": "U_00D4" + } + ] + }, + { + "id": "K_P", + "text": "P" + }, + { + "id": "T_GRV", + "text": "`", + "sk": [ + { + "text": "´", + "id": "T_ACU" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_A", + "text": "A", + "pad": "70", + "sk": [ + { + "text": "À", + "id": "U_00C0" + }, + { + "text": "Â", + "id": "U_00C2" + } + ] + }, + { + "id": "K_S", + "text": "S" + }, + { + "id": "K_D", + "text": "D" + }, + { + "id": "K_F", + "text": "F" + }, + { + "id": "K_G", + "text": "G" + }, + { + "id": "T_H", + "text": "Sh", + "sk": [ + { + "text": "H", + "id": "U_0048" + }, + { + "text": "Ṣ", + "id": "U_1E62" + } + ] + }, + { + "id": "K_J", + "text": "J" + }, + { + "id": "K_K", + "text": "K" + }, + { + "id": "K_L", + "text": "L" + }, + { + "id": "T_CCM", + "text": "ˆ", + "sk": [ + { + "text": "ˇ", + "id": "T_CRN" + } + ] + }, + { + "id": "T_SPC", + "text": "", + "width": "40", + "sp": "10" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "pad": "50", + "width": "120", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_Z", + "text": "Z" + }, + { + "id": "T_X", + "text": "Ọ", + "sk": [ + { + "text": "Ọ̀", + "id": "U_1ECC_0300" + }, + { + "text": "Ộ", + "id": "U_1ED8" + }, + { + "text": "X", + "id": "U_0058" + } + ] + }, + { + "id": "T_C", + "text": "N̄", + "sk": [ + { + "text": "Ñ", + "id": "U_00D1" + }, + { + "text": "C", + "id": "U_0043" + } + ] + }, + { + "id": "K_V", + "text": "V" + }, + { + "id": "K_B", + "text": "B" + }, + { + "id": "K_N", + "text": "N", + "sk": [ + { + "text": "Ǹ", + "id": "U_01F8" + } + ] + }, + { + "id": "K_M", + "text": "M", + "sk": [ + { + "text": "M̀", + "id": "U_004D_0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "text": "!", + "id": "U_0021" + }, + { + "text": "/", + "id": "U_002F" + }, + { + "text": "'", + "id": "U_0027" + }, + { + "text": "\"", + "id": "U_0022" + }, + { + "text": "(", + "id": "U_0028" + }, + { + "text": ")", + "id": "U_0029" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "120", + "sp": "1" + }, + { + "id": "T_SPD", + "text": "", + "width": "20", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_ALT", + "text": "*Symbol*", + "width": "120", + "sp": "1", + "nextlayer": "alt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "", + "sp": "1" + }, + { + "id": "U_002C", + "text": ",", + "width": "", + "sk": [ + { + "text": ";", + "id": "U_003B" + } + ] + }, + { + "id": "K_SPACE", + "text": "", + "width": "520", + "sp": "0" + }, + { + "id": "U_002E", + "text": ".", + "sk": [ + { + "text": ":", + "id": "U_003A" + } + ] + }, + { + "id": "T_ENG", + "text": "⨷", + "sp": "1", + "sk": [ + { + "text": "–", + "id": "U_2013" + }, + { + "text": "—", + "id": "U_2014" + }, + { + "text": "_", + "id": "U_005F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "120", + "sp": "1" + } + ] + } + ] + }, + { + "id": "alt", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "1", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "¹", + "id": "U_00B9" + }, + { + "text": "₁", + "id": "U_2081" + } + ] + }, + { + "id": "K_2", + "text": "2", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "²", + "id": "U_00B2" + }, + { + "text": "₂", + "id": "U_2082" + } + ] + }, + { + "id": "K_3", + "text": "3", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "³", + "id": "U_00B3" + }, + { + "text": "₃", + "id": "U_2083" + } + ] + }, + { + "id": "K_4", + "text": "4", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁴", + "id": "U_2074" + }, + { + "text": "₄", + "id": "U_2084" + } + ] + }, + { + "id": "K_5", + "text": "5", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁵", + "id": "U_2075" + }, + { + "text": "₅", + "id": "U_2085" + } + ] + }, + { + "id": "K_6", + "text": "6", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁶", + "id": "U_2076" + }, + { + "text": "₆", + "id": "U_2086" + } + ] + }, + { + "id": "K_7", + "text": "7", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁷", + "id": "U_2077" + }, + { + "text": "₇", + "id": "U_2087" + } + ] + }, + { + "id": "K_8", + "text": "8", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁸", + "id": "U_2078" + }, + { + "text": "₈", + "id": "U_2088" + } + ] + }, + { + "id": "K_9", + "text": "9", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁹", + "id": "U_2079" + }, + { + "text": "₉", + "id": "U_2089" + } + ] + }, + { + "id": "K_0", + "text": "0", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁰", + "id": "U_2070" + }, + { + "text": "₀", + "id": "U_2080" + } + ] + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "U_002B", + "text": "+", + "pad": "", + "sk": [ + { + "text": "±", + "id": "U_00B1" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "text": "∓", + "id": "U_2213" + } + ] + }, + { + "id": "U_00D7", + "text": "×" + }, + { + "id": "U_00F7", + "text": "÷" + }, + { + "id": "U_2236", + "text": "∶", + "sk": [ + { + "text": "·", + "id": "U_00B7" + }, + { + "text": "∴", + "id": "U_2234" + }, + { + "text": "∵", + "id": "U_2235" + } + ] + }, + { + "id": "U_221A", + "text": "√", + "sk": [ + { + "text": "∛", + "id": "U_221B" + }, + { + "text": "∜", + "id": "U_221C" + } + ] + }, + { + "id": "U_005E", + "text": "^" + }, + { + "id": "U_003D", + "text": "=", + "sk": [ + { + "text": "≠", + "id": "U_2260" + }, + { + "text": "≈", + "id": "U_2248" + }, + { + "text": "≡", + "id": "U_2261" + } + ] + }, + { + "id": "U_007E", + "text": "~" + }, + { + "id": "U_203D", + "text": "‽", + "width": "", + "sk": [ + { + "text": "¡", + "id": "U_00A1" + } + ] + }, + { + "id": "U_2713", + "text": "✓", + "sk": [ + { + "text": "Δ", + "id": "U_0394" + }, + { + "text": "✗", + "id": "U_2717" + }, + { + "text": "⛯", + "id": "U_26EF" + }, + { + "text": "⛭", + "id": "U_26ED" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "U_007B", + "text": "{", + "pad": "" + }, + { + "id": "U_00AB", + "text": "«" + }, + { + "id": "U_003C", + "text": "<", + "sk": [ + { + "text": "≪", + "id": "U_226A" + }, + { + "text": "≤", + "id": "U_2264" + } + ] + }, + { + "id": "U_005B", + "text": "[" + }, + { + "id": "U_0028", + "text": "(" + }, + { + "id": "U_007C", + "text": "|" + }, + { + "id": "U_0029", + "text": ")" + }, + { + "id": "U_005D", + "text": "]" + }, + { + "id": "U_003E", + "text": ">", + "sk": [ + { + "text": "≫", + "id": "U_226B" + }, + { + "text": "≥", + "id": "U_2265" + } + ] + }, + { + "id": "U_00BB", + "text": "»" + }, + { + "id": "U_007D", + "text": "}" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "pad": "50", + "width": "120", + "sp": "1", + "nextlayer": "shift" + }, + { + "id": "U_221E", + "text": "∞", + "sk": [ + { + "text": "∂", + "id": "U_2202" + } + ] + }, + { + "id": "U_222B", + "text": "∫", + "sk": [ + { + "text": "ẋ", + "id": "U_1E8B" + }, + { + "text": "ẍ", + "id": "U_1E8D" + }, + { + "text": "ẏ", + "id": "U_1E8F" + }, + { + "text": "ӱ", + "id": "U_04F1" + } + ] + }, + { + "id": "U_00B0", + "text": "°", + "sk": [ + { + "text": "℃", + "id": "U_2103" + }, + { + "text": "℉", + "id": "U_2109" + } + ] + }, + { + "id": "U_03C0", + "text": "π" + }, + { + "id": "U_03B8", + "text": "θ" + }, + { + "id": "U_33D1", + "text": "㏑", + "sk": [ + { + "text": "㏒", + "id": "U_33D2" + } + ] + }, + { + "id": "U_00A9", + "text": "©", + "sk": [ + { + "text": "®", + "id": "U_00AE" + }, + { + "text": "℗", + "id": "U_2117" + }, + { + "text": "🛈", + "id": "U_1F6C8" + }, + { + "text": "™", + "id": "U_2122" + }, + { + "text": "℅", + "id": "U_2105" + } + ] + }, + { + "id": "U_002F", + "text": "/", + "sk": [ + { + "text": "\\", + "id": "U_005C" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "120", + "sp": "1" + }, + { + "id": "T_SPF", + "text": "", + "width": "20", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_ALT", + "text": "*abc*", + "width": "120", + "sp": "1", + "nextlayer": "default" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "", + "sp": "1" + }, + { + "id": "U_00A7", + "text": "§", + "sk": [ + { + "text": "₍", + "id": "U_208D" + }, + { + "text": "ₓ", + "id": "U_2093" + }, + { + "text": "₊", + "id": "U_208A" + }, + { + "text": "₋", + "id": "U_208B" + }, + { + "text": "₎", + "id": "U_208E" + }, + { + "text": "₌", + "id": "U_208C" + } + ] + }, + { + "id": "K_SPACE", + "text": "", + "width": "520", + "sp": "0", + "layer": "default" + }, + { + "id": "U_00B6", + "text": "¶", + "sk": [ + { + "text": "⁽", + "id": "U_207D" + }, + { + "text": "ⁿ", + "id": "U_207F" + }, + { + "text": "⁺", + "id": "U_207A" + }, + { + "text": "⁻", + "id": "U_207B" + }, + { + "text": "⁾", + "id": "U_207E" + }, + { + "text": "⁼", + "id": "U_207C" + } + ] + }, + { + "id": "U_03A9", + "text": "Ω", + "sp": "1", + "sk": [ + { + "text": "♚", + "id": "U_265A" + }, + { + "text": "♔", + "id": "U_2654" + }, + { + "text": "♛", + "id": "U_265B" + }, + { + "text": "♕", + "id": "U_2655" + }, + { + "text": "♝", + "id": "U_265D" + }, + { + "text": "♗", + "id": "U_2657" + }, + { + "text": "♜", + "id": "U_265C" + }, + { + "text": "♖", + "id": "U_2656" + }, + { + "text": "♞", + "id": "U_265E" + }, + { + "text": "♘", + "id": "U_2658" + }, + { + "text": "♟", + "id": "U_265F" + }, + { + "text": "♙", + "id": "U_2659" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "120", + "sp": "1" + } + ] + } + ] + }, + { + "id": "caps", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "1", + "width": "111" + }, + { + "id": "K_2", + "text": "2", + "width": "111" + }, + { + "id": "K_3", + "text": "3", + "width": "111" + }, + { + "id": "K_4", + "text": "4", + "width": "111" + }, + { + "id": "K_5", + "text": "5", + "width": "111" + }, + { + "id": "K_6", + "text": "6", + "width": "111" + }, + { + "id": "K_7", + "text": "7", + "width": "111" + }, + { + "id": "K_8", + "text": "8", + "width": "111" + }, + { + "id": "K_9", + "text": "9", + "width": "111" + }, + { + "id": "K_0", + "text": "0", + "width": "111" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "T_Q", + "text": "CH", + "pad": "", + "sk": [ + { + "text": "Q", + "id": "U_0051" + } + ] + }, + { + "id": "K_W", + "text": "W" + }, + { + "id": "K_E", + "text": "E", + "sk": [ + { + "text": "È", + "id": "U_00C8" + }, + { + "text": "Ê", + "id": "U_00CA" + } + ] + }, + { + "id": "K_R", + "text": "R" + }, + { + "id": "K_T", + "text": "T" + }, + { + "id": "K_Y", + "text": "Y" + }, + { + "id": "K_U", + "text": "U", + "sk": [ + { + "text": "Ù", + "id": "U_00D9" + }, + { + "text": "Û", + "id": "U_00DB" + } + ] + }, + { + "id": "K_I", + "text": "I", + "sk": [ + { + "text": "Ì", + "id": "U_00CC" + }, + { + "text": "Î", + "id": "U_00CE" + } + ] + }, + { + "id": "K_O", + "text": "O", + "sk": [ + { + "text": "Ò", + "id": "U_00D2" + }, + { + "text": "Ô", + "id": "U_00D4" + } + ] + }, + { + "id": "K_P", + "text": "P" + }, + { + "id": "T_GRV", + "text": "`", + "sk": [ + { + "text": "´", + "id": "T_ACU" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_A", + "text": "A", + "pad": "70", + "sk": [ + { + "text": "À", + "id": "U_00C0" + }, + { + "text": "Â", + "id": "U_00C2" + } + ] + }, + { + "id": "K_S", + "text": "S" + }, + { + "id": "K_D", + "text": "D" + }, + { + "id": "K_F", + "text": "F" + }, + { + "id": "K_G", + "text": "G" + }, + { + "id": "T_H", + "text": "SH", + "sk": [ + { + "text": "H", + "id": "U_0048" + }, + { + "text": "Ṣ", + "id": "U_1E62" + } + ] + }, + { + "id": "K_J", + "text": "J" + }, + { + "id": "K_K", + "text": "K" + }, + { + "id": "K_L", + "text": "L" + }, + { + "id": "T_CCM", + "text": "ˆ", + "sk": [ + { + "text": "ˇ", + "id": "T_CRN" + } + ] + }, + { + "id": "T_SPC", + "text": "", + "width": "40", + "sp": "10" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "pad": "50", + "width": "120", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_Z", + "text": "Z" + }, + { + "id": "T_X", + "text": "Ọ", + "sk": [ + { + "text": "Ọ̀", + "id": "U_1ECC_0300" + }, + { + "text": "Ộ", + "id": "U_1ED8" + }, + { + "text": "X", + "id": "U_0058" + } + ] + }, + { + "id": "T_C", + "text": "N̄", + "sk": [ + { + "text": "Ñ", + "id": "U_00D1" + }, + { + "text": "C", + "id": "U_0043" + } + ] + }, + { + "id": "K_V", + "text": "V" + }, + { + "id": "K_B", + "text": "B" + }, + { + "id": "K_N", + "text": "N", + "sk": [ + { + "text": "Ǹ", + "id": "U_01F8" + } + ] + }, + { + "id": "K_M", + "text": "M", + "sk": [ + { + "text": "M̀", + "id": "U_004D_0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "text": "!", + "id": "U_0021" + }, + { + "text": "/", + "id": "U_002F" + }, + { + "text": "'", + "id": "U_0027" + }, + { + "text": "\"", + "id": "U_0022" + }, + { + "text": "(", + "id": "U_0028" + }, + { + "text": ")", + "id": "U_0029" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "120", + "sp": "1" + }, + { + "id": "T_SPD", + "text": "", + "width": "20", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_ALT", + "text": "*Symbol*", + "width": "120", + "sp": "1", + "nextlayer": "alt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "", + "sp": "1" + }, + { + "id": "U_002C", + "text": ",", + "width": "", + "sk": [ + { + "text": ";", + "id": "U_003B" + } + ] + }, + { + "id": "K_SPACE", + "text": "", + "width": "520", + "sp": "0" + }, + { + "id": "U_002E", + "text": ".", + "sk": [ + { + "text": ":", + "id": "U_003A" + } + ] + }, + { + "id": "T_ENG", + "text": "⨷", + "sp": "1", + "sk": [ + { + "text": "–", + "id": "U_2013" + }, + { + "text": "—", + "id": "U_2014" + }, + { + "text": "_", + "id": "U_005F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "120", + "sp": "1" + } + ] + } + ] + } + ], + "displayUnderlying": false, + "fontsize": "" + } +} \ No newline at end of file diff --git a/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kmn b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kmn new file mode 100644 index 0000000000..1c14839431 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kmn @@ -0,0 +1,254 @@ +store(&VERSION) '15.0' +store(&NAME) 'Obolo Chwerty #6347' +store(©RIGHT) '© 2019-2022 Rogers Katelem Edeh' +store(&TARGETS) 'any' +store(&VISUALKEYBOARD) 'obolo_chwerty_6347.kvks' +store(&LAYOUTFILE) 'obolo_chwerty_6347.keyman-touch-layout' +store(&BITMAP) 'obolo_chwerty_6347.ico' +store(&MESSAGE) 'A keyboard layout (chwerty) for the Obolo language of Nigeria. The keyboard covers the need of every dialect in that language.' +store(&KMW_HELPTEXT) 'A simple keyboard layout (chwerty) to help you type very easily in Obolo language.' +store(&KEYBOARDVERSION) '1.2.1' +store(&KMW_EMBEDCSS) 'obolo_chwerty_6347.css' + +begin Unicode > use(main) +begin NewContext > use(NewContext) +begin PostKeystroke > use(PostKeystroke) + +c store(capskeys) [CAPS K_A] [CAPS K_B] [CAPS K_C] [CAPS K_D] [CAPS K_E] [CAPS K_F] [CAPS K_G] [CAPS K_H] [CAPS K_I] [CAPS K_J] [CAPS K_K] [CAPS K_L] [CAPS K_M] [CAPS K_N] [CAPS K_O] [CAPS K_P] [CAPS K_Q] [CAPS K_R] [CAPS K_S] [CAPS K_T] [CAPS K_U] [CAPS K_V] [CAPS K_W] [CAPS K_X] [CAPS K_Y] [CAPS K_Z] +c store(caps) 'A' 'B' 'N̄' 'D' 'E' 'F' 'G' 'SH' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'CH' 'R' 'S' 'T' 'U' 'V' 'W' 'Ọ' 'Y' 'Z' +store(digit) '0'..'9' + +group(NewContext) readonly + nomatch > use(detectStartOfSentence) +group(PostKeystroke) readonly + if(&layerChanged = "0") if(&layer = 'numeric') any(digit) > context + if(&layer = 'caps') > context + if(&layerChanged = "0") > use(detectStartOfSentence) +group(detectStartOfSentence) readonly + store(sentencePunctuation) '.?!‽' + nul > layer('shift') + any(sentencePunctuation) ' ' > layer('shift') + any(sentencePunctuation) ' ' > layer('shift') + nomatch > layer('default') +c group(main) using keys +c + any(key) > index(out, 1) + +store(accentibles) 'aeiọoumnAEIỌOUMNn̄' +store(accents) [T_GRV] [T_ACU] [T_CCM] [T_CRN] [SHIFT T_GRV] [SHIFT T_ACU] [SHIFT T_CCM] [SHIFT T_CRN] [CAPS T_GRV] [CAPS T_ACU] [CAPS T_CCM] [CAPS T_CRN] c [K_BKQUOTE] [K_BKSLASH] +store(nasals) 'mnMN' +store(nnas) [NCAPS T_CCM] [NCAPS T_CRN] [SHIFT NCAPS T_CCM] [SHIFT NCAPS T_CRN] [CAPS T_CCM] [CAPS T_CRN] c [K_BKSLASH] [SHIFT K_BKSLASH] +store(vow) 'aeiouAEIOU' +store(grave) 'àèìòùÀÈÌÒÙ' +store(acute) 'áéíóúÁÉÍÓÚ' +store(circum) 'âêîôûÂÊÎÔÛ' +store(caron) 'ǎěǐǒǔǍĚǏǑǓ' +store(acnasals) 'ḿńḾŃ' +store(spguy) 'mnọMNỌ' +store(spguyop) 'ḿǹộḾǸỘ' +store(erase) [NCAPS K_BKSP] [NCAPS SHIFT K_BKSP] [CAPS K_BKSP] [NCAPS ALT K_BKSP] +store(gravekeys) [NCAPS T_GRV] [SHIFT NCAPS T_GRV] [CAPS T_GRV] [K_BKQUOTE] +store(acutekeys) [NCAPS T_ACU] [SHIFT NCAPS T_ACU] [CAPS T_ACU] [SHIFT K_BKQUOTE] +store(circumflexkeys) [NCAPS T_CCM] [SHIFT NCAPS T_CCM] [CAPS T_CCM] [K_BKSLASH] +store(caronkeys) [NCAPS T_CRN] [SHIFT NCAPS T_CRN] [CAPS T_CRN] [SHIFT K_BKSLASH] + +group(main) using keys + +c + any(capskeys) > index(caps, 1) c by self to solve caps + ++ [NCAPS T_ENG] > dk(1) ++ [SHIFT NCAPS T_ENG] > dk(2) ++ [CAPS T_ENG] > dk(3) + +c caps ++ [CAPS K_A] > 'A' ++ [CAPS K_B] > 'B' ++ [CAPS K_D] > 'D' ++ [CAPS K_E] > 'E' ++ [CAPS K_F] > 'F' ++ [CAPS K_G] > 'G' ++ [CAPS K_I] > 'I' ++ [CAPS K_J] > 'J' ++ [CAPS K_K] > 'K' ++ [CAPS K_L] > 'L' ++ [CAPS K_M] > 'M' ++ [CAPS K_N] > 'N' ++ [CAPS K_O] > 'O' ++ [CAPS K_P] > 'P' ++ [CAPS K_R] > 'R' ++ [CAPS K_S] > 'S' ++ [CAPS K_T] > 'T' ++ [CAPS K_U] > 'U' ++ [CAPS K_V] > 'V' ++ [CAPS K_W] > 'W' ++ [CAPS K_Y] > 'Y' ++ [CAPS K_Z] > 'Z' + ++ [CAPS K_Q] > 'CH' ++ [CAPS K_H] > 'SH' ++ [CAPS K_X] > 'Ọ' ++ [CAPS K_C] > 'N̄' + ++ [NCAPS K_Q] > 'ch' ++ [NCAPS K_H] > 'sh' ++ [NCAPS K_X] > 'ọ' ++ [NCAPS K_C] > 'n̄' + ++ [SHIFT CAPS K_Q] > 'Ch' ++ [SHIFT CAPS K_H] > 'Sh' ++ [SHIFT CAPS K_X] > 'ọ' ++ [SHIFT CAPS K_C] > 'n̄' + ++ [SHIFT NCAPS K_Q] > 'Ch' ++ [SHIFT NCAPS K_H] > 'Sh' ++ [SHIFT NCAPS K_X] > 'Ọ' ++ [SHIFT NCAPS K_C] > 'N̄' + ++ [SHIFT K_6] > '₦' + +c (for touch layout) ++ [NCAPS T_Q] > 'ch' ++ [NCAPS SHIFT T_Q] > 'Ch' ++ [CAPS T_Q] > 'CH' + ++ [NCAPS T_H] > 'sh' ++ [NCAPS SHIFT T_H] > 'Sh' ++ [CAPS T_H] > 'SH' + ++ [NCAPS T_X] > 'ọ' ++ [NCAPS SHIFT T_X] > 'Ọ' ++ [CAPS T_X] > 'Ọ' + ++ [NCAPS T_C] > 'n̄' ++ [NCAPS SHIFT T_C] > 'N̄' ++ [CAPS T_C] > 'N̄' + +c for mobile longpress +c + [SHIFT T_MWG] > 'M̀' +c + [T_MWG] > 'm̀' +c + [SHIFT T_ORWG] > 'Ọ̀' +c + [T_ORWG] > 'ọ̀' + + +c English equivalent (for desktop) +']' + [CAPS K_C] > 'C' +']' + [NCAPS K_C] > 'c' +']' + [SHIFT NCAPS K_C] > 'C' +']' + [SHIFT CAPS K_C] > 'c' + +']' + [CAPS K_X] > 'X' +']' + [NCAPS K_X] > 'x' +']' + [SHIFT NCAPS K_X] > 'X' +']' + [SHIFT CAPS K_X] > 'x' + +']' + [CAPS K_H] > 'H' +']' + [NCAPS K_H] > 'h' +']' + [SHIFT NCAPS K_H] > 'H' +']' + [SHIFT CAPS K_H] > 'h' + +']' + [CAPS K_Q] > 'Q' +']' + [NCAPS K_Q] > 'q' +']' + [NCAPS SHIFT K_Q] > 'Q' +']' + [SHIFT CAPS K_Q] > 'q' + +']' + [SHIFT K_6] > '^' + +c space modifier accents +']' + [K_BKQUOTE] > "`" +']' + [SHIFT K_BKQUOTE] > "´" + +']' + [K_BKSLASH] > "ˆ" +']' + [SHIFT K_BKSLASH] > "ˇ" + +c English equivalent (for touch layout) +dk(1) + [NCAPS T_Q] > 'q' +dk(2) + [NCAPS SHIFT T_Q] > 'Q' +dk(3) + [CAPS T_Q] > 'Q' + +dk(1) + [NCAPS T_H] > 'h' +dk(2) + [SHIFT NCAPS T_H] > 'H' +dk(3) + [CAPS T_H] > 'H' + +dk(1) + [NCAPS T_X] > 'x' +dk(2) + [SHIFT NCAPS T_X] > 'X' +dk(3) + [CAPS T_X] > 'X' + +dk(1) + [NCAPS T_C] > 'c' +dk(2) + [SHIFT NCAPS T_C] > 'C' +dk(3) + [CAPS T_C] > 'C' + +dk(1) + [NCAPS K_S] > 'ṣ' +dk(2) + [SHIFT NCAPS K_S] > 'Ṣ' +dk(3) + [CAPS K_S] > 'Ṣ' + +c deadkey for tones (touch layout only) +dk(1) + [NCAPS T_GRV] > "`" +dk(2) + [SHIFT NCAPS T_GRV] > "`" +dk(3) + [CAPS T_GRV] > "`" + +dk(1) + [NCAPS T_ACU] > "´" +dk(2) + [SHIFT NCAPS T_ACU] > "´" +dk(3) + [CAPS T_ACU] > "´" + +dk(1) + [NCAPS T_CCM] > "ˆ" +dk(2) + [SHIFT NCAPS T_CCM] > "ˆ" +dk(3) + [CAPS T_CCM] > "ˆ" + +dk(1) + [NCAPS T_CRN] > "ˇ" +dk(2) + [SHIFT NCAPS T_CRN] > "ˇ" +dk(3) + [CAPS T_CRN] > "ˇ" + +dk(1) + [NCAPS K_HYPHEN] > "¯" +dk(2) + [SHIFT NCAPS K_HYPHEN] > "¯" +dk(3) + [CAPS K_HYPHEN] > "¯" + +c make up for +'m' + any(gravekeys) > 'm̀' +'M' + any(gravekeys) > 'M̀' + +'n' + any(gravekeys) > 'ǹ' +'N' + any(gravekeys) > 'Ǹ' + +'ọ' + any(gravekeys) > 'ọ̀' +'Ọ' + any(gravekeys) > 'Ọ̀' + +'ọ' + any(acutekeys) > 'ọ́' +'Ọ' + any(acutekeys) > 'Ọ́' + +'ọ' + any(circumflexkeys) > 'ộ' +'Ọ' + any(circumflexkeys) > 'Ộ' + +'ọ' + any(caronkeys) > 'ọ̌' +'Ọ' + any(caronkeys) > 'Ọ̌' + +'n̄' + [K_BKSLASH] > 'ñ' +'N̄' + [K_BKSLASH] > 'Ñ' + +'s' + [K_BKSLASH] > 'ṣ' +'S' + [K_BKSLASH] > 'Ṣ' + +c any and index +any(vow) + any(gravekeys) > index(grave,1) +any(vow) + any(acutekeys) > index(acute,1) +any(vow) + any(circumflexkeys) > index(circum,1) +any(vow) + any(caronkeys) > index(caron,1) +any(nasals) + any(acutekeys) > index(acnasals,1) + +c change backspace behaviour for special diagraphs +'ch' + any(erase) > nul +'Ch' + any(erase) > nul +'CH' + any(erase) > nul +'sh' + any(erase) > nul +'Sh' + any(erase) > nul +'SH' + any(erase) > nul +'n̄' + any(erase) > nul +'N̄' + any(erase) > nul + +c virtual keys +any(grave) + any(erase) > index(vow,1) +any(acute) + any(erase) > index(vow,1) +any(circum) + any(erase) > index(vow,1) +any(caron) + any(erase) > index(vow,1) +any(spguyop) + any(erase) > index(spguy,1) + +any(nasals) + any(nnas) > context beep c prevent certain accents on nasal consonants +c notany(accentibles) + any(accents) > context beep c prevent diacritics (stacking, on empty space, and plain consonants) diff --git a/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kps b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kps new file mode 100644 index 0000000000..c6688a853b --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kps @@ -0,0 +1,121 @@ + + + + 15.0.206.0 + 7.0 + + + + readme.htm + + + + + + + + + + + Obolo Chwerty + © 2019-2022 Rogers Katelem Edeh + Rogers Katelem Edeh + + + + ..\build\obolo_chwerty_6347.kvk + File obolo_chwerty_6347.kvk + 0 + .kvk + + + ..\build\obolo_chwerty_6347.kmx + Keyboard Obolo Chwerty + 0 + .kmx + + + ..\build\obolo_chwerty_6347.js + File obolo_chwerty_6347.js + 0 + .js + + + welcome\chwerty_default.png + File chwerty_default.png + 0 + .png + + + welcome\chwerty_keycombi.png + File chwerty_keycombi.png + 0 + .png + + + welcome\chwerty_mobi_alt.png + File chwerty_mobi_alt.png + 0 + .png + + + welcome\chwerty_mobi_default.png + File chwerty_mobi_default.png + 0 + .png + + + welcome\chwerty_mobi_shift.png + File chwerty_mobi_shift.png + 0 + .png + + + welcome\chwerty_shift.png + File chwerty_shift.png + 0 + .png + + + welcome\chwertyftkey1.png + File chwertyftkey1.png + 0 + .png + + + welcome\chwertyftkey2.png + File chwertyftkey2.png + 0 + .png + + + welcome\chwertyftkey3.png + File chwertyftkey3.png + 0 + .png + + + welcome\welcome.htm + File welcome.htm + 0 + .htm + + + readme.htm + File readme.htm + 0 + .htm + + + + + Obolo Chwerty + obolo_chwerty + 1.2.1 + + Obolo (Andoni) + + + + + diff --git a/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kvks b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kvks new file mode 100644 index 0000000000..0ba3c147a0 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kvks @@ -0,0 +1,114 @@ + + +
+ 10.0 + obolo_chwerty + + + +
+ + + ` + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + - + = + ch + w + e + r + t + y + u + i + o + p + [ + ] + a + s + d + f + g + sh + j + k + l + ; + ` + z + ọ + n̄ + v + b + n + m + , + . + / + + ' + \ˆ + + + ¬ + ! + @ + # + $ + % + & + * + ( + ) + _ + + + CH + W + E + R + T + Y + U + I + O + P + { + } + " + A + S + D + F + G + SH + J + K + L + : + Z + Ọ + N̄ + V + B + N + M + < + > + ? + + ~´ + |ˇ + ₦ + + +
diff --git a/common/test/keyboards/obolo_chwerty_6347/source/readme.htm b/common/test/keyboards/obolo_chwerty_6347/source/readme.htm new file mode 100644 index 0000000000..291bff96dc --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/source/readme.htm @@ -0,0 +1,28 @@ + + + + + Obolo Chwerty + + + + +

Obolo Chwerty

+

This is a keyboard layout (chwerty) for the Obolo language of Nigeria. This layout covers the need of every dialect in that language. + +

NOTE: This keyboard has been modified from the original for the purposes of +testing https://github.com/keymanapp/keyman/issues/6347. It is not intended to +be used for general purposes, and is not the final release version. Changes +made:

+ + + + + diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_default.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_default.png new file mode 100644 index 0000000000..097553943e Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_default.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_keycombi.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_keycombi.png new file mode 100644 index 0000000000..a71cdd524f Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_keycombi.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_alt.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_alt.png new file mode 100644 index 0000000000..81b2472a00 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_alt.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_default.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_default.png new file mode 100644 index 0000000000..a80191a561 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_default.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_shift.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_shift.png new file mode 100644 index 0000000000..c9fca97313 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_shift.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_shift.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_shift.png new file mode 100644 index 0000000000..460ee067ce Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_shift.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey1.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey1.png new file mode 100644 index 0000000000..66406ba6e4 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey1.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey2.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey2.png new file mode 100644 index 0000000000..8554a69418 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey2.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey3.png b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey3.png new file mode 100644 index 0000000000..73d72a13d0 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey3.png differ diff --git a/common/test/keyboards/obolo_chwerty_6347/source/welcome/welcome.htm b/common/test/keyboards/obolo_chwerty_6347/source/welcome/welcome.htm new file mode 100644 index 0000000000..625fd6ffd3 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6347/source/welcome/welcome.htm @@ -0,0 +1,97 @@ + + + + + Start Using Obolo Chwerty Keyboard + + + + + +

+Obolo Chwerty Keyboard

+

Rogers Katelem Edeh


+ +

Onu! (Welcome!)

+

+This is the Chwerty layout for writing Obolo language. In this keyboard, accents are typed after the base letters. +

+So, to type "usem Obolo" with this keyboard layout, simply tap the given letters and tap the appropriate accents to pace them on the letters. +

+ + +

Keyboard Layout

+

+The keyboard uses CHWERTY layout. +

+"Ebi Obolo" do not have 'C' and 'H' in their "abiche" (alphabet), but they have the 'CH' sound (as well as the 'SH' sound in some dialect).
+This and other features make Obolo Language unique, hence this unique layout. +

+

Desktop Layout

+ + +

+ +

+

Mobile/Tablet Layout

+

Due to the size and number of keys, some characters are hidden in the long press. Press and hold on the key with a little dot on the top right to reveal and use them.

+

+ +

+ +

+ +

+ In this language, note that: +

(1) Only one tone mark can sit on a letter. So, diacritic stacking is not allowed. +

(2) Some tones are not to be marked in writing; they are not required. They are only used in primers and for beginners. +

(3) Some letters do not accept some accents. +

(4) Others do not accept accents at all. +

+Except for the optional accents which are not required, the keyboard will notify you when you inadvertently go against the spelling rules. +

+On mobile devices, tap the deadkey (⨷) then the given key to get the English letter in that position. +

+On desktop, if what you are doing does not support 'n̄' or does not render it well, then you can tap the BACKSLASH key after the 'n̄' to get 'ñ'. +

+The position of your BACKSLASH key depends on type of keyboard you are using. You can tell where your BACKSLASH key is by looking at the shape of the ENTER/RETURN key on your keyboard +

The three keyboard types and the respective position of the BACKSLASH keys are shown below: +

+ +

+ +

+ +

+Use this sentence to test your keyboard and character set: +

+mkpinyọn̄ kè evion̄ îben nchat balì ije bûu kire ǹnàan̄ iraka òsô mè ùkộ fiâm ikilap mudim m̀fọ̀tọ̀ shishini me èwê ozugbo +

+MKPINYỌN̄ KÈ EVION̄ ÎBEN NCHAT BALÌ IJE BÛU KIRE ǸNÀAN̄ IRAKA ÒSÔ MÈ ÙKỘ FIÂM IKILAP MUDIM M̀FỌ̀TỌ̀ SHISHINI ME ÈWÊ OZUGBO +

+Keyman ... type to the world in your language. +
+Obolo Chwerty ... ge inu me usem kwun̄ ria si ere geelek me linyọn̄. +

Onirọ-o! +

Itọn̄ ikup inyi Awaji! + + diff --git a/common/test/keyboards/obolo_chwerty_6351/HISTORY.md b/common/test/keyboards/obolo_chwerty_6351/HISTORY.md new file mode 100644 index 0000000000..e4b8b51ee0 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/HISTORY.md @@ -0,0 +1,36 @@ +Obolo Chwerty Keyboard Change History +==================== + +1.2.1 (2021-11-23) +---------------- +* Removed accent key from numbers row on default layer, and from symbols row on shift layer. + +1.2.0 (2021-07-05) +---------------- +* Updated keycap for key 6 to match output on mobile shift layer, and added longpress for ^ +* Activated spacebar on layer alt for mobile/tablet layout +* Updated documentation +* Miscellaneous minor updates + +1.1.2 (2021-02-04) +---------------- +* Updated output for keys CH and SH on SHIFT layer to match key cap on touchscreen and desktop. +* Resolved capslock issue for keys CH, SH, Ọ and N̄ on desktop. +* Added long press on touchscreen for frequently used accented letters. +* Added the Naira sign (₦) and Ñ (an alternative where software cannot render N̄ well, though Ñ is not part of the Obolo orthography.) + +1.1.1 (2020-10-27) +---------------- +* Increment version number to force recompile of touch layout + +1.1 (2020-07-07) +---------------- +* Moved the high tone (which is not required, except in primers) to long press on low tone button (for touchscreen). +* Changed backspace behavior for ch, sh, n̄. +* Added long press for Q, H, X and C keys on touchscreen. +* Added hyphen-dash (a frequently used mark) to default and shift layers for touchscreen. +* Fixed typo and omissions in documentation. + +1.0 (2019-07-20) +---------------- +* Created by Rogers Katelem Edeh diff --git a/common/test/keyboards/obolo_chwerty_6351/LICENSE.md b/common/test/keyboards/obolo_chwerty_6351/LICENSE.md new file mode 100644 index 0000000000..eee2ba508b --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +© 2019 - 2021 Rogers Katelem Edeh + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/common/test/keyboards/obolo_chwerty_6351/README.md b/common/test/keyboards/obolo_chwerty_6351/README.md new file mode 100644 index 0000000000..2c5fe9b38d --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/README.md @@ -0,0 +1,37 @@ +Obolo Chwerty keyboard +============== + +© 2019 - 2021 Rogers Katelem Edeh + +Version 1.2.0 + +Description +----------- + +NOTE: This keyboard has been modified from the original for the purposes of testing https://github.com/keymanapp/keyman/issues/6351. It is not intended to be used for general purposes, and is not the final release version. Changes made: + +* NCAPS mismatches have been resolved +* Files renamed +* Font and PHP help have been removed (reduce distribution size) + +Obolo Chwerty Keyboard is a keyboard layout for the Obolo language of Nigeria. This layout covers the need of every dialect in that language. +On this keyboard, accents are typed after the base letters. So, to type Obolo language, simply tap the given latters and tap the appropriate accent key to place the accent on the letter. + +Links +----- +https://keyman.com/keyboards/obolo_chwerty + +Supported Platforms +------------------- + * Windows + * macOS + * Linux + * Web + * iPhone + * iPad + * Android phone + * Android tablet + * Mobile devices + * Desktop devices + * Tablet devices + diff --git a/common/test/keyboards/obolo_chwerty_6351/obolo_chwerty_6351.keyboard_info b/common/test/keyboards/obolo_chwerty_6351/obolo_chwerty_6351.keyboard_info new file mode 100644 index 0000000000..1513b8bb47 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/obolo_chwerty_6351.keyboard_info @@ -0,0 +1,7 @@ +{ + "license": "mit", + "languages": [ + "ann-Latn" + ], + "description": "Obolo Chwerty Keyboard: A keyboard layout for the Obolo language of Nigeria. It covers the need of every dialect in that language" +} diff --git a/common/test/keyboards/obolo_chwerty_6351/obolo_chwerty_6351.kpj b/common/test/keyboards/obolo_chwerty_6351/obolo_chwerty_6351.kpj new file mode 100644 index 0000000000..7f076c964a --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/obolo_chwerty_6351.kpj @@ -0,0 +1,183 @@ + + + + $PROJECTPATH\build + True + True + True + keyboard + + + + id_e2041c991cdc20c570b342a5803447b0 + obolo_chwerty_6351.kmn + source\obolo_chwerty_6351.kmn + 1.2.1 + .kmn +

+ Obolo Chwerty + © 2019-2022 Rogers Katelem Edeh + A keyboard layout (chwerty) for the Obolo language of Nigeria. The keyboard covers the need of every dialect in that language. +
+ + + id_4ed7acb803d5177bff445780f774fdb3 + obolo_chwerty_6351.kps + source\obolo_chwerty_6351.kps + + .kps +
+ Obolo Chwerty + © 2019-2022 Rogers Katelem Edeh +
+
+ + id_ede98e4633e239f933cbfd1f4e1b766c + HISTORY.md + HISTORY.md + + .md + + + id_53e892b8b41cc4caece1cfd5ef21d6e7 + LICENSE.md + LICENSE.md + + .md + + + id_0730bb7c2e8f9ea2438b52e419dd86c9 + README.md + README.md + + .md + + + id_fa9ac62e52c7671ac61602e3583305fd + obolo_chwerty_6351.keyboard_info + obolo_chwerty_6351.keyboard_info + + .keyboard_info + + + id_ef2a383b75a0364689701ecbf2f6fefa + obolo_chwerty_6351.ico + source\obolo_chwerty_6351.ico + + .ico + id_e2041c991cdc20c570b342a5803447b0 + + + id_fa2b1b4a5977c1283d061d23611709ef + obolo_chwerty_6351.kvk + source\..\build\obolo_chwerty_6351.kvk + + .kvk + id_4ed7acb803d5177bff445780f774fdb3 + + + id_13adcc1b6b8e23edd35cfc6ab7c245b0 + obolo_chwerty_6351.kmx + source\..\build\obolo_chwerty_6351.kmx + + .kmx + id_4ed7acb803d5177bff445780f774fdb3 + + + id_3ec4dad3d83c69fc4b33eb86d401d8cb + obolo_chwerty_6351.js + source\..\build\obolo_chwerty_6351.js + + .js + id_4ed7acb803d5177bff445780f774fdb3 + + + id_f6212220adf6c5eb0ae25c33cb973c64 + chwerty_default.png + source\welcome\chwerty_default.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_cd62e578000692c9966c069950904d06 + chwerty_keycombi.png + source\welcome\chwerty_keycombi.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_2d29737f21e65a75ca98a9c3ab1f4a6f + chwerty_mobi_alt.png + source\welcome\chwerty_mobi_alt.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_2d856489cc6083c4b74a1b8c2b528785 + chwerty_mobi_default.png + source\welcome\chwerty_mobi_default.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_ee5bdb44f34cd08e1c6012f91790c302 + chwerty_mobi_shift.png + source\welcome\chwerty_mobi_shift.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_743e9cd02f1d4004a5320b9faa355587 + chwerty_shift.png + source\welcome\chwerty_shift.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_a81a3f903e8ce052259e09e4a6fbabb0 + chwertyftkey1.png + source\welcome\chwertyftkey1.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_cb8167846a4ac07edd78e5a39a7cc587 + chwertyftkey2.png + source\welcome\chwertyftkey2.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_7325a11eaf4f66357aa7185056091802 + chwertyftkey3.png + source\welcome\chwertyftkey3.png + + .png + id_4ed7acb803d5177bff445780f774fdb3 + + + id_724e5b4c63f10bc0abf7077f7c3172fc + welcome.htm + source\welcome\welcome.htm + + .htm + id_4ed7acb803d5177bff445780f774fdb3 + + + id_8da344c4cea6f467013357fe099006f5 + readme.htm + source\readme.htm + + .htm + id_4ed7acb803d5177bff445780f774fdb3 + + + diff --git a/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.css b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.css new file mode 100644 index 0000000000..c07f696e50 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.css @@ -0,0 +1,7 @@ +/* tone keys colour */ +.android .kmw-keyboard-obolo_chwerty_6351 #default-T_GRV {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6351 #default-T_CCM {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6351 #shift-T_GRV {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6351 #shift-T_CCM {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6351 #caps-T_GRV {color: #02ff02;} +.android .kmw-keyboard-obolo_chwerty_6351 #caps-T_CCM {color: #02ff02;} diff --git a/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.ico b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.ico new file mode 100644 index 0000000000..4d329aaf90 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.ico differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.keyman-touch-layout b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.keyman-touch-layout new file mode 100644 index 0000000000..c9e7ea336e --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.keyman-touch-layout @@ -0,0 +1,2053 @@ +{ + "tablet": { + "font": "Tahoma", + "layer": [ + { + "id": "default", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "1", + "width": "111", + "sk": [ + { + "text": "¹", + "id": "U_00B9" + }, + { + "text": "₁", + "id": "U_2081" + } + ] + }, + { + "id": "K_2", + "text": "2", + "width": "111", + "sk": [ + { + "text": "²", + "id": "U_00B2" + }, + { + "id": "U_2082" + } + ] + }, + { + "id": "K_3", + "text": "3", + "width": "111", + "sk": [ + { + "text": "³", + "id": "U_00B3" + }, + { + "id": "U_2083" + } + ] + }, + { + "id": "K_4", + "text": "4", + "width": "111", + "sk": [ + { + "text": "⁴", + "id": "U_2074" + }, + { + "text": "₄", + "id": "U_2084" + } + ] + }, + { + "id": "K_5", + "text": "5", + "width": "111", + "sk": [ + { + "text": "⁵", + "id": "U_2075" + }, + { + "id": "U_2085" + } + ] + }, + { + "id": "K_6", + "text": "6", + "width": "111", + "sk": [ + { + "text": "⁶", + "id": "U_2076" + }, + { + "id": "U_2086" + } + ] + }, + { + "id": "K_7", + "text": "7", + "width": "111", + "sk": [ + { + "text": "⁷", + "id": "U_2077" + }, + { + "id": "U_2087" + } + ] + }, + { + "id": "K_8", + "text": "8", + "width": "111", + "sk": [ + { + "text": "⁸", + "id": "U_2078" + }, + { + "text": "₈", + "id": "U_2088" + } + ] + }, + { + "id": "K_9", + "text": "9", + "width": "111", + "sk": [ + { + "text": "⁹", + "id": "U_2079" + }, + { + "id": "U_2089" + } + ] + }, + { + "id": "K_0", + "text": "0", + "width": "111", + "sk": [ + { + "text": "⁰", + "id": "U_2070" + }, + { + "id": "U_2080" + } + ] + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "T_Q", + "text": "ch", + "pad": "", + "width": "", + "sk": [ + { + "text": "q", + "id": "U_0071" + } + ] + }, + { + "id": "K_W", + "text": "w" + }, + { + "id": "K_E", + "text": "e", + "sk": [ + { + "text": "è", + "id": "U_00E8" + }, + { + "text": "ê", + "id": "U_00EA" + } + ] + }, + { + "id": "K_R", + "text": "r" + }, + { + "id": "K_T", + "text": "t" + }, + { + "id": "K_Y", + "text": "y" + }, + { + "id": "K_U", + "text": "u", + "sk": [ + { + "text": "ù", + "id": "U_00F9" + }, + { + "text": "û", + "id": "U_00FB" + } + ] + }, + { + "id": "K_I", + "text": "i", + "sk": [ + { + "text": "ì", + "id": "U_00EC" + }, + { + "text": "î", + "id": "U_00EE" + } + ] + }, + { + "id": "K_O", + "text": "o", + "sk": [ + { + "text": "ò", + "id": "U_00F2" + }, + { + "text": "ô", + "id": "U_00F4" + } + ] + }, + { + "id": "K_P", + "text": "p" + }, + { + "id": "T_GRV", + "text": "ˋ", + "sk": [ + { + "text": "´", + "id": "T_ACU" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_A", + "text": "a", + "pad": "70", + "sk": [ + { + "text": "à", + "id": "U_00E0" + }, + { + "text": "â", + "id": "U_00E2" + } + ] + }, + { + "id": "K_S", + "text": "s" + }, + { + "id": "K_D", + "text": "d" + }, + { + "id": "K_F", + "text": "f" + }, + { + "id": "K_G", + "text": "g" + }, + { + "id": "T_H", + "text": "sh", + "sk": [ + { + "text": "h", + "id": "U_0068" + }, + { + "text": "ṣ", + "id": "U_1E63" + } + ] + }, + { + "id": "K_J", + "text": "j" + }, + { + "id": "K_K", + "text": "k" + }, + { + "id": "K_L", + "text": "l" + }, + { + "id": "T_CCM", + "text": "ˆ", + "sk": [ + { + "text": "ˇ", + "id": "T_CRN" + } + ] + }, + { + "id": "T_SPA", + "text": "", + "width": "40", + "sp": "10" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "pad": "50", + "width": "120", + "sp": "1", + "nextlayer": "shift" + }, + { + "id": "K_Z", + "text": "z" + }, + { + "id": "T_X", + "text": "ọ", + "sk": [ + { + "text": "ọ̀", + "id": "U_1ECD_0300" + }, + { + "text": "ộ", + "id": "U_1ED9" + }, + { + "text": "x", + "id": "U_0078" + } + ] + }, + { + "id": "T_C", + "text": "n̄", + "sk": [ + { + "text": "ñ", + "id": "U_00F1" + }, + { + "text": "c", + "id": "U_0063" + } + ] + }, + { + "id": "K_V", + "text": "v" + }, + { + "id": "K_B", + "text": "b" + }, + { + "id": "K_N", + "text": "n", + "sk": [ + { + "text": "ǹ", + "id": "U_01F9" + } + ] + }, + { + "id": "K_M", + "text": "m", + "sk": [ + { + "text": "m̀", + "id": "U_006D_0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "text": "!", + "id": "U_0021" + }, + { + "text": "/", + "id": "U_002F" + }, + { + "text": "'", + "id": "U_0027" + }, + { + "text": "\"", + "id": "U_0022" + }, + { + "text": "(", + "id": "U_0028" + }, + { + "text": ")", + "id": "U_0029" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "120", + "sp": "1" + }, + { + "id": "T_SPB", + "text": "", + "width": "20", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_ALT", + "text": "*Symbol*", + "width": "120", + "sp": "1", + "nextlayer": "alt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "", + "sp": "1" + }, + { + "id": "K_COMMA", + "text": ",", + "sk": [ + { + "text": ";", + "id": "U_003B" + } + ] + }, + { + "id": "K_SPACE", + "text": "", + "width": "520", + "sp": "0" + }, + { + "id": "K_PERIOD", + "text": ".", + "sk": [ + { + "text": ":", + "id": "U_003A" + } + ] + }, + { + "id": "T_ENG", + "text": "⨷", + "sp": "1", + "sk": [ + { + "text": "–", + "id": "U_2013" + }, + { + "text": "—", + "id": "U_2014" + }, + { + "text": "_", + "id": "U_005F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "120", + "sp": "1" + } + ] + } + ] + }, + { + "id": "shift", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "!", + "width": "111" + }, + { + "id": "K_2", + "text": "@", + "width": "111" + }, + { + "id": "K_3", + "text": "#", + "width": "111" + }, + { + "id": "K_4", + "text": "$", + "width": "111" + }, + { + "id": "K_5", + "text": "%", + "width": "111", + "sk": [ + { + "text": "‰", + "id": "U_2030" + }, + { + "text": "‱", + "id": "U_2031" + } + ] + }, + { + "id": "U_20A6", + "text": "₦", + "width": "111", + "sk": [ + { + "text": "^", + "id": "U_005E" + } + ] + }, + { + "id": "K_7", + "text": "&", + "width": "111" + }, + { + "id": "K_8", + "text": "*", + "width": "111" + }, + { + "id": "K_9", + "text": "(", + "width": "111" + }, + { + "id": "K_0", + "text": ")", + "width": "111" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "T_Q", + "text": "Ch", + "pad": "", + "sk": [ + { + "text": "Q", + "id": "U_0051" + } + ] + }, + { + "id": "K_W", + "text": "W" + }, + { + "id": "K_E", + "text": "E", + "sk": [ + { + "text": "È", + "id": "U_00C8" + }, + { + "text": "Ê", + "id": "U_00CA" + } + ] + }, + { + "id": "K_R", + "text": "R" + }, + { + "id": "K_T", + "text": "T" + }, + { + "id": "K_Y", + "text": "Y" + }, + { + "id": "K_U", + "text": "U", + "sk": [ + { + "text": "Ù", + "id": "U_00D9" + }, + { + "text": "Û", + "id": "U_00DB" + } + ] + }, + { + "id": "K_I", + "text": "I", + "sk": [ + { + "text": "Ì", + "id": "U_00CC" + }, + { + "text": "Î", + "id": "U_00CE" + } + ] + }, + { + "id": "K_O", + "text": "O", + "sk": [ + { + "text": "Ò", + "id": "U_00D2" + }, + { + "text": "Ô", + "id": "U_00D4" + } + ] + }, + { + "id": "K_P", + "text": "P" + }, + { + "id": "T_GRV", + "text": "`", + "sk": [ + { + "text": "´", + "id": "T_ACU" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_A", + "text": "A", + "pad": "70", + "sk": [ + { + "text": "À", + "id": "U_00C0" + }, + { + "text": "Â", + "id": "U_00C2" + } + ] + }, + { + "id": "K_S", + "text": "S" + }, + { + "id": "K_D", + "text": "D" + }, + { + "id": "K_F", + "text": "F" + }, + { + "id": "K_G", + "text": "G" + }, + { + "id": "T_H", + "text": "Sh", + "sk": [ + { + "text": "H", + "id": "U_0048" + }, + { + "text": "Ṣ", + "id": "U_1E62" + } + ] + }, + { + "id": "K_J", + "text": "J" + }, + { + "id": "K_K", + "text": "K" + }, + { + "id": "K_L", + "text": "L" + }, + { + "id": "T_CCM", + "text": "ˆ", + "sk": [ + { + "text": "ˇ", + "id": "T_CRN" + } + ] + }, + { + "id": "T_SPC", + "text": "", + "width": "40", + "sp": "10" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "pad": "50", + "width": "120", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_Z", + "text": "Z" + }, + { + "id": "T_X", + "text": "Ọ", + "sk": [ + { + "text": "Ọ̀", + "id": "U_1ECC_0300" + }, + { + "text": "Ộ", + "id": "U_1ED8" + }, + { + "text": "X", + "id": "U_0058" + } + ] + }, + { + "id": "T_C", + "text": "N̄", + "sk": [ + { + "text": "Ñ", + "id": "U_00D1" + }, + { + "text": "C", + "id": "U_0043" + } + ] + }, + { + "id": "K_V", + "text": "V" + }, + { + "id": "K_B", + "text": "B" + }, + { + "id": "K_N", + "text": "N", + "sk": [ + { + "text": "Ǹ", + "id": "U_01F8" + } + ] + }, + { + "id": "K_M", + "text": "M", + "sk": [ + { + "text": "M̀", + "id": "U_004D_0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "text": "!", + "id": "U_0021" + }, + { + "text": "/", + "id": "U_002F" + }, + { + "text": "'", + "id": "U_0027" + }, + { + "text": "\"", + "id": "U_0022" + }, + { + "text": "(", + "id": "U_0028" + }, + { + "text": ")", + "id": "U_0029" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "120", + "sp": "1" + }, + { + "id": "T_SPD", + "text": "", + "width": "20", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_ALT", + "text": "*Symbol*", + "width": "120", + "sp": "1", + "nextlayer": "alt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "", + "sp": "1" + }, + { + "id": "U_002C", + "text": ",", + "width": "", + "sk": [ + { + "text": ";", + "id": "U_003B" + } + ] + }, + { + "id": "K_SPACE", + "text": "", + "width": "520", + "sp": "0" + }, + { + "id": "U_002E", + "text": ".", + "sk": [ + { + "text": ":", + "id": "U_003A" + } + ] + }, + { + "id": "T_ENG", + "text": "⨷", + "sp": "1", + "sk": [ + { + "text": "–", + "id": "U_2013" + }, + { + "text": "—", + "id": "U_2014" + }, + { + "text": "_", + "id": "U_005F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "120", + "sp": "1" + } + ] + } + ] + }, + { + "id": "alt", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "1", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "¹", + "id": "U_00B9" + }, + { + "text": "₁", + "id": "U_2081" + } + ] + }, + { + "id": "K_2", + "text": "2", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "²", + "id": "U_00B2" + }, + { + "text": "₂", + "id": "U_2082" + } + ] + }, + { + "id": "K_3", + "text": "3", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "³", + "id": "U_00B3" + }, + { + "text": "₃", + "id": "U_2083" + } + ] + }, + { + "id": "K_4", + "text": "4", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁴", + "id": "U_2074" + }, + { + "text": "₄", + "id": "U_2084" + } + ] + }, + { + "id": "K_5", + "text": "5", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁵", + "id": "U_2075" + }, + { + "text": "₅", + "id": "U_2085" + } + ] + }, + { + "id": "K_6", + "text": "6", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁶", + "id": "U_2076" + }, + { + "text": "₆", + "id": "U_2086" + } + ] + }, + { + "id": "K_7", + "text": "7", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁷", + "id": "U_2077" + }, + { + "text": "₇", + "id": "U_2087" + } + ] + }, + { + "id": "K_8", + "text": "8", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁸", + "id": "U_2078" + }, + { + "text": "₈", + "id": "U_2088" + } + ] + }, + { + "id": "K_9", + "text": "9", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁹", + "id": "U_2079" + }, + { + "text": "₉", + "id": "U_2089" + } + ] + }, + { + "id": "K_0", + "text": "0", + "width": "111", + "layer": "default", + "sk": [ + { + "text": "⁰", + "id": "U_2070" + }, + { + "text": "₀", + "id": "U_2080" + } + ] + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "U_002B", + "text": "+", + "pad": "", + "sk": [ + { + "text": "±", + "id": "U_00B1" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "text": "∓", + "id": "U_2213" + } + ] + }, + { + "id": "U_00D7", + "text": "×" + }, + { + "id": "U_00F7", + "text": "÷" + }, + { + "id": "U_2236", + "text": "∶", + "sk": [ + { + "text": "·", + "id": "U_00B7" + }, + { + "text": "∴", + "id": "U_2234" + }, + { + "text": "∵", + "id": "U_2235" + } + ] + }, + { + "id": "U_221A", + "text": "√", + "sk": [ + { + "text": "∛", + "id": "U_221B" + }, + { + "text": "∜", + "id": "U_221C" + } + ] + }, + { + "id": "U_005E", + "text": "^" + }, + { + "id": "U_003D", + "text": "=", + "sk": [ + { + "text": "≠", + "id": "U_2260" + }, + { + "text": "≈", + "id": "U_2248" + }, + { + "text": "≡", + "id": "U_2261" + } + ] + }, + { + "id": "U_007E", + "text": "~" + }, + { + "id": "U_203D", + "text": "‽", + "width": "", + "sk": [ + { + "text": "¡", + "id": "U_00A1" + } + ] + }, + { + "id": "U_2713", + "text": "✓", + "sk": [ + { + "text": "Δ", + "id": "U_0394" + }, + { + "text": "✗", + "id": "U_2717" + }, + { + "text": "⛯", + "id": "U_26EF" + }, + { + "text": "⛭", + "id": "U_26ED" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "U_007B", + "text": "{", + "pad": "" + }, + { + "id": "U_00AB", + "text": "«" + }, + { + "id": "U_003C", + "text": "<", + "sk": [ + { + "text": "≪", + "id": "U_226A" + }, + { + "text": "≤", + "id": "U_2264" + } + ] + }, + { + "id": "U_005B", + "text": "[" + }, + { + "id": "U_0028", + "text": "(" + }, + { + "id": "U_007C", + "text": "|" + }, + { + "id": "U_0029", + "text": ")" + }, + { + "id": "U_005D", + "text": "]" + }, + { + "id": "U_003E", + "text": ">", + "sk": [ + { + "text": "≫", + "id": "U_226B" + }, + { + "text": "≥", + "id": "U_2265" + } + ] + }, + { + "id": "U_00BB", + "text": "»" + }, + { + "id": "U_007D", + "text": "}" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "pad": "50", + "width": "120", + "sp": "1", + "nextlayer": "shift" + }, + { + "id": "U_221E", + "text": "∞", + "sk": [ + { + "text": "∂", + "id": "U_2202" + } + ] + }, + { + "id": "U_222B", + "text": "∫", + "sk": [ + { + "text": "ẋ", + "id": "U_1E8B" + }, + { + "text": "ẍ", + "id": "U_1E8D" + }, + { + "text": "ẏ", + "id": "U_1E8F" + }, + { + "text": "ӱ", + "id": "U_04F1" + } + ] + }, + { + "id": "U_00B0", + "text": "°", + "sk": [ + { + "text": "℃", + "id": "U_2103" + }, + { + "text": "℉", + "id": "U_2109" + } + ] + }, + { + "id": "U_03C0", + "text": "π" + }, + { + "id": "U_03B8", + "text": "θ" + }, + { + "id": "U_33D1", + "text": "㏑", + "sk": [ + { + "text": "㏒", + "id": "U_33D2" + } + ] + }, + { + "id": "U_00A9", + "text": "©", + "sk": [ + { + "text": "®", + "id": "U_00AE" + }, + { + "text": "℗", + "id": "U_2117" + }, + { + "text": "🛈", + "id": "U_1F6C8" + }, + { + "text": "™", + "id": "U_2122" + }, + { + "text": "℅", + "id": "U_2105" + } + ] + }, + { + "id": "U_002F", + "text": "/", + "sk": [ + { + "text": "\\", + "id": "U_005C" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "120", + "sp": "1" + }, + { + "id": "T_SPF", + "text": "", + "width": "20", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_ALT", + "text": "*abc*", + "width": "120", + "sp": "1", + "nextlayer": "default" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "", + "sp": "1" + }, + { + "id": "U_00A7", + "text": "§", + "sk": [ + { + "text": "₍", + "id": "U_208D" + }, + { + "text": "ₓ", + "id": "U_2093" + }, + { + "text": "₊", + "id": "U_208A" + }, + { + "text": "₋", + "id": "U_208B" + }, + { + "text": "₎", + "id": "U_208E" + }, + { + "text": "₌", + "id": "U_208C" + } + ] + }, + { + "id": "K_SPACE", + "text": "", + "width": "520", + "sp": "0", + "layer": "default" + }, + { + "id": "U_00B6", + "text": "¶", + "sk": [ + { + "text": "⁽", + "id": "U_207D" + }, + { + "text": "ⁿ", + "id": "U_207F" + }, + { + "text": "⁺", + "id": "U_207A" + }, + { + "text": "⁻", + "id": "U_207B" + }, + { + "text": "⁾", + "id": "U_207E" + }, + { + "text": "⁼", + "id": "U_207C" + } + ] + }, + { + "id": "U_03A9", + "text": "Ω", + "sp": "1", + "sk": [ + { + "text": "♚", + "id": "U_265A" + }, + { + "text": "♔", + "id": "U_2654" + }, + { + "text": "♛", + "id": "U_265B" + }, + { + "text": "♕", + "id": "U_2655" + }, + { + "text": "♝", + "id": "U_265D" + }, + { + "text": "♗", + "id": "U_2657" + }, + { + "text": "♜", + "id": "U_265C" + }, + { + "text": "♖", + "id": "U_2656" + }, + { + "text": "♞", + "id": "U_265E" + }, + { + "text": "♘", + "id": "U_2658" + }, + { + "text": "♟", + "id": "U_265F" + }, + { + "text": "♙", + "id": "U_2659" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "120", + "sp": "1" + } + ] + } + ] + }, + { + "id": "caps", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "1", + "width": "111" + }, + { + "id": "K_2", + "text": "2", + "width": "111" + }, + { + "id": "K_3", + "text": "3", + "width": "111" + }, + { + "id": "K_4", + "text": "4", + "width": "111" + }, + { + "id": "K_5", + "text": "5", + "width": "111" + }, + { + "id": "K_6", + "text": "6", + "width": "111" + }, + { + "id": "K_7", + "text": "7", + "width": "111" + }, + { + "id": "K_8", + "text": "8", + "width": "111" + }, + { + "id": "K_9", + "text": "9", + "width": "111" + }, + { + "id": "K_0", + "text": "0", + "width": "111" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "T_Q", + "text": "CH", + "pad": "", + "sk": [ + { + "text": "Q", + "id": "U_0051" + } + ] + }, + { + "id": "K_W", + "text": "W" + }, + { + "id": "K_E", + "text": "E", + "sk": [ + { + "text": "È", + "id": "U_00C8" + }, + { + "text": "Ê", + "id": "U_00CA" + } + ] + }, + { + "id": "K_R", + "text": "R" + }, + { + "id": "K_T", + "text": "T" + }, + { + "id": "K_Y", + "text": "Y" + }, + { + "id": "K_U", + "text": "U", + "sk": [ + { + "text": "Ù", + "id": "U_00D9" + }, + { + "text": "Û", + "id": "U_00DB" + } + ] + }, + { + "id": "K_I", + "text": "I", + "sk": [ + { + "text": "Ì", + "id": "U_00CC" + }, + { + "text": "Î", + "id": "U_00CE" + } + ] + }, + { + "id": "K_O", + "text": "O", + "sk": [ + { + "text": "Ò", + "id": "U_00D2" + }, + { + "text": "Ô", + "id": "U_00D4" + } + ] + }, + { + "id": "K_P", + "text": "P" + }, + { + "id": "T_GRV", + "text": "`", + "sk": [ + { + "text": "´", + "id": "T_ACU" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_A", + "text": "A", + "pad": "70", + "sk": [ + { + "text": "À", + "id": "U_00C0" + }, + { + "text": "Â", + "id": "U_00C2" + } + ] + }, + { + "id": "K_S", + "text": "S" + }, + { + "id": "K_D", + "text": "D" + }, + { + "id": "K_F", + "text": "F" + }, + { + "id": "K_G", + "text": "G" + }, + { + "id": "T_H", + "text": "SH", + "sk": [ + { + "text": "H", + "id": "U_0048" + }, + { + "text": "Ṣ", + "id": "U_1E62" + } + ] + }, + { + "id": "K_J", + "text": "J" + }, + { + "id": "K_K", + "text": "K" + }, + { + "id": "K_L", + "text": "L" + }, + { + "id": "T_CCM", + "text": "ˆ", + "sk": [ + { + "text": "ˇ", + "id": "T_CRN" + } + ] + }, + { + "id": "T_SPC", + "text": "", + "width": "40", + "sp": "10" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "pad": "50", + "width": "120", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_Z", + "text": "Z" + }, + { + "id": "T_X", + "text": "Ọ", + "sk": [ + { + "text": "Ọ̀", + "id": "U_1ECC_0300" + }, + { + "text": "Ộ", + "id": "U_1ED8" + }, + { + "text": "X", + "id": "U_0058" + } + ] + }, + { + "id": "T_C", + "text": "N̄", + "sk": [ + { + "text": "Ñ", + "id": "U_00D1" + }, + { + "text": "C", + "id": "U_0043" + } + ] + }, + { + "id": "K_V", + "text": "V" + }, + { + "id": "K_B", + "text": "B" + }, + { + "id": "K_N", + "text": "N", + "sk": [ + { + "text": "Ǹ", + "id": "U_01F8" + } + ] + }, + { + "id": "K_M", + "text": "M", + "sk": [ + { + "text": "M̀", + "id": "U_004D_0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "text": "!", + "id": "U_0021" + }, + { + "text": "/", + "id": "U_002F" + }, + { + "text": "'", + "id": "U_0027" + }, + { + "text": "\"", + "id": "U_0022" + }, + { + "text": "(", + "id": "U_0028" + }, + { + "text": ")", + "id": "U_0029" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "120", + "sp": "1" + }, + { + "id": "T_SPD", + "text": "", + "width": "20", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_ALT", + "text": "*Symbol*", + "width": "120", + "sp": "1", + "nextlayer": "alt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "", + "sp": "1" + }, + { + "id": "U_002C", + "text": ",", + "width": "", + "sk": [ + { + "text": ";", + "id": "U_003B" + } + ] + }, + { + "id": "K_SPACE", + "text": "", + "width": "520", + "sp": "0" + }, + { + "id": "U_002E", + "text": ".", + "sk": [ + { + "text": ":", + "id": "U_003A" + } + ] + }, + { + "id": "T_ENG", + "text": "⨷", + "sp": "1", + "sk": [ + { + "text": "–", + "id": "U_2013" + }, + { + "text": "—", + "id": "U_2014" + }, + { + "text": "_", + "id": "U_005F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "120", + "sp": "1" + } + ] + } + ] + } + ], + "displayUnderlying": false, + "fontsize": "" + } +} \ No newline at end of file diff --git a/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kmn b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kmn new file mode 100644 index 0000000000..f5ae9bc72d --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kmn @@ -0,0 +1,254 @@ +store(&VERSION) '15.0' +store(&NAME) 'Obolo Chwerty #6351' +store(©RIGHT) '© 2019-2022 Rogers Katelem Edeh' +store(&TARGETS) 'any' +store(&VISUALKEYBOARD) 'obolo_chwerty_6351.kvks' +store(&LAYOUTFILE) 'obolo_chwerty_6351.keyman-touch-layout' +store(&BITMAP) 'obolo_chwerty_6351.ico' +store(&MESSAGE) 'A keyboard layout (chwerty) for the Obolo language of Nigeria. The keyboard covers the need of every dialect in that language.' +store(&KMW_HELPTEXT) 'A simple keyboard layout (chwerty) to help you type very easily in Obolo language.' +store(&KEYBOARDVERSION) '1.2.1' +store(&KMW_EMBEDCSS) 'obolo_chwerty_6351.css' + +begin Unicode > use(main) +begin NewContext > use(NewContext) +begin PostKeystroke > use(PostKeystroke) + +c store(capskeys) [CAPS K_A] [CAPS K_B] [CAPS K_C] [CAPS K_D] [CAPS K_E] [CAPS K_F] [CAPS K_G] [CAPS K_H] [CAPS K_I] [CAPS K_J] [CAPS K_K] [CAPS K_L] [CAPS K_M] [CAPS K_N] [CAPS K_O] [CAPS K_P] [CAPS K_Q] [CAPS K_R] [CAPS K_S] [CAPS K_T] [CAPS K_U] [CAPS K_V] [CAPS K_W] [CAPS K_X] [CAPS K_Y] [CAPS K_Z] +c store(caps) 'A' 'B' 'N̄' 'D' 'E' 'F' 'G' 'SH' 'I' 'J' 'K' 'L' 'M' 'N' 'O' 'P' 'CH' 'R' 'S' 'T' 'U' 'V' 'W' 'Ọ' 'Y' 'Z' +store(digit) '0'..'9' + +group(NewContext) readonly + nomatch > use(detectStartOfSentence) +group(PostKeystroke) readonly + if(&layerChanged = "0") if(&layer = 'numeric') any(digit) > context + if(&layer = 'caps') > context + if(&layerChanged = "0") > use(detectStartOfSentence) +group(detectStartOfSentence) readonly + store(sentencePunctuation) '.?!‽' + nul > layer('shift') + any(sentencePunctuation) ' ' > layer('shift') + any(sentencePunctuation) ' ' > layer('shift') + nomatch > layer('default') +c group(main) using keys +c + any(key) > index(out, 1) + +store(accentibles) 'aeiọoumnAEIỌOUMNn̄' +store(accents) [T_GRV] [T_ACU] [T_CCM] [T_CRN] [SHIFT T_GRV] [SHIFT T_ACU] [SHIFT T_CCM] [SHIFT T_CRN] [CAPS T_GRV] [CAPS T_ACU] [CAPS T_CCM] [CAPS T_CRN] c [K_BKQUOTE] [K_BKSLASH] +store(nasals) 'mnMN' +store(nnas) [NCAPS T_CCM] [NCAPS T_CRN] [SHIFT NCAPS T_CCM] [SHIFT NCAPS T_CRN] [CAPS T_CCM] [CAPS T_CRN] c [K_BKSLASH] [SHIFT K_BKSLASH] +store(vow) 'aeiouAEIOU' +store(grave) 'àèìòùÀÈÌÒÙ' +store(acute) 'áéíóúÁÉÍÓÚ' +store(circum) 'âêîôûÂÊÎÔÛ' +store(caron) 'ǎěǐǒǔǍĚǏǑǓ' +store(acnasals) 'ḿńḾŃ' +store(spguy) 'mnọMNỌ' +store(spguyop) 'ḿǹộḾǸỘ' +store(erase) [NCAPS K_BKSP] [NCAPS SHIFT K_BKSP] [CAPS K_BKSP] [NCAPS ALT K_BKSP] +store(gravekeys) [NCAPS T_GRV] [SHIFT NCAPS T_GRV] [CAPS T_GRV] [K_BKQUOTE] +store(acutekeys) [NCAPS T_ACU] [SHIFT NCAPS T_ACU] [CAPS T_ACU] [SHIFT K_BKQUOTE] +store(circumflexkeys) [NCAPS T_CCM] [SHIFT NCAPS T_CCM] [CAPS T_CCM] [K_BKSLASH] +store(caronkeys) [NCAPS T_CRN] [SHIFT NCAPS T_CRN] [CAPS T_CRN] [SHIFT K_BKSLASH] + +group(main) using keys + +c + any(capskeys) > index(caps, 1) c by self to solve caps + ++ [NCAPS T_ENG] > dk(1) ++ [SHIFT NCAPS T_ENG] > dk(2) ++ [CAPS T_ENG] > dk(3) + +c caps ++ [CAPS K_A] > 'A' ++ [CAPS K_B] > 'B' ++ [CAPS K_D] > 'D' ++ [CAPS K_E] > 'E' ++ [CAPS K_F] > 'F' ++ [CAPS K_G] > 'G' ++ [CAPS K_I] > 'I' ++ [CAPS K_J] > 'J' ++ [CAPS K_K] > 'K' ++ [CAPS K_L] > 'L' ++ [CAPS K_M] > 'M' ++ [CAPS K_N] > 'N' ++ [CAPS K_O] > 'O' ++ [CAPS K_P] > 'P' ++ [CAPS K_R] > 'R' ++ [CAPS K_S] > 'S' ++ [CAPS K_T] > 'T' ++ [CAPS K_U] > 'U' ++ [CAPS K_V] > 'V' ++ [CAPS K_W] > 'W' ++ [CAPS K_Y] > 'Y' ++ [CAPS K_Z] > 'Z' + ++ [CAPS K_Q] > 'CH' ++ [CAPS K_H] > 'SH' ++ [CAPS K_X] > 'Ọ' ++ [CAPS K_C] > 'N̄' + ++ [NCAPS K_Q] > 'ch' ++ [NCAPS K_H] > 'sh' ++ [NCAPS K_X] > 'ọ' ++ [NCAPS K_C] > 'n̄' + ++ [SHIFT CAPS K_Q] > 'Ch' ++ [SHIFT CAPS K_H] > 'Sh' ++ [SHIFT CAPS K_X] > 'ọ' ++ [SHIFT CAPS K_C] > 'n̄' + ++ [SHIFT NCAPS K_Q] > 'Ch' ++ [SHIFT NCAPS K_H] > 'Sh' ++ [SHIFT NCAPS K_X] > 'Ọ' ++ [SHIFT NCAPS K_C] > 'N̄' + ++ [SHIFT K_6] > '₦' + +c (for touch layout) ++ [NCAPS T_Q] > 'ch' ++ [NCAPS SHIFT T_Q] > 'Ch' ++ [CAPS T_Q] > 'CH' + ++ [NCAPS T_H] > 'sh' ++ [NCAPS SHIFT T_H] > 'Sh' ++ [CAPS T_H] > 'SH' + ++ [NCAPS T_X] > 'ọ' ++ [NCAPS SHIFT T_X] > 'Ọ' ++ [CAPS T_X] > 'Ọ' + ++ [NCAPS T_C] > 'n̄' ++ [NCAPS SHIFT T_C] > 'N̄' ++ [CAPS T_C] > 'N̄' + +c for mobile longpress +c + [SHIFT T_MWG] > 'M̀' +c + [T_MWG] > 'm̀' +c + [SHIFT T_ORWG] > 'Ọ̀' +c + [T_ORWG] > 'ọ̀' + + +c English equivalent (for desktop) +']' + [CAPS K_C] > 'C' +']' + [NCAPS K_C] > 'c' +']' + [SHIFT NCAPS K_C] > 'C' +']' + [SHIFT CAPS K_C] > 'c' + +']' + [CAPS K_X] > 'X' +']' + [NCAPS K_X] > 'x' +']' + [SHIFT NCAPS K_X] > 'X' +']' + [SHIFT CAPS K_X] > 'x' + +']' + [CAPS K_H] > 'H' +']' + [NCAPS K_H] > 'h' +']' + [SHIFT NCAPS K_H] > 'H' +']' + [SHIFT CAPS K_H] > 'h' + +']' + [CAPS K_Q] > 'Q' +']' + [NCAPS K_Q] > 'q' +']' + [NCAPS SHIFT K_Q] > 'Q' +']' + [SHIFT CAPS K_Q] > 'q' + +']' + [SHIFT K_6] > '^' + +c space modifier accents +']' + [K_BKQUOTE] > "`" +']' + [SHIFT K_BKQUOTE] > "´" + +']' + [K_BKSLASH] > "ˆ" +']' + [SHIFT K_BKSLASH] > "ˇ" + +c English equivalent (for touch layout) +dk(1) + [NCAPS T_Q] > 'q' +dk(2) + [NCAPS SHIFT T_Q] > 'Q' +dk(3) + [CAPS T_Q] > 'Q' + +dk(1) + [NCAPS T_H] > 'h' +dk(2) + [SHIFT NCAPS T_H] > 'H' +dk(3) + [CAPS T_H] > 'H' + +dk(1) + [NCAPS T_X] > 'x' +dk(2) + [SHIFT NCAPS T_X] > 'X' +dk(3) + [CAPS T_X] > 'X' + +dk(1) + [NCAPS T_C] > 'c' +dk(2) + [SHIFT NCAPS T_C] > 'C' +dk(3) + [CAPS T_C] > 'C' + +dk(1) + [NCAPS K_S] > 'ṣ' +dk(2) + [SHIFT NCAPS K_S] > 'Ṣ' +dk(3) + [CAPS K_S] > 'Ṣ' + +c deadkey for tones (touch layout only) +dk(1) + [NCAPS T_GRV] > "`" +dk(2) + [SHIFT NCAPS T_GRV] > "`" +dk(3) + [CAPS T_GRV] > "`" + +dk(1) + [NCAPS T_ACU] > "´" +dk(2) + [SHIFT NCAPS T_ACU] > "´" +dk(3) + [CAPS T_ACU] > "´" + +dk(1) + [NCAPS T_CCM] > "ˆ" +dk(2) + [SHIFT NCAPS T_CCM] > "ˆ" +dk(3) + [CAPS T_CCM] > "ˆ" + +dk(1) + [NCAPS T_CRN] > "ˇ" +dk(2) + [SHIFT NCAPS T_CRN] > "ˇ" +dk(3) + [CAPS T_CRN] > "ˇ" + +dk(1) + [NCAPS K_HYPHEN] > "¯" +dk(2) + [SHIFT NCAPS K_HYPHEN] > "¯" +dk(3) + [CAPS K_HYPHEN] > "¯" + +c make up for +'m' + any(gravekeys) > 'm̀' +'M' + any(gravekeys) > 'M̀' + +'n' + any(gravekeys) > 'ǹ' +'N' + any(gravekeys) > 'Ǹ' + +'ọ' + any(gravekeys) > 'ọ̀' +'Ọ' + any(gravekeys) > 'Ọ̀' + +'ọ' + any(acutekeys) > 'ọ́' +'Ọ' + any(acutekeys) > 'Ọ́' + +'ọ' + any(circumflexkeys) > 'ộ' +'Ọ' + any(circumflexkeys) > 'Ộ' + +'ọ' + any(caronkeys) > 'ọ̌' +'Ọ' + any(caronkeys) > 'Ọ̌' + +'n̄' + [K_BKSLASH] > 'ñ' +'N̄' + [K_BKSLASH] > 'Ñ' + +'s' + [K_BKSLASH] > 'ṣ' +'S' + [K_BKSLASH] > 'Ṣ' + +c any and index +any(vow) + any(gravekeys) > index(grave,1) +any(vow) + any(acutekeys) > index(acute,1) +any(vow) + any(circumflexkeys) > index(circum,1) +any(vow) + any(caronkeys) > index(caron,1) +any(nasals) + any(acutekeys) > index(acnasals,1) + +c change backspace behaviour for special diagraphs +'ch' + any(erase) > nul +'Ch' + any(erase) > nul +'CH' + any(erase) > nul +'sh' + any(erase) > nul +'Sh' + any(erase) > nul +'SH' + any(erase) > nul +'n̄' + any(erase) > nul +'N̄' + any(erase) > nul + +c virtual keys +any(grave) + any(erase) > index(vow,1) +any(acute) + any(erase) > index(vow,1) +any(circum) + any(erase) > index(vow,1) +any(caron) + any(erase) > index(vow,1) +any(spguyop) + any(erase) > index(spguy,1) + +any(nasals) + any(nnas) > context beep c prevent certain accents on nasal consonants +c notany(accentibles) + any(accents) > context beep c prevent diacritics (stacking, on empty space, and plain consonants) diff --git a/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kps b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kps new file mode 100644 index 0000000000..60ba61477a --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kps @@ -0,0 +1,121 @@ + + + + 15.0.206.0 + 7.0 + + + + readme.htm + + + + + + + + + + + Obolo Chwerty + © 2019-2022 Rogers Katelem Edeh + Rogers Katelem Edeh + + + + ..\build\obolo_chwerty_6351.kvk + File obolo_chwerty_6351.kvk + 0 + .kvk + + + ..\build\obolo_chwerty_6351.kmx + Keyboard Obolo Chwerty + 0 + .kmx + + + ..\build\obolo_chwerty_6351.js + File obolo_chwerty_6351.js + 0 + .js + + + welcome\chwerty_default.png + File chwerty_default.png + 0 + .png + + + welcome\chwerty_keycombi.png + File chwerty_keycombi.png + 0 + .png + + + welcome\chwerty_mobi_alt.png + File chwerty_mobi_alt.png + 0 + .png + + + welcome\chwerty_mobi_default.png + File chwerty_mobi_default.png + 0 + .png + + + welcome\chwerty_mobi_shift.png + File chwerty_mobi_shift.png + 0 + .png + + + welcome\chwerty_shift.png + File chwerty_shift.png + 0 + .png + + + welcome\chwertyftkey1.png + File chwertyftkey1.png + 0 + .png + + + welcome\chwertyftkey2.png + File chwertyftkey2.png + 0 + .png + + + welcome\chwertyftkey3.png + File chwertyftkey3.png + 0 + .png + + + welcome\welcome.htm + File welcome.htm + 0 + .htm + + + readme.htm + File readme.htm + 0 + .htm + + + + + Obolo Chwerty + obolo_chwerty + 1.2.1 + + Obolo (Andoni) + + + + + diff --git a/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kvks b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kvks new file mode 100644 index 0000000000..0ba3c147a0 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kvks @@ -0,0 +1,114 @@ + + +
+ 10.0 + obolo_chwerty + + + +
+ + + ` + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + - + = + ch + w + e + r + t + y + u + i + o + p + [ + ] + a + s + d + f + g + sh + j + k + l + ; + ` + z + ọ + n̄ + v + b + n + m + , + . + / + + ' + \ˆ + + + ¬ + ! + @ + # + $ + % + & + * + ( + ) + _ + + + CH + W + E + R + T + Y + U + I + O + P + { + } + " + A + S + D + F + G + SH + J + K + L + : + Z + Ọ + N̄ + V + B + N + M + < + > + ? + + ~´ + |ˇ + ₦ + + +
diff --git a/common/test/keyboards/obolo_chwerty_6351/source/readme.htm b/common/test/keyboards/obolo_chwerty_6351/source/readme.htm new file mode 100644 index 0000000000..a4f9c5d456 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/source/readme.htm @@ -0,0 +1,29 @@ + + + + + Obolo Chwerty + + + + +

Obolo Chwerty

+

This is a keyboard layout (chwerty) for the Obolo language of Nigeria. This layout covers the need of every dialect in that language. + +

NOTE: This keyboard has been modified from the original for the purposes of +testing https://github.com/keymanapp/keyman/issues/6351. It is not intended to +be used for general purposes, and is not the final release version. Changes +made:

+ + + + + diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_default.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_default.png new file mode 100644 index 0000000000..097553943e Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_default.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_keycombi.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_keycombi.png new file mode 100644 index 0000000000..a71cdd524f Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_keycombi.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_alt.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_alt.png new file mode 100644 index 0000000000..81b2472a00 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_alt.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_default.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_default.png new file mode 100644 index 0000000000..a80191a561 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_default.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_shift.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_shift.png new file mode 100644 index 0000000000..c9fca97313 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_shift.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_shift.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_shift.png new file mode 100644 index 0000000000..460ee067ce Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_shift.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey1.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey1.png new file mode 100644 index 0000000000..66406ba6e4 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey1.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey2.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey2.png new file mode 100644 index 0000000000..8554a69418 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey2.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey3.png b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey3.png new file mode 100644 index 0000000000..73d72a13d0 Binary files /dev/null and b/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey3.png differ diff --git a/common/test/keyboards/obolo_chwerty_6351/source/welcome/welcome.htm b/common/test/keyboards/obolo_chwerty_6351/source/welcome/welcome.htm new file mode 100644 index 0000000000..625fd6ffd3 --- /dev/null +++ b/common/test/keyboards/obolo_chwerty_6351/source/welcome/welcome.htm @@ -0,0 +1,97 @@ + + + + + Start Using Obolo Chwerty Keyboard + + + + + +

+Obolo Chwerty Keyboard

+

Rogers Katelem Edeh


+ +

Onu! (Welcome!)

+

+This is the Chwerty layout for writing Obolo language. In this keyboard, accents are typed after the base letters. +

+So, to type "usem Obolo" with this keyboard layout, simply tap the given letters and tap the appropriate accents to pace them on the letters. +

+ + +

Keyboard Layout

+

+The keyboard uses CHWERTY layout. +

+"Ebi Obolo" do not have 'C' and 'H' in their "abiche" (alphabet), but they have the 'CH' sound (as well as the 'SH' sound in some dialect).
+This and other features make Obolo Language unique, hence this unique layout. +

+

Desktop Layout

+ + +

+ +

+

Mobile/Tablet Layout

+

Due to the size and number of keys, some characters are hidden in the long press. Press and hold on the key with a little dot on the top right to reveal and use them.

+

+ +

+ +

+ +

+ In this language, note that: +

(1) Only one tone mark can sit on a letter. So, diacritic stacking is not allowed. +

(2) Some tones are not to be marked in writing; they are not required. They are only used in primers and for beginners. +

(3) Some letters do not accept some accents. +

(4) Others do not accept accents at all. +

+Except for the optional accents which are not required, the keyboard will notify you when you inadvertently go against the spelling rules. +

+On mobile devices, tap the deadkey (⨷) then the given key to get the English letter in that position. +

+On desktop, if what you are doing does not support 'n̄' or does not render it well, then you can tap the BACKSLASH key after the 'n̄' to get 'ñ'. +

+The position of your BACKSLASH key depends on type of keyboard you are using. You can tell where your BACKSLASH key is by looking at the shape of the ENTER/RETURN key on your keyboard +

The three keyboard types and the respective position of the BACKSLASH keys are shown below: +

+ +

+ +

+ +

+Use this sentence to test your keyboard and character set: +

+mkpinyọn̄ kè evion̄ îben nchat balì ije bûu kire ǹnàan̄ iraka òsô mè ùkộ fiâm ikilap mudim m̀fọ̀tọ̀ shishini me èwê ozugbo +

+MKPINYỌN̄ KÈ EVION̄ ÎBEN NCHAT BALÌ IJE BÛU KIRE ǸNÀAN̄ IRAKA ÒSÔ MÈ ÙKỘ FIÂM IKILAP MUDIM M̀FỌ̀TỌ̀ SHISHINI ME ÈWÊ OZUGBO +

+Keyman ... type to the world in your language. +
+Obolo Chwerty ... ge inu me usem kwun̄ ria si ere geelek me linyọn̄. +

Onirọ-o! +

Itọn̄ ikup inyi Awaji! + + diff --git a/common/test/keyboards/the_99/README.md b/common/test/keyboards/the_99/README.md new file mode 100644 index 0000000000..4479efe738 --- /dev/null +++ b/common/test/keyboards/the_99/README.md @@ -0,0 +1,34 @@ +the 99 keyboard +============== + +Version 1.0 + +Description +----------- +the 99 generated from template. kmp.json manually edited to have system.fileVersion = "99.0" +to validate the minimum keyboard version is checked before package installation. + +Links +----- +See Github issue #6254 +https://github.com/keymanapp/keyman/issues/6254 + + +Copyright +--------- +See [LICENSE.md](LICENSE.md) + +Supported Platforms +------------------- + * Windows + * macOS + * Linux + * Web + * iPhone + * iPad + * Android phone + * Android tablet + * Mobile devices + * Desktop devices + * Tablet devices + diff --git a/common/test/keyboards/the_99/build.sh b/common/test/keyboards/the_99/build.sh new file mode 100755 index 0000000000..8ea4680ada --- /dev/null +++ b/common/test/keyboards/the_99/build.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash + +set -e +set -u + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../../resources/build/build-utils.sh" +# . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +## END STANDARD BUILD SCRIPT INCLUDE +THIS_DIR="$(dirname "$THIS_SCRIPT")" + +display_usage() { + echo "Usage: build.sh [-c]" + exit $1 +} + +# Parse args +shopt -s nocasematch + +CLEAN=false +DEBUG=false +QUIET=false +KEYBOARDS_ONLY=false + +while [[ $# -gt 0 ]] ; do + key="$1" + case $key in + --help|-h|-\?) + display_usage 0 + ;; + --clean|-c) + CLEAN=true + ;; + --debug|-d) + DEBUG=true + ;; + --silent|-s) + QUIET=true + ;; + --keyboard|-k) + KEYBOARDS_ONLY=true + ;; + *) + display_usage 1 + ;; + esac + shift +done + +if $CLEAN; then + if ! $QUIET; then + echo Cleaning the_99.kmp from build/ + fi + rm -rf "$THIS_DIR"/build +else + if ! $QUIET; then + echo Copying the_99.kmp to build/ + fi + mkdir -p "$THIS_DIR"/build + cp "$THIS_DIR"/the_99.kmp build/the_99.kmp +fi \ No newline at end of file diff --git a/common/test/keyboards/the_99/the_99.kmp b/common/test/keyboards/the_99/the_99.kmp new file mode 100644 index 0000000000..f634601670 Binary files /dev/null and b/common/test/keyboards/the_99/the_99.kmp differ diff --git a/developer/js/package-lock.json b/developer/js/package-lock.json index e9f86e6d49..7c5242c7ad 100644 --- a/developer/js/package-lock.json +++ b/developer/js/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/lexical-model-compiler", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/developer/js/package.json b/developer/js/package.json index d6110c62dd..feb257b144 100644 --- a/developer/js/package.json +++ b/developer/js/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/lexical-model-compiler", - "version": "15.0.211", + "version": "15.0.216", "description": "Keyman Developer lexical model compiler", "keywords": [ "keyboard", @@ -37,14 +37,14 @@ "node": ">=12.0.0" }, "dependencies": { - "@keymanapp/models-types": "^15.0.211", + "@keymanapp/models-types": "^15.0.216", "commander": "^3.0.0", "typescript": "^3.8.3", "xml2js": "^0.4.19" }, "devDependencies": { - "@keymanapp/models-templates": "^15.0.211", - "@keymanapp/models-wordbreakers": "^15.0.211", + "@keymanapp/models-templates": "^15.0.216", + "@keymanapp/models-wordbreakers": "^15.0.216", "@types/chai": "^4.1.7", "@types/mocha": "^5.2.7", "@types/node": "^10.14.6", diff --git a/developer/server/package-lock.json b/developer/server/package-lock.json index 85e02f8f68..d446541e4f 100644 --- a/developer/server/package-lock.json +++ b/developer/server/package-lock.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/developer-server", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/developer/server/package.json b/developer/server/package.json index 09eca855d5..aa88108be2 100644 --- a/developer/server/package.json +++ b/developer/server/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/developer-server", - "version": "15.0.211", + "version": "15.0.216", "description": "Keyman Developer backend server", "main": "dist/index.js", "scripts": { diff --git a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/InputViewController.swift b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/InputViewController.swift index 031bb9daab..ec7807110f 100644 --- a/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/InputViewController.swift +++ b/ios/engine/KMEI/KeymanEngine/Classes/Keyboard/InputViewController.swift @@ -287,7 +287,7 @@ open class InputViewController: UIInputViewController, KeymanWebDelegate { return } - // What the actual heck, Apple. Apparently, in system-keyboard mode, this is also self-triggered if we erase back to a newline. + // Apparently, in system-keyboard mode, this is also self-triggered if we erase back to a newline. // Refer to https://github.com/keymanapp/keyman/pull/2770 for context. if self.swallowBackspaceTextChange && Manager.shared.isSystemKeyboard && textDocumentProxy.documentContextBeforeInput == "\n" { self.swallowBackspaceTextChange = false @@ -333,6 +333,11 @@ open class InputViewController: UIInputViewController, KeymanWebDelegate { return } + if numCharsToDelete > 0 && textDocumentProxy.documentContextBeforeInput == nil { + textDocumentProxy.deleteBackward() + return + } + for _ in 0.. Mon, 02 Aug 2021 18:13:58 +0200 +keyman-config (14.0.287-1) unstable; urgency=medium + + * New upstream release + * Re-release to Debian + + -- Eberhard Beilharz Fri, 11 Mar 2022 12:32:34 +0100 + keyman-config (14.0.284-3) unstable; urgency=medium * Team upload diff --git a/linux/debian/control b/linux/debian/control index 3346bd0238..a599ab7ae6 100644 --- a/linux/debian/control +++ b/linux/debian/control @@ -36,17 +36,19 @@ Build-Depends: xvfb, metacity, gawk, -Standards-Version: 4.5.1 +Standards-Version: 4.6.0 Vcs-Git: https://github.com/keymanapp/keyman.git Vcs-Browser: https://github.com/keymanapp/keyman Homepage: https://www.keyman.com +Rules-Requires-Root: binary-targets Package: keyman Architecture: all Depends: libglib2.0-bin, python3-keyman-config (= ${binary:Version}), - ibus-keyman (= ${binary:Version}), + ibus-keyman (>= ${binary:Version}), + ibus-keyman (<< ${binary:Version}.1~), ${misc:Depends}, Recommends: onboard-keyman, diff --git a/linux/debian/copyright b/linux/debian/copyright index 837c30622f..5c7c5e9189 100644 --- a/linux/debian/copyright +++ b/linux/debian/copyright @@ -1,27 +1,105 @@ -Format: http://anonscm.debian.org/viewvc/dep/web/deps/dep5.mdwn?view=markup&pathrev=174 +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: keyman Upstream-Contact: Keyman team +Source: https://github.com/keymanapp/keyman Files: * -Copyright: Copyright (C) 2018-2021 SIL International +Copyright: 2018-2022 SIL International License: MIT Files: linux/ibus-keyman/* -Copyright: 2004-2021 SIL International +Copyright: 2004-2022 SIL International 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-2021 SIL International +Copyright: 2009-2022 SIL International License: GPL-2+ or MIT Files: linux/ibus-keyman/src/keyman-service.c linux/ibus-keyman/src/keyman-service.h -Copyright: 2018-2021 SIL International + linux/keyman-config/buildtools/help2md +Copyright: 2018-2022 SIL International License: GPL-3+ +Files: linux/ibus-keyman/config.rpath + linux/ibus-keyman/m4/* +Copyright: 1996-2003, 2009-2015, Free Software Foundation, Inc. +License: FSFULLR + +Files: linux/ibus-keyman/Makefile.am + linux/ibus-keyman/Makefile.in + linux/ibus-keyman/compile + linux/ibus-keyman/configure.ac + linux/ibus-keyman/depcomp + linux/ibus-keyman/m4/Makefile.am + linux/ibus-keyman/m4/Makefile.in + linux/ibus-keyman/missing + linux/ibus-keyman/src/Makefile.am + linux/ibus-keyman/src/Makefile.in + linux/ibus-keyman/src/engine.c + linux/ibus-keyman/src/engine.h + linux/ibus-keyman/src/main.c + linux/ibus-keyman/src/test/Makefile.am + linux/ibus-keyman/src/test/Makefile.in + linux/ibus-keyman/tap-driver.sh + linux/ibus-keyman/test-driver + linux/ibus-keyman/tests/Makefile.am + linux/ibus-keyman/tests/Makefile.in +Copyright: 1994-2017, Free Software Foundation, Inc. + 2009-2022, SIL International +License: GPL-2+ + +Files: linux/ibus-keyman/m4/gettext.m4 + linux/ibus-keyman/m4/intl.m4 + linux/ibus-keyman/m4/intldir.m4 + linux/ibus-keyman/m4/intlmacosx.m4 + linux/ibus-keyman/m4/lcmessage.m4 + linux/ibus-keyman/m4/nls.m4 + linux/ibus-keyman/m4/po.m4 + linux/ibus-keyman/m4/progtest.m4 +Copyright: 1995-2014, Free Software Foundation, Inc. +License: FSFULLR or GPL-3 or LGPL-3 + +Files: linux/ibus-keyman/install-sh +Copyright: 1994, X Consortium + 2018, SIL International +License: MIT + +Files: linux/ibus-keyman/INSTALL + linux/ibus-keyman/po/Makefile.in.in +Copyright: 1994-1996, 1999-2002, 2004-2016, Free Software Foundation, Inc. + 1995-1997, 2000-2007, 2009-2010, Ulrich Drepper +License: FSFAP + +Files: linux/ibus-keyman/icons/Makefile.am + linux/ibus-keyman/icons/Makefile.in +Copyright: 1994-2017, Free Software Foundation, Inc. + 2018, SIL International +License: LGPL-2+ + +Files: linux/ibus-keyman/tests/ibusimcontext.c + linux/ibus-keyman/tests/ibusimcontext.h +Copyright: 2008-2010, Peng Huang + 2008-2010, Red Hat, Inc. + 2008-2013, Peng Huang + 2008-2021, Red Hat, Inc. + 2015-2021, Takao Fujiwara + 2021-2022, SIL International +License: LGPL-2.1+ + +Files: linux/keyman-config/buildtools/help2man +Copyright: 1997-2005, 2009-2017, 2020-2021, Free Software Foundation, Inc. +License: GPL-3+ + +Files: debian/com.keyman.config.appdata.xml + debian/com.keyman.ibus_keyman.metainfo.xml +Copyright: 2019 Daniel Glassey + 2022 SIL International +License: MIT + License: MIT Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -61,6 +139,24 @@ License: GPL-2+ License version 2 can be found in the file `/usr/share/common-licenses/GPL-2'. +License: GPL-3 + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 3. + . + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + . + On Debian systems, the full text of the GNU General Public + License version 3 can be found in the file + `/usr/share/common-licenses/GPL-3'. + License: GPL-3+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -79,3 +175,55 @@ License: GPL-3+ On Debian systems, the full text of the GNU General Public License version 3 can be found in the file `/usr/share/common-licenses/GPL-3'. + +License: FSFULLR + This file is free software; the Free Software Foundation gives unlimited + permission to copy and/or distribute it, with or without modifications, as long + as this notice is preserved. + +License: FSFAP + Copying and distribution of this file, with or without modification, are + permitted in any medium without royalty provided the copyright notice and this + notice are preserved. This file is offered as-is, without any warranty. + +License: LGPL-2+ + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + . + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + . + You should have received a copy of the GNU Library General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + . + On Debian systems, the full text of the GNU Library General Public + License version 2 can be found in the file + `/usr/share/common-licenses/LGPL-2'. + +License: LGPL-2.1+ + This library is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at your option) + any later version. + . + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more + details. + . + You should have received a copy of the GNU Lesser General Public License + along with this library; if not, write to the Free Software Foundation, Inc., + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + . + On Debian systems, the full text of the GNU Lesser General Public + License version 2.1 can be found in the file + `/usr/share/common-licenses/LGPL-2.1'. + +License: LGPL-3 + On Debian systems, the full text of the GNU Lesser General Public + License version 3 can be found in `/usr/share/common-licenses/LGPL-3'. diff --git a/linux/debian/ibus-keyman.manpages b/linux/debian/ibus-keyman.manpages index a85b71d286..82aa3721aa 100644 --- a/linux/debian/ibus-keyman.manpages +++ b/linux/debian/ibus-keyman.manpages @@ -1 +1 @@ -debian/man/ibus-engine-keyman.1 +linux/ibus-keyman/man/ibus-engine-keyman.1 diff --git a/linux/debian/keyman.install b/linux/debian/keyman.install index 4bc765e59b..8096e324ae 100644 --- a/linux/debian/keyman.install +++ b/linux/debian/keyman.install @@ -10,5 +10,5 @@ linux/keyman-config/icons/48/km-config.png usr/share/icons/hicolor/48x48/apps/ linux/keyman-config/icons/64/application-x-kmp.png usr/share/icons/hicolor/64x64/mimetypes/ linux/keyman-config/icons/64/km-config.png usr/share/icons/hicolor/64x64/apps/ linux/keyman-config/keyman_config/icons/* usr/share/keyman/icons/ +linux/keyman-config/km-config.desktop usr/share/applications debian/com.keyman.config.appdata.xml usr/share/metainfo -debian/km-config.desktop usr/share/applications diff --git a/linux/debian/rules b/linux/debian/rules index 5effa0a117..f32d01f500 100755 --- a/linux/debian/rules +++ b/linux/debian/rules @@ -44,12 +44,14 @@ override_dh_auto_build: dh_auto_build --sourcedir=linux/keyman-config --buildsystem=pybuild $@ override_dh_auto_test: +ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) # keymankeyboardprocessor cd common/core/desktop && ./build.sh tests # ibus-keyman cd linux/ibus-keyman && make check VERBOSE=1 # keyman-config dh_auto_test --sourcedir=linux/keyman-config --buildsystem=pybuild $@ +endif override_dh_auto_install: # keymankeyboardprocessor diff --git a/linux/debian/man/ibus-engine-keyman.1 b/linux/ibus-keyman/man/ibus-engine-keyman.1 similarity index 100% rename from linux/debian/man/ibus-engine-keyman.1 rename to linux/ibus-keyman/man/ibus-engine-keyman.1 diff --git a/linux/ibus-keyman/tests/ibusimcontext.c b/linux/ibus-keyman/tests/ibusimcontext.c index 248c2833cf..ba958daaec 100644 --- a/linux/ibus-keyman/tests/ibusimcontext.c +++ b/linux/ibus-keyman/tests/ibusimcontext.c @@ -4,6 +4,7 @@ * Copyright (C) 2008-2013 Peng Huang * Copyright (C) 2015-2021 Takao Fujiwara * Copyright (C) 2008-2021 Red Hat, Inc. + * Copyright (C) 2021-2022 SIL International * * 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 3d901dbc0a..f45b404a26 100644 --- a/linux/ibus-keyman/tests/ibusimcontext.h +++ b/linux/ibus-keyman/tests/ibusimcontext.h @@ -3,6 +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 * * 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/buildtools/build-langtags.py b/linux/keyman-config/buildtools/build-langtags.py index 6253087df0..d05e9746a6 100755 --- a/linux/keyman-config/buildtools/build-langtags.py +++ b/linux/keyman-config/buildtools/build-langtags.py @@ -42,7 +42,7 @@ class LangTagsMap(): if len(lang['tag']) < 3: map3To2.append("'%s': '%s'" % (lang['iso639_3'], lang['tag'])) langTags.append( - "'%s': { 'full': '%s', 'region': '%s', 'script': '%s', 'suppress': %s }" % (lang['tag'], lang['full'], region, script, suppress)) + "'%s': {'full': '%s', 'region': '%s', 'script': '%s', 'suppress': %s}" % (lang['tag'], lang['full'], region, script, suppress)) allTags.append("'%s': '%s'" % (lang['tag'], lang['tag'])) if lang['tag'] != lang['full']: allTags.append("'%s': '%s'" % (lang['full'], lang['tag'])) @@ -52,8 +52,8 @@ class LangTagsMap(): allTags.append("'%s': '%s'" % (tag, lang['tag'])) langTagsString = ',\n '.join(map(str, langTags)) - allTagsString = ', '.join(allTags) - map3To2String = ', '.join(map3To2) + allTagsString = ',\n '.join(allTags) + map3To2String = ',\n '.join(map3To2) outputFile.write(" __langTags = {\n %s }\n\n" % langTagsString) outputFile.write(" __allTags = { %s }\n\n" % allTagsString) outputFile.write(" __map3To2 = { %s }\n" % map3To2String) diff --git a/linux/keyman-config/keyman_config/ibus_util.py b/linux/keyman-config/keyman_config/ibus_util.py index 0ba5d773f3..1e992d7aa8 100644 --- a/linux/keyman-config/keyman_config/ibus_util.py +++ b/linux/keyman-config/keyman_config/ibus_util.py @@ -79,7 +79,7 @@ def restart_ibus_subp(): subprocess.run(["ibus", "restart"]) -def _verify_ibus_daemon(): +def verify_ibus_daemon(start): realuser = os.environ.get('SUDO_USER') user = os.environ.get('USER') if realuser: @@ -89,10 +89,20 @@ def _verify_ibus_daemon(): try: ps = subprocess.run(('ps', '--user', user, '-o', 's=', '-o', 'cmd'), stdout=subprocess.PIPE).stdout - if not re.search('^[^ZT] ibus-daemon .*--xim.*', ps.decode('utf-8'), re.MULTILINE): + ibus_daemons = re.findall('^[^ZT] ibus-daemon .*--xim.*', ps.decode('utf-8'), re.MULTILINE) + if len(ibus_daemons) <= 0: + if start: + _start_ibus_daemon(realuser) + elif len(ibus_daemons) > 1: + logging.error('More than one ibus-daemon instance running! Keyman keyboards might not work as expected. ' + 'Please reboot your machine.') + else: + logging.debug('ibus already running') + except subprocess.CalledProcessError as e: + # Log critical error in order to track down #6237 + logging.critical('getting ibus-daemon failed (%s: %s)', type(e), e.args) + if start: _start_ibus_daemon(realuser) - except subprocess.CalledProcessError: - _start_ibus_daemon(realuser) def _start_ibus_daemon(realuser): @@ -114,23 +124,30 @@ def _start_ibus_daemon(realuser): def restart_ibus(bus=None): + verify_ibus_daemon(False) realuser = os.environ.get('SUDO_USER') if realuser: # we have been called with `sudo`. Restart ibus for the real user. logging.info('restarting IBus by subprocess for user %s', realuser) subprocess.run(['sudo', '-u', realuser, 'ibus', 'restart']) else: + logging.info('restarting IBus through API') try: if not bus: bus = get_ibus_bus() if bus: logging.info("restarting IBus") - bus.exit(True) + # we no longer try to restart since we sometimes ended up with more than one + # ibus-daemon process (#6237). Instead we only exit ibus here, and start + # ibus again below. + bus.exit(False) bus.destroy() except Exception as e: logging.warning("Failed to restart IBus") logging.warning(e) - _verify_ibus_daemon() + # give ibus a chance to shutdown (#6237) + time.sleep(1) # 1s + verify_ibus_daemon(True) def bus_has_engine(bus, name): diff --git a/linux/keyman-config/km-config b/linux/keyman-config/km-config index b7e73bf46d..30f8a21ece 100755 --- a/linux/keyman-config/km-config +++ b/linux/keyman-config/km-config @@ -5,6 +5,7 @@ import logging from keyman_config import __versionwithtag__, __pkgversion__ from keyman_config.handle_install import download_and_install_package +from keyman_config.ibus_util import verify_ibus_daemon if __name__ == '__main__': @@ -38,6 +39,10 @@ if __name__ == '__main__': else: logging.basicConfig(format='%(levelname)s:%(message)s') + logging.info('Keyman version %s %s', __versionwithtag__, __pkgversion__) + + verify_ibus_daemon(False) + if args.install: download_and_install_package(args.install) elif args.url: diff --git a/linux/debian/km-config.desktop b/linux/keyman-config/km-config.desktop similarity index 100% rename from linux/debian/km-config.desktop rename to linux/keyman-config/km-config.desktop diff --git a/mac/bashHelperFunctions.sh b/mac/bashHelperFunctions.sh index 5374ab9ee1..1836fec621 100755 --- a/mac/bashHelperFunctions.sh +++ b/mac/bashHelperFunctions.sh @@ -1,5 +1,7 @@ #!/bin/sh +# TODO: deprecate and replace with shellHelperFunctions.sh. + # The following allows coloring of warning and error lines, but only works if there's a # terminal attached, so not on the build machine. if ! [[ "$TERM" == "" || "$TERM" == "dumb" ]]; then diff --git a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVKeyboardListAdapter.java b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVKeyboardListAdapter.java index 8f43bd8d90..6deba05efd 100644 --- a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVKeyboardListAdapter.java +++ b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVKeyboardListAdapter.java @@ -54,10 +54,6 @@ class FVKeyboardListAdapter extends ArrayAdapter { holder.nextButton = convertView.findViewById(R.id.imageNext); holder.nextButton.setOnClickListener(new FVKeyboardListAdapter.FVOnClickNextListener()); convertView.setTag(holder); - - if (listFont != null) { - holder.text1.setTypeface(listFont, Typeface.BOLD); - } } else { holder = (ViewHolder) convertView.getTag(); } diff --git a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVKeyboardSettingsActivity.java b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVKeyboardSettingsActivity.java index 6b844f0fd5..02e00f7c40 100644 --- a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVKeyboardSettingsActivity.java +++ b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVKeyboardSettingsActivity.java @@ -1,12 +1,18 @@ package com.firstvoices.keyboards; +import static android.view.View.INVISIBLE; +import static android.view.View.VISIBLE; + +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.database.DataSetObserver; import android.os.Bundle; import android.view.View; import android.view.Window; -import android.widget.ImageView; +import android.widget.AdapterView; +import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; @@ -15,7 +21,10 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.SwitchCompat; import androidx.appcompat.widget.Toolbar; +import com.tavultesoft.kmea.KMKeyboardDownloaderActivity; import com.tavultesoft.kmea.KMManager; +import com.tavultesoft.kmea.KeyboardPickerActivity; +import com.tavultesoft.kmea.ModelInfoActivity; import com.tavultesoft.kmea.ModelPickerActivity; import com.tavultesoft.kmea.cloud.CloudApiTypes; import com.tavultesoft.kmea.cloud.CloudDownloadMgr; @@ -24,9 +33,12 @@ import com.tavultesoft.kmea.data.CloudRepository; import com.tavultesoft.kmea.data.Dataset; import com.tavultesoft.kmea.data.Keyboard; import com.tavultesoft.kmea.data.KeyboardController; +import com.tavultesoft.kmea.data.LexicalModel; import com.tavultesoft.kmea.util.BCP47; import com.tavultesoft.kmea.util.KMLog; +import com.tavultesoft.kmea.util.MapCompat; +import java.io.File; import java.util.ArrayList; import java.util.HashMap; @@ -34,16 +46,20 @@ import java.util.HashMap; * Displays an FV Keyboard enable and some lexical model switches. */ public final class FVKeyboardSettingsActivity extends AppCompatActivity { - private Context context; + private static Context context = null; private static Toolbar toolbar = null; private static TextView fvKeyboardTextView = null; private static TextView fvVersionTextView = null; - private static TextView lexicalModelTextView = null; private static TextView correctionsTextView = null; private static SwitchCompat fvKeyboardToggle = null; private static SwitchCompat correctionsToggle = null; + private static ModelPickerActivity.FilteredLexicalModelAdapter listAdapter = null; private String associatedLexicalModel = ""; private String lgCode; + private static RelativeLayout checkModelLayout = null; + private static Intent intent = null; + private static Bundle bundle = null; + private static ListView listView = null; private String lgName; private String kbId; private String kbName; @@ -51,6 +67,7 @@ public final class FVKeyboardSettingsActivity extends AppCompatActivity { private String version; private SharedPreferences prefs; + private DataSetObserver repoObserver; private static Dataset repo; private boolean didExecuteParser = false; @@ -104,7 +121,10 @@ public final class FVKeyboardSettingsActivity extends AppCompatActivity { context = this; setContentView(R.layout.fv_keyboard_settings_list_layout); - Bundle bundle = getIntent().getExtras(); + if (getIntent() != null && getIntent().getExtras() != null) { + intent = getIntent(); + bundle = intent.getExtras(); + } if (bundle == null) { // Should never actually happen. KMLog.LogError(TAG, "Language data not specified for FVKeyboardSettingsActivity!"); @@ -117,11 +137,17 @@ public final class FVKeyboardSettingsActivity extends AppCompatActivity { } } - // Force the cloud catalog to update + // Establish the list view based on the CloudRepository's Dataset if (!didExecuteParser) { didExecuteParser = true; repo = CloudRepository.shared.fetchDataset(context); } + // add listener to dataset to get event for catalog update. + repoObserver = new DataSetObserver() { + @Override public void onChanged() { + } + }; + repo.registerDataSetObserver(repoObserver); kbId = bundle.getString(KMManager.KMKey_KeyboardID); kbName = bundle.getString(KMManager.KMKey_KeyboardName); @@ -149,22 +175,8 @@ public final class FVKeyboardSettingsActivity extends AppCompatActivity { public void onClick(View v) { // If keyboard enabled, determine if associated lexical model should be downloaded // Check if associated model is not already installed - if (fvKeyboardToggle.isChecked() && (KMManager.getAssociatedLexicalModel(lgCode) == null) && KMManager.hasConnection(context)) { - String _downloadid = CloudLexicalModelMetaDataDownloadCallback.createDownloadId(lgCode); - CloudLexicalModelMetaDataDownloadCallback _callback = new CloudLexicalModelMetaDataDownloadCallback(); - - Toast.makeText(context, - context.getString(R.string.query_associated_model), - Toast.LENGTH_SHORT).show(); - - ArrayList aPreparedCloudApiParams = new ArrayList<>(); - String url = CloudRepository.prepareLexicalModelQuery(lgCode); - aPreparedCloudApiParams.add(new CloudApiTypes.CloudApiParam( - CloudApiTypes.ApiTarget.KeyboardLexicalModels, url).setType(CloudApiTypes.JSONType.Array)); - - CloudDownloadMgr.getInstance().executeAsDownload( - context, _downloadid, null, _callback, - aPreparedCloudApiParams.toArray(new CloudApiTypes.CloudApiParam[0])); + if (fvKeyboardToggle.isChecked() && (KMManager.getAssociatedLexicalModel(lgCode) == null)) { + queryModel(); } FVShared.getInstance().setCheckState(kbId, fvKeyboardToggle.isChecked()); @@ -172,10 +184,9 @@ public final class FVKeyboardSettingsActivity extends AppCompatActivity { }); // The following two layouts/toggles will need to link with these objects. - Context appContext = this.getApplicationContext(); - prefs = appContext.getSharedPreferences(appContext.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); - boolean mayPredict = prefs.getBoolean(KMManager.getLanguagePredictionPreferenceKey(lgCode), true); - boolean mayCorrect = prefs.getBoolean(KMManager.getLanguageCorrectionPreferenceKey(lgCode), true); + prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); + boolean mayPredict = prefs.getBoolean(KMManager.getLanguagePredictionPreferenceKey(lgCode), false); + boolean mayCorrect = prefs.getBoolean(KMManager.getLanguageCorrectionPreferenceKey(lgCode), false); layout = (RelativeLayout)findViewById(R.id.corrections_toggle); @@ -197,71 +208,184 @@ public final class FVKeyboardSettingsActivity extends AppCompatActivity { overrideCorrectionsToggle(mayPredict); - layout = (RelativeLayout)findViewById(R.id.model_picker); - textView = (TextView) layout.findViewById(R.id.text1); - textView.setText(getString(R.string.model_label)); + checkModelLayout = (RelativeLayout)findViewById(R.id.check_model); + textView = checkModelLayout.findViewById(R.id.text1); + textView.setText(getString(R.string.check_model_online)); - lexicalModelTextView = layout.findViewById(R.id.text2); - - updateActiveLexicalModel(); - - ImageView imageView = (ImageView) layout.findViewById(R.id.image1); - imageView.setImageResource(R.drawable.ic_arrow_forward); - layout.setEnabled(true); - layout.setOnClickListener(new View.OnClickListener() { + checkModelLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - // Start ModelPickerActivity - Bundle bundle = new Bundle(); - bundle.putString(KMManager.KMKey_LanguageID, lgCode); - bundle.putString(KMManager.KMKey_LanguageName, lgName); - bundle.putString(KMManager.KMKey_CustomHelpLink, customHelpLink); - Intent i = new Intent(context, ModelPickerActivity.class); - i.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); - i.putExtras(bundle); - startActivity(i); + queryModel(); } }); - /** - * This is a placeholder for "Manage dictionary" settings - * - * layout = (RelativeLayout)findViewById(R.id.manage_dictionary); - * textView = (TextView) layout.findViewById(R.id.text1); - * textView.setText(getString(R.string.manage_dictionary)); - * imageView = (ImageView) layout.findViewById(R.id.image1); - * imageView.setImageResource(R.drawable.ic_arrow_forward); - */ + // Display model picker list + listView = (ListView)findViewById(R.id.listView); + listView.setFastScrollEnabled(true); + + // Initialize the dataset of available lexical models (installed and from the cloud catalog) + listAdapter = new ModelPickerActivity.FilteredLexicalModelAdapter(context, repo, lgCode); + listView.setAdapter(listAdapter); + listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + + @Override + public void onItemClick(AdapterView parent, View view, final int position, long id) { + int selectedIndex = position; + LexicalModel model = ((ModelPickerActivity.FilteredLexicalModelAdapter) listView.getAdapter()).getItem(position); + String packageID = model.getPackageID(); + String languageID = model.getLanguageID(); + String modelID = model.getLexicalModelID(); + String modelName = model.getLexicalModelName(); + String langName = model.getLanguageName(); + String version = model.getVersion(); + + boolean immediateRegister = false; + + // File check to see if lexical model file already exists locally (may not be currently installed) + File modelCheck = new File(KMManager.getLexicalModelsDir() + packageID + File.separator + modelID + ".model.js"); + String modelKey = model.getKey(); + boolean modelInstalled = KeyboardPickerActivity.containsLexicalModel(context, modelKey); + if (modelInstalled) { + // Show Model Info + listView.setItemChecked(position, true); + listView.setSelection(position); + + // Start intent for selected Predictive Text Model screen + Intent i = new Intent(context, ModelInfoActivity.class); + i.putExtra(KMManager.KMKey_LexicalModel, model); + startActivityForResult(i, 1); + } else if (modelCheck.exists()) { + // Handle scenario where previously installed kmp already exists so + // we only need to add the model to the list of installed models + HashMap modelInfo = new HashMap(); + modelInfo.put(KMManager.KMKey_PackageID, packageID); + modelInfo.put(KMManager.KMKey_LexicalModelID, modelID); + modelInfo.put(KMManager.KMKey_LanguageID, languageID); + modelInfo.put(KMManager.KMKey_LexicalModelName, modelName); + modelInfo.put(KMManager.KMKey_LanguageName, langName); + modelInfo.put(KMManager.KMKey_LexicalModelVersion, version); + // Add help link + modelInfo.put(KMManager.KMKey_CustomHelpLink, ""); + + boolean result = KMManager.addLexicalModel(context, new HashMap<>(modelInfo)); + if (result) { + Toast.makeText(context, getString(R.string.model_install_toast), Toast.LENGTH_SHORT).show(); + } + + immediateRegister = true; + } else { + // Model isn't installed so prompt to download it + Bundle args = model.buildDownloadBundle(); + Intent i = new Intent(getApplicationContext(), KMKeyboardDownloaderActivity.class); + i.putExtras(args); + startActivity(i); + } + + // If we had a previously-installed lexical model, we should 'deinstall' it so that only + // one model is actively linked to any given language. + if(!modelInstalled && !immediateRegister) { + // While awkward, we must obtain the preInstalledModelMap before any installations occur. + // We don't want to remove the model we just installed, after all! + HashMap preInstalledModelMap = KMManager.getAssociatedLexicalModel(languageID); + if(preInstalledModelMap != null) { + // This might be unnecessary + LexicalModel preInstalled = new LexicalModel( + preInstalledModelMap.get(KMManager.KMKey_PackageID), + preInstalledModelMap.get(KMManager.KMKey_LexicalModelID), + preInstalledModelMap.get(KMManager.KMKey_LexicalModelName), + preInstalledModelMap.get(KMManager.KMKey_LanguageID), + preInstalledModelMap.get(KMManager.KMKey_LanguageName), + preInstalledModelMap.get(KMManager.KMKey_LexicalModelVersion), + preInstalledModelMap.get(KMManager.KMKey_CustomHelpLink), + MapCompat.getOrDefault(preInstalledModelMap, KMManager.KMKey_KMPLink, "")); + String itemKey = preInstalled.getKey(); + int modelIndex = KeyboardPickerActivity.getLexicalModelIndex(context, itemKey); + KMManager.deleteLexicalModel(context, modelIndex, true); + } + } + + if(immediateRegister) { + // Register associated lexical model if it matches the active keyboard's language code; + // it's safe since we're on the same thread. Needs to be called AFTER deinstalling the old one. + String kbdLgCode = KMManager.getCurrentKeyboardInfo(context).getLanguageID(); + if(BCP47.languageEquals(kbdLgCode, languageID)) { + KMManager.registerAssociatedLexicalModel(languageID); + } + } + + // Force a display refresh. + notifyDataSetChanged(); + } + }); + + Intent i = getIntent(); + listView.setSelectionFromTop(i.getIntExtra("listPosition", 0), + i.getIntExtra("offsetY", 0)); + + // Rescale listview and hide "Dictionaries" header if no dictionaries installed + updateDictionariesSection(); + } + + public void updateDictionariesSection() { + if (listAdapter != null && toolbar != null) { + int actionBarHeight = toolbar.getLayoutParams().height; + int numModels = listAdapter.getCount(); + listView.getLayoutParams().height = actionBarHeight * (numModels); + + TextView label = findViewById(R.id.model_label); + if (label != null) { + if (numModels == 0) { + label.setVisibility(View.GONE); + } else { + label.setVisibility(VISIBLE); + } + } + } + } + + private void queryModel() { + if (!KMManager.hasConnection(context)) { + Toast.makeText(context, + context.getString(R.string.cannot_query_associated_model), + Toast.LENGTH_SHORT).show(); + return; + } + + String _downloadid = CloudLexicalModelMetaDataDownloadCallback.createDownloadId(lgCode); + CloudLexicalModelMetaDataDownloadCallback _callback = new CloudLexicalModelMetaDataDownloadCallback(); + + Toast.makeText(context, + context.getString(R.string.query_associated_model), + Toast.LENGTH_SHORT).show(); + + ArrayList aPreparedCloudApiParams = new ArrayList<>(); + String url = CloudRepository.prepareLexicalModelQuery(lgCode); + aPreparedCloudApiParams.add(new CloudApiTypes.CloudApiParam( + CloudApiTypes.ApiTarget.KeyboardLexicalModels, url).setType(CloudApiTypes.JSONType.Array)); + + CloudDownloadMgr.getInstance().executeAsDownload( + context, _downloadid, null, _callback, + aPreparedCloudApiParams.toArray(new CloudApiTypes.CloudApiParam[0])); } @Override public void onResume() { super.onResume(); - updateActiveLexicalModel(); + notifyDataSetChanged(); } - /** - * Updates the active lexical model label with the name of the associated lexical model. - * If there's no associated lexical model, the label displays a prompt to check for an available model. - */ - public void updateActiveLexicalModel() { - HashMap lexModelMap = KMManager.getAssociatedLexicalModel(lgCode); - if(lexModelMap != null) { - associatedLexicalModel = lexModelMap.get(KMManager.KMKey_LexicalModelName); - } else { - // Prompt to check for available dictionary - associatedLexicalModel = getString(R.string.check_available_model); + public static void notifyDataSetChanged() { + if (listAdapter != null) { + listAdapter.notifyDataSetChanged(); } - - lexicalModelTextView.setText(associatedLexicalModel); - lexicalModelTextView.setEnabled(true); } - public static void setActiveLexicalModelLabel(String lexicalModelLabel) { - if (lexicalModelTextView != null && lexicalModelLabel != null && !lexicalModelLabel.isEmpty()) { - lexicalModelTextView.setText(lexicalModelLabel); - lexicalModelTextView.setEnabled(true); + public static void restartActivity() { + if (context != null) { + // Not using Activity.recreate() because we need to recalculate the items + ((Activity)context).finish(); + ((Activity)context).startActivity(intent); } } @@ -295,7 +419,7 @@ public final class FVKeyboardSettingsActivity extends AppCompatActivity { } if (correctionsToggle != null) { correctionsToggle.setEnabled(override); - int visibility = override ? View.VISIBLE : View.INVISIBLE; + int visibility = override ? VISIBLE : INVISIBLE; correctionsToggle.setVisibility(visibility); } } diff --git a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVRegionListAdapter.java b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVRegionListAdapter.java index e61e9ce29a..3792fc9453 100644 --- a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVRegionListAdapter.java +++ b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/FVRegionListAdapter.java @@ -37,10 +37,6 @@ final class FVRegionListAdapter extends ArrayAdapter { holder.text1 = convertView.findViewById(R.id.text1); holder.text2 = convertView.findViewById(R.id.text2); - if (listFont != null) { - holder.text1.setTypeface(listFont, Typeface.BOLD); - holder.text2.setTypeface(listFont, Typeface.NORMAL); - } convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); diff --git a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java index 747a938cfa..5d3e5c5939 100644 --- a/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java +++ b/oem/firstvoices/android/app/src/main/java/com/firstvoices/keyboards/MainActivity.java @@ -2,6 +2,7 @@ package com.firstvoices.keyboards; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -18,6 +19,7 @@ import io.sentry.android.core.SentryAndroid; import com.tavultesoft.kmea.*; import com.tavultesoft.kmea.data.Keyboard; +import com.tavultesoft.kmea.util.BCP47; import com.tavultesoft.kmea.util.DownloadFileUtils; import com.tavultesoft.kmea.KeyboardEventHandler.OnKeyboardDownloadEventListener; @@ -27,7 +29,7 @@ import java.util.List; import java.util.Map; public class MainActivity extends AppCompatActivity implements OnKeyboardDownloadEventListener { - public static Context context; + public Context context; FVDownloadResultReceiver resultReceiver; @@ -89,10 +91,6 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardDownloa webView.getSettings().setUseWideViewPort(true); webView.getSettings().setLoadWithOverviewMode(true); webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); - /* - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - webView.setWebContentsDebuggingEnabled(true); - }*/ webView.setWebViewClient(new WebViewClient() { @Override @@ -204,30 +202,6 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardDownloa // ensure onKeyboardDownloadFinished() gets called } - /* - @Override - public boolean onCreateOptionsMenu(Menu menu) { - // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.menu_main, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - // Handle action bar item clicks here. The action bar will - // automatically handle clicks on the Home/Up button, so long - // as you specify a parent activity in AndroidManifest.xml. - int id = item.getItemId(); - - //noinspection SimplifiableIfStatement - if (id == R.id.action_settings) { - return true; - } - - return super.onOptionsItemSelected(item); - } - */ - private static final class JSHandler { final private Context context; @@ -277,31 +251,36 @@ public class MainActivity extends AppCompatActivity implements OnKeyboardDownloa @Override public void onLexicalModelInstalled(List> lexicalModelsInstalled) { - String langId = (KMManager.getCurrentKeyboardInfo(this) != null) ? + String keyboardLangId = (KMManager.getCurrentKeyboardInfo(this) != null) ? KMManager.getCurrentKeyboardInfo(this).getLanguageID() : KMManager.KMDefault_LanguageID; boolean matchingModel = false; - String lexicalModelName = ""; + + SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.kma_prefs_name), Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); for(int i=0; ilexicalModelInfo = new HashMap<>(lexicalModelsInstalled.get(i)); - if(lexicalModelInfo.get(KMManager.KMKey_LanguageID).equals(langId)) { + String lexicalModelLangId = lexicalModelInfo.get(KMManager.KMKey_LanguageID); + if(BCP47.languageEquals(keyboardLangId, lexicalModelLangId)) { matchingModel = true; - lexicalModelName = lexicalModelInfo.get(KMManager.KMKey_LexicalModelName); } KMManager.addLexicalModel(this, lexicalModelInfo); + + // Enable predictions and corrections toggles + editor.putBoolean(KMManager.getLanguagePredictionPreferenceKey(lexicalModelLangId), true); + editor.putBoolean(KMManager.getLanguageCorrectionPreferenceKey(lexicalModelLangId), true); } + editor.commit(); // We're on the main thread, so if the active keyboard's language code matches, // let's register the associated lexical model. if(matchingModel) { - KMManager.registerAssociatedLexicalModel(langId); - - // Update associated dictionary string if applicable - FVKeyboardSettingsActivity.setActiveLexicalModelLabel(lexicalModelName); - + KMManager.registerAssociatedLexicalModel(keyboardLangId); } + // Launch/refresh FV Keyboard Settings menu + FVKeyboardSettingsActivity.restartActivity(); } } diff --git a/oem/firstvoices/android/app/src/main/res/layout/fv_keyboard_settings_list_layout.xml b/oem/firstvoices/android/app/src/main/res/layout/fv_keyboard_settings_list_layout.xml index 0f192968b2..bdc2f0cf73 100644 --- a/oem/firstvoices/android/app/src/main/res/layout/fv_keyboard_settings_list_layout.xml +++ b/oem/firstvoices/android/app/src/main/res/layout/fv_keyboard_settings_list_layout.xml @@ -1,12 +1,10 @@ - + - - + + + + + + + + + - - - - - - - - - diff --git a/oem/firstvoices/android/app/src/main/res/layout/fv_list_row_layout.xml b/oem/firstvoices/android/app/src/main/res/layout/fv_list_row_layout.xml index dfa0725335..dc04f86bb7 100644 --- a/oem/firstvoices/android/app/src/main/res/layout/fv_list_row_layout.xml +++ b/oem/firstvoices/android/app/src/main/res/layout/fv_list_row_layout.xml @@ -22,8 +22,7 @@ android:layout_marginTop="5dp" android:ellipsize="end" android:singleLine="true" - android:textSize="16sp" - android:textStyle="bold" /> + android:textSize="16sp" /> - + android:textSize="14sp" /> + + android:textSize="16sp" /> diff --git a/oem/firstvoices/android/app/src/main/res/values/strings.xml b/oem/firstvoices/android/app/src/main/res/values/strings.xml index 02f85987a0..83edf8f86b 100644 --- a/oem/firstvoices/android/app/src/main/res/values/strings.xml +++ b/oem/firstvoices/android/app/src/main/res/values/strings.xml @@ -4,6 +4,7 @@ Setup Regions Keyboards + Dictionaries %1$s Settings Enable keyboard Version %1$s diff --git a/resources/gosh/package-lock.json b/resources/gosh/package-lock.json index e74d68f5d9..52c6bf6913 100644 --- a/resources/gosh/package-lock.json +++ b/resources/gosh/package-lock.json @@ -1,5 +1,5 @@ { "name": "@keymanapp/resources-gosh", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 1 } diff --git a/resources/gosh/package.json b/resources/gosh/package.json index addfce08b2..88c1df00d1 100644 --- a/resources/gosh/package.json +++ b/resources/gosh/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/resources-gosh", - "version": "15.0.211", + "version": "15.0.216", "description": "Good Ol' Shell", "author": "Marc Durdin (https://github.com/mcdurdin)", "contributors": [ diff --git a/resources/shellHelperFunctions.sh b/resources/shellHelperFunctions.sh index 6fcbb2127f..1e95a6a7d4 100755 --- a/resources/shellHelperFunctions.sh +++ b/resources/shellHelperFunctions.sh @@ -85,21 +85,21 @@ get_platform_folder() { # The following allows coloring of warning and error lines, but only works if there's a # terminal attached, so not on the build machine. if [[ -n "$TERM" ]] && [[ "$TERM" != "dumb" ]] && [[ "$TERM" != "unknown" ]]; then - ERROR_RED=$(tput setaf 1) - SUCCESS_GREEN=$(tput setaf 2) - WARNING_YELLOW=$(tput setaf 3) - NORMAL=$(tput sgr0) - TERM_HEADING=$(tput setaf 4) + COLOR_RED=$(tput setaf 1) + COLOR_GREEN=$(tput setaf 2) + COLOR_BLUE=$(tput setaf 4) + COLOR_YELLOW=$(tput setaf 3) + COLOR_RESET=$(tput sgr0) else - ERROR_RED= - SUCCESS_GREEN= - WARNING_YELLOW= - NORMAL= - TERM_HEADING= + COLOR_RED= + COLOR_GREEN= + COLOR_BLUE= + COLOR_YELLOW= + COLOR_RESET= fi echo_heading() { - echo "${TERM_HEADING}$*${NORMAL}" + echo "${COLOR_BLUE}$*${COLOR_RESET}" } fail() { @@ -107,11 +107,11 @@ fail() { if [[ "$FAILURE_MSG" == "" ]]; then FAILURE_MSG="Unknown failure" fi - echo "${ERROR_RED}$FAILURE_MSG${NORMAL}" + echo "${COLOR_RED}$FAILURE_MSG${COLOR_RESET}" exit 1 } -warn() { echo "${WARNING_YELLOW}$*${NORMAL}"; } +warn() { echo "${COLOR_YELLOW}$*${COLOR_RESET}"; } displayInfo() { if [ "$QUIET" != true ]; then diff --git a/resources/web-environment/package-lock.json b/resources/web-environment/package-lock.json index e506a8102a..29b4be57ff 100644 --- a/resources/web-environment/package-lock.json +++ b/resources/web-environment/package-lock.json @@ -1,5 +1,5 @@ { "name": "@keymanapp/web-environment", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 1 } diff --git a/resources/web-environment/package.json b/resources/web-environment/package.json index 2cb3fbc417..001df8b36a 100644 --- a/resources/web-environment/package.json +++ b/resources/web-environment/package.json @@ -1,6 +1,6 @@ { "name": "@keymanapp/web-environment", - "version": "15.0.211", + "version": "15.0.216", "description": "A compilation utility for passing select environment variables into our TS builds", "author": "Joshua Horton (https://github.com/jahorton)", "homepage": "https://github.com/keymanapp/keyman", @@ -17,6 +17,6 @@ "url": "https://github.com/keymanapp/keyman/issues" }, "devDependencies": { - "@keymanapp/resources-gosh": "^15.0.211" + "@keymanapp/resources-gosh": "^15.0.216" } } diff --git a/web/bulk_rendering/build.sh b/web/bulk_rendering/build.sh index 63d4d8c2aa..f63687ead9 100755 --- a/web/bulk_rendering/build.sh +++ b/web/bulk_rendering/build.sh @@ -1,5 +1,5 @@ #! /bin/bash -# +# # Compile the KeymanWeb bulk-renderer module for use with developing/running engine tests. ## START STANDARD BUILD SCRIPT INCLUDE @@ -9,23 +9,6 @@ THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BA . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" ## END STANDARD BUILD SCRIPT INCLUDE -# Fails the build if a specified file does not exist. -assert ( ) { - if ! [ -f $1 ]; then - fail "Build failed." - exit 1 - fi -} - -fail() { - FAILURE_MSG="$1" - if [[ "$FAILURE_MSG" == "" ]]; then - FAILURE_MSG="Unknown failure" - fi - echo "${ERROR_RED}$FAILURE_MSG${NORMAL}" - exit 1 -} - # Ensure the dependencies are downloaded. --no-optional should help block fsevents warnings. verify_npm_setup diff --git a/web/package-lock.json b/web/package-lock.json index 446fd75e19..1e3873552f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,6 +1,6 @@ { "name": "keyman", - "version": "15.0.211", + "version": "15.0.216", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/web/package.json b/web/package.json index fbf5fa52a0..b952160f48 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "keyman", - "version": "15.0.211", + "version": "15.0.216", "description": "Facilitates text input in any language.", "repository": { "type": "git", @@ -18,8 +18,8 @@ }, "homepage": "https://github.com/keymanapp/keyman#readme", "devDependencies": { - "@keymanapp/resources-gosh": "^15.0.211", - "@keymanapp/web-sentry-manager": "^15.0.211", + "@keymanapp/resources-gosh": "^15.0.216", + "@keymanapp/web-sentry-manager": "^15.0.216", "@sentry/cli": "^1.52.3", "chai": "^4.3.4", "google-closure-compiler-java": "^20200224.0.0", @@ -52,13 +52,13 @@ "sentry-cli": "sentry-cli" }, "dependencies": { - "@keymanapp/input-processor": "^15.0.211", - "@keymanapp/keyboard-processor": "^15.0.211", - "@keymanapp/lexical-model-layer": "^15.0.211", - "@keymanapp/models-types": "^15.0.211", - "@keymanapp/recorder-core": "^15.0.211", - "@keymanapp/web-environment": "^15.0.211", - "@keymanapp/web-utils": "^15.0.211", + "@keymanapp/input-processor": "^15.0.216", + "@keymanapp/keyboard-processor": "^15.0.216", + "@keymanapp/lexical-model-layer": "^15.0.216", + "@keymanapp/models-types": "^15.0.216", + "@keymanapp/recorder-core": "^15.0.216", + "@keymanapp/web-environment": "^15.0.216", + "@keymanapp/web-utils": "^15.0.216", "@types/node": "^11.9.4", "es6-shim": "^0.35.5", "eventemitter3": "^4.0.0" diff --git a/web/source/build.sh b/web/source/build.sh index fc99ac4f6b..4bdabb0ba9 100755 --- a/web/source/build.sh +++ b/web/source/build.sh @@ -355,11 +355,11 @@ if [ $BUILD_CORE = true ]; then CORE_FLAGS="-skip-package-install" # Build the sentry-manager module - it's used in embedded contexts and on one testing page. - echo "${TERM_HEADING}Compiling KeymanWeb's sentry-manager module...${NORMAL}" + echo_heading "Compiling KeymanWeb's sentry-manager module..." pushd ../../common/core/web/tools/sentry-manager/src ./build.sh $CORE_FLAGS || fail "Failed to compile the sentry-manager module" popd - echo "${TERM_HEADING}sentry-manager module compiled successfully.${NORMAL}" + echo_heading "sentry-manager module compiled successfully." if [ $BUILD_LMLAYER = false ]; then CORE_FLAGS="$CORE_FLAGS -test" @@ -368,10 +368,10 @@ if [ $BUILD_CORE = true ]; then # Ensure that the Input Processor module compiles properly. cd ../../common/core/web/input-processor/src echo "" - echo "${TERM_HEADING}Compiling local KeymanWeb dependencies...${NORMAL}" + echo_heading "Compiling local KeymanWeb dependencies..." ./build.sh $CORE_FLAGS || fail "Failed to compile KeymanWeb dependencies" cd $WORKING_DIRECTORY - echo "${TERM_HEADING}Local KeymanWeb dependency compilations completed successfully.${NORMAL}" + echo_heading "Local KeymanWeb dependency compilations completed successfully." echo "" fi diff --git a/web/source/keymanweb.ts b/web/source/keymanweb.ts index f612438615..61d523f6fa 100644 --- a/web/source/keymanweb.ts +++ b/web/source/keymanweb.ts @@ -8,13 +8,13 @@ Copyright 2019 SIL International ***/ -// If KMW is already initialized, the KMW script has been loaded more than once. We wish to prevent resetting the +// If KMW is already initialized, the KMW script has been loaded more than once. We wish to prevent resetting the // KMW system, so we use the fact that 'initialized' is only 1 / true after all scripts are loaded for the initial // load of KMW. -if(!window['keyman']['initialized']) { +if(!window['keyman']['initialized']) { // Continued KeymanWeb initialization. - (function() + (function() { // Declare KeymanWeb, OnScreen Keyboard and Util object variables @@ -25,8 +25,8 @@ if(!window['keyman']['initialized']) { * Scope Private * @param {(string|Object)} s string (or object) to print * Description Simple debug display (upper right of screen) - * Extended to support multiple arguments May 2015 - */ + * Extended to support multiple arguments May 2015 + */ keymanweb['debug']=keymanweb.debug=function(s){ var p; if(keymanweb.debugElement == null) @@ -36,10 +36,10 @@ if(!window['keyman']['initialized']) { ds.minHeight='50px'; ds.border='1px solid blue'; ds.whiteSpace='pre-line';ds.overflowY='scroll'; p=document.createElement('P'); p.id='debug_output';p.style.margin='2px'; d.appendChild(p); - document.body.appendChild(d); - keymanweb.debugElement=p; - } - if((p=document.getElementById('debug_output')) == null) return; + document.body.appendChild(d); + keymanweb.debugElement=p; + } + if((p=document.getElementById('debug_output')) == null) return; if(arguments.length == 0) if(typeof p.textContent != 'undefined') p.textContent=''; else p.innerHTML=''; @@ -59,10 +59,10 @@ if(!window['keyman']['initialized']) { else { t1 = ''; - for(m in sx) + for(m in sx) { if(t1.length > 0) t1 = t1 + ', '; - t1 = t1 + m + ':'; + t1 = t1 + m + ':'; switch(typeof sx[m]) { case 'string': @@ -72,7 +72,7 @@ if(!window['keyman']['initialized']) { default: t1 = t1 + typeof sx[m]; break; } - if(t1.length > 1024) + if(t1.length > 1024) { t1 = t1.substr(0,1000)+'...'; break; } @@ -84,15 +84,15 @@ if(!window['keyman']['initialized']) { { t = t + sx; } - } + } // Truncate if necessary to avoid memory problems - if(t.length > 1500) t = t.substr(0,1500) + ' (more)'; - + if(t.length > 1500) t = t.substr(0,1500) + ' (more)'; + if(typeof p.textContent != 'undefined') p.textContent=t+'\n'+p.textContent; else p.innerHTML=t+'
'+p.innerHTML; - + } } @@ -102,28 +102,28 @@ if(!window['keyman']['initialized']) { */ keymanweb.debugElement=null; var dbg=keymanweb.debug; - + keymanweb.delayedInit(); //TODO: find all references to next three routines and disambiguate!! - + // Complete page initialization only after the page is fully loaded, including any embedded fonts // This avoids the need to use a timer to test for the fonts - + util.attachDOMEvent(window, 'load', keymanweb.domManager._WindowLoad,false); - util.attachDOMEvent(window, 'unload', keymanweb.domManager._WindowUnload,false); // added fourth argument (default value) - + util.attachDOMEvent(window, 'unload', keymanweb.domManager._WindowUnload,false); // added fourth argument (default value) + // *** I3319 Supplementary Plane modifications - end new code util.attachDOMEvent(document, 'keyup', keymanweb.hotkeyManager._Process, false); /** * Reset OSK shift states when entering or exiting the active element - **/ + **/ function resetVKShift() { let keyman = com.keyman.singleton; - if(!keyman.uiManager.isActivating && keyman.osk.vkbd) { - keyman.core.keyboardProcessor._UpdateVKShift(null, 15, 0); //this should be enabled !!!!! TODO + if(!keyman.uiManager.isActivating && keyman.osk?.vkbd) { + keyman.core.keyboardProcessor._UpdateVKShift(null); //this should be enabled !!!!! TODO } } @@ -131,9 +131,9 @@ if(!window['keyman']['initialized']) { keymanweb['pageFocusHandler'] = resetVKShift; util.attachDOMEvent(window, 'focus', keymanweb['pageFocusHandler'], false); // I775 util.attachDOMEvent(window, 'blur', keymanweb['pageFocusHandler'], false); // I775 - + // Initialize supplementary plane string extensions - String.kmwEnableSupplementaryPlane(true); + String.kmwEnableSupplementaryPlane(true); })(); } \ No newline at end of file diff --git a/web/source/osk/browser/pendingMultiTap.ts b/web/source/osk/browser/pendingMultiTap.ts index 072ba0b412..5d11ac01f8 100644 --- a/web/source/osk/browser/pendingMultiTap.ts +++ b/web/source/osk/browser/pendingMultiTap.ts @@ -111,6 +111,8 @@ namespace com.keyman.osk { // description. let e = text.KeyEvent.constructNullKeyEvent(this.vkbd.device); e.kNextLayer = 'caps'; + e.Lstates = text.Codes.stateBitmasks.CAPS; + e.LmodifierChange = true; PreProcessor.raiseKeyEvent(e); } } diff --git a/web/source/osk/oskKey.ts b/web/source/osk/oskKey.ts index d156c07b27..0b71253890 100644 --- a/web/source/osk/oskKey.ts +++ b/web/source/osk/oskKey.ts @@ -509,26 +509,8 @@ namespace com.keyman.osk { let y = input.y; let btn = this.btn; - // These functions do not account for 'fixed' positioning. let x0 = dom.Utils.getAbsoluteX(btn); let y0 = dom.Utils.getAbsoluteY(btn); - - let isFixed = false; - let node: HTMLElement = btn; - while(node) { - if(getComputedStyle(node).position == 'fixed') { - isFixed = true; - break; - } else { - node = node.offsetParent as HTMLElement; - } - } - - if(isFixed) { - x0 += window.pageXOffset; - y0 += window.pageYOffset; - } - let x1 = x0 + btn.offsetWidth; let y1 = y0 + btn.offsetHeight; diff --git a/web/testing/commonHeader.js b/web/testing/commonHeader.js index 16ea1326fe..b9c3a27c39 100644 --- a/web/testing/commonHeader.js +++ b/web/testing/commonHeader.js @@ -93,7 +93,13 @@ doAddKeyboards({id:'web_context_tests',name:'Web Context Tests',languages:{id:'en',name:'English'}, filename:(prefix + 'web_context_tests.js')}); - // Add more keyboards to the language menu, by keyboard name, + doAddKeyboards({id:'test_chirality',name:'test_chirality',languages:{id:'en',name:'English'}, + filename:(prefix + 'test_chirality.js')}); + + doAddKeyboards({id:'obolo_chwerty',name:'obolo_chwerty',languages:{id:'en',name:'English'}, + filename:(prefix + 'obolo_chwerty.js')}); + + // Add more keyboards to the language menu, by keyboard name, // keyboard name and language code, or just the BCP-47 language code. // We use a different loading pattern here than in the samples version to provide a slightly different set of test cases. doAddKeyboards('french','@he'); diff --git a/web/testing/obolo_chwerty.js b/web/testing/obolo_chwerty.js new file mode 100644 index 0000000000..26b7ac59b3 --- /dev/null +++ b/web/testing/obolo_chwerty.js @@ -0,0 +1,3475 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_obolo_chwerty()); +} +function Keyboard_obolo_chwerty() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_obolo_chwerty"; + this.KN="Obolo Chwerty"; + this.KMINVER="15.0"; + this.KV={F:' 1em "Tahoma"',K102:1}; + this.KV.KLS={ + "default": ["`","1","2","3","4","5","6","7","8","9","0","-","=","","","","ch","w","e","r","t","y","u","i","o","p","[","]","\\ˆ","","","","a","s","d","f","g","sh","j","k","l",";","'","","","","","","","z","ọ","n̄","v","b","n","m",",",".","/","","","","","",""], + "shift": ["~´","!","@","#","$","%","₦","&","*","(",")","_","+","","","","CH","W","E","R","T","Y","U","I","O","P","{","}","|ˇ","","","","A","S","D","F","G","SH","J","K","L",":","\"","","","","","","","Z","Ọ","N̄","V","B","N","M","<",">","?","","","","","",""] + }; + this.KV.BK=(function(x){ + var + empty=Array.apply(null, Array(65)).map(String.prototype.valueOf,""), + result=[], v, i, + modifiers=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt']; + for(i=modifiers.length-1;i>=0;i--) { + v = x[modifiers[i]]; + if(v || result.length > 0) { + result=(v ? v : empty).slice().concat(result); + } + } + return result; + })(this.KV.KLS); + this.KDU=0; + this.KH="A simple keyboard layout (chwerty) to help you type very easily in Obolo language."; + this.KM=0; + this.KBVER="1.2.1"; + this.KMBM=modCodes.SHIFT | modCodes.ALT | modCodes.CAPS | modCodes.NO_CAPS /* 0x0350 */; + this.KVKD="T_GRV T_ACU T_CCM T_CRN T_ENG T_Q T_H T_X T_C"; + this.KVKL={ + "tablet": { + "font": "Tahoma", + "displayUnderlying": false, + "layer": [ + { + "id": "default", + "row": [ + { + "id": "1", + "key": [ + { + "width": "111", + "id": "K_1", + "text": "1", + "sk": [ + { + "id": "U_00B9", + "text": "\u00B9" + }, + { + "id": "U_2081", + "text": "\u2081" + } + ] + }, + { + "width": "111", + "id": "K_2", + "text": "2", + "sk": [ + { + "id": "U_00B2", + "text": "\u00B2" + }, + { + "id": "U_2082" + } + ] + }, + { + "width": "111", + "id": "K_3", + "text": "3", + "sk": [ + { + "id": "U_00B3", + "text": "\u00B3" + }, + { + "id": "U_2083" + } + ] + }, + { + "width": "111", + "id": "K_4", + "text": "4", + "sk": [ + { + "id": "U_2074", + "text": "\u2074" + }, + { + "id": "U_2084", + "text": "\u2084" + } + ] + }, + { + "width": "111", + "id": "K_5", + "text": "5", + "sk": [ + { + "id": "U_2075", + "text": "\u2075" + }, + { + "id": "U_2085" + } + ] + }, + { + "width": "111", + "id": "K_6", + "text": "6", + "sk": [ + { + "id": "U_2076", + "text": "\u2076" + }, + { + "id": "U_2086" + } + ] + }, + { + "width": "111", + "id": "K_7", + "text": "7", + "sk": [ + { + "id": "U_2077", + "text": "\u2077" + }, + { + "id": "U_2087" + } + ] + }, + { + "width": "111", + "id": "K_8", + "text": "8", + "sk": [ + { + "id": "U_2078", + "text": "\u2078" + }, + { + "id": "U_2088", + "text": "\u2088" + } + ] + }, + { + "width": "111", + "id": "K_9", + "text": "9", + "sk": [ + { + "id": "U_2079", + "text": "\u2079" + }, + { + "id": "U_2089" + } + ] + }, + { + "width": "111", + "id": "K_0", + "text": "0", + "sk": [ + { + "id": "U_2070", + "text": "\u2070" + }, + { + "id": "U_2080" + } + ] + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "T_Q", + "text": "ch", + "sk": [ + { + "id": "U_0071", + "text": "q" + } + ] + }, + { + "id": "K_W", + "text": "w" + }, + { + "id": "K_E", + "text": "e", + "sk": [ + { + "id": "U_00E8", + "text": "\u00E8" + }, + { + "id": "U_00EA", + "text": "\u00EA" + } + ] + }, + { + "id": "K_R", + "text": "r" + }, + { + "id": "K_T", + "text": "t" + }, + { + "id": "K_Y", + "text": "y" + }, + { + "id": "K_U", + "text": "u", + "sk": [ + { + "id": "U_00F9", + "text": "\u00F9" + }, + { + "id": "U_00FB", + "text": "\u00FB" + } + ] + }, + { + "id": "K_I", + "text": "i", + "sk": [ + { + "id": "U_00EC", + "text": "\u00EC" + }, + { + "id": "U_00EE", + "text": "\u00EE" + } + ] + }, + { + "id": "K_O", + "text": "o", + "sk": [ + { + "id": "U_00F2", + "text": "\u00F2" + }, + { + "id": "U_00F4", + "text": "\u00F4" + } + ] + }, + { + "id": "K_P", + "text": "p" + }, + { + "id": "T_GRV", + "text": "\u02CB", + "sk": [ + { + "id": "T_ACU", + "text": "\u00B4" + } + ] + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_A", + "pad": "70", + "text": "a", + "sk": [ + { + "id": "U_00E0", + "text": "\u00E0" + }, + { + "id": "U_00E2", + "text": "\u00E2" + } + ] + }, + { + "id": "K_S", + "text": "s" + }, + { + "id": "K_D", + "text": "d" + }, + { + "id": "K_F", + "text": "f" + }, + { + "id": "K_G", + "text": "g" + }, + { + "id": "T_H", + "text": "sh", + "sk": [ + { + "id": "U_0068", + "text": "h" + }, + { + "id": "U_1E63", + "text": "\u1E63" + } + ] + }, + { + "id": "K_J", + "text": "j" + }, + { + "id": "K_K", + "text": "k" + }, + { + "id": "K_L", + "text": "l" + }, + { + "id": "T_CCM", + "text": "\u02C6", + "sk": [ + { + "id": "T_CRN", + "text": "\u02C7" + } + ] + }, + { + "width": "40", + "id": "T_SPA", + "sp": "10" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "shift", + "width": "120", + "id": "K_SHIFT", + "pad": "50", + "sp": "1", + "text": "*Shift*" + }, + { + "id": "K_Z", + "text": "z" + }, + { + "id": "T_X", + "text": "\u1ECD", + "sk": [ + { + "id": "U_1ECD_0300", + "text": "\u1ECD\u0300" + }, + { + "id": "U_1ED9", + "text": "\u1ED9" + }, + { + "id": "U_0078", + "text": "x" + } + ] + }, + { + "id": "T_C", + "text": "n\u0304", + "sk": [ + { + "id": "U_00F1", + "text": "\u00F1" + }, + { + "id": "U_0063", + "text": "c" + } + ] + }, + { + "id": "K_V", + "text": "v" + }, + { + "id": "K_B", + "text": "b" + }, + { + "id": "K_N", + "text": "n", + "sk": [ + { + "id": "U_01F9", + "text": "\u01F9" + } + ] + }, + { + "id": "K_M", + "text": "m", + "sk": [ + { + "id": "U_006D_0300", + "text": "m\u0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "id": "U_0021", + "text": "!" + }, + { + "id": "U_002F", + "text": "/" + }, + { + "id": "U_0027", + "text": "'" + }, + { + "id": "U_0022", + "text": "\"" + }, + { + "id": "U_0028", + "text": "(" + }, + { + "id": "U_0029", + "text": ")" + }, + { + "id": "U_003F", + "text": "?" + } + ] + }, + { + "width": "120", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + }, + { + "width": "20", + "id": "T_SPB", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "alt", + "width": "120", + "id": "K_ALT", + "sp": "1", + "text": "*Symbol*" + }, + { + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "id": "K_COMMA", + "text": ",", + "sk": [ + { + "id": "U_003B", + "text": ";" + } + ] + }, + { + "width": "520", + "id": "K_SPACE" + }, + { + "id": "K_PERIOD", + "text": ".", + "sk": [ + { + "id": "U_003A", + "text": ":" + } + ] + }, + { + "id": "T_ENG", + "sp": "1", + "text": "\u2A37", + "sk": [ + { + "id": "U_2013", + "text": "\u2013" + }, + { + "id": "U_2014", + "text": "\u2014" + }, + { + "id": "U_005F", + "text": "_" + } + ] + }, + { + "width": "120", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "shift", + "row": [ + { + "id": "1", + "key": [ + { + "width": "111", + "id": "K_1", + "text": "!" + }, + { + "width": "111", + "id": "K_2", + "text": "@" + }, + { + "width": "111", + "id": "K_3", + "text": "#" + }, + { + "width": "111", + "id": "K_4", + "text": "$" + }, + { + "width": "111", + "id": "K_5", + "text": "%", + "sk": [ + { + "id": "U_2030", + "text": "\u2030" + }, + { + "id": "U_2031", + "text": "\u2031" + } + ] + }, + { + "width": "111", + "id": "U_20A6", + "text": "\u20A6", + "sk": [ + { + "id": "U_005E", + "text": "^" + } + ] + }, + { + "width": "111", + "id": "K_7", + "text": "&" + }, + { + "width": "111", + "id": "K_8", + "text": "*" + }, + { + "width": "111", + "id": "K_9", + "text": "(" + }, + { + "width": "111", + "id": "K_0", + "text": ")" + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "T_Q", + "text": "Ch", + "sk": [ + { + "id": "U_0051", + "text": "Q" + } + ] + }, + { + "id": "K_W", + "text": "W" + }, + { + "id": "K_E", + "text": "E", + "sk": [ + { + "id": "U_00C8", + "text": "\u00C8" + }, + { + "id": "U_00CA", + "text": "\u00CA" + } + ] + }, + { + "id": "K_R", + "text": "R" + }, + { + "id": "K_T", + "text": "T" + }, + { + "id": "K_Y", + "text": "Y" + }, + { + "id": "K_U", + "text": "U", + "sk": [ + { + "id": "U_00D9", + "text": "\u00D9" + }, + { + "id": "U_00DB", + "text": "\u00DB" + } + ] + }, + { + "id": "K_I", + "text": "I", + "sk": [ + { + "id": "U_00CC", + "text": "\u00CC" + }, + { + "id": "U_00CE", + "text": "\u00CE" + } + ] + }, + { + "id": "K_O", + "text": "O", + "sk": [ + { + "id": "U_00D2", + "text": "\u00D2" + }, + { + "id": "U_00D4", + "text": "\u00D4" + } + ] + }, + { + "id": "K_P", + "text": "P" + }, + { + "id": "T_GRV", + "text": "`", + "sk": [ + { + "id": "T_ACU", + "text": "\u00B4" + } + ] + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_A", + "pad": "70", + "text": "A", + "sk": [ + { + "id": "U_00C0", + "text": "\u00C0" + }, + { + "id": "U_00C2", + "text": "\u00C2" + } + ] + }, + { + "id": "K_S", + "text": "S" + }, + { + "id": "K_D", + "text": "D" + }, + { + "id": "K_F", + "text": "F" + }, + { + "id": "K_G", + "text": "G" + }, + { + "id": "T_H", + "text": "Sh", + "sk": [ + { + "id": "U_0048", + "text": "H" + }, + { + "id": "U_1E62", + "text": "\u1E62" + } + ] + }, + { + "id": "K_J", + "text": "J" + }, + { + "id": "K_K", + "text": "K" + }, + { + "id": "K_L", + "text": "L" + }, + { + "id": "T_CCM", + "text": "\u02C6", + "sk": [ + { + "id": "T_CRN", + "text": "\u02C7" + } + ] + }, + { + "width": "40", + "id": "T_SPC", + "sp": "10" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "default", + "width": "120", + "id": "K_SHIFT", + "pad": "50", + "sp": "2", + "text": "*Shift*" + }, + { + "id": "K_Z", + "text": "Z" + }, + { + "id": "T_X", + "text": "\u1ECC", + "sk": [ + { + "id": "U_1ECC_0300", + "text": "\u1ECC\u0300" + }, + { + "id": "U_1ED8", + "text": "\u1ED8" + }, + { + "id": "U_0058", + "text": "X" + } + ] + }, + { + "id": "T_C", + "text": "N\u0304", + "sk": [ + { + "id": "U_00D1", + "text": "\u00D1" + }, + { + "id": "U_0043", + "text": "C" + } + ] + }, + { + "id": "K_V", + "text": "V" + }, + { + "id": "K_B", + "text": "B" + }, + { + "id": "K_N", + "text": "N", + "sk": [ + { + "id": "U_01F8", + "text": "\u01F8" + } + ] + }, + { + "id": "K_M", + "text": "M", + "sk": [ + { + "id": "U_004D_0300", + "text": "M\u0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "id": "U_0021", + "text": "!" + }, + { + "id": "U_002F", + "text": "/" + }, + { + "id": "U_0027", + "text": "'" + }, + { + "id": "U_0022", + "text": "\"" + }, + { + "id": "U_0028", + "text": "(" + }, + { + "id": "U_0029", + "text": ")" + }, + { + "id": "U_003F", + "text": "?" + } + ] + }, + { + "width": "120", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + }, + { + "width": "20", + "id": "T_SPD", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "alt", + "width": "120", + "id": "K_ALT", + "sp": "1", + "text": "*Symbol*" + }, + { + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "id": "U_002C", + "text": ",", + "sk": [ + { + "id": "U_003B", + "text": ";" + } + ] + }, + { + "width": "520", + "id": "K_SPACE" + }, + { + "id": "U_002E", + "text": ".", + "sk": [ + { + "id": "U_003A", + "text": ":" + } + ] + }, + { + "id": "T_ENG", + "sp": "1", + "text": "\u2A37", + "sk": [ + { + "id": "U_2013", + "text": "\u2013" + }, + { + "id": "U_2014", + "text": "\u2014" + }, + { + "id": "U_005F", + "text": "_" + } + ] + }, + { + "width": "120", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "alt", + "row": [ + { + "id": "1", + "key": [ + { + "layer": "default", + "width": "111", + "id": "K_1", + "text": "1", + "sk": [ + { + "id": "U_00B9", + "text": "\u00B9" + }, + { + "id": "U_2081", + "text": "\u2081" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_2", + "text": "2", + "sk": [ + { + "id": "U_00B2", + "text": "\u00B2" + }, + { + "id": "U_2082", + "text": "\u2082" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_3", + "text": "3", + "sk": [ + { + "id": "U_00B3", + "text": "\u00B3" + }, + { + "id": "U_2083", + "text": "\u2083" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_4", + "text": "4", + "sk": [ + { + "id": "U_2074", + "text": "\u2074" + }, + { + "id": "U_2084", + "text": "\u2084" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_5", + "text": "5", + "sk": [ + { + "id": "U_2075", + "text": "\u2075" + }, + { + "id": "U_2085", + "text": "\u2085" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_6", + "text": "6", + "sk": [ + { + "id": "U_2076", + "text": "\u2076" + }, + { + "id": "U_2086", + "text": "\u2086" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_7", + "text": "7", + "sk": [ + { + "id": "U_2077", + "text": "\u2077" + }, + { + "id": "U_2087", + "text": "\u2087" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_8", + "text": "8", + "sk": [ + { + "id": "U_2078", + "text": "\u2078" + }, + { + "id": "U_2088", + "text": "\u2088" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_9", + "text": "9", + "sk": [ + { + "id": "U_2079", + "text": "\u2079" + }, + { + "id": "U_2089", + "text": "\u2089" + } + ] + }, + { + "layer": "default", + "width": "111", + "id": "K_0", + "text": "0", + "sk": [ + { + "id": "U_2070", + "text": "\u2070" + }, + { + "id": "U_2080", + "text": "\u2080" + } + ] + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "U_002B", + "text": "+", + "sk": [ + { + "id": "U_00B1", + "text": "\u00B1" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "id": "U_2213", + "text": "\u2213" + } + ] + }, + { + "id": "U_00D7", + "text": "\u00D7" + }, + { + "id": "U_00F7", + "text": "\u00F7" + }, + { + "id": "U_2236", + "text": "\u2236", + "sk": [ + { + "id": "U_00B7", + "text": "\u00B7" + }, + { + "id": "U_2234", + "text": "\u2234" + }, + { + "id": "U_2235", + "text": "\u2235" + } + ] + }, + { + "id": "U_221A", + "text": "\u221A", + "sk": [ + { + "id": "U_221B", + "text": "\u221B" + }, + { + "id": "U_221C", + "text": "\u221C" + } + ] + }, + { + "id": "U_005E", + "text": "^" + }, + { + "id": "U_003D", + "text": "=", + "sk": [ + { + "id": "U_2260", + "text": "\u2260" + }, + { + "id": "U_2248", + "text": "\u2248" + }, + { + "id": "U_2261", + "text": "\u2261" + } + ] + }, + { + "id": "U_007E", + "text": "~" + }, + { + "id": "U_203D", + "text": "\u203D", + "sk": [ + { + "id": "U_00A1", + "text": "\u00A1" + } + ] + }, + { + "id": "U_2713", + "text": "\u2713", + "sk": [ + { + "id": "U_0394", + "text": "\u0394" + }, + { + "id": "U_2717", + "text": "\u2717" + }, + { + "id": "U_26EF", + "text": "\u26EF" + }, + { + "id": "U_26ED", + "text": "\u26ED" + } + ] + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "U_007B", + "text": "{" + }, + { + "id": "U_00AB", + "text": "\u00AB" + }, + { + "id": "U_003C", + "text": "<", + "sk": [ + { + "id": "U_226A", + "text": "\u226A" + }, + { + "id": "U_2264", + "text": "\u2264" + } + ] + }, + { + "id": "U_005B", + "text": "[" + }, + { + "id": "U_0028", + "text": "(" + }, + { + "id": "U_007C", + "text": "|" + }, + { + "id": "U_0029", + "text": ")" + }, + { + "id": "U_005D", + "text": "]" + }, + { + "id": "U_003E", + "text": ">", + "sk": [ + { + "id": "U_226B", + "text": "\u226B" + }, + { + "id": "U_2265", + "text": "\u2265" + } + ] + }, + { + "id": "U_00BB", + "text": "\u00BB" + }, + { + "id": "U_007D", + "text": "}" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "shift", + "width": "120", + "id": "K_SHIFT", + "pad": "50", + "sp": "1", + "text": "*Shift*" + }, + { + "id": "U_221E", + "text": "\u221E", + "sk": [ + { + "id": "U_2202", + "text": "\u2202" + } + ] + }, + { + "id": "U_222B", + "text": "\u222B", + "sk": [ + { + "id": "U_1E8B", + "text": "\u1E8B" + }, + { + "id": "U_1E8D", + "text": "\u1E8D" + }, + { + "id": "U_1E8F", + "text": "\u1E8F" + }, + { + "id": "U_04F1", + "text": "\u04F1" + } + ] + }, + { + "id": "U_00B0", + "text": "\u00B0", + "sk": [ + { + "id": "U_2103", + "text": "\u2103" + }, + { + "id": "U_2109", + "text": "\u2109" + } + ] + }, + { + "id": "U_03C0", + "text": "\u03C0" + }, + { + "id": "U_03B8", + "text": "\u03B8" + }, + { + "id": "U_33D1", + "text": "\u33D1", + "sk": [ + { + "id": "U_33D2", + "text": "\u33D2" + } + ] + }, + { + "id": "U_00A9", + "text": "\u00A9", + "sk": [ + { + "id": "U_00AE", + "text": "\u00AE" + }, + { + "id": "U_2117", + "text": "\u2117" + }, + { + "id": "U_1F6C8", + "text": "\uD83D\uDEC8" + }, + { + "id": "U_2122", + "text": "\u2122" + }, + { + "id": "U_2105", + "text": "\u2105" + } + ] + }, + { + "id": "U_002F", + "text": "/", + "sk": [ + { + "id": "U_005C", + "text": "\\" + } + ] + }, + { + "width": "120", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + }, + { + "width": "20", + "id": "T_SPF", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "default", + "width": "120", + "id": "K_ALT", + "sp": "1", + "text": "*abc*" + }, + { + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "id": "U_00A7", + "text": "\u00A7", + "sk": [ + { + "id": "U_208D", + "text": "\u208D" + }, + { + "id": "U_2093", + "text": "\u2093" + }, + { + "id": "U_208A", + "text": "\u208A" + }, + { + "id": "U_208B", + "text": "\u208B" + }, + { + "id": "U_208E", + "text": "\u208E" + }, + { + "id": "U_208C", + "text": "\u208C" + } + ] + }, + { + "layer": "default", + "width": "520", + "id": "K_SPACE" + }, + { + "id": "U_00B6", + "text": "\u00B6", + "sk": [ + { + "id": "U_207D", + "text": "\u207D" + }, + { + "id": "U_207F", + "text": "\u207F" + }, + { + "id": "U_207A", + "text": "\u207A" + }, + { + "id": "U_207B", + "text": "\u207B" + }, + { + "id": "U_207E", + "text": "\u207E" + }, + { + "id": "U_207C", + "text": "\u207C" + } + ] + }, + { + "id": "U_03A9", + "sp": "1", + "text": "\u03A9", + "sk": [ + { + "id": "U_265A", + "text": "\u265A" + }, + { + "id": "U_2654", + "text": "\u2654" + }, + { + "id": "U_265B", + "text": "\u265B" + }, + { + "id": "U_2655", + "text": "\u2655" + }, + { + "id": "U_265D", + "text": "\u265D" + }, + { + "id": "U_2657", + "text": "\u2657" + }, + { + "id": "U_265C", + "text": "\u265C" + }, + { + "id": "U_2656", + "text": "\u2656" + }, + { + "id": "U_265E", + "text": "\u265E" + }, + { + "id": "U_2658", + "text": "\u2658" + }, + { + "id": "U_265F", + "text": "\u265F" + }, + { + "id": "U_2659", + "text": "\u2659" + } + ] + }, + { + "width": "120", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "caps", + "row": [ + { + "id": "1", + "key": [ + { + "width": "111", + "id": "K_1", + "text": "1" + }, + { + "width": "111", + "id": "K_2", + "text": "2" + }, + { + "width": "111", + "id": "K_3", + "text": "3" + }, + { + "width": "111", + "id": "K_4", + "text": "4" + }, + { + "width": "111", + "id": "K_5", + "text": "5" + }, + { + "width": "111", + "id": "K_6", + "text": "6" + }, + { + "width": "111", + "id": "K_7", + "text": "7" + }, + { + "width": "111", + "id": "K_8", + "text": "8" + }, + { + "width": "111", + "id": "K_9", + "text": "9" + }, + { + "width": "111", + "id": "K_0", + "text": "0" + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "T_Q", + "text": "CH", + "sk": [ + { + "id": "U_0051", + "text": "Q" + } + ] + }, + { + "id": "K_W", + "text": "W" + }, + { + "id": "K_E", + "text": "E", + "sk": [ + { + "id": "U_00C8", + "text": "\u00C8" + }, + { + "id": "U_00CA", + "text": "\u00CA" + } + ] + }, + { + "id": "K_R", + "text": "R" + }, + { + "id": "K_T", + "text": "T" + }, + { + "id": "K_Y", + "text": "Y" + }, + { + "id": "K_U", + "text": "U", + "sk": [ + { + "id": "U_00D9", + "text": "\u00D9" + }, + { + "id": "U_00DB", + "text": "\u00DB" + } + ] + }, + { + "id": "K_I", + "text": "I", + "sk": [ + { + "id": "U_00CC", + "text": "\u00CC" + }, + { + "id": "U_00CE", + "text": "\u00CE" + } + ] + }, + { + "id": "K_O", + "text": "O", + "sk": [ + { + "id": "U_00D2", + "text": "\u00D2" + }, + { + "id": "U_00D4", + "text": "\u00D4" + } + ] + }, + { + "id": "K_P", + "text": "P" + }, + { + "id": "T_GRV", + "text": "`", + "sk": [ + { + "id": "T_ACU", + "text": "\u00B4" + } + ] + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_A", + "pad": "70", + "text": "A", + "sk": [ + { + "id": "U_00C0", + "text": "\u00C0" + }, + { + "id": "U_00C2", + "text": "\u00C2" + } + ] + }, + { + "id": "K_S", + "text": "S" + }, + { + "id": "K_D", + "text": "D" + }, + { + "id": "K_F", + "text": "F" + }, + { + "id": "K_G", + "text": "G" + }, + { + "id": "T_H", + "text": "SH", + "sk": [ + { + "id": "U_0048", + "text": "H" + }, + { + "id": "U_1E62", + "text": "\u1E62" + } + ] + }, + { + "id": "K_J", + "text": "J" + }, + { + "id": "K_K", + "text": "K" + }, + { + "id": "K_L", + "text": "L" + }, + { + "id": "T_CCM", + "text": "\u02C6", + "sk": [ + { + "id": "T_CRN", + "text": "\u02C7" + } + ] + }, + { + "width": "40", + "id": "T_SPC", + "sp": "10" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "default", + "width": "120", + "id": "K_SHIFT", + "pad": "50", + "sp": "2", + "text": "*Shift*" + }, + { + "id": "K_Z", + "text": "Z" + }, + { + "id": "T_X", + "text": "\u1ECC", + "sk": [ + { + "id": "U_1ECC_0300", + "text": "\u1ECC\u0300" + }, + { + "id": "U_1ED8", + "text": "\u1ED8" + }, + { + "id": "U_0058", + "text": "X" + } + ] + }, + { + "id": "T_C", + "text": "N\u0304", + "sk": [ + { + "id": "U_00D1", + "text": "\u00D1" + }, + { + "id": "U_0043", + "text": "C" + } + ] + }, + { + "id": "K_V", + "text": "V" + }, + { + "id": "K_B", + "text": "B" + }, + { + "id": "K_N", + "text": "N", + "sk": [ + { + "id": "U_01F8", + "text": "\u01F8" + } + ] + }, + { + "id": "K_M", + "text": "M", + "sk": [ + { + "id": "U_004D_0300", + "text": "M\u0300" + } + ] + }, + { + "id": "U_002D", + "text": "-", + "sk": [ + { + "id": "U_0021", + "text": "!" + }, + { + "id": "U_002F", + "text": "/" + }, + { + "id": "U_0027", + "text": "'" + }, + { + "id": "U_0022", + "text": "\"" + }, + { + "id": "U_0028", + "text": "(" + }, + { + "id": "U_0029", + "text": ")" + }, + { + "id": "U_003F", + "text": "?" + } + ] + }, + { + "width": "120", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + }, + { + "width": "20", + "id": "T_SPD", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "alt", + "width": "120", + "id": "K_ALT", + "sp": "1", + "text": "*Symbol*" + }, + { + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "id": "U_002C", + "text": ",", + "sk": [ + { + "id": "U_003B", + "text": ";" + } + ] + }, + { + "width": "520", + "id": "K_SPACE" + }, + { + "id": "U_002E", + "text": ".", + "sk": [ + { + "id": "U_003A", + "text": ":" + } + ] + }, + { + "id": "T_ENG", + "sp": "1", + "text": "\u2A37", + "sk": [ + { + "id": "U_2013", + "text": "\u2013" + }, + { + "id": "U_2014", + "text": "\u2014" + }, + { + "id": "U_005F", + "text": "_" + } + ] + }, + { + "width": "120", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + } + ] + } +} +; + this.KCSS="/* tone keys colour */\n .android .kmw-keyboard-obolo_chwerty #default-T_GRV {color: #02ff02;}\n .android .kmw-keyboard-obolo_chwerty #default-T_CCM {color: #02ff02;}\n .android .kmw-keyboard-obolo_chwerty #shift-T_GRV {color: #02ff02;}\n .android .kmw-keyboard-obolo_chwerty #shift-T_CCM {color: #02ff02;}\n .android .kmw-keyboard-obolo_chwerty #caps-T_GRV {color: #02ff02;}\n .android .kmw-keyboard-obolo_chwerty #caps-T_CCM {color: #02ff02;}\n "; + this.s_digit_14="0123456789"; + this.s_sentencePunctuation_18=".?!‽"; + this.s_accentibles_19="aeiọoumnAEIỌOUMNn̄"; + this.s_accents_20=['','','','','','','','','','','','']; + this.s_nasals_21="mnMN"; + this.s_nnas_22=['','','','','','']; + this.s_vow_23="aeiouAEIOU"; + this.s_grave_24="àèìòùÀÈÌÒÙ"; + this.s_acute_25="áéíóúÁÉÍÓÚ"; + this.s_circum_26="âêîôûÂÊÎÔÛ"; + this.s_caron_27="ǎěǐǒǔǍĚǏǑǓ"; + this.s_acnasals_28="ḿńḾŃ"; + this.s_spguy_29="mnọMNỌ"; + this.s_spguyop_30="ḿǹộḾǸỘ"; + this.s_erase_31=['','','','']; + this.s_gravekeys_32=['','','','']; + this.s_acutekeys_33=['','','','']; + this.s_circumflexkeys_34=['','','','']; + this.s_caronkeys_35=['','','','']; + this.s41="0"; + this.s42="numeric"; + this.s43="caps"; + this.s44="0"; + this.s45="shift"; + this.s46="shift"; + this.s47="shift"; + this.s48="default"; + this.KVER="15.0.204.0"; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_3(t,e); + }; + this.gn=function(t,e) { + return this.g_NewContext_0(t,e); + }; + this.gpk=function(t,e) { + return this.g_PostKeystroke_1(t,e); + }; + this.gs=function(t,e) { + return this.g_main_3(t,e); + }; + this.g_NewContext_0=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(!m) { + + k.KDC(-1,t); + r=this.g_detectStartOfSentence_2(t,e); + m=2; + } + return r; + }; + this.g_PostKeystroke_1=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(1,t,[{t:'a',a:this.s_digit_14}])&&k.KIFS(42,this.s41,t)&&k.KIFS(33,this.s42,t)){ + m=1; // Line 24 + k.KDC(1,t); + k.KIO(-1,this.s_digit_14,1,t); + } + else if(k.KIFS(33,this.s43,t)){ + m=1; // Line 25 + k.KDC(0,t); + } + else if(k.KIFS(42,this.s44,t)){ + m=1; // Line 26 + k.KDC(0,t); + r=this.g_detectStartOfSentence_2(t,e); + m=2; + } + return r; + }; + this.g_detectStartOfSentence_2=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(3,t,[{t:'a',a:this.s_sentencePunctuation_18},' ',' '])){ + m=1; // Line 31 + k.KDC(3,t); + k.KIO(-1,this.s_sentencePunctuation_18,1,t); + k.KO(-1,t," "); + k.KSETS(33,this.s47,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_sentencePunctuation_18},' '])){ + m=1; // Line 30 + k.KDC(2,t); + k.KIO(-1,this.s_sentencePunctuation_18,1,t); + k.KO(-1,t," "); + k.KSETS(33,this.s46,t); + } + else if(k.KFCM(1,t,[{t:'n'}])){ + m=1; // Line 29 + k.KDC(0,t); + k.KSETS(33,this.s45,t); + } + if(!m) { + + k.KDC(-1,t); + k.KSETS(33,this.s48,t); + } + return r; + }; + this.g_main_3=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_BKSP /* 0x08 */)) { + if(k.KFCM(2,t,['c','h'])){ + r=m=1; // Line 237 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['C','h'])){ + r=m=1; // Line 238 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['C','H'])){ + r=m=1; // Line 239 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['s','h'])){ + r=m=1; // Line 240 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['S','h'])){ + r=m=1; // Line 241 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['S','H'])){ + r=m=1; // Line 242 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['n','̄'])){ + r=m=1; // Line 243 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['N','̄'])){ + r=m=1; // Line 244 + k.KDC(2,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_grave_24}])){ + r=m=1; // Line 247 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_acute_25}])){ + r=m=1; // Line 248 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_circum_26}])){ + r=m=1; // Line 249 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_caron_27}])){ + r=m=1; // Line 250 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_spguyop_30}])){ + r=m=1; // Line 251 + k.KDC(1,t); + k.KIO(-1,this.s_spguy_29,1,t); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_BKSP /* 0x08 */)) { + if(k.KFCM(2,t,['c','h'])){ + r=m=1; // Line 237 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['C','h'])){ + r=m=1; // Line 238 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['C','H'])){ + r=m=1; // Line 239 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['s','h'])){ + r=m=1; // Line 240 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['S','h'])){ + r=m=1; // Line 241 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['S','H'])){ + r=m=1; // Line 242 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['n','̄'])){ + r=m=1; // Line 243 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['N','̄'])){ + r=m=1; // Line 244 + k.KDC(2,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_grave_24}])){ + r=m=1; // Line 247 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_acute_25}])){ + r=m=1; // Line 248 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_circum_26}])){ + r=m=1; // Line 249 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_caron_27}])){ + r=m=1; // Line 250 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_spguyop_30}])){ + r=m=1; // Line 251 + k.KDC(1,t); + k.KIO(-1,this.s_spguy_29,1,t); + } + } + else if(k.KKM(e, modCodes.ALT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4240 */, keyCodes.K_BKSP /* 0x08 */)) { + if(k.KFCM(2,t,['c','h'])){ + r=m=1; // Line 237 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['C','h'])){ + r=m=1; // Line 238 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['C','H'])){ + r=m=1; // Line 239 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['s','h'])){ + r=m=1; // Line 240 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['S','h'])){ + r=m=1; // Line 241 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['S','H'])){ + r=m=1; // Line 242 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['n','̄'])){ + r=m=1; // Line 243 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['N','̄'])){ + r=m=1; // Line 244 + k.KDC(2,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_grave_24}])){ + r=m=1; // Line 247 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_acute_25}])){ + r=m=1; // Line 248 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_circum_26}])){ + r=m=1; // Line 249 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_caron_27}])){ + r=m=1; // Line 250 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_spguyop_30}])){ + r=m=1; // Line 251 + k.KDC(1,t); + k.KIO(-1,this.s_spguy_29,1,t); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_BKSP /* 0x08 */)) { + if(k.KFCM(2,t,['c','h'])){ + r=m=1; // Line 237 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['C','h'])){ + r=m=1; // Line 238 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['C','H'])){ + r=m=1; // Line 239 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['s','h'])){ + r=m=1; // Line 240 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['S','h'])){ + r=m=1; // Line 241 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['S','H'])){ + r=m=1; // Line 242 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['n','̄'])){ + r=m=1; // Line 243 + k.KDC(2,t); + } + else if(k.KFCM(2,t,['N','̄'])){ + r=m=1; // Line 244 + k.KDC(2,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_grave_24}])){ + r=m=1; // Line 247 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_acute_25}])){ + r=m=1; // Line 248 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_circum_26}])){ + r=m=1; // Line 249 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_caron_27}])){ + r=m=1; // Line 250 + k.KDC(1,t); + k.KIO(-1,this.s_vow_23,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_spguyop_30}])){ + r=m=1; // Line 251 + k.KDC(1,t); + k.KIO(-1,this.s_spguy_29,1,t); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x105)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 163 + k.KDC(1,t); + k.KO(-1,t,"q"); + } + else if(1){ + r=m=1; // Line 109 + k.KDC(0,t); + k.KO(-1,t,"ch"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x105)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 164 + k.KDC(1,t); + k.KO(-1,t,"Q"); + } + else if(1){ + r=m=1; // Line 110 + k.KDC(0,t); + k.KO(-1,t,"Ch"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x105)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 165 + k.KDC(1,t); + k.KO(-1,t,"Q"); + } + else if(1){ + r=m=1; // Line 111 + k.KDC(0,t); + k.KO(-1,t,"CH"); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x106)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 167 + k.KDC(1,t); + k.KO(-1,t,"h"); + } + else if(1){ + r=m=1; // Line 113 + k.KDC(0,t); + k.KO(-1,t,"sh"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x106)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 168 + k.KDC(1,t); + k.KO(-1,t,"H"); + } + else if(1){ + r=m=1; // Line 114 + k.KDC(0,t); + k.KO(-1,t,"Sh"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x106)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 169 + k.KDC(1,t); + k.KO(-1,t,"H"); + } + else if(1){ + r=m=1; // Line 115 + k.KDC(0,t); + k.KO(-1,t,"SH"); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x107)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 171 + k.KDC(1,t); + k.KO(-1,t,"x"); + } + else if(1){ + r=m=1; // Line 117 + k.KDC(0,t); + k.KO(-1,t,"ọ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x107)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 172 + k.KDC(1,t); + k.KO(-1,t,"X"); + } + else if(1){ + r=m=1; // Line 118 + k.KDC(0,t); + k.KO(-1,t,"Ọ"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x107)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 173 + k.KDC(1,t); + k.KO(-1,t,"X"); + } + else if(1){ + r=m=1; // Line 119 + k.KDC(0,t); + k.KO(-1,t,"Ọ"); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x108)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 175 + k.KDC(1,t); + k.KO(-1,t,"c"); + } + else if(1){ + r=m=1; // Line 121 + k.KDC(0,t); + k.KO(-1,t,"n̄"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x108)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 176 + k.KDC(1,t); + k.KO(-1,t,"C"); + } + else if(1){ + r=m=1; // Line 122 + k.KDC(0,t); + k.KO(-1,t,"N̄"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x108)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 177 + k.KDC(1,t); + k.KO(-1,t,"C"); + } + else if(1){ + r=m=1; // Line 123 + k.KDC(0,t); + k.KO(-1,t,"N̄"); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x100)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 184 + k.KDC(1,t); + k.KO(-1,t,"`"); + } + else if(k.KFCM(1,t,['m'])){ + r=m=1; // Line 205 + k.KDC(1,t); + k.KO(-1,t,"m̀"); + } + else if(k.KFCM(1,t,['M'])){ + r=m=1; // Line 206 + k.KDC(1,t); + k.KO(-1,t,"M̀"); + } + else if(k.KFCM(1,t,['n'])){ + r=m=1; // Line 208 + k.KDC(1,t); + k.KO(-1,t,"ǹ"); + } + else if(k.KFCM(1,t,['N'])){ + r=m=1; // Line 209 + k.KDC(1,t); + k.KO(-1,t,"Ǹ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 211 + k.KDC(1,t); + k.KO(-1,t,"ọ̀"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 212 + k.KDC(1,t); + k.KO(-1,t,"Ọ̀"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 230 + k.KDC(1,t); + k.KIO(-1,this.s_grave_24,1,t); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x100)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 185 + k.KDC(1,t); + k.KO(-1,t,"`"); + } + else if(k.KFCM(1,t,['m'])){ + r=m=1; // Line 205 + k.KDC(1,t); + k.KO(-1,t,"m̀"); + } + else if(k.KFCM(1,t,['M'])){ + r=m=1; // Line 206 + k.KDC(1,t); + k.KO(-1,t,"M̀"); + } + else if(k.KFCM(1,t,['n'])){ + r=m=1; // Line 208 + k.KDC(1,t); + k.KO(-1,t,"ǹ"); + } + else if(k.KFCM(1,t,['N'])){ + r=m=1; // Line 209 + k.KDC(1,t); + k.KO(-1,t,"Ǹ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 211 + k.KDC(1,t); + k.KO(-1,t,"ọ̀"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 212 + k.KDC(1,t); + k.KO(-1,t,"Ọ̀"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 230 + k.KDC(1,t); + k.KIO(-1,this.s_grave_24,1,t); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x100)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 186 + k.KDC(1,t); + k.KO(-1,t,"`"); + } + else if(k.KFCM(1,t,['m'])){ + r=m=1; // Line 205 + k.KDC(1,t); + k.KO(-1,t,"m̀"); + } + else if(k.KFCM(1,t,['M'])){ + r=m=1; // Line 206 + k.KDC(1,t); + k.KO(-1,t,"M̀"); + } + else if(k.KFCM(1,t,['n'])){ + r=m=1; // Line 208 + k.KDC(1,t); + k.KO(-1,t,"ǹ"); + } + else if(k.KFCM(1,t,['N'])){ + r=m=1; // Line 209 + k.KDC(1,t); + k.KO(-1,t,"Ǹ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 211 + k.KDC(1,t); + k.KO(-1,t,"ọ̀"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 212 + k.KDC(1,t); + k.KO(-1,t,"Ọ̀"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 230 + k.KDC(1,t); + k.KIO(-1,this.s_grave_24,1,t); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x101)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 188 + k.KDC(1,t); + k.KO(-1,t,"´"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 214 + k.KDC(1,t); + k.KO(-1,t,"ọ́"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 215 + k.KDC(1,t); + k.KO(-1,t,"Ọ́"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 231 + k.KDC(1,t); + k.KIO(-1,this.s_acute_25,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 234 + k.KDC(1,t); + k.KIO(-1,this.s_acnasals_28,1,t); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x101)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 189 + k.KDC(1,t); + k.KO(-1,t,"´"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 214 + k.KDC(1,t); + k.KO(-1,t,"ọ́"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 215 + k.KDC(1,t); + k.KO(-1,t,"Ọ́"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 231 + k.KDC(1,t); + k.KIO(-1,this.s_acute_25,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 234 + k.KDC(1,t); + k.KIO(-1,this.s_acnasals_28,1,t); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x101)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 190 + k.KDC(1,t); + k.KO(-1,t,"´"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 214 + k.KDC(1,t); + k.KO(-1,t,"ọ́"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 215 + k.KDC(1,t); + k.KO(-1,t,"Ọ́"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 231 + k.KDC(1,t); + k.KIO(-1,this.s_acute_25,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 234 + k.KDC(1,t); + k.KIO(-1,this.s_acnasals_28,1,t); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x102)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 192 + k.KDC(1,t); + k.KO(-1,t,"ˆ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 217 + k.KDC(1,t); + k.KO(-1,t,"ộ"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 218 + k.KDC(1,t); + k.KO(-1,t,"Ộ"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 232 + k.KDC(1,t); + k.KIO(-1,this.s_circum_26,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 253 + k.KDC(1,t); + k.KIO(-1,this.s_nasals_21,1,t); + k.KB(t); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x102)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 193 + k.KDC(1,t); + k.KO(-1,t,"ˆ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 217 + k.KDC(1,t); + k.KO(-1,t,"ộ"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 218 + k.KDC(1,t); + k.KO(-1,t,"Ộ"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 232 + k.KDC(1,t); + k.KIO(-1,this.s_circum_26,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 253 + k.KDC(1,t); + k.KIO(-1,this.s_nasals_21,1,t); + k.KB(t); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x102)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 194 + k.KDC(1,t); + k.KO(-1,t,"ˆ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 217 + k.KDC(1,t); + k.KO(-1,t,"ộ"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 218 + k.KDC(1,t); + k.KO(-1,t,"Ộ"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 232 + k.KDC(1,t); + k.KIO(-1,this.s_circum_26,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 253 + k.KDC(1,t); + k.KIO(-1,this.s_nasals_21,1,t); + k.KB(t); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x103)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 196 + k.KDC(1,t); + k.KO(-1,t,"ˇ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 220 + k.KDC(1,t); + k.KO(-1,t,"ọ̌"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 221 + k.KDC(1,t); + k.KO(-1,t,"Ọ̌"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 233 + k.KDC(1,t); + k.KIO(-1,this.s_caron_27,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 253 + k.KDC(1,t); + k.KIO(-1,this.s_nasals_21,1,t); + k.KB(t); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x103)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 197 + k.KDC(1,t); + k.KO(-1,t,"ˇ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 220 + k.KDC(1,t); + k.KO(-1,t,"ọ̌"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 221 + k.KDC(1,t); + k.KO(-1,t,"Ọ̌"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 233 + k.KDC(1,t); + k.KIO(-1,this.s_caron_27,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 253 + k.KDC(1,t); + k.KIO(-1,this.s_nasals_21,1,t); + k.KB(t); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x103)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 198 + k.KDC(1,t); + k.KO(-1,t,"ˇ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 220 + k.KDC(1,t); + k.KO(-1,t,"ọ̌"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 221 + k.KDC(1,t); + k.KO(-1,t,"Ọ̌"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 233 + k.KDC(1,t); + k.KIO(-1,this.s_caron_27,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 253 + k.KDC(1,t); + k.KIO(-1,this.s_nasals_21,1,t); + k.KB(t); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, 0x104)) { + if(1){ + r=m=1; // Line 58 + k.KDC(0,t); + k.KDO(-1,t,0); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, 0x104)) { + if(1){ + r=m=1; // Line 59 + k.KDC(0,t); + k.KDO(-1,t,1); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, 0x104)) { + if(1){ + r=m=1; // Line 60 + k.KDC(0,t); + k.KDO(-1,t,2); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 200 + k.KDC(1,t); + k.KO(-1,t,"¯"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 202 + k.KDC(1,t); + k.KO(-1,t,"¯"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 63 + k.KDC(0,t); + k.KO(-1,t,"A"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 64 + k.KDC(0,t); + k.KO(-1,t,"B"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_C /* 0x43 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 133 + k.KDC(1,t); + k.KO(-1,t,"C"); + } + else if(1){ + r=m=1; // Line 89 + k.KDC(0,t); + k.KO(-1,t,"N̄"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_C /* 0x43 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 135 + k.KDC(1,t); + k.KO(-1,t,"C"); + } + else if(1){ + r=m=1; // Line 104 + k.KDC(0,t); + k.KO(-1,t,"N̄"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 65 + k.KDC(0,t); + k.KO(-1,t,"D"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 66 + k.KDC(0,t); + k.KO(-1,t,"E"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 67 + k.KDC(0,t); + k.KO(-1,t,"F"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 68 + k.KDC(0,t); + k.KO(-1,t,"G"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_H /* 0x48 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 143 + k.KDC(1,t); + k.KO(-1,t,"H"); + } + else if(1){ + r=m=1; // Line 87 + k.KDC(0,t); + k.KO(-1,t,"SH"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_H /* 0x48 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 145 + k.KDC(1,t); + k.KO(-1,t,"H"); + } + else if(1){ + r=m=1; // Line 102 + k.KDC(0,t); + k.KO(-1,t,"Sh"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 69 + k.KDC(0,t); + k.KO(-1,t,"I"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 70 + k.KDC(0,t); + k.KO(-1,t,"J"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 71 + k.KDC(0,t); + k.KO(-1,t,"K"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 72 + k.KDC(0,t); + k.KO(-1,t,"L"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 73 + k.KDC(0,t); + k.KO(-1,t,"M"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 74 + k.KDC(0,t); + k.KO(-1,t,"N"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 75 + k.KDC(0,t); + k.KO(-1,t,"O"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 76 + k.KDC(0,t); + k.KO(-1,t,"P"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_Q /* 0x51 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 148 + k.KDC(1,t); + k.KO(-1,t,"Q"); + } + else if(1){ + r=m=1; // Line 86 + k.KDC(0,t); + k.KO(-1,t,"CH"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_Q /* 0x51 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 150 + k.KDC(1,t); + k.KO(-1,t,"Q"); + } + else if(1){ + r=m=1; // Line 101 + k.KDC(0,t); + k.KO(-1,t,"Ch"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 77 + k.KDC(0,t); + k.KO(-1,t,"R"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_S /* 0x53 */)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 180 + k.KDC(1,t); + k.KO(-1,t,"Ṣ"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_S /* 0x53 */)) { + if(k.KFCM(1,t,[{t:'d',d:2}])){ + r=m=1; // Line 181 + k.KDC(1,t); + k.KO(-1,t,"Ṣ"); + } + else if(1){ + r=m=1; // Line 78 + k.KDC(0,t); + k.KO(-1,t,"S"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 79 + k.KDC(0,t); + k.KO(-1,t,"T"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_U /* 0x55 */)) { + if(1){ + r=m=1; // Line 80 + k.KDC(0,t); + k.KO(-1,t,"U"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 81 + k.KDC(0,t); + k.KO(-1,t,"V"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 82 + k.KDC(0,t); + k.KO(-1,t,"W"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_X /* 0x58 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 138 + k.KDC(1,t); + k.KO(-1,t,"X"); + } + else if(1){ + r=m=1; // Line 88 + k.KDC(0,t); + k.KO(-1,t,"Ọ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_X /* 0x58 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 140 + k.KDC(1,t); + k.KO(-1,t,"X"); + } + else if(1){ + r=m=1; // Line 103 + k.KDC(0,t); + k.KO(-1,t,"Ọ"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 83 + k.KDC(0,t); + k.KO(-1,t,"Y"); + } + } + else if(k.KKM(e, modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4100 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 84 + k.KDC(0,t); + k.KO(-1,t,"Z"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKSLASH /* 0xDC */)) { + if(k.KFCM(2,t,['n','̄'])){ + r=m=1; // Line 223 + k.KDC(2,t); + k.KO(-1,t,"ñ"); + } + else if(k.KFCM(2,t,['N','̄'])){ + r=m=1; // Line 224 + k.KDC(2,t); + k.KO(-1,t,"Ñ"); + } + else if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 159 + k.KDC(1,t); + k.KO(-1,t,"ˆ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 217 + k.KDC(1,t); + k.KO(-1,t,"ộ"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 218 + k.KDC(1,t); + k.KO(-1,t,"Ộ"); + } + else if(k.KFCM(1,t,['s'])){ + r=m=1; // Line 226 + k.KDC(1,t); + k.KO(-1,t,"ṣ"); + } + else if(k.KFCM(1,t,['S'])){ + r=m=1; // Line 227 + k.KDC(1,t); + k.KO(-1,t,"Ṣ"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 232 + k.KDC(1,t); + k.KIO(-1,this.s_circum_26,1,t); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_6 /* 0x36 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 153 + k.KDC(1,t); + k.KO(-1,t,"^"); + } + else if(1){ + r=m=1; // Line 106 + k.KDC(0,t); + k.KO(-1,t,"₦"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4210 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(k.KFCM(1,t,[{t:'d',d:1}])){ + r=m=1; // Line 201 + k.KDC(1,t); + k.KO(-1,t,"¯"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKQUOTE /* 0xC0 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 156 + k.KDC(1,t); + k.KO(-1,t,"`"); + } + else if(k.KFCM(1,t,['m'])){ + r=m=1; // Line 205 + k.KDC(1,t); + k.KO(-1,t,"m̀"); + } + else if(k.KFCM(1,t,['M'])){ + r=m=1; // Line 206 + k.KDC(1,t); + k.KO(-1,t,"M̀"); + } + else if(k.KFCM(1,t,['n'])){ + r=m=1; // Line 208 + k.KDC(1,t); + k.KO(-1,t,"ǹ"); + } + else if(k.KFCM(1,t,['N'])){ + r=m=1; // Line 209 + k.KDC(1,t); + k.KO(-1,t,"Ǹ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 211 + k.KDC(1,t); + k.KO(-1,t,"ọ̀"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 212 + k.KDC(1,t); + k.KO(-1,t,"Ọ̀"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 230 + k.KDC(1,t); + k.KIO(-1,this.s_grave_24,1,t); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_C /* 0x43 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 134 + k.KDC(1,t); + k.KO(-1,t,"c"); + } + else if(1){ + r=m=1; // Line 94 + k.KDC(0,t); + k.KO(-1,t,"n̄"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 */, keyCodes.K_C /* 0x43 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 136 + k.KDC(1,t); + k.KO(-1,t,"c"); + } + else if(1){ + r=m=1; // Line 99 + k.KDC(0,t); + k.KO(-1,t,"n̄"); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_H /* 0x48 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 144 + k.KDC(1,t); + k.KO(-1,t,"h"); + } + else if(1){ + r=m=1; // Line 92 + k.KDC(0,t); + k.KO(-1,t,"sh"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 */, keyCodes.K_H /* 0x48 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 146 + k.KDC(1,t); + k.KO(-1,t,"h"); + } + else if(1){ + r=m=1; // Line 97 + k.KDC(0,t); + k.KO(-1,t,"Sh"); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_Q /* 0x51 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 149 + k.KDC(1,t); + k.KO(-1,t,"q"); + } + else if(1){ + r=m=1; // Line 91 + k.KDC(0,t); + k.KO(-1,t,"ch"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 */, keyCodes.K_Q /* 0x51 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 151 + k.KDC(1,t); + k.KO(-1,t,"q"); + } + else if(1){ + r=m=1; // Line 96 + k.KDC(0,t); + k.KO(-1,t,"Ch"); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_S /* 0x53 */)) { + if(k.KFCM(1,t,[{t:'d',d:0}])){ + r=m=1; // Line 179 + k.KDC(1,t); + k.KO(-1,t,"ṣ"); + } + } + else if(k.KKM(e, modCodes.NO_CAPS | modCodes.VIRTUAL_KEY /* 0x4200 */, keyCodes.K_X /* 0x58 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 139 + k.KDC(1,t); + k.KO(-1,t,"x"); + } + else if(1){ + r=m=1; // Line 93 + k.KDC(0,t); + k.KO(-1,t,"ọ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 */, keyCodes.K_X /* 0x58 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 141 + k.KDC(1,t); + k.KO(-1,t,"x"); + } + else if(1){ + r=m=1; // Line 98 + k.KDC(0,t); + k.KO(-1,t,"ọ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_BKSLASH /* 0xDC */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 160 + k.KDC(1,t); + k.KO(-1,t,"ˇ"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 220 + k.KDC(1,t); + k.KO(-1,t,"ọ̌"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 221 + k.KDC(1,t); + k.KO(-1,t,"Ọ̌"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 233 + k.KDC(1,t); + k.KIO(-1,this.s_caron_27,1,t); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_BKQUOTE /* 0xC0 */)) { + if(k.KFCM(1,t,[']'])){ + r=m=1; // Line 157 + k.KDC(1,t); + k.KO(-1,t,"´"); + } + else if(k.KFCM(1,t,['ọ'])){ + r=m=1; // Line 214 + k.KDC(1,t); + k.KO(-1,t,"ọ́"); + } + else if(k.KFCM(1,t,['Ọ'])){ + r=m=1; // Line 215 + k.KDC(1,t); + k.KO(-1,t,"Ọ́"); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_vow_23}])){ + r=m=1; // Line 231 + k.KDC(1,t); + k.KIO(-1,this.s_acute_25,1,t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_nasals_21}])){ + r=m=1; // Line 234 + k.KDC(1,t); + k.KIO(-1,this.s_acnasals_28,1,t); + } + } + return r; + }; +} diff --git a/web/testing/test_chirality.js b/web/testing/test_chirality.js new file mode 100644 index 0000000000..1011b551b3 --- /dev/null +++ b/web/testing/test_chirality.js @@ -0,0 +1 @@ +if(typeof keyman === 'undefined') {console.log('Keyboard requires KeymanWeb 10.0 or later');if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");} else {KeymanWeb.KR(new Keyboard_test_chirality());}function Keyboard_test_chirality(){this.KI="Keyboard_test_chirality";this.KN="KeymanWeb Chirality Tester";this.KMINVER="10.0";this.KV={F:' 1em "Arial"',K102:0};this.KDU=1;this.KV.KLS={};this.KV.BK=(function(x){var e=Array.apply(null,Array(65)).map(String.prototype.valueOf,""),r=[],v,i,m=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt'];for(i=m.length-1;i>=0;i--)if((v=x[m[i]])||r.length)r=(v?v:e).slice().concat(r);return r})(this.KV.KLS);this.KH='';this.KM=0;this.KBVER="1.0";this.KMBM=0x031F;this.KVER="10.0.1057.0";this.gs=function(t,e) {return this.g0(t,e);};this.g0=function(t,e) {var k=KeymanWeb,r=0,m=0;if(k.KKM(e,16658,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_RC_CAP_a");}else if(k.KKM(e,16666,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_RCA_CAP_a");}else if(k.KKM(e,16664,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_RA_CAP_a");}else if(k.KKM(e,16657,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_LC_CAP_a");}else if(k.KKM(e,16660,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_LA_CAP_a");}else if(k.KKM(e,16642,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_RC_a");}else if(k.KKM(e,16650,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_RCA_a");}else if(k.KKM(e,16648,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_RA_a");}else if(k.KKM(e,16644,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_LA_a");}else if(k.KKM(e,16641,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_LC_a");}else if(k.KKM(e,16645,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_LCA_a");}else if(k.KKM(e,16644,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_LA_a");}else if(k.KKM(e,16641,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_LC_a");}else if(k.KKM(e,16914,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"RC_CAP_a");}else if(k.KKM(e,16922,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"RCA_CAP_a");}else if(k.KKM(e,16920,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"RA_CAP_a");}else if(k.KKM(e,16913,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"LC_CAP_a");}else if(k.KKM(e,16916,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"LA_CAP_a");}else if(k.KKM(e,16898,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"RC_a");}else if(k.KKM(e,16906,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"RCA_a");}else if(k.KKM(e,16904,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"RA_a");}else if(k.KKM(e,16900,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"LA_a");}else if(k.KKM(e,16897,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"LC_a");}else if(k.KKM(e,16901,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"LCA_a");}else if(k.KKM(e,16900,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"LA_a");}else if(k.KKM(e,16897,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"LC_a");}else if(k.KKM(e,16640,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_DF_a");}else if(k.KKM(e,16912,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"DF_CAP_a");}else if(k.KKM(e,16656,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"CAPSLOCK_DF_CAP_a");}else if(k.KKM(e,16896,65)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"DF_a");}else if(k.KKM(e,16384,66)) {r=m=1;k.KDC(0,t);k.KO(-1,t,"b");}return r;};} \ No newline at end of file diff --git a/web/testing/unminified.html b/web/testing/unminified.html index 4f1a28c731..8cefb8fe60 100644 --- a/web/testing/unminified.html +++ b/web/testing/unminified.html @@ -18,7 +18,7 @@ @@ -83,6 +83,10 @@

Return to testing home page

+ +
+

--End of Document--

+