keyman/0000775000000000000000000000000014600607130007227 5ustar keyman/.clang-format0000664000000000000000000000754614600607066011626 0ustar --- Language: Cpp # BasedOnStyle: LLVM AccessModifierOffset: -2 AlignAfterOpenBracket: AlwaysBreak AlignConsecutiveMacros: false AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: false AlignEscapedNewlines: Left AlignOperands: true AlignTrailingComments: true AllowAllArgumentsOnNextLine: true AllowAllConstructorInitializersOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: None AllowShortLambdasOnASingleLine: All AllowShortIfStatementsOnASingleLine: Never AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: AllDefinitions AlwaysBreakBeforeMultilineStrings: true AlwaysBreakTemplateDeclarations: MultiLine BinPackArguments: true BinPackParameters: false BraceWrapping: AfterCaseLabel: false AfterClass: false AfterControlStatement: false AfterEnum: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false AfterExternBlock: false BeforeCatch: false BeforeElse: false IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeBraces: Attach BreakBeforeInheritanceComma: false BreakInheritanceList: BeforeColon BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 130 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: false ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DeriveLineEnding: true DerivePointerAlignment: true DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH IncludeBlocks: Preserve IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 SortPriority: 0 - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 SortPriority: 0 - Regex: '.*' Priority: 1 SortPriority: 0 IncludeIsMainRegex: '(Test)?$' IncludeIsMainSourceRegex: '' IndentCaseLabels: false IndentGotoLabels: true IndentPPDirectives: None IndentWidth: 2 IndentWrappedFunctionNames: false JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: false MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None ObjCBinPackProtocolList: Auto ObjCBlockIndentWidth: 2 ObjCSpaceAfterProperty: false ObjCSpaceBeforeProtocolList: true PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left ReflowComments: true SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements SpaceBeforeRangeBasedForLoopColon: true SpaceInEmptyBlock: false SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 2 SpacesInAngles: false SpacesInConditionalStatement: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false SpaceBeforeSquareBrackets: false Standard: Auto StatementMacros: - Q_UNUSED - QT_REQUIRE_VERSION TabWidth: 8 UseCRLF: false UseTab: Never ... keyman/.editorconfig0000664000000000000000000000037414600607066011720 0ustar # Editor configuration, see https://editorconfig.org root = true [*] charset = utf-8 indent_style = space indent_size = 2 insert_final_newline = true trim_trailing_whitespace = true [*.md] max_line_length = 160 [{Makefile,rules}] indent_style = tab keyman/.eslintrc.cjs0000664000000000000000000000074414600607066011646 0ustar module.exports = { root: true, env: { browser: true, es2021: true, node: true, }, // TODO: we need to move to the following, but this gets us started with infrastructure without breaking our build // extends: [ "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended"], extends: ["plugin:@typescript-eslint/eslint-recommended"], parser: "@typescript-eslint/parser", parserOptions: { ecmaVersion: "latest", sourceType: "module", }, }; keyman/.flake80000664000000000000000000000022614600607066010412 0ustar [flake8] max-line-length = 120 indent-size = 2 ignore = E402, # module level import not at top of file W504, # line break after binary operator keyman/.nycrc.json0000664000000000000000000000014514600607066011326 0ustar { "check-coverage": true, "temp-directory": ".nyc_output", "lines": 90, "reporter": "text" } keyman/.shellcheckrc0000664000000000000000000000025214600607066011671 0ustar external-sources=true # If you get SC1091 for sourced files, add the following setting to # your .vscode/settings.json file: # "shellcheck.useWorkspaceRootAsCwd": false keyman/CODE_OF_CONDUCT.md0000664000000000000000000001214614600607066012042 0ustar # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at community@keyman.com. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction **Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. **Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning **Community Impact**: A violation through a single incident or series of actions. **Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban **Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. **Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban **Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. **Consequence**: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. keyman/CONTRIBUTING.md0000664000000000000000000005422414600607066011477 0ustar # Contributing to Keyman ⭐ Thank you for your contribution! ⭐ The following is a set of guidelines for contributing to Keyman, Keyman keyboards, Keyman lexical models and Keyman websites, which are hosted in the [Keymanapp Organization](https://github.com/keymanapp) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request. (These guidelines have been adapted from [Atom Guidelines](https://github.com/atom/atom/blob/master/CONTRIBUTING.md).) ## Table Of Contents [Code of Conduct](#code-of-conduct) [I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question) [What should I know before I get started?](#what-should-i-know-before-i-get-started) * [Keyman, Keyboard Layouts and Lexical Models](#keyman-keyboard-layouts-and-lexical-models) [How Can I Contribute?](#how-can-i-contribute) * [Reporting Bugs](#reporting-bugs) * [Suggesting Enhancements](#suggesting-enhancements) * [Your First Code Contribution](#your-first-code-contribution) * [Building Keyman](#building-keyman) * [Localize Keyman](#localize-keyman) * [Other Ways of Getting Involved](#other-ways-of-getting-involved) [Style Guides](#style-guides) * [Principles of Keyman Code Changes](#principles-of-keyman-code-changes) * [Pull Request and Commit Workflow](#pull-request-and-commit-workflow) * [Code Style Guide](#code-style-guide) * [User Testing](#user-testing) * [Documentation Style Guide](#documentation-style-guide) [Additional Notes](#additional-notes) * [Issue and Pull Request Labels](#issue-and-pull-request-labels) ## Code of Conduct This project and everyone participating in it is governed by the [Keyman Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [community@keyman.com](mailto:community@keyman.com). ## I don't want to read this whole thing I just have a question!!! **Note:** If you have a question about using Keyman, you'll get faster results by asking in the Keyman Community, where many other users may also be able to assist you. If you have a question about the Keyman source code, feel free to open an issue! * [Keyman Community](https://community.software.sil.org/c/keyman) ## What should I know before I get started? ### Keyman, Keyboard Layouts and Lexical Models Keyman is a complex project that spans six different platforms, with many a variety of components on each platform. We have chosen to host the Keyman project in the [keymanapp/keyman](https://github.com/keymanapp/keyman) monorepo, but [keyboard layouts](https://github.com/keymanapp/keyboards) and [lexical models](https://github.com/keymanapp/lexical-models) are stored in their own repositories. * Issues relating to the Keyman apps and their interactions with operating systems or other apps should be opened in the Keyman repo * For keyboard-specific or model-specific issues, open issues in the corresponding repository. * The Keyman websites are also hosted in their own repositories. Contributions, including issues and pull requests can be opened against these repositories also. * Product documentation for the Keyman app is hosted in the Keyman app repository, and replicated to the help.keyman.com repository. The primary repositories you are most likely to interact with are: * [Keyman app](https://github.com/keymanapp/keyman) * [Keyboards](https://github.com/keymanapp/keyboards) * [Lexical models](https://github.com/keymanapp/lexical-models) * [keyman.com site](https://github.com/keymanapp/keyman.com) * [help.keyman.com site](https://github.com/keymanapp/help.keyman.com) * [keymanweb.com site](https://github.com/keymanapp/keymanweb.com) * [api.keyman.com site](https://github.com/keymanapp/api.keyman.com) ## How Can I Contribute? ### Reporting Bugs This section guides you through submitting a bug report for Keyman. Following these guidelines helps maintainers and the community understand your report :pencil:, reproduce the behavior :computer: :computer:, and find related reports :mag_right:. Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](https://github.com/keymanapp/keyman/issues/new?assignees=&labels=bug&template=bug_report.md&title=bug%3A+); the information it asks for helps us resolve issues faster. > **Note:** If you find a **Closed** issue that seems like it is the > same thing that you're experiencing, open a new issue and include a > link to the original issue in the body of your new one. #### Before Submitting A Bug Report * **Check that you are running the [latest version](https://keyman.com/downloads).** * **Check the [community](https://community.software.sil.org/c/keyman)** for common questions and problems; search there to see if other people have reported the issue and possible solutions. * **Determine [which repository the problem should be reported in](#keyman-keyboard-layouts-and-lexical-models)**. * **Perform a [cursory search](https://github.com/search?q=+is%3Aissue+user%3Akeymanapp+label%3Abug)** to see if the problem has already been reported. If it has **and the issue is still open**, add a comment to the existing issue instead of opening a new one. #### How Do I Submit A (Good) Bug Report? Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#keyman-keyboard-layouts-and-lexical-models) your bug is related to, create an issue on that repository and provide the following information by filling in the template (not all repositories currently have a bug reporting template; in those cases, you can start with the [Keyman bug report template](https://github.com/keymanapp/keyman/blob/master/.github/ISSUE_TEMPLATE/bug_report.md?plain=1) if you wish). Explain the problem and include additional details to help maintainers reproduce the problem: * **Use a clear and descriptive title** for the issue to identify the problem. * **Describe the exact steps which reproduce the problem** in as many details as possible. When listing steps, **don't just say what you did, but explain how you did it**. For example, if you typed on Android using a bluetooth keyboard, instead of with the touch keyboard, note that. * **Provide specific examples to demonstrate the steps** If you are documenting a problem with unexpected output from a keyboard, make sure you include the exact keystroke sequence you typed, the output you received, and the expected output. * **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. * **If you're reporting that Keyman crashed**, include the reference number from the crash report, if available. Provide more context by answering these questions: * **Did the problem start happening recently** (e.g. after updating to a new version of Keyman, keyboard, app or operating system) or was this always a problem? * If the problem started happening recently, **can you reproduce the problem in an older version of Keyman?** What's the most recent version in which the problem doesn't happen? You can download older versions of Keyman from [the Downloads page](https://keyman.com/downloads). * **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens. Include details about your configuration and environment: * **Which version of Keyman are you using?** The version information is typically available in the About or Info screen, depending on your device type. * **What's the name and version of the OS you're using**? Note exactly which type of device you are using, the version of the operating system. * **Are you running Keyman in a virtual machine?** If so, which VM software are you using and which operating systems and versions are used for the host and the guest? * **Which keyboards and models do you have installed?** You can get that list by running `apm list --installed`. * **What app are you interacting with?** If the problem is in interaction with a specific app, note the app you are trying to work with, and its version. * **Which keyboard layout experiences the problem?** Capture the keyboard ID and the version of the keyboard layout. On Windows, tell us also the base keyboard layout, found in Keyman Configuration, Options tab. * **Diagnostic reports** On Windows, you can capture a diagnostic report by clicking Diagnostics in the Support tab of Keyman Configuration, save it and attach it to the issue. ### Suggesting Enhancements 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 Submitting An Enhancement Suggestion * **Determine [which repository the enhancement should be suggested in](#keyman-keyboard-layouts-and-lexical-models).** * **Perform a [cursory search](https://github.com/search?q=+is%3Aissue+user%3Akeymanapp+label%3Afeat)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. #### How Do I Submit A (Good) Enhancement Suggestion? Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#keyman-keyboard-layouts-and-lexical-models) your enhancement suggestion is related to, create an issue on that repository and provide the following information: * **Use a clear and descriptive title** for the issue to identify the suggestion. * **Provide a step-by-step description of the suggested enhancement** in as many details as possible. * **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). * **Describe the current behavior** and **explain which behavior you expected to see instead** and why. * **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Keyman which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. * **Explain why this enhancement would be useful** to most Keyman users. * **List some other keyboard tools or operating systems where this enhancement exists.** * **Specify which version of Keyman you're using.** The version information is typically available in the About or Info screen, depending on your device type. * **Specify the name and version of the OS you're using.** ### Your First Code Contribution Unsure where to begin contributing to Keyman? You can start by looking through these `good-first-issue` and `help-wanted` issues: * [Good first issues](https://github.com/keymanapp/keyman/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) - issues which should only require a few lines of code, and a test or two. * [Help wanted issues](https://github.com/keymanapp/keyman/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) - issues which should be a bit more involved than `Good First Issues` issues. ### Building Keyman Keyman can be built locally. For instructions on how to do this, see the [build documentation](./docs/build/index.md). ### Localize Keyman We use CrowdIn to develop translations for the Keyman user interface. * [Localize Keyman](https://translate.keyman.com/project/keyman) [![Crowdin](https://badges.crowdin.net/keyman/localized.svg)](https://translate.keyman.com/project/keyman) ### Other Ways of Getting Involved Even if you are not a coder, there are many other ways you can help with the Keyman project: * [Other Ways of Getting Involved](https://keyman.com/about/get-involved) ## Style Guides ### Principles of Keyman Code Changes These are some general principles that we need to be following when we create features or bug fixes in Keyman. These principles help to uphold a good user experience for Keyman end users and keyboard/model developers. * [Principles of Keyman Code Changes Wiki](https://github.com/keymanapp/keyman/wiki/Principles-of-Keyman-Code-Changes) ### Pull Request and Commit Workflow We have a number of git commit and pull request formatting preferences. We can review your pull request faster if you follow these guidelines: * [Pull Request and Commit workflow wiki](https://github.com/keymanapp/keyman/wiki/Pull-Request-and-Commit-workflow-notes) ### Code Style Guide The Keyman style guide will help you to prepare code in a way that matches the Keyman source. Note that older source may not yet meet this guide, so if you are fixing up an old piece of code, you may need to use your judgment to determine the code styling to use. * [Code Style Guide wiki](https://github.com/keymanapp/keyman/wiki/Keyman-Code-Style-Guide) ### User Testing Any pull request that impacts end user experience should include a user test. This is a set of instructions that an experienced user of Keyman could follow to validate that your pull request does what it should do. A good tester may depart from the test steps you provide to check the things you forgot -- but you should try and provide comprehensive test steps. The Keyman app repository has a bot which coordinates user testing for each pull request: * [User Testing wiki](https://github.com/keymanapp/keyman/wiki/User-Testing-Workflows) ### Documentation Style Guide This applies to user documentation found both on [help.keyman.com](https://github.com/keymanapp/help.keyman.com) and the application user documentation found in the [Keyman repository](https://github.com/keymanapp/keyman). Remember that application documentation is replicated to help.keyman.com but should be edited in the Keyman repository. * All new documentation pages should be written in [Markdown](https://daringfireball.net/projects/markdown). * Older documentation may be written in HTML or a strange hybrid of PHP scripts and HTML. If you make more than a minor change to an older doc, rewrite it to Markdown: 1. View Source on the page from your browser 2. Find the documentation content (often within the `
` tag) 3. Use a tool such as [Browserling HTML to Markdown](https://www.browserling.com/tools/html-to-markdown) to convert the document to Markdown 4. Paste this into a new file with the same name but the .md extension, and remove the old .html or .php file. The style guide for code documentation and comments can be found in the [Code Style Guide wiki](https://github.com/keymanapp/keyman/wiki/Keyman-Code-Style-Guide). ## Additional Notes ### Issue and Pull Request Labels This section lists the labels we use to help us track and manage issues and pull requests. These labels are used on the [Keyman app repo and the website repos](#keyman-keyboard-layouts-and-lexical-models). [GitHub search](https://help.github.com/articles/searching-issues/) makes it easy to use labels for finding groups of issues or pull requests you're interested in. The labels are loosely grouped by their purpose, but it's not required that every issue has a label from every group or that an issue can't have more than one label from the same group. #### Type of Issue | Label name | `keyman` :mag_right: | Description | | --- | --- | --- | | `feat` | [search][search-feat] | Feature requests. | | `bug` | [search][search-bug] | Confirmed bugs or reports that are very likely to be bugs. | | `chore` | [search][search-chore] | Minor updates to Keyman. | | `question` | [search][search-question] | Questions more than bug reports or feature requests (e.g. how do I do X). [**Usually better on the Keyman Community**](https://community.software.sil.org/c/keyman) | | `spec` | [search][search-spec] | Issues which are specifications for a large scale feature. | | `docs` | [search][search-docs] | Related to any type of documentation. | #### Issue State | Label name | `keyman` :mag_right: | Description | | --- | --- | --- | | `requires-design-work` | [search][search-requires-design-work] | Issues which need design before they can proceed. | | `help wanted` | [search][search-help-wanted] | The Keyman core team would appreciate help from the community in resolving these issues. | | `good first issue` | [search][search-good-first-issue] | Less complex issues which would be good first issues to work on for users who want to contribute to Keyman. | | `duplicate` | [search][search-duplicate] | Issues which are duplicates of other issues, i.e. they have been reported before. | | `low-priority` | [search][search-low-priority] | The Keyman core team has decided not to fix these issues for now, but may in the future as time permits. | | `wontfix` | [search][search-wontfix] | The Keyman core team has decided not to fix these issues for now, either because they're working as intended or for some other reason. | | `invalid` | [search][search-invalid] | Issues which aren't valid (e.g. user errors). | | `auto` | [search][search-auto] | Pull requests created automatically, e.g. version increments. | | `compatibility` | [search][search-compatibility] | Related to interactions with other applications. | | `dependencies` | [search][search-dependencies] | Related to changes in dependencies, often automatically generated. | | `external` | [search][search-external] | Related to issues that require changes to third party applications in order to be resolved. | #### Platform and Feature Categories These labels also include sublabels, such as `windows/config/`. | Label name | `keyman` :mag_right: | Description | | --- | --- | --- | | `windows/` | [search][search-windows] | Related to Keyman running on Windows. | | `linux/` | [search][search-linux] | Related to Keyman running on Linux. | | `mac/` | [search][search-mac] | Related to Keyman running on macOS. | | `ios/` | [search][search-ios] | Related to Keyman running on iOS. | | `android/` | [search][search-android] | Related to Keyman running on Android. | | `web/` | [search][search-web] | Related to KeymanWeb. | | `developer/` | [search][search-developer] | Related to Keyman Developer. | | `common/` | [search][search-common] | Related to Keyman Core and shared code. | | `oem/` | [search][search-oem] | Related to third party projects that are built together with Keyman. | #### Pull Request Labels | Label name | `keyman` :mag_right: | Description | | --- | --- | --- | | `cherry-pick` | [search][search-cherry-pick] | Pull requests which are essentially identical to another pull request, but for a different release version of Keyman. | | `refactor` | [search][search-refactor] | Pull requests which include no functional changes but reorganise code. | | `user-test-missing` | [search][search-user-test-missing] | Pull requests where no user tests have been defined. | | `user-test-required` | [search][search-user-test-required] | Pull requests where user testing is incomplete. | [search-feat]: https://github.com/keymanapp/keyman/labels/feat [search-bug]: https://github.com/keymanapp/keyman/labels/bug [search-chore]: https://github.com/keymanapp/keyman/labels/chore [search-question]: https://github.com/keymanapp/keyman/labels/question [search-spec]: https://github.com/keymanapp/keyman/labels/spec [search-docs]: https://github.com/keymanapp/keyman/labels/docs [search-requires-design-work]: https://github.com/keymanapp/keyman/labels/requires-design-work [search-help-wanted]: https://github.com/keymanapp/keyman/labels/help%20wanted [search-good-first-issue]: https://github.com/keymanapp/keyman/labels/good%20first%20issue [search-duplicate]: https://github.com/keymanapp/keyman/labels/duplicate [search-low-priority]: https://github.com/keymanapp/keyman/labels/low-priority [search-wontfix]: https://github.com/keymanapp/keyman/labels/wontfix [search-invalid]: https://github.com/keymanapp/keyman/labels/invalid [search-auto]: https://github.com/keymanapp/keyman/labels/auto [search-compatibility]: https://github.com/keymanapp/keyman/labels/compatibility [search-dependencies]: https://github.com/keymanapp/keyman/labels/dependencies [search-external]: https://github.com/keymanapp/keyman/labels/external [search-windows]: https://github.com/keymanapp/keyman/labels/windows%2F [search-linux]: https://github.com/keymanapp/keyman/labels/linux%2F [search-mac]: https://github.com/keymanapp/keyman/labels/mac%2F [search-ios]: https://github.com/keymanapp/keyman/labels/ios%2F [search-android]: https://github.com/keymanapp/keyman/labels/android%2F [search-web]: https://github.com/keymanapp/keyman/labels/web%2F [search-developer]: https://github.com/keymanapp/keyman/labels/developer%2F [search-common]: https://github.com/keymanapp/keyman/labels/common%2F [search-oem]: https://github.com/keymanapp/keyman/labels/oem%2F [search-cherry-pick]: https://github.com/keymanapp/keyman/labels/cherry-pick [search-refactor]: https://github.com/keymanapp/keyman/labels/refactor [search-user-test-missing]: https://github.com/keymanapp/keyman/labels/user-test-missing [search-user-test-required]: https://github.com/keymanapp/keyman/labels/user-test-required keyman/HISTORY.md0000664000000000000000000074611014600607066010733 0ustar # Keyman Version History ## 17.0.294 beta 2024-03-25 * chore(android,windows): Update crowdin strings for French (#11063) * chore(common): Fix missing entries in HISTORY.md (#11064) * fix(developer): catch sharing violation when saving mru (#11047) * fix(developer): capture alt shortcuts in LDML keyboard debugger (#11049) * fix(developer): correct path for kmc sourcemaps in sentry upload (#11051) ## 17.0.293 beta 2024-03-22 * chore(oem/fv): Update keyboard versions in keyboards.csv (#11013) * fix(developer): suppress emission of new empty fields in package editor (#11009) * fix(developer): return after calling await exitProcess (#11016) * chore(core): refresh API docs for 17.0 (#10986) ## 17.0.292 beta 2024-03-21 * fix(developer): remove unused keyboard info compiler messages (#10991) * fix(developer): font file meta data is invalid error (#10995) ## 17.0.291 beta 2024-03-20 * chore(mac): clean up code obsoleted by core (#10877) * fix(linux): Replace deprecated `pkg_resources` module with `packaging.version` (#10860) ## 17.0.290 beta 2024-03-19 * fix(ios): Sync selection range for long contexts (#10956) ## 17.0.289 beta 2024-03-16 * fix(common): add unit test for --debug flag for builder (#10974) ## 17.0.288 beta 2024-03-13 * test(developer): kmc keyboard info compiler messages unit tests (#10848) * fix(developer): getFontFamily now returns null if ttfMeta.promise errors (#10983) * docs(android/app): Add data privacy policy page (#10985) * fix(developer): min Keyman version for LDML is 17.0 (#10977) ## 17.0.287 beta 2024-03-12 * chore(developer): resolve excessive-fatal-exception issue (#10949) * fix(linux): Remove `ibus-keyman.post{inst,rm}` and verify that `ibus-daemon` is running when we start km-config (#10788) ## 17.0.286 beta 2024-03-11 * chore(web): improve the clarity of hints on OSK for Android (#10971) ## 17.0.285 beta 2024-03-08 * fix(windows): GetKeyboardLanguage exits early on an invalid keyboard ID (#10936) ## 17.0.284 beta 2024-03-07 * fix(web): globe key highlighting (#10932) * chore(web): updates mtnt model used by test page (#10935) * fix(developer): kmc keyboard info compiler no kmp error (#10893) * fix(developer): Treat Right Shift as Shift in debugger (#10919) * docs(developer): kmc-model api documentation (#10921) * docs(developer): kmc-model-info api documentation (#10922) * docs(developer): kmc-keyboard-info api documentation (#10923) * docs(developer): kmc-package api documentation (#10924) * fix(developer): normalize all input paths in .kps compiler (#10950) ## 17.0.283 beta 2024-03-06 * fix(android): fixes context-change detection for repeated-char cases (#10873) * fix(developer): search-term quote replacement was not global (#10934) * chore(common): Update ldml out of techpreview (#10913) * fix(developer): fix for errant \uXXXX error (#10946) * fix(developer): suppport loose match for CompilerEvents (#10948) * refactor(oem/fv/android): Install fallback keyboard (#10907) * refactor(android/app): Move storage permission checks (#10904) * fix(common): missing script exec bit (#10951) ## 17.0.282 beta 2024-03-05 * fix(developer): move osk.ts from developer-utils to kmc-kmn (#10903) * fix(developer): hint text special characters (#10927) * docs(developer): kmc-ldml api documentation (#10917) * chore(developer): consolidate external links in Developer messages (#10918) * fix(developer): message export filename was title case (#10941) ## 17.0.281 beta 2024-03-04 * chore(linux): Update debian changelog (#10897) * fix(ios): cross-paragraph keyboard rules (#10905) * chore(developer): deploy compiler messages to help site (#10906) ## 17.0.280 beta 2024-03-01 * fix(developer): make sure scroll bar appears when needed in global welcome (#10818) * chore(common): loosen .keyman-touch-layout schema layer id requirements (#10819) * docs(developer): kmc-kmn api documentation and some message documentation (#10856) * refactor(developer): cleanup kmn compiler message namespaces (#10867) * refactor(developer): reorganize messages for adding details (#10878) * fix(ios): context-initial diacritic handling (#10589) * feat(developer): adds kmc message command (#10888) * test(developer): kmc unit test infrastructure messages (#10825) * fix(android): handle surrogate pairs in selection range indexing (#10885) * feat(windows): move the code kmshell.dpr to unit so that only the includes are in dpr (#10871) ## 17.0.279 beta 2024-02-29 * fix(linux): Fix libkeymancore-dev dependencies (#10880) * chore(resources): update to latest ldml: xmlns, uset (#10865) ## 17.0.278 beta 2024-02-28 * docs(linux): Updated whatsnew for Keyman for Linux 17 (#10858) * fix(web): Save context state on reset (#10869) * chore(android/engine): Reduce toast notifications after installations (#10868) * fix(android/engine): Check selection indexes (#10857) ## 17.0.277 beta 2024-02-27 * fix(developer): exit kmc test data if any failure messages occurred (#10805) * docs(windows): add whats new Keyman for Windows 17.0 (#10783) * feat(developer): add api-extractor and api-documenter, config, and build integration (#10839) * feat(developer): publish api documentation to help.keyman.com (#10841) * docs(developer): npm package readme files (#10842) * refactor(developer): move osk module from common-types to developer-utils (#10845) * chore(linux): Update debian changelog (#10828) * fix(developer): repeated options in kmc must now be fully specified (#10821) * docs(developer): add documentation for kmc-analyze (#10854) ## 17.0.276 beta 2024-02-26 * chore(linux): Fix autopkg tests (#10824) ## 17.0.275 beta 2024-02-23 * chore(core): Update sample ldml keyboard (#10791) * fix(developer): publish keymancore-1.dll symbols (#10797) * fix(developer): improve uploading of sourcemaps to sentry (#10798) * fix(android/engine): Fix how keyboard picker menu exits (#10806) * chore(linux): Fix `upload-to-debian.sh` script for beta releases (#10784) * chore(linux): Fix API verification after adding SONAME (#10813) * chore(linux): Address comments from Debian mailing list (#10800) * docs(linux): Update how to build binary package with docker (#10814) * chore(linux): Update debian changelog (#10785) ## 17.0.274 beta 2024-02-22 * fix(android/engine): Remove logs for uninitialized default keyboard (#10782) * refactor(android/app): Allow SystemKeyboard to install default keyboard and dictionary (#10794) * chore(android/app): Remove logging for install referrer details (#10795) * docs(android/app): Update tablet screenshots (again) (#10796) * docs(android): Update screenshots for help (#10808) * chore(web): proper reporting of errors from es5 KMW (#10807) * fix(android): first keystroke when context is empty (#10809) * chore(linux): Update Debian `control` file (#10787) ## 17.0.273 beta 2024-02-21 * fix(developer): match kmc console formatting for messages in IDE (#10775) * fix(developer): ensure fatal errors report message or made non-fatal (#10777) * chore(developer): add LDML specific text to Project view (#10779) * fix(developer): reset debugger after ldml keyboard compile (#10780) * fix(developer): crash opening invalid project (#10781) * docs(ios): document gestures (#10763) ## 17.0.272 beta 2024-02-20 * fix(core): fix output append logic in any_group::apply_transform (#10758) * fix(android): Match phone suggestion banner styling on tablet (#10760) * docs(mac): Document What's New for version 17.0 (#10764) * fix(developer): Rename missing variables in tests (#10773) * chore(developer): reduce WARN_TouchLayoutUsesUnsupportedGesturesDownlevel to HINT (#10766) * fix(developer): prevent renaming of new project types in New Project dialog (#10767) * fix(developer): return an error code if build-test-data fails (#10765) * fix(developer): allow more parameters in kmc.cmd (#10759) * chore(linux): Ignore missing .symbols file in stable branch (#10674) * chore(linux): Update symbols file with current version (#10575) * docs(linux): Update screenshots and FAQ (#10768) * chore(linux): Fix `debian.sh` by removing quotes (#10772) ## 17.0.271 beta 2024-02-19 * chore(developer): add infrastructure messages tests (#10756) * chore(windows): Update more PT strings (#10718) * docs(android/app): Update tablet screenshots (#10726) * fix(web): sticky special-key highlighting (#10729) * fix(web): disables modipress for layer-switch keys with subkeys (#10745) * fix(web): missing null-guard for hardware keystrokes without active Keyman keyboard (#10740) * docs(ios): add what's new in 17.0 (#10748) * fix(web): handling of page-elements focused before engine initialization (#10744) * fix(ios): multitap consistency after new-lines (#10728) * docs(common): Update website README (#10738) ## 17.0.270 beta 2024-02-17 * fix(core): Update more tests and fix ldml_transforms (#10735) ## 17.0.269 beta 2024-02-15 * docs(android): Document using gestures on touch, and remove references to Browser (#10686) * docs(android/app): Add help page on using the banner (#10691) * fix(web): corrects Android over-deletion of selected text, other context diffs involving selected text (#10662) * fix(web): disables banner interaction when suggestions are absent (#10695) * fix(web): longpress validation by base key, not current location (#10707) ## 17.0.268 beta 2024-02-15 * chore: move to beta ## 17.0.267 alpha 2024-02-14 * fix(linux): Use temp dir if we can't create cache dir (#10681) * feat(developer): errs on unparseable regex (#10689) * feat(developer): errs on \uXXXX escapes (#10701) * docs(common): Fill in missing HISTORY.md entries (#10704) ## 17.0.266 alpha 2024-02-13 * chore(windows): add const to argument definition (#10677) * feat(windows): update windows engine unit tests to match removal of engine cached context (#10184) * fix(web): prevent invalid longpress shortcut triggers (#10641) ## 17.0.265 alpha 2024-02-12 * fix(developer): keyboard that targets only web can cause crashes and other problems (#10664) * fix(android/engine): Download multiple dictionaries (#10680) ## 17.0.264 alpha 2024-02-09 * chore(linux): Don't set VERSION_TAG to …-local in .deb packages (#10675) * fix(web): banner robustness when touched 2+ times at once (#10672) ## 17.0.263 alpha 2024-02-08 * fix(linux): Ignore keys with IBUS_MOD4_MASK set (#10668) ## 17.0.262 alpha 2024-02-07 * refactor(windows): Use km_core_actions struct instead of queue (#10557) * chore(core): move action apis into keyman_core_api_actions.h (#10569) * feat(core,developer): support normalization=disabled (#10586) * feat(developer): range warning for non-NFD chars (#10614) * fix(core): make `km_core_state_get_actions()` idempotent (#10585) * fix(core): strip markers in `actions_update_app_context_nfu()` (#10607) * fix(core): surrogate handling, markers in app context, and memory leak (#10618) * fix(windows): support unicode strings properly in logs (#10650) * fix(developer): ensure project populate files actually adds files (#10651) * fix(linux): Use raw string for regex (#10652) * fix(windows): `wstrtostr` should use `WideCharToMultiByte` (#10660) * chore(windows): rename actionItem to outputString for clarity (#10661) * fix(web): handling of backspaces when left-context is empty (#10584) * fix(ios): long-held backspace handling (#10633) * fix(web): banner scroll positioning after reversions (#10643) * chore(web): removes unused banner events (#10644) ## 17.0.261 alpha 2024-02-06 * fix(web): app/webview sourcemap inlining (#10631) * fix(android/app): Cleanup AndroidManifest handling of *.kmp (#10624) ## 17.0.260 alpha 2024-02-03 * chore(oem/fv): Update versions in keyboards.csv (#10606) * fix(linux): Fix path to artifacts when uploading to llso (#10609) * docs(linux): Update sample settings (#10610) * chore(linux): Fix API check if lines got removed in .symbols file (#10612) ## 17.0.259 alpha 2024-02-02 * feat(developer): double markers once again (#10541) * feat(core): ldml double marker, C++ side (#10563) * feat(core,developer): simplify markers (#10565) * chore(common): cancel earlier builds when new test builds triggered (#10593) * chore(linux): Use correct format specifier for `g_utf8_strlen` (#10599) * fix(linux): Fix version comparison (#10576) * chore(common): Add entries from 16.0.145 HISTORY.md (#10603) * chore(common): history missing message fixup (#10601) * chore(linux): Update debian changelog (#10596) ## 17.0.258 alpha 2024-02-01 * chore(developer): add unicode-license.txt for ldml keyboards data (#10568) * feat(core): ldml reorder marker processing (#10539) * chore(developer): kmc ldml build - call c8 directly for tests (#10522) * fix(web): app/webview control flow for initial layer (#10571) * chore(linux): Upgrade artifacts to v4 (#10577) * chore(linux): Fix the path of downloaded artifacts (#10594) ## 17.0.257 alpha 2024-01-31 * epic: Keyman Core normalization (#10390) * fix(web): OSK resource-loading promise's font-wait (#10506) * fix(web): documentation-keyboard font size, font scaling (#10507) * feat(web): testing page for font-load / key-scale interactions (#10534) * fix(web): proper await for special-osk font, use of it in key scaling (#10535) * fix(web): ensure use of actual key-cap / label font in key-scale ops (#10555) * docs: Update websites README.md (#10566) * fix(developer): kmc exit needs to wait for Sentry (#10558) * fix(developer): make sourcePath calculation for kmc-keyboard-info more lenient (#10559) * chore(developer): disable .js output for LDML keyboard compiler for 17.0 (#10560) * chore(linux): Replace Lunar with Noble (#10561) * chore(linux): Adjust test expectations for ICU >= 73 (#10573) ## 17.0.256 alpha 2024-01-30 * fix(linux): packaging on Ubuntu and Debian servers should give message instead of warning because we don't have patched ibus there (#10537) * feat(developer): turn on developer side normalization (#10528) ## 17.0.255 alpha 2024-01-29 * chore(ios): eliminate xcglogger dependency (#10446) * feat(developer): ldml marker normalization fix (#10527) * chore(linux): Build with webkitgtk 4.1 instead of 4.0 (#10483) ## 17.0.254 alpha 2024-01-27 * feat(core): ldml marker normalization fix (#10517) ## 17.0.253 alpha 2024-01-26 * feat(web): keystroke pre-processing unit tests (#10464) * feat(web): key-event rule processing unit tests for mnemonic, KMW 1.0 keyboards (#10475) * fix(web): touch-layout fontsize property use (#10504) ## 17.0.252 alpha 2024-01-25 * fix(common): ldml: fix typo in kmc error message (#10484) * chore(developer): `--enable-source-maps` parameter for kmc wrapper (#10496) * fix(android/engine): Fix OSK widths (#10442) * fix(web): banner suggestion resizing after device rotation (#10508) ## 17.0.251 alpha 2024-01-24 * chore(developer): upgrade ngrok to v3 (#10359) ## 17.0.250 alpha 2024-01-23 * fix(android/engine): Add RECEIVER_EXPORTED flag for broadcast receiver (#10463) * fix(web): osk responsiveness to held modifiers on legacy kbds (#10437) * fix(android/engine): Skip final globe key action (#10465) * feat(developer): marker normalization in .ts (#10443) * fix(android): hardware keystrokes now include mnemonic processing (#10445) ## 17.0.249 alpha 2024-01-22 * feat(web): suggestion banner UI enhancements - suggestion expanding + scrollable banner (#7934) * chore(web): worker sourcemap cleanup, mobile app webview sourcemap compat (#10413) ## 17.0.248 alpha 2024-01-19 * chore(android): Update targetSdkVersion to 34 (#10393) * fix(web): cancels active gestures on globe-key use (#10352) * fix(web): keyboard-documentation rendering mode (#10417) * fix(ios): multiple keyboard slide-in animations on app start (#10362) * fix(web): U_ key id -> text for all subkeys; is now preprocessed (#10434) * chore(android/app): Update whatsnew for 17.0 (#10395) * fix(web): bulk renderer interface for recent-version targeting keyboards (#10427) * feat(core): cross-segment markers (#10394) ## 17.0.247 alpha 2024-01-18 * fix(ios): banner image management (#10337) * feat(core): unescape u (#10356) * chore(developer,core): change sample and test files to use \u{…} (#10391) ## 17.0.246 alpha 2024-01-17 * fix(web): Add null check for changing the keyboard during typing (#10346) * chore(common): Update crowdin strings for Khmer (#10411) * docs(common): Update website README.md (#10399) * docs(linux): Add documentation for Core API verification (#10409) * fix(web): right-flick gesture-preview positioning (#10406) ## 17.0.245 alpha 2024-01-16 * chore(core): Ignore C++ symbols (#10386) * fix(android): Fix OSK rotation issues (#10373) * feat(developer): add `-m` parameter to kmc to control message severity (#10258) ## 17.0.244 alpha 2024-01-15 * refactor(core): Move `km_core_state_context_*` tests to separate file (#10375) * feat(developer): warn on gesture support for downlevel (#10364) * fix(web): use KMW OSK font for "**" special-text in key hints (#10371) * docs(linux): Update sample settings (#10374) ## 17.0.243 alpha 2024-01-12 * chore(core): split out some files (#10327) * chore(common): Update crowdin strings for French, German, Spanish (Latin America) (#10368) * fix(web): prediction time-limiter issues, performance (#10330) * fix(developer): test-page model loading (#10328) * fix(ios): use safe area to position Keyman menu correctly (#10339) * chore(linux): fix GHA packaging (#10366) * refactor(linux): Use `km_core_state_context_set_if_needed` (#10354) ## 17.0.242 alpha 2024-01-11 * fix(windows): serve images for readme files in Keyboard Install (#10312) * fix(developer): remove unused tools/customise menu (#10321) * fix(developer): cleanly handle filling a new osk file from layout (#10322) * fix(developer): new file support for project 2.0 (#10323) * chore(common): builder action launch typos (#10361) * feat(core): support stacked markers, prep for marker segments (#10326) ## 17.0.241 alpha 2024-01-10 * chore(deps-dev): bump follow-redirects from 1.14.9 to 1.15.4 (#10340) * Update character-map.md (#10345) * chore(linux): Output dput exit code after upload to llso (#10349) * fix(android/engine): Use fallback keyboard if keyboard index undefined (#10342) * fix(android): Use alert dialog when package is missing touch keyboards (#10335) * chore: cleanup recent history entries without PR title (#10298) * chore(web): better logging for gesture-recognizer tools build script (#10329) ## 17.0.240 alpha 2024-01-09 * chore(linux): Retry llso upload (#10331) ## 17.0.239 alpha 2024-01-08 * fix(mac): write persisted options returned from Core (#10275) * chore(web): remove lm-worker `Array.from` polyfill and make `Symbol` polyfill conditional (#10255) * change(web): lm-worker bundling + wrapper script rework (#10264) * refactor(web): transformation of build-bundler into a common es-bundling command (#10265) * change(web): KeymanWeb bundler-script centralization (#10267) * feat(web): alternate artifact - es6-bundled Web (#10257) * feat(web): es6 artifact for app/webview (#10274) * fix(web): adds null-guard for longpress-key validation (#10299) * fix(web): special key highlighting when pressed (#10296) ## 17.0.238 alpha 2024-01-03 * fix(developer): quell internal error when a section fails (#10300) * fix(core): ldml fixes for normalization between transform groups (#10290) * feat(core): more regex testing (#10304) * chore(core): better reporting in ldml tests (#10305) * feat(developer): escape bad markers (#10306) ## 17.0.237 alpha 2024-01-02 * feat(developer): Consolidate public APIs for kmc modules (#10208) * chore(developer): honor prompt to upgrade in kmc (#10218) ## 17.0.236 alpha 2023-12-22 * fix(oem/fv): Add fv_kwadacha_tsekene (#10292) * fix(common): give warning if emcc.py is present but not executable (#10289) ## 17.0.235 alpha 2023-12-21 * feat(developer): ldml: more improvement for key-not-found (#10236) ## 17.0.234 alpha 2023-12-20 * fix(mac): Improve detection of non-compliant apps (#10282) * fix(web): default multitap logic for shift-layer shift multitaps (#10281) * fix(web): keyboard functionality on Android 5.0 / Chrome 35 (#10284) ## 17.0.233 alpha 2023-12-19 * fix(web): unbreak some ts paths (#10279) * fix(core): clear core context on invalidate cache (#10230) * fix(oem/fv): Add fv_hulquminum_combine (#10269) ## 17.0.232 alpha 2023-12-18 * feat(web): adds highlighting to BKSP while held (#10270) ## 17.0.231 alpha 2023-12-15 * chore(web): Better match directory structure for headless engine tests (#10232) * fix(web): Fix types that listInputs and isKMWInput accept (#10233) * chore(web): Add unit tests for `pageContextAttachment` (#10250) ## 17.0.230 alpha 2023-12-14 * fix(core): ldml: fix bad usage of unique_ptr (#10252) * chore(linux): docker: fix Node.js install, make customizable (#10251) * fix(web): unit test for null-null keyboard switch event from #10245 (#10253) * fix(web): fixes android-webview emulation Web test page (#10238) * epic: new gesture engine (#7324) * fix(mac): improve code signing robustness (#10243) * chore(mac): use core actions struct (#10066) * chore(common): Add entries from 16.0.144 HISTORY.md (#10260) * chore(web): Remove dead code (#10231) ## 17.0.229 alpha 2023-12-13 * chore(ios): FV certificate key (#10228) * feat(core): action struct to action items conversion (#10115) * fix(developer): various project fixes (#10151) * feat(developer): Add Window menu (#10154) * feat(developer): New Project opens in new process (#10155) * fix(developer): two errors in touch layout editor (#10211) * feat(developer): Move options to ~/.keymandeveloper/options.json (#10216) * feat(core): ldml improve key-not-found (#10090) * fix(core): remove a TODO-LDML (#10198) * fix(core): improve memory allocation issues in calling into icu (#10222) ## 17.0.228 alpha 2023-12-11 * chore(mac): force detach of disk image during build after 5 failures (#10201) * chore(linux): Small refactoring to make it easier to read (#10196) * chore(common): Specify Keyman repo on GitHub actions (#10203) * chore(android,mac): Update Kibaku crowdin strings (#10174) * chore(android,mac): Update Mon crowdin strings (#10175) * fix(developer): crash loading a project when referenced .xml is missing (#10209) * feat(developer): kmc emit hint if project file is old version (#10158) * fix(common): kpj loader needs to handle empty Files element (#10157) ## 17.0.227 alpha 2023-12-08 * fix(windows): debug includes libcmtd vs libcmt.dll (#10176) * fix(linux): Do not restart Fcitx (#10180) ## 17.0.226 alpha 2023-12-07 * fix(web): accidental suggestion-banner retoggle when disabling predictions (#10014) * fix(web): Fix null error with legacy keyboards (#10141) ## 17.0.225 alpha 2023-12-06 * feat(developer): Multi-process model for projects (#10114) * fix(developer): prevent opening .kpj in multiple processes (#10137) * fix(android/app): InfoActivity pass external links to browser (#10153) ## 17.0.224 alpha 2023-12-05 * chore(linux): Update debian changelog (#10121) ## 17.0.223 alpha 2023-12-04 * chore(web): Add option to create test coverage report file (#10124) ## 17.0.222 alpha 2023-12-02 * fix(common): publish @keymanapp/developer-utils as npm module (#10118) ## 17.0.221 alpha 2023-12-01 * chore(windows): removed cached context windows engine (#10065) * change(android): flishy flashy mitigation, round 1 (#10017) * change(android): smoother keyboard initialization (#10022) * fix(android): no suggestions available when swapping pred-text target language (#10061) * chore(developer): require project file to exist (#10092) * chore(linux): Add support for loong64 architecture (#10109) * fix(web): Don't throw errors after detach (#10086) ## 17.0.220 alpha 2023-11-30 * fix(core): set_if_needed updates an empty cached context (#10098) * fix(core): check for null termination (#10101) ## 17.0.219 alpha 2023-11-29 * fix(developer): path separator for kmc-package (#10064) * fix(developer): projects 2.0 internal path enumeration (#10016) * fix(web): Fix attachment-api tests (#10085) * fix(web): Also move source map (#10089) ## 17.0.218 alpha 2023-11-27 * feat(developer): ldml: err/hint on illegal/pua chars (#10029) ## 17.0.217 alpha 2023-11-24 * feat(developer): warn on usage of virtual keys in rule output (#10062) * fix(core): memory management of options in action struct (#10073) * chore(linux): Update debian changelog (#10047) * chore(core): Add test keyboard for text selection tests (#10026) ## 17.0.216 alpha 2023-11-23 * fix(common): kmx struct alignment (#9977) * fix(developer): vis kbd callbacks instead of throw (#9979) * fix(core): dx: ldml: startContext should be optional in ldml test data (#10021) * chore(windows): remove `wm_keymandebug` messages and functions (#10055) * chore(windows): remove legacy LoadKeyboard (#10057) * chore(windows): remove unused globals relating to old keyboard debugging (#10058) * chore(core): remove vkey output from kmx processor (#10060) * fix(web): app/webview did not clear deadkeys on context-reset (#10039) ## 17.0.215 alpha 2023-11-22 * feat(core): ldml marker normalization (#9761) * feat(core): ldml backspace transform (#9960) * feat(core): ldml tertiary reordering (#9962) * fix(web): fixes OSK viewport scaling on iOS devices (#10035) ## 17.0.214 alpha 2023-11-20 * fix(ios): fv: replace Zip framework to prevent crash on startup (#10018) ## 17.0.213 alpha 2023-11-17 * fix(linux): Fix packaging GHA (#10020) * fix(android): Always display HTML banner when suggestions aren't available (#9696) ## 17.0.212 alpha 2023-11-16 * chore(web): splits banner.ts into separate files per banner type (#9987) * refactor(web): inactive banner management (#9988) ## 17.0.211 alpha 2023-11-15 * fix(windows): setup.inf generation had whitespace (#10000) * feat(developer): Support v2.0 projects in TIKE (#9949) * feat(developer): New Project - Description field and tweaks (#9950) * chore(developer): hide 'Remove From Project' for v2.0 projects (#9956) * feat(developer): Support loading XML LDML keyboards in TIKE (#9963) * feat(developer): show .xml LDML keyboards in project (#9964) * fix(developer): kmc build ldml keyboard should create output folder (#9966) * fix(developer): Project upgrade messages now show in Messages panel (#9969) * feat(developer): Project Settings Form for 17.0+ projects (#9984) * chore(developer): only build source files (#9985) * chore(developer): manage SourcePath in project upgrade (#9986) * feat(developer): handle errors loading projects (#9989) * chore(developer): show only source path files in project views (#9995) * chore(developer): handle project version checks cleanly in kmc (#9996) * fix(common): dx: don't call exit(0) on failure (#10005) * fix(linux): Improve triggering of packaging GHA (#10009) * chore(web,developer): Move keymanweb-osk.ttf to common/resources (#9993) ## 17.0.210 alpha 2023-11-14 * docs(common): Update CODEOWNERS for web (#9997) * chore(core): Add additional API checks (#9867) ## 17.0.209 alpha 2023-11-13 * docs(windows): update meson and emscripten details (#9933) * fix(web): Increase size of spacebar text (#9954) ## 17.0.208 alpha 2023-11-08 * fix(web): Fix clearing of deadkeys (#9944) * fix(web): Ignore `osk-always-visible` on non-desktop devices (#9951) * fix(linux): Fix baseline tests (#9967) * chore(linux): Fix GHA triggering (#9965) * fix(linux): Fix trigger for baseline tests (#9968) ## 17.0.207 alpha 2023-11-07 * refactor(web): Link to `index.html` in test pages (#9953) * feat(developer): Add more non-printing characters (#9846) ## 17.0.206 alpha 2023-11-06 * chore(developer): remove compile.pas and CompileErrorCodes.pas (#9924) * chore(common): remove prepublish step from package.json (#9937) * feat(developer): provide line number for some kmw compiler messages (#9938) * fix(developer): Sentry in Server should honour reporting settings (#9940) * fix(developer): resilience in loading Server config and cache files (#9941) ## 17.0.205 alpha 2023-11-03 * fix(developer): use KeymanWeb.Codes for 17.0+ (#9913) * fix(developer): don't use osk-always-visible on touch devices (#9917) * chore(linux): Improve repository_dispatch (#9865) * chore(linux): Refactor deb-packaging.sh script (#9866) * chore(linux): Add Core API version number (#9877) * fix(developer): kmc code generation for context(n) in context (#9932) * chore(developer): remove obsolete 'Allow Multiple Instances' and 'Use Legacy Compiler' options (#9934) * chore(developer): common/include dep for kmcmplib (#9935) * feat(common): ldml update to WIP cldr data (#9919) ## 17.0.204 alpha 2023-11-02 * fix(web): fixes doc-kbd display of default layer when it's not defined first (#9891) * fix(developer): compiler crash when no project loaded (#9898) * fix(developer): debug flag for compiling keyboards (#9901) * chore(developer): verify kmp.json output from kmc-package (#9844) * fix(developer): Project MRU now saves correctly (#9902) * chore(common): fixup SchemaValidators error handling (#9903) * chore(developer): change field label to 'Related Package ID' in Related Packages dialog (#9904) * fix(developer): open editor links in new window (#9905) * fix(developer): enable and update unit tests (#9907) * fix(developer): layout builder - maintain presentation during undo (#9914) * feat(developer): extract font family from .ttf in kmc-keyboard-info (#9859) * fix(developer): raise error if virtual key in context string (#9908) * feat(developer): Compile button in TIKE toolbar (#9910) * chore(developer): rename messages.ts for clarity (#9920) * fix(developer): warn if layer switch key is missing ID (#9921) * fix(developer): restore selection in layout builder even with duplicate ids (#9922) * fix(developer): enable line breaks in debugger (#9906) ## 17.0.203 alpha 2023-10-30 * fix(linux): Fix uninstallation of shared keyboard (#9880) * chore: include ci/pull-requests.inc.sh for help uploads (#9897) ## 17.0.202 alpha 2023-10-30 * chore(common): unify pull-request creation scripts (#9888) * epic: Keyman Core for Mac (#7857) ## 17.0.201 alpha 2023-10-28 * fix(core): build: support -t parameter correctly (#9820) * fix(developer): handle displayMap correctly with 'fill from layout' (#9861) ## 17.0.200 alpha 2023-10-27 * chore(developer,common,core): update to latest CLDR v44 (#9842) ## 17.0.199 alpha 2023-10-26 * fix(developer): handle xml errors in package compiler (#9821) * fix(developer): server download Keyman link (#9822) * chore(common): handle invalid XML in kpj-file-reader (#9824) * fix(developer): reduce confusion in Unicode fields in touch layout editor (#9839) ## 17.0.198 alpha 2023-10-25 * chore(common): Add entries from 16.0 HISTORY.md (#9826) * feat(core): new actions APIs (#9828) ## 17.0.197 alpha 2023-10-24 * chore(linux): Rename (lib)kmnkbp to (lib)keymancore ️ (#9793) * chore(linux): Rename `namespace kbp` to `core` ️ (#9792) * chore(linux): rename keyboardprocessor_ldml.* to keyman_core_ldml ️ (#9791) * chore(linux): Rename libkmnkbp0-0 package ️ (#9795) * fix(web): proper disabling of prediction timeout for prediction unit tests (#9835) ## 17.0.196 alpha 2023-10-20 * fix(mac): move keyboard menu items to main Input Menu from submenu (#9777) * feat(core): initial normalization (#9728) * chore(core): dx: ldml test improvement, backspace test (#9759) * docs(common): macos build update (#9809) * fix(web): enhances integrated test stability (#9718) * chore(linux): Update packaging GHA ️ (#9812) * chore(linux): Rename KBP to CORE ️ (#9794) * chore(linux): Fix build by adding one character (#9817) ## 17.0.195 alpha 2023-10-19 * chore(linux): Allow to collect coverage on TC (#9790) * fix(common): don't use URL in common/web/types (#9798) * chore: update kmp.schema.json and docs for kps schema (#9800) * docs(windows): update text and images for windows 11 (#9689) ## 17.0.194 alpha 2023-10-18 * chore(linux): Re-enable building for Ubuntu 23.10 Mantic (#9780) * chore(linux): Add missing tests (#9783) * fix(web): fixes touch form-factor default kbd on cookieless keymanweb.com page load (#9786) * fix(developer): three kmc .keyboard_info generation bugs (#9784) * fix(developer): handle invalid project folders cleanly (#9785) * chore(linux): Fix build scripts (#9781) ## 17.0.193 alpha 2023-10-17 * fix(developer): kmc crash on start (#9771) * fix(core): don't use double newlines in debuglog (#9258) * chore(linux): Add code coverage index page (#9758) * feat(linux): Allow installing keyboards with arbitrary language ️ (#9756) * fix(linux): Fix crash initializing Sentry with Python < 3.10 (#9774) * chore(linux): Rename `kbp_state_get_intermediate_context` to `km_core…` ️ (#9775) ## 17.0.192 alpha 2023-10-16 * fix(ios): missing backslash in build script (#9765) * chore(linux): Speed up ibus-util tests (#9754) * feat(linux): Allow loading of keyboards with arbitrary language ️ (#9735) ## 17.0.191 alpha 2023-10-15 * chore: update readme for keyboard_info schema (#9746) ## 17.0.190 alpha 2023-10-12 * chore(web): web build streamlining (#9743) * chore(linux): Add code coverage reports for keyman-config and keyman-system-service (#9753) ## 17.0.189 alpha 2023-10-11 * refactor(linux): Use auto cleanup (and fix some memory leaks) (#9648) * refactor(linux): Simplify adding keyboard (#9734) ## 17.0.188 alpha 2023-10-11 * chore(android,windows): Update crowdin strings for Kannada (#9737) ## 17.0.187 alpha 2023-10-11 * chore(developer): convert Server to ES Modules (#9673) * chore(common): convert hextobin to ES Modules (#9676) * chore(common): convert resources/build/version to ES Modules (#9678) * chore(common): keyman-version now generates only es module (#9680) * chore(common): cleanup final Typescript non-ESM metadata (#9681) * chore(ios): renew certificate (#9697) * feat(core): match any marker (#9687) * feat(developer): ldml fix all remaining TODOs around markers and variables (#9688) * fix(windows): re-enable signature check (#9695) * fix(common): fix schema fixer (#9727) * chore(core): rename keyboardprocessor.h to keyman_core_api.h (#9723) * chore: rename km_kbp_ to km_core_ (#9724) * chore(developer): fixup signcode paths for server (#9730) * fix(linux): Explicitly initialize GTK (#9706) * chore(linux): Improve Sentry reports (#9725) * epic(developer): refactor package-metadata for 17.0 (#9485) * chore: clean up a few minor discrepancies in builder.inc.sh (#9731) * fix: path for ESM increment-version, and exit code (#9738) ## 17.0.186 alpha 2023-10-04 * feat(developer): show an INFO message when warnings have failed a build (#9652) * chore(developer): reduce duplicate words warning to hint (#9653) * feat(developer): issue hint if package includes keyboard source files (#9658) * chore(developer): switch on code coverage reporting for kmc (#9662) * fix(core): clean cached ICU in core (#9668) * feat(developer): warn if .kps includes a .js which is not touch-capable (#9667) ## 17.0.185 alpha 2023-10-03 * chore(web): Add non-printing characters to the OSK (#9547) * feat(developer): support `store(&version) '17.0'` (#9656) * chore(developer): add test for `checkFilenameConventions == false` or unset (#9661) * feat(developer): ldml scan codes support (#9615) ## 17.0.184 alpha 2023-10-02 * fix(web): fixes toolbar refocus timing after a keyboard change (#9618) ## 17.0.183 alpha 2023-09-29 * feat(web): browser-KMW support for default subkeys (#9496) * refactor(linux): Add more tests for `keymanutil.c` ️ (#9595) ## 17.0.182 alpha 2023-09-28 * chore(web): builds that output to web/build/publish should also clean it (#9613) * chore(linux): Dynamically choose display number (#9629) * docs(linux): Update sample tasks.json for Linux (#9634) * chore(common): Add Crowdin strings for Mon (#9550) * fix(developer): only include mobile touch platform in basic project (#9549) * fix(windows): fix the ellipsis for longer text on buttons (#9638) ## 17.0.181 alpha 2023-09-26 * chore: workaround npm/cli#3466 when bundling internal deps (#9536) * chore(linux): Check and restart background processes (#9608) ## 17.0.180 alpha 2023-09-25 * fix(linux): Fix detection of unit tests (#9606) ## 17.0.179 alpha 2023-09-22 * chore(resources): ldml: update to keyboard3 (#9588) * change(android,web) Use web-based popup key longpresses (#9591) ## 17.0.178 alpha 2023-09-21 * fix(linux): Correctly open files linked from help page (#9601) * chore(linux): Fix bugs, add dependency and update documentation (#9602) ## 17.0.177 alpha 2023-09-20 * chore(linux): Add coverage action to `ibus-keyman/build.sh` (#9583) * docs(common): Fix documentation for `builder_describe_internal_dependency` (#9582) ## 17.0.176 alpha 2023-09-19 * chore(oem/fv/android): Update Gradle to 7.4 (#9590) * refactor(linux): Rename defines to clarify purpose ️ (#9584) * feat(core): drop \u1234 format (#9560) ## 17.0.175 alpha 2023-09-18 * chore(linux): Split startup process (#9570) ## 17.0.174 alpha 2023-09-16 * refactor(linux): Reformat file (#9569) ## 17.0.173 alpha 2023-09-13 * chore(common): Update to Unicode 15.1 (#9555) ## 17.0.172 alpha 2023-09-12 * fix(linux): Prevent exception if neither USER, LOGNAME nor SUDO_USER set (#9543) * chore(linux): Exclude environment.sh from build (#9553) ## 17.0.171 alpha 2023-09-01 * chore(linux): Add `clean` target to `rules` (#9531) ## 17.0.170 alpha 2023-08-31 * fix(common): builder_parse broke on option parameters (#9489) * docs(linux): Explicitly specify emscripten version (#9527) ## 17.0.169 alpha 2023-08-30 * fix(linux): Fix exception in km-kvk2ldml (#9523) ## 17.0.168 alpha 2023-08-29 * refactor(linux): Fix warning (#9513) ## 17.0.167 alpha 2023-08-25 * feat(core): implement mapped set mapping (#9504) * feat(resources): add pcm keyboard (#9508) ## 17.0.166 alpha 2023-08-24 * chore(common): Update crowdin strings for French (#9505) ## 17.0.165 alpha 2023-08-23 * feat(core): add display=id (#9484) ## 17.0.164 alpha 2023-08-22 * fix(common): don't crash on illegal unicodesets (#9492) ## 17.0.163 alpha 2023-08-21 * chore(web): Update keymanweb-osk.ttf to v. 3.0 (#9469) ## 17.0.162 alpha 2023-08-18 * fix(common): marker test (#9483) * fix(windows): allow QR share box to grow to edge of default configuration parent window (#9472) * chore(resources): update CLDR to post-PRI (#9482) ## 17.0.161 alpha 2023-08-16 * feat(core) actual regex (#9440) ## 17.0.160 alpha 2023-08-14 * feat(core): limit max marker to 0xD7FF (#9448) ## 17.0.159 alpha 2023-08-11 * feat(core): marker implementation (#9405) ## 17.0.158 alpha 2023-08-09 * chore(linux): Disable Mantic builds on Launchpad (#9435) * feat(windows): Use Keyboard Activated event API call to turn off caps lock (if required) (#9353) * chore: stats script parameters (#9431) * feat(developer): add 'default' property for longpress keys (#9432) * chore(developer): improve kmc sentry reporting on fatal build errors (#9441) ## 17.0.157 alpha 2023-08-08 * fix(linux): fix memory leaks and method name (#9413) ## 17.0.156 alpha 2023-08-07 * epic: kmc-kmw KeymanWeb compiler in Typescript (#8954) ## 17.0.155 alpha 2023-08-05 * chore(developer): update markers per review (#9374) ## 17.0.154 alpha 2023-08-04 * chore(common): Update crowdin GHA to trigger daily (#9410) * fix(web): forgot to target es5 when minifying polyfilled worker (#9409) * chore(common): Update history.md with 16.0 stable entries (#9419) ## 17.0.153 alpha 2023-08-03 * docs(windows): Update OS requirement to Windows 10 (#9381) * fix(web): maintenance of focus when changing keyboard via Toolbar UI (#9397) * chore(linux): Remove Kinetic from GHA (#9399) * chore(linux): Properly treat test builds with packaging GHA (#9400) ## 17.0.152 alpha 2023-08-02 * fix(developer): more wasm uset fixes (#9382) * docs(windows): corrected nmake cmd for certificates (#9376) * chore: add run-name to deb-packaging (#9386) * chore: try another variable for reporting (#9388) * chore(linux): Remove package build on Jenkins for Keyman 17 (#9380) * docs(linux): Add build doc for Keyman Web and Android (#9383) ## 17.0.151 alpha 2023-08-01 * feat(developer) marker steps (#9364) * feat(common): marker processing (#9365) * chore(linux): Don't fail on parallel builds (#9368) * fix(developer): fix breakage from emscripten 3.1.44 (#9375) * docs(core): Document how to build Core on Linux (#9328) ## 17.0.150 alpha 2023-07-31 * chore(linux): Update debian changelog (#9358) * chore(linux): Fix creation of PRs after uploading to Debian (#9360) ## 17.0.149 alpha 2023-07-30 * fix(core): Better range check for Uni_IsValid() (#9346) * chore(core): update documentation in transform logic and processor (#9352) ## 17.0.148 alpha 2023-07-27 * feat(core): merge transform/reorder processing w/ u32 (#9293) * chore(developer): make unknown vkey a hint, not error (#9344) * chore(linux): Update supported Ubuntu versions (#9341) ## 17.0.147 alpha 2023-07-25 * chore(linux): Update debian changelog (#9327) ## 17.0.146 alpha 2023-07-24 * chore(deps-dev): bump word-wrap from 1.2.3 to 1.2.4 (#9314) ## 17.0.145 alpha 2023-07-21 * fix(linux): Fix logging (#9310) * fix(windows): open pdf in an external browser (#9295) * fix(linux): Fix installation of keyboards with lang tag `mul` (#9027) * fix(web): allows registering precached keyboards (#9304) ## 17.0.144 alpha 2023-07-20 * refactor(linux): Use better way to get username (#9313) ## 17.0.143 alpha 2023-07-19 * spec(core): minor fix to tran spec (#9292) * docs(linux): Update man page and remove do-nothing option (#9291) * docs(linux): Update documentation (#9277) ## 17.0.142 alpha 2023-07-17 * chore(windows): disable wix compression for debug builds (#9074) ## 17.0.141 alpha 2023-07-15 * feat(core): implement reorder (#9223) * chore(common): add BUILDER_STR_REF (#9248) * feat(core): load reorder from kmx+, test case (#9260) ## 17.0.140 alpha 2023-07-14 * chore(common): add engine clause to package.json (#9008) ## 17.0.139 alpha 2023-07-13 * fix(common): set variables need to serialize elementstring (#9259) * chore(linux): Add unit tests for dconf_util.py (#9215) * refactor(linux): Refactor image loading (#9245) ## 17.0.138 alpha 2023-07-11 * chore: Update standards data (#9193) * chore(linux): Trigger Linux integration tests (#9221) ## 17.0.137 alpha 2023-07-10 * chore: authenticate github request when triggering test builds (#9225) * feat(web): logs enhanced debug info for error reports (#9217) * fix(web): silences low-priority warning that shows up in iOS kbd init (#9206) ## 17.0.136 alpha 2023-07-07 * chore(common): Update crowdin strings for Kibaku (#9214) * feat(core): kmxplus uset implementation in core (#9197) * chore(linux): Add support for `--no-integration` flag to build files (#9212) * spec(core): marker spec (#9196) ## 17.0.135 alpha 2023-07-06 * chore(common): improve coverage, fix todos (#9195) * chore(ios): minor build-script cleanup (#9201) * chore(linux): Allow to run tests without integration tests (#9192) * fix(web): sentry sourcemapping round 2 - yesterday's 'fix' unfortunately doesn't upload the maps (#9199) * chore(web): normalizes sourcemap paths for cleaner Sentry reports (#9200) * feat(linux): Allow to install keyboard for multiple languages (#9017) ## 17.0.134 alpha 2023-07-05 * fix(linux): Fix packaging GHA (#9172) * chore(ios): standardizes iOS build scripts (#9092) * fix(web): fixes up Web's InlinedOSK manual test page (#9175) * fix(web): re-establishes web srcmap uploading (#9179) * refactor(linux): Code refactoring (#9129) * refactor(linux): Extract methods (#9168) * fix(linux): Fix vertical alignment of labels in About dialog (#9167) * fix(linux): Add scrollbar to About dialog (#9166) * fix(linux): Remove tags from package description (#9165) * docs(linux): Update readme (#9190) * feat(developer): uset in element string (#9144) * fix(developer): improve coverage, add todos (#9170) * chore(developer): refactor so KmnCompiler only created once within kmc (#9171) * fix(common): support multichar escapes in element sets (#9173) * chore(linux): Update docker builds (#9188) ## 17.0.133 alpha 2023-07-04 * feat(common): add segmenter for element strings (#9141) * fix(windows): adds an extra row for Change Hotkey text label (#9149) * fix(linux): Another attempt to fix packaging GHA (#9155) * fix(linux): Fix packaging GHA (#9164) * fix(linux): Fix packaging GHA (#9169) ## 17.0.132 alpha 2023-06-30 * docs(mac): Update requirements.md (#9137) * fix(linux): Fix GHA package builds for non-Jammy dists (#9123) * fix(linux): Fix packaging GHA (#9142) ## 17.0.131 alpha 2023-06-27 * feat(developer,common,core): ldml UTF-32 literals in binary (#9084) * fix(web): fixes Web build zip artifact construction (#9096) ## 17.0.130 alpha 2023-06-26 * chore(deps): bump semver from 7.3.8 to 7.5.2 (#9085) * epic: conversion of Keyman Engine for Web to ES modules (#8560) ## 17.0.129 alpha 2023-06-23 * chore(common): Update crowdin strings for Spanish (es-ES and es-419) (#9040) * chore(android/app): Address some pre-launch accessibility report warnings (#9070) * fix(windows): support kmxplus in mcompile (#9071) * fix(core): fix ldml transforms (#9072) * feat(common,developer,core): add uset section (#9049) ## 17.0.128 alpha 2023-06-22 * fix(windows): testhost improve error message (#9061) * docs(windows): add more steps for clarity (#9063) ## 17.0.127 alpha 2023-06-21 * feat(core): implementation of non-regex components of tran (#9019) * chore: enable common ci for web (#9047) ## 17.0.126 alpha 2023-06-19 * chore(mac): move from altool to notarytool (#9010) ## 17.0.125 alpha 2023-06-17 * fix(android/samples): Cleanup Sample/Tests apk's (#9030) * chore(common): Bump crowdin github action to 1.3.2 (#9029) ## 17.0.124 alpha 2023-06-14 * fix(windows): qr code id uses keyboard name and not package name (#9002) * refactor(linux): Extract widgets to separate classes and files (#9007) ## 17.0.123 alpha 2023-06-13 * chore(developer): support cp1252 'ansi' keyboards (#8988) * fix(developer): keep kmc-kmn messages within namespace (#8999) * fix(linux): Fix display of installed keyboard version (#8948) * fix(linux): Fix creation of markdown help files for Linux (#9001) ## 17.0.122 alpha 2023-06-12 * refactor(developer): import kmcmplib errors into kmc-kmn (#8962) ## 17.0.121 alpha 2023-06-09 * fix(linux): Fix disabling of buttons (#8946) * chore(developer): check for nodejs deps in kmc-kmn (#8961) * spec(core): spec/impl for transform and vars (#8695) * feat(developer): improve tran/bksp tests, other improvements (#8967) ## 17.0.120 alpha 2023-06-07 * chore(core): look for emcc.py, not emcc (#8934) * chore(linux): Move some files to keyman-config (#8917) * fix(linux): Fix title of reference page and links (#8939) * fix(android/engine): Re-enable KMManager tests (#8940) ## 17.0.119 alpha 2023-06-06 * chore(developer): ensure kmcmplib messages are all UTF-8 (#8927) * chore(linux): Fix lintian warnings (#8931) ## 17.0.118 alpha 2023-06-05 * chore(ios): replace fv cert (#8900) * fix(core): Fix compilation if hotdoc is installed (#8912) * feat(linux): Rename column and add tooltip (#8918) ## 17.0.117 alpha 2023-06-04 * chore(developer): verify long lines compile correctly (#8915) ## 17.0.116 alpha 2023-06-02 * feat(linux): Add column for installation location (#8897) * chore(developer): verify kvks files and report errors (#8892) * refactor(developer): rearrange kmcmplib interface source (#8899) * refactor(developer): move filename consistency check to kmc (#8907) * chore(developer): loadFile callback error check and optimization (#8908) * chore(common): remove url module ref from common/web/types (#8914) ## 17.0.115 alpha 2023-06-01 * refactor(developer): complete fs move out of kmcmplib (#8882) * fix(common): tweak pack/publish support for npm 9.5.1 and node 18.16.0 (#8894) * feat(linux): Implement Options page and option to disable Sentry error reporting (#7989) ## 17.0.114 alpha 2023-05-31 * chore(developer): replace cwrap wasm bindings (#8857) * chore(developer): refactor kmcmplib interfaces (#8870) * chore(developer): move keyboard repo fixtures (#8874) * chore(linux): Move build steps to build.sh (#8864) ## 17.0.113 alpha 2023-05-26 * docs(android): Update documentation for building Android on Linux (#8860) * fix(android): Fix typo in build-utils.sh (#8859) * refactor(developer): compiler interface part 1 for wasm (#8850) * chore(developer): remove SetError macro (#8856) ## 17.0.112 alpha 2023-05-25 * refactor(developer): move file write out of WriteCompiledKeyboard and CompileKeyboard merge (#8796) ## 17.0.111 alpha 2023-05-24 * fix(android/app): Pathing for publish script (#8845) * chore(developer): add test for missing .js file to kmc-package (#8846) * feat(linux): Add dbus system service (#8509) * chore(linux): Add missing dependency to GHA (#8849) ## 17.0.110 alpha 2023-05-22 * fix(common): ensure child builds don't rebuild dependencies unnecessarily (#8834) ## 17.0.109 alpha 2023-05-17 * fix(windows): add wrap-symbols to Text Editor Makefile (#8819) * chore(linux): Make postinst script comply with Debian policy (#8810) * chore(windows): remove legacy core and flag ️ (#8593) ## 17.0.108 alpha 2023-05-16 * feat(windows): add text editor to the support makefile (#8750) * feat(developer): verify keyboard versions in kmc-package (#8769) * feat(developer): verify bcp47 tags are valid and minimal in kmc-package (#8778) * feat(developer): verify at least one language in package (#8783) * chore(developer): verify file types of content files in package (#8792) * chore(developer): verify that package has at least a model or keyboard (#8793) * chore(ios): Changes required for XCode 14.3 (#8746) ## 17.0.107 alpha 2023-05-15 * chore(linux): Fix installation build step on TC (#8784) * refactor(android/engine): Consolidate updateSelection (#8739) ## 17.0.106 alpha 2023-05-12 * chore(developer): move package formats to common/web/types (#8729) * feat(developer): add package validation (#8740) * feat(developer): add validation of package filenames (#8751) * feat(developer): validate content file names in packages (#8755) * feat(developer): validate package name in compiler (#8757) * chore(developer): rename Compiler and related classes (#8726) * feat(developer): uset api from wasm! (#8716) ## 17.0.105 alpha 2023-05-11 * chore(common): Update crowdin strings for Amharic (#8748) * chore(android/app): Cleanup build-play-store-notes script (#8749) * chore(linux): Add build.sh for keyman-config (#8733) ## 17.0.104 alpha 2023-05-10 * chore(developer): rename kmc-keyboard to kmc-ldml (#8725) * chore(linux): bring kmp.json for unit test up to spec (#8732) * feat(common): add `builder_run_action` shorthand function (#8742) ## 17.0.103 alpha 2023-05-09 * fix(mac): `$CONFIG` not `$CONFIGURATION` in build path (#8724) * chore(linux): Fix another problem uploading to launchpad (#8727) ## 17.0.102 alpha 2023-05-08 * chore(linux): Build for Lunar on all platforms (#8713) * fix(linux): Fix linux tests (#8510) * chore(linux): Fix uploading to launchpad (#8720) ## 17.0.101 alpha 2023-05-05 * chore(common): `set -eu` in build-utils.sh (#8698) * fix(android/app): Resize OSK when resuming app from background (#8704) ## 17.0.100 alpha 2023-05-04 * fix(developer): warning fixes in kmcmplib (#8690) * feat(developer): add uset api in kmcmplib (#8691) ## 17.0.99 alpha 2023-05-03 * chore(linux): Fix build script (#8705) ## 17.0.98 alpha 2023-05-02 * chore(common): run common and resources tests (#8692) ## 17.0.97 alpha 2023-04-28 * docs(windows): Add verify vs build tools (#8676) * feat(developer): groundwork for support new transform, developer side (#8686) ## 17.0.96 alpha 2023-04-27 * chore(android): Update QRGen version for Java 11 (#8673) * refactor(android/engine): Move toggleSuggestionBanner to KMKeyboard (#8679) * refactor(android/engine): Use isKeyboardLoaded() on a consistent basis (#8680) * chore(developer): test message correctness in compiler modules (#8664) * chore(developer): add eslint devDependency for kmc (#8665) * chore(developer): kmc-keyboard should not use any node-specific modules (#8666) * fix(common): builder parse multi-param order (#8668) * refactor(developer): use callbacks to avoid direct fs access in kmc-package (#8674) * refactor(android/engine): Move shouldIgnore booleans to KMKeyboard (#8682) * chore(linux): Build for Ubuntu 23.04 Lunar as well (#8683) ## 17.0.95 alpha 2023-04-26 * refactor(android/engine): Move currentBanner to KMKeyboard (#8671) * chore(android/engine): Remove jvm args (#8675) * fix(developer): kmc: fix jis/abnt2 scan codes (#8670) ## 17.0.94 alpha 2023-04-25 * fix(android/engine): Update InApp input connection (#8647) * chore(common): Move the_99 test fixture keyboard (#8660) * chore(android): Move namespace to Gradle files (#8667) ## 17.0.93 alpha 2023-04-24 * feat(common): kmx file reader (#8641) * feat(developer): support FollowKeyboardVersion in kmc-package (#8642) * chore(common): Update crowdin strings for Simplified Chinese (#8653) * fix(common): builder - pass deps flags to child scripts (#8654) * feat(developer): use CompilerEvent for messages in all of kmc (#8651) * chore(developer): fixup deps for kmc modules (#8652) * feat(core): ldml repertoire test, initial ICU integration (#8441) ## 17.0.92 alpha 2023-04-21 * fix(developer): kmc-package path reference (#8634) * chore(developer): only run keyboards-repo tests for a full-test (#8635) * refactor(developer): move comperr.h to kmn_compiler_errors.h (#8636) * refactor(developer): kmc-model to use `CompilerEvent` (#8637) ## 17.0.91 alpha 2023-04-20 * fix(developer): kmc-kmn would abort build on warnings (#8617) * fix(developer): kmc no longer emits double file extension for models (#8618) * refactor(developer): move build activities (#8622) * feat(developer): add warning options to kmc (#8623) * feat(developer): use new message infrastructure in kmc-kmn (#8625) * refactor(developer): move shared test helpers into common (#8626) * feat(developer): add CompilerMessages support to kmc-package (#8627) * feat(developer): warn if .kps file includes a non-binary .kvk file (#8628) * chore(web): sets kmc-model as dependency of input-processor test action (#8629) * fix(android/engine): Fix resetContext calls when selection changes (#8611) ## 17.0.90 alpha 2023-04-19 * chore(android/engine): Cleanup old SDK calls (#8612) * fix(developer): package editor no longer loses RTL flag for LMs (#8606) ## 17.0.89 alpha 2023-04-18 * chore(developer): tweak build of extension list in kmc (#8597) * docs(ios): Add help page for Settings (#8546) * fix(developer): add missing dependencies (#8605) ## 17.0.88 alpha 2023-04-17 * docs(android): Update Linux dev environment for Java 11 (#8596) ## 17.0.87 alpha 2023-04-13 * refactor(developer): DRY kmc module references (#8577) * chore(developer): kmc-kmn should build all baseline fixtures (#8578) * fix(developer): kmc should not validate as well as compile keyboard (#8579) * fix(developer): improve 'does not exist' error message (#8580) * fix(common): consolidate npm publishing (#8587) * chore(common): add missing deps and files for npm publish (#8588) ## 17.0.86 alpha 2023-04-12 * docs(windows): link to wiki architecture faq page (#8584) ## 17.0.85 alpha 2023-04-11 * chore(developer): AddWarning and SetError cleanup (#8571) * fix(developer): add DRY_RUN variable to build.sh (#8576) * fix(ios): fixes xcode-triggered debug, run builds (#8575) ## 17.0.84 alpha 2023-04-10 * epic: kmcompx - kmcmpdll cross-platform compiler (#7330) * chore(android): Update projects to use Java 11 (#8543) * docs: clarify dependency meanings in build-utils (#8567) * fix(mac): fix corrupt installer (#8565) ## 17.0.83 alpha 2023-04-05 * fix(windows): use right instead of left alignment for popup buttons (#8561) ## 17.0.82 alpha 2023-03-31 * feat(developer): support jis and abnt2 (#8513) * revert: #8549 "chore(web): merge master into feature-esmodule-web-engine (A17S9 end) " (#8553) ## 17.0.81 alpha 2023-03-30 * feat(windows): simple text editor using Edit Control (#8391) ## 17.0.80 alpha 2023-03-29 * chore(linux): Remove dependency on `sudo` (#8535) * chore(linux): Improve robustness of test cleanup (#8536) * fix(linux): Remove warning after pressing Close button (#8538) ## 17.0.79 alpha 2023-03-28 * chore(linux): Revert "Run and ignore autopkgtests on s390x" (#8506) * docs(linux): Update minimum required Ubuntu version (#8526) * docs(linux): Update common questions (#8532) ## 17.0.78 alpha 2023-03-27 * chore(linux): Remove python3-raven dependency (#8507) * refactor(android/engine): Make KMKeyboardJSHandler a normal class (#8494) ## 17.0.77 alpha 2023-03-25 * chore(common): use mac /usr/bin/stat rather than homebrew version (#8498) ## 17.0.76 alpha 2023-03-24 * chore(linux): Run and ignore autopkgtests on s390x (#8492) * refactor(android/engine): Consolidate dispatchKey (#8483) ## 17.0.75 alpha 2023-03-23 * chore(common): define BUILDER_CONFIGURATION env var (#8496) ## 17.0.74 alpha 2023-03-22 * chore(windows): update sentry-native to 0.6.0 (#8464) * chore(linux): Prevent building on s390x (#8477) * fix(linux): Display error message for corrupt .kmp file (#8479) ## 17.0.73 alpha 2023-03-21 * refactor(android/engine): Consolidate insertText (#8438) * chore(common): prevent multiple npm ci runs in child scripts (#8484) ## 17.0.72 alpha 2023-03-20 * chore(common): die early when --ci and --debug passed to test.sh (#8465) * chore(common): Update crowdin strings for Kibaku (#8447) ## 17.0.71 alpha 2023-03-18 * fix(core): ldml update fr-azerty for VKEY mapping (#8434) ## 17.0.70 alpha 2023-03-17 * chore(android): Document builder script steps (#8449) ## 17.0.69 alpha 2023-03-16 * chore(web): Cleanup build echo (#8446) * fix(developer): lm compiler handle missing line no in errors (#8444) * fix(android/app): Temporarily disable Keyman browser (#8430) * fix(android/engine): Add builder output for configure (#8442) * chore(linux): Update debian changelog (#8452) ## 17.0.68 alpha 2023-03-15 * chore(common): add common test build configurations (#8431) * fix(common): fix broken common/web/types cases (#8426) * fix(developer/compilers): locks esbuild target detection for kmc building (#8437) * chore(developer): ldml March 2023 update to tech-preview (#8412) * fix(core): ldml more TODO-LDML fixes (#8436) * chore(linux): Use dependency on core in ibus-keyman/build.sh (#8423) ## 17.0.67 alpha 2023-03-14 * chore(developer): Update copyright period in License.rtf (#8425) * chore(common): support shorthand for build.sh (#8415) * chore(common): build script performance improvements (#8416) * chore(common): TS updates to non-sync'd packages, feature-esmodule merge conflict prevention (#8429) ## 17.0.66 alpha 2023-03-13 * refactor(android): Use builder scripts (#7407) ## 17.0.65 alpha 2023-03-12 * refactor(core): consolidate wasm defs (#8409) ## 17.0.64 alpha 2023-03-10 * feat(common): support single target for a dependency (#8404) * chore(core): breadth-first build (#8400) * refactor(common): Make build-help into helper functions (#8386) ## 17.0.63 alpha 2023-03-09 * fix(web): --no-minify, not --skip-minify (#8394) * chore(core): Remove obsolete `--target-path` option (#8376) ## 17.0.62 alpha 2023-03-08 * chore(linux): Remove debug output from packaging GHA (#8372) * chore: merge feature-ldml to master, again (#8377) * chore(common): cleanup build.inc.sh echo (#8344) * chore(common): remove vswhere (#8357) * feat(linux): Add DBus method `SendText` (#8039) * chore(core): Create both dynamic and static libs on Linux (#8375) * chore(common): clean up `--debug` usage in build scripts (#8382) * feat(common): builder.inc.sh inheritable options (#8384) ## 17.0.61 alpha 2023-03-03 * fix(android/app): Another attempt at fixing OSK rotation (#8353) ## 17.0.60 alpha 2023-03-02 * fix(android/engine): Fix various OSK bugs due to refactor (#8349) * feat(core): Build both architectures for mac and generate a 'fat' library for them (#8342) * fix(common): fixup npm publish (#8350) * chore(linux): More GHA debugging (#8354) ## 17.0.59 alpha 2023-03-01 * fix(common): builder: skip dependency build for clean action (#8341) * chore(web): fixup dependencies in web build script (#8332) * chore(linux): More debug output (#8345) ## 17.0.58 alpha 2023-02-28 * chore(common): fix child build error handling (#8327) * chore(linux): Improve and fix packaging GHA (#8328) * fix(linux): Fix ibus-keyman/build.sh (#8329) * epic: LDML keyboard support (#7054) * fix(linux): Fix debian postinst script (#8294) ## 17.0.57 alpha 2023-02-26 * chore(android/app): Revert #8291 (#8314) ## 17.0.56 alpha 2023-02-24 * fix(linux): Fix upload in packaging GHA (#8308) * feat(common): adds warning if described output does not exist (#8304) * chore(linux): Improve detecting presence of test files (#8313) ## 17.0.55 alpha 2023-02-23 * chore(docs): update docs due to Mac Ventura (#8277) * chore: remove greadlink from standard script prolog (#8288) * chore: use builtin instead of dirname for perf (#8289) * chore(common): stats script for planning (#7861) ## 17.0.54 alpha 2023-02-22 * fix(ios): allow duplicate languages in kmp file (#8125) * fix(linux): Fix paths in upload action of packaging GHA (#8285) * fix(android/app): Fix OSK width when rotating (#8291) ## 17.0.53 alpha 2023-02-21 * chore(windows): Remove old Kannada setup strings (#8257) * fix(linux): Collect consecutive backspaces (#8274) * chore(linux): Improve deb-packaging GHA (#8281) * chore(linux): Cleanup GHA (#8282) ## 17.0.52 alpha 2023-02-20 * fix(windows): use min-width allow to expand (#8215) * chore(web): minor cleanup of web/build.sh (#8254) * fix(web): `--no-minify`, not `--skip-minify` (#8264) * chore(web): Actually skip browser-stack for non-web builds (#8266) * chore: cleanup some of shellHelperFunctions.sh (#8260) * chore: consolidate script helper functions (#8261) * chore(linux): Output results of API verification on stderr (#8241) * chore(linux): Create draft PR after updating changelog (#8242) * fix(linux): Checkout before running apt-install (#8247) * fix(linux): Fix bug in deb-packaging script (#8273) * chore(developer): update bundled node to 18.14.1 LTS (#8268) * chore(developer): ignore Esc key when compiling (#8263) * docs: builder.inc.sh improved documentation around dependencies (#8173) * chore(linux): Add build.sh to ibus-keyman ️ (#8112) ## 17.0.51 alpha 2023-02-18 * chore(common): Update Fula strings for Sprint A17S6 (#8245) ## 17.0.50 alpha 2023-02-16 * feat(common): parent-child scripts for builder (#8198) * fix(linux): Another iteration to fix packaging GHA (#8230) * chore(common): updates Web & Web-related dependencies (#8196) * fix(linux): Fix syntax for skipping upload in packaging GHA (#8236) ## 17.0.49 alpha 2023-02-15 * feat(linux): Pass PR# in the event type (#8221) * feat(linux): Implement uploading of packages in packaging GHA (#8223) * fix(linux): Fix GHA package build (#8225) * fix(linux): Another fix for GHA package build (#8228) ## 17.0.48 alpha 2023-02-14 * fix(developer): Select BCP47 Code dialog inconsistencies (#8179) * chore(common): automatically apply _builder_check_color (#8197) * docs(linux): Update packaging documentation (#8202) * chore(common): Report status if no platform needs build (#8210) * chore(linux): Exclude autopkg tests on s390x (#8218) * fix(linux): Fix path to symbols file in packaging GHA (#8209) ## 17.0.47 alpha 2023-02-10 * fix(linux): Fix autopkgtests (#8201) * fix(linux): Fix Verify-API step of GHA (#8199) ## 17.0.46 alpha 2023-02-09 * fix(windows): add remove lang id uses correct keyboard id (#8186) * chore(common): add `builder_term` function (#8187) * chore(common): builder internal dependencies (#8188) * chore(linux): Update changelog from Debian (#8192) * feat(linux): Add debian packaging GHA (#7911) ## 17.0.45 alpha 2023-02-08 * chore(ios): update certificate (#8176) * fix(linux): Fix autopkgtests (#8181) * chore(common): Cleanup Kannada locale (#8182) * chore(windows): Fix Portuguese UI language name (#8184) ## 17.0.44 alpha 2023-02-07 * chore(linux): Set test-helper script executable (#8178) * chore(linux): Update debian changelog (#8156) ## 17.0.43 alpha 2023-02-06 * chore(linux): Build with meson instead of autotools ️ (#8111) ## 17.0.42 alpha 2023-02-03 * chore(deps): bump http-cache-semantics from 4.1.0 to 4.1.1 (#8144) * feat(developer): check for duplicated language codes in package editor and compiler (#8151) * chore: Fail TC build if triggering Jenkins build fails (#8152) * chore(linux): Fix lintian warnings (#8154) * chore(core): Update meson version (#7882) * refactor(android/engine): Consolidate Keyboard picker intent (#8163) ## 17.0.41 alpha 2023-02-02 * chore(web): main web build & test script rework to our common script format + nomenclature (#7474) * change(web): conversion to standard filesystem layout: source -> src, intermediate + release -> build (#7513) * change(web): conversion to standard filesystem layout: testing -> src/test/manual, unit_tests -> src/test/auto (#7515) * change(web): conversion to standard filesystem layout: tools -> src/tools (#7556) * chore(web): updates build product references, extracts CI test-build scripts (#7831) * feat(common): TS-based sourcemap remapping tool (#7894) * feat(web): implements shell scripting for CI release-build configurations (#8001) ## 17.0.40 alpha 2023-02-01 * chore(developer): kmcmpdll debug src path (#8127) * chore(common): Merge end of beta from Sprint A17S5 (#8135) * refactor(android): Change com.tavultesoft.kmea package to com.keyman.engine (#7981) * refactor(android/engine): Split KMInAppKeyboardWebViewClient to new class (#7983) * refactor(android/engine): Refactor KMSystemKeyboardWebViewClient (#7993) ## 17.0.39 alpha 2023-01-31 * feat(windows): add additional registry keys to report (#8126) ## 17.0.38 alpha 2023-01-30 * chore(deps): bump ua-parser-js from 0.7.31 to 0.7.33 (#8109) * fix(linux): Fix CI build (#8121) ## 17.0.37 alpha 2023-01-27 * chore(linux): Fix warnings (#8103) * chore(linux): Remove legacy projects (#8102) * Specify the path to the Debian package in the Vcs-Git header (#8104) ## 17.0.36 alpha 2023-01-26 * chore(common): Add crowdin strings for Kannada (#8074) ## 17.0.35 alpha 2023-01-25 * chore(common): revise tag variable name to VERSION_GIT_TAG (#8063) * chore(common): Add crowdin strings for Czech (#8070) * feat(linux): Improve uninstallation (#8011) ## 17.0.34 alpha 2023-01-24 * chore: merge beta to alpha, end of A17S4 (#8065) ## 17.0.33 alpha 2023-01-23 * chore: Xcode 14.2 update (#8015) ## 17.0.32 alpha 2023-01-20 * fix(ios): use mobile mode for keyboard download pages (#8042) * docs(common/resources): Update configure step in Docker readme (#8034) * fix(linux): JSON File missing after installation (#8040) ## 17.0.31 alpha 2023-01-19 * chore: git tag with release@semver (#8035) * fix(linux): Properly set context after changing IP (#8026) * chore(linux): use faster zero-length string check (#8037) * chore(linux): log failures to `km_kbp_context_clear(context)` (#8036) * chore(linux): Update recommended extension (#8038) ## 17.0.30 alpha 2023-01-17 * chore(linux): Fix vertical alignment of label (#8016) * fix(common): update sentry release identifiers to support semver (#8031) ## 17.0.29 alpha 2023-01-16 * fix(linux): Fix crash (un-)installing shared keyboard (#8020) * chore(linux): Don't report KeyboardInterrupt to Sentry (#8021) * chore(linux): Update sample settings (#8018) * feat(linux): Enhance tab completion in km-package-install (#8005) ## 17.0.28 alpha 2023-01-12 * feat(linux): Display error messages in the UI (#8006) * bug(linux): Empty keyboard after failed installation (#8008) ## 17.0.27 alpha 2023-01-11 * chore(linux): Refactor completion script (#8002) ## 17.0.26 alpha 2023-01-10 * feat(linux): Add Back button to "Download Keyman Keyboards" dialog (#7994) * feat(linux): List fonts in the uninstall confirmation dialog (#7995) ## 17.0.25 alpha 2023-01-09 * chore(linux): Remove unnecessary variable (#7988) ## 17.0.24 alpha 2023-01-06 * chore(common/resources): Add Docker readme (#7980) ## 17.0.23 alpha 2023-01-03 * fix(linux): add IBUS_HAS_PREFILTER ifdef to linux/ibus-keyman/tests (#7958) * docs(linux): document fullbuild using docker (#7960) ## 17.0.22 alpha 2023-01-02 * chore: merge beta to master (A17S2) (#7948) * chore(linux): Remove unused JENKINS parameter (#7920) ## 17.0.21 alpha 2022-12-21 * fix(windows): shutdown fix masked modal result (#7933) ## 17.0.20 alpha 2022-12-19 * chore(android/samples): Remove Sentry dependencies (#7901) * chore: Revert "chore(common): Fix shellcheck warnings" (#7925) ## 17.0.19 alpha 2022-12-17 * fix(linux): Fix dependency of ibus-keyman (#7918) ## 17.0.18 alpha 2022-12-16 * chore(common): Fix shellcheck warnings (#7910) ## 17.0.17 alpha 2022-12-15 * chore: merge beta to master (#7885) * chore(android): Update Gradle dependencies; targetSDKVersion to 33 (#7897) ## 17.0.16 alpha 2022-12-11 * refactor(linux): Update ibusimcontext.c (#7813) ## 17.0.15 alpha 2022-12-08 * chore(linux): Update vscode settings for Linux (#7876) ## 17.0.14 alpha 2022-12-07 * docs(linux): Move Linux documentation (#7868) * chore(linux): Remove building for Bionic (#7873) * chore(linux): Remove some shellcheck warnings (#7874) ## 17.0.13 alpha 2022-11-29 * fix(windows): lower case filenames for projects (#7837) * refactor(linux): Refactor setting keyboard options (#7804) ## 17.0.12 alpha 2022-11-25 * chore(common): Merge beta from Sprint B16S2 to master (#7815) ## 17.0.11 alpha 2022-11-24 * refactor(linux): Use consts instead of strings (#7803) ## 17.0.10 alpha 2022-11-21 * fix: automatically merge changes to history back to master (#7777) * chore: cleanup history (#7776) ## 17.0.9 alpha 2022-11-18 * chore: github issue template config.yml (#7751) * chore(windows): tweak sentry client for cross-module messages (#7752) * chore(android): Update Target SDK Version to 31 (#7761) ## 17.0.8 alpha 2022-11-17 * fix(android): bump version_code major calculation (#7736) ## 17.0.7 alpha 2022-11-13 * chore: fix TIER.md for master (#7704) ## 17.0.6 alpha 2022-11-12 * chore: merge beta to master B16S1 (#7693) * chore(deps): bump minimatch from 3.0.4 to 3.1.2 (#7675) ## 17.0.5 alpha 2022-11-11 * chore(linux): Update debian changelog (#7681) ## 17.0.4 alpha 2022-11-10 * chore(deps): bump socket.io-parser from 4.0.4 to 4.0.5 (#7672) ## 17.0.3 alpha 2022-11-09 * fix(windows): Cleanup CEF more correctly in shutdown (#7661) ## 17.0.2 alpha 2022-11-01 * fix(android): Handle empty Play Store release notes (#7581) ## 17.0.1 alpha 2022-10-31 * fix(ios): iPad was not recognised as tablet device (#7563) * feat(windows): configuration UI polish (#7206) * chore: move to 17.0-alpha (#7577) * chore: Move to 17.0 alpha ## 16.0.145 stable 2024-02-01 * chore(linux): Add support for loong64 architecture (#10108) * chore(linux): Update debian changelog (#10122) * fix(web): Fix null error with legacy keyboards (#10177) * chore(ios): FV certificate key (#10229) * fix(oem/fv): Add fv_hulquminum_combine and fv_kwadacha_tsekene (#10285) * chore(developer): upgrade ngrok to v3 (#10360) * chore(linux): Build with webkitgtk 4.1 instead of 4.0 (#10574) ## 16.0.144 stable 2023-11-30 * chore(linux): Update debian changelog (#10046) * fix(android/app) Disable in-app Browser (#10077) ## 16.0.143 stable 2023-11-22 * chore(android): Update targetSdkVersion from 31 to 33 (#9823) * chore(linux): Exclude environment.sh from build (#9814) * chore(mac): move from altool to notarytool (#9896) * fix(web): fixes doc-kbd display of default layer when it's not defined first (#9892) * fix(ios): fv: replace Zip framework to prevent crash on startup (#9958) ## 16.0.142 stable 2023-10-20 * chore(linux): Update debian changelog (#9326) * chore(linux): Remove obsolete dist from uploading to launchpad (#9340) * chore(linux): Stop building Kinetic on Jenkins (#9354) * chore(linux): Work around build failure on Debian mips64el (#9342) * chore(linux): Update debian changelog (#9359) * chore(android): Update targetSDKVersion to 33 (#9494) * chore(linux): Remove workaround for mips64el (#9519) * chore(linux): Workaround: Don't run Wayland tests (#9530) * chore(linux): Add `clean` target to `rules` (#9532) * fix(linux): Prevent exception if neither USER, LOGNAME nor SUDO_USER set (#9544) * chore(linux): Ignore tests that fail on ba-jammy-64-ta (#9556) * chore(ios): renew certificate (#9811) * fix(mac): move keyboard menu items to main Input Menu from submenu (#9810) ## 16.0.141 stable 2023-07-25 * chore(mac): fix corrupt installer (#9332) ## 16.0.140 stable 2023-07-21 * chore(linux): Update debian changelog (#8451) * chore(linux): Prevent building on s390x (#8476) * fix(linux): Display error message for corrupt .kmp file (#8480) * chore(linux): Run and ignore autopkgtests on s390x (#8491) * chore(linux): Revert "Run and ignore autopkgtests on s390x" (#8505) * chore(ios): Xcode 14 upgrade (#8487) * fix(developer): package editor no longer loses RTL flag for LMs (#8607) * chore(common): use mac /usr/bin/stat rather than homebrew version (#8925) * chore(ios): replace fv cert (#8923) * fix(core): Fix compilation if hotdoc is installed :cherries: (#8929) * chore(linux): Move some files to keyman-config :cherries: (#8930) * fix(core): Fix compiling with GCC 13 (#8932) ## 16.0.139 stable 2023-03-16 * chore: Fail TC build if triggering Jenkins build fails (#8141) * chore(linux): Fix lintian warnings (#8153) * chore(linux): Update debian changelog (#8155) * chore(ios): update certificate (#8177) * cherrypick(windows): Fix Portuguese UI language name (#8190) * fix(linux): Fix autopkgtests (#8180) * chore(linux): Update changelog from Debian (#8191) * cherrypick(common): Cleanup Kannada locale (#8189) * fix(windows): add remove lang id uses correct kbd (#8195) * fix(linux): Fix autopkgtests (#8200) * chore(linux): Exclude autopkg tests on s390x (#8217) * chore(common): Update Fula strings for Sprint A17S6 (#8246) * chore(windows): Remove old Kannada setup strings (#8258) * fix(linux): Fix debian postinst script (#8295) * fix(developer): lm compiler handle missing line no in errors (#8445) ## 16.0.138 stable 2023-02-01 * chore: add new developer build trigger (#8139) ## 16.0.137 stable 2023-02-01 * chore(common): Release 16.0 ## 16.0.136 beta 2023-01-31 * chore(common): Update crowdin strings for Shuwa (Latin) (#8097) * chore(common): Check in crowdin for Russian (#8072) * chore(common): Check in crowdin for Ukrainian (#8073) * chore(common): Add crowdin for Swedish (#8071) * chore(common): Add crowdin strings for Czech (#8095) ## 16.0.135 beta 2023-01-30 * chore(linux): Include packaging path in Vcs-Git header (#8110) ## 16.0.134 beta 2023-01-25 * chore(common): Add crowdin strings for Kannada (#7970) ## 16.0.133 beta 2023-01-19 * fix(linux): Properly set context after changing IP (#8025) ## 16.0.132 beta 2023-01-18 * docs(windows): update screenshots and documentation for Keyman for Windows config (#8014) ## 16.0.131 beta 2023-01-16 * chore(linux): Don't report KeyboardInterrupt to Sentry (#8022) * fix(linux): Fix crash (un-)installing shared keyboard (#8019) ## 16.0.130 beta 2023-01-09 * fix(windows): kmshell -ikl install language and enable keyboard (#7856) ## 16.0.129 beta 2023-01-06 * fix(android/engine): Add utility for localized strings (#7976) ## 16.0.128 beta 2022-12-22 * fix(developer): force ES3 code generation for LMs (#7927) ## 16.0.127 beta 2022-12-21 * fix(oem/fv/android): Fix keyboard version title (again) (#7941) * fix(oem/fv/android): Add view permission of online help (#7909) * fix(windows): modifer event is always serialized (#7935) ## 16.0.126 beta 2022-12-21 * fix(windows): shutdown fix masked modal result (#7932) ## 16.0.125 beta 2022-12-19 * fix(windows): no languages warning source changed (#7900) ## 16.0.124 beta 2022-12-18 * fix(oem/fv/android): Cleanup version title (#7908) ## 16.0.123 beta 2022-12-17 * fix(linux): Fix dependency of ibus-keyman (#7917) ## 16.0.122 beta 2022-12-14 * fix(windows): modify disable keyboard display (#7898) * fix(developer): invalid charmap cell selection when updating to empty search result (#7887) ## 16.0.121 beta 2022-12-11 * chore(linux): Fix `make install` (#7886) ## 16.0.120 beta 2022-12-07 * chore(linux): Improve package build (#7875) ## 16.0.119 beta 2022-12-05 * chore: Change platform advocates (#7867) ## 16.0.118 beta 2022-12-04 * chore(linux): Update debian changelog (#7860) ## 16.0.117 beta 2022-12-01 * fix(developer): OnlineUpdate crash on shutdown (#7830) * fix(developer): EncodeURL was not handling spaces (#7820) ## 16.0.116 beta 2022-11-30 * fix(android/app): Toggle keyboard update notifications for landscape and tablets (#7832) * fix(android/engine): Append languageID for keyboard updates (#7807) * fix(android/engine): Use FLAG_IMMUTABLE for PendingIntent for Android S+ (#7844) ## 16.0.115 beta 2022-11-29 * fix(windows): Cleanup CEF more correctly in shutdown (#7825) * fix(windows): lower case filenames for projects (#7836) * chore(linux): Update debian changelog (#7835) * chore(linux): Fix upload-to-debian script (#7833) ## 16.0.114 beta 2022-11-28 * fix(mac): Caps processing was not consistent with core (#7795) * fix(web): locks page scroll when scrolling lang menu (#7790) ## 16.0.113 beta 2022-11-26 * docs(android/app): Add note of haptic feedback to whatsnew (#7817) * fix(developer): remove missing files from MRU list (#7821) ## 16.0.112 beta 2022-11-25 * fix: test builds should always run latest changes (#7806) * fix(web): unit test breakages (#7797) ## 16.0.111 beta 2022-11-24 * fix(android/engine): Make it easier to test keyboard updates (#7781) ## 16.0.110 beta 2022-11-23 * fix(linux): Revert "fix(linux): Fix a warning" (#7783) * fix: automatically merge changes to history back to master (#7780) * chore(common): Update whatsnew for 16.0 (#7789) * fix(web): inferred key text + spacebar caption scaling (#7741) * feat(web): re-implementation of introductory globe-key help bubble (#7612) * fix(android/engine): Fix logic error for updateKMP (#7799) * fix(linux): Allow to build without patched ibus version (#7792) * chore(linux): Update autotools configuration (#7793) * docs(ios): Update help documentation about Install and Allow Full Access (#7791) * fix(android/engine): Update versions of matching package and keyboard ID (#7740) ## 16.0.109 beta 2022-11-22 * fix(windows): arrow keys need to select next/prev item in options tab (#7756) * fix(windows): buttons should be in list in Options tab (#7757) * fix(android/engine): Add null check on kmp filename (#7787) * fix(ios): make text size of in-app editor consistent with slider (#7782) * fix(android/engine): Check if kmp.json is null (#7788) * fix(mac): Enable right-alt/option key mapping (#7762) * feat(linux): Add symbols file (#7742) ## 16.0.108 beta 2022-11-21 * fix(windows): backout ms button style for add lang pop up (#7765) * fix(android/app): Only check Install Referrer API with Play Store installs (#7766) * fix(windows): Fix text selectable configuration (#7758) * feat(common/models): directional quote insensitivity (#7767) * chore(windows): remove unused options from locales and UI (#7760) * fix(developer): cast to prevent ERangeError for failed http reqs in CEF (#7775) * chore(android): Update Target SDK Version to 31 (#7768) ## 16.0.107 beta 2022-11-18 * fix(windows): Download Keyboard blue footer (#7755) * fix(windows): tweak elevate icon in Config dialog (#7754) * fix(web): documentation keyboard style application + layout (#7694) * fix(windows): fix checkbox and hint help button styles (#7764) * chore(common): Update crowin strings for Fulfulde (#7715) * fix(linux): Fix installation if shared kbd already installed (#7730) * fix(linux): Fix a warning (#7746) * chore(common): Update crowdin strings for Simplified Chinese (#7713) ## 16.0.106 beta 2022-11-17 * chore(windows): set platform core env explicitly (#7689) * fix(android): bump version_code major calculation (#7735) * fix(android/engine): Remove duplicate file suffix when installing .kmp (#7720) * fix(linux): Ignore dbus exception when testing for fcitx (#7732) * fix(linux): Fix lintian warnings (#7733) * feat(linux): Add optional bcp47 parameter to km-package-install (#7731) ## 16.0.105 beta 2022-11-16 * chore(windows): add unit test for SetupCoreEnvironment (#7714) * docs(linux): Add example for keyman:// URL format (#7726) * fix(linux): set DEB_VERSION (#7727) * fix(linux): Don't crash if `und` is specified without `fonipa` (#7728) ## 16.0.104 beta 2022-11-15 * chore(android/engine): Add more logging for keyboard restart (#7719) ## 16.0.103 beta 2022-11-14 * fix(windows): click in 1 pixel high box in Language Switch window caused crash (#7699) * chore(windows): add sentry traces for unsolved crashes (#7703) * fix(windows): handle timeout in downloads (#7709) * chore(windows): Add safecall for internal CustomisationStorage API interface (#7707) * chore(windows): include debug info in keyman build (#7710) * fix(windows): check if permissions for thread to access file (#7207) * refactor(linux): Use consts instead of strings (#7686) ## 16.0.102 beta 2022-11-12 * fix(windows): make sure IdStackWindows finalizes after Vcl.Forms (#7692) * fix(android/app): Append tier to app name (#7674) * chore(android/app): Remove debugging info on build.gradle (#7700) ## 16.0.101 beta 2022-11-11 * fix(windows): Improve shutdown robustness (#7677) * fix(windows): base layout support in Keyman Core (#7667) * fix(developer): URL parameters should be UTF-8 (#7631) * fix(android/engine): Use IME package name if query permission denied (#7668) * fix(linux): Fix keyboard icon in system tray (#7678) * chore(linux): Update debian changelog :cherries: (#7682) * chore(linux): Update Debian standards version (#7683) ## 16.0.100 beta 2022-11-10 * chore(linux): Update whatsnew (#7660) * chore: Update history-and-versioning to match history (#7669) * chore(linux): Update debian changelog (#7492) * chore(android/engine): Don't show Toast errors on stable tier (#7676) * fix(web): Add additional checks on className.indexOf (#7662) ## 16.0.99 beta 2022-11-09 * fix(web): Add polyfill for Array.includes() (#7646) * fix(web): Add polyfill for Array.findIndex() (#7652) * fix(developer): handle edge cases for app sources (#7654) * fix(developer): handle shutdown cleanup more cleanly (#7655) * fix(developer): handle crash reports without Keyman Engine installed (#7657) * fix(developer): handle unpaired surrogate (#7659) * fix(core): `save()` should be on internal kmx action queue (#7644) * fix(core): emit keystroke was writing to wrong queue (#7650) ## 16.0.98 beta 2022-11-08 * fix(android/engine): Check temporary kmp file is valid (#7620) * fix(developer): set keyman.osk immediately after switching device type (#7624) * fix(developer): update monaco editor to 0.15.6 (#7626) * chore(developer): tidy up compile hints (#7633) * fix(developer): handle EEncodingError loading text file (#7635) * fix(developer): prevent exception in charmap when unable to focus (#7640) * fix(developer): disable Keyboard|Compile if no project loaded (#7642) * fix(web): Handle undefined keyId in multi-tap (#7648) * fix(developer): kmlmc has runtime dependency on keyman-version (#7651) * fix(web): avoid reset for touch system keyboard (#7638) * fix(developer): improve support for inferred key cap text (#7617) ## 16.0.97 beta 2022-11-04 * fix(android/app): Don't show "Get Started" after setting Keyman as default system keyboard (#7587) * fix(windows): include debug info in kmshell build (#7600) * fix(developer): tweak captions for consistency (#7607) * fix(mac): replace white background keyman system menu icon with transparent one (#7610) ## 16.0.96 beta 2022-11-03 * fix(developer): Make Details and Build tabs scrollable (#7593) * fix(developer): support gif preview images in Package Editor (#7594) * fix(developer): handle high-bit-set HKL correctly (#7601) * fix(android/app): Add check if bundle to PackageActivity is null (#7603) * fix(common): always define dry_run variable (#7604) * feat(web): Custom layer targets for Shift double-tap (#7608) * fix(android/engine): Handle parsing empty JSONArray as JSONObject (#7611) ## 16.0.95 beta 2022-11-02 * fix(developer): Use US base layout for debugger (#7531) * fix(developer): ensure kmlmp handles paths (#7580) * fix(developer): prevent repeated `begin` statements (#7583) * fix(developer): remove ancient samples (#7586) * fix(developer): generate a default icon for basic keyboard projects (#7584) * fix(developer): avoid reformatting unchanged system stores (#7585) * fix(developer): publish `@keymanapp/keyman-version` to npm (#7595) ## 16.0.94 beta 2022-10-31 * fix(ios): iPad was not recognised as tablet device (#7563) * feat(windows): configuration UI polish (#7206) ## 16.0.93 beta 2022-11-01 * chore: move to 16.0 beta ## 16.0.92 alpha 2022-10-31 * fix(android/engine): Add FLAG_ACTIVITY_NEW_TASK flag for resource update (#7572) * change(common/models): prevent integration test flakiness due to prediction-search timeouts (#7571) * chore: make git pre-commit hook executable (#7573) * fix(web): bulk renderer update (#7516) ## 16.0.91 alpha 2022-10-28 * fix(developer): handle LControl being set by Windows when AltGr pressed (#7530) * chore(windows): convert `wm_keyman_keyevent` and `wm_keyman_modifierevent` to private `WM_USER` messages (#7546) * chore(common): Update help references from 15.0 to 16.0 (#7558) * fix(core): remove `KMN_API` from callback spec (#7520) * fix(developer): exclude `nocaps` from layer id modifier components (#7553) * fix(web): model language ids now case-insensitive (#7557) * fix(android/engine): Dismiss subkeys when hiding keyboard (#7555) ## 16.0.90 alpha 2022-10-27 * chore(common): update configure-repo.sh to include pre-commit hook (#7545) * chore(common): Add crowdin strings for Dutch (#7498) ## 16.0.89 alpha 2022-10-26 * fix(core): Add missing include files (#7504) * fix(linux): Improve setting context (#7084) * feat(windows): Change "None" to "No Hotkey" matching new config (#7539) * feat(web): keyboard layout spec now allows numeric width, pad, sp (#7486) * chore(common): update actions to node16 (#7525) * chore(web): KMW dev-tools reorganization, cleanup, script updates (#7463) * fix(web): allow `isChiral()` to accept string name parameter of keyboard (#7544) * fix(web): ensures keyboard does not change underneath OSK keystroke (#7543) ## 16.0.88 alpha 2022-10-25 * fix(common): ignore deps when formatting help (#7514) * refactor(linux): Comment unused methods (#7501) * chore(linux): Rename internal method to `commit_string` (#7502) * chore(linux): call `reset_context` instead of `...focus_in` (#7503) * chore(common): Update crowdin strings for Amharic (#7522) * chore(android): Update help whatsnew for 16.0 (#7507) * chore(common): Update existing crowdin strings for 16.0 (#7524) ## 16.0.87 alpha 2022-10-24 * fix(web): touch-platform language menu initial scrolling + index scrolling (#7488) ## 16.0.86 alpha 2022-10-21 * fix(developer): Handle invalid graphics in icon editor (#7431) * chore(common): move to new GitHub issue form templates (#7470) * change(web): removes unused config, help buttons from OSK (#7484) * fix(windows): ensure all modifier events go to serialized queue (#7449) * chore(common): automatically run internal dependencies on builder (#7464) * fix(mac): Prompt for required permissions at start time (#7354) ## 16.0.85 alpha 2022-10-20 * chore(android/engine): Remove help bubble tool tip (#7473) * fix(linux): Fix upload script (#7494) * docs(linux): Update sample vscode settings (#7491) * fix(android/engine): Dismiss key preview and subkeys on globe action (#7472) * refactor(linux): Cleanup whitespace (#7500) * chore(linux): Improve debug output (#7499) ## 16.0.84 alpha 2022-10-19 * fix(developer): Handle hints and warnings cleanly (#7372) * fix(developer): Ctrl key to select key was conflicting with shortcuts (#7430) * modify(android/engine): Stop logging if keyboard index not found (#7415) * chore(android/engine): Update Keyman references in android-host.js (#7466) ## 16.0.83 alpha 2022-10-18 * docs(linux): Update readmes (#7468) ## 16.0.82 alpha 2022-10-17 * change(web): now utilizes 'inputMode="none"' on supported touch devices (#7343) * chore(web): drops alignInputs, hideInputs (#7360) * fix(web): better element inputmode management (#7395) * chore(common): `--debug` standard flag for builder (#7462) * fix(ios): Allow Full Access enabled to fix ios 16 invisible keyboard (#7459) ## 16.0.81 alpha 2022-10-16 * fix(developer): manual attachment for kmw in server (#7457) ## 16.0.80 alpha 2022-10-14 * feat(common): builder script dependency and legacy script report (#7453) * chore(linux): Adjust Linux specific files in `.gitignore` (#7451) ## 16.0.79 alpha 2022-10-13 * chore(common/models, web): more script updates (#7392) * feat(common): builder dependency support (#7438) * chore(common): further tweaks to builder scripts (#7439) ## 16.0.78 alpha 2022-10-12 * fix(linux): Fix reordering of output (#7079) * fix(linux): Fix make install (#7434) * chore(linux): Add Node.js to the docker container (#7435) ## 16.0.77 alpha 2022-10-10 * fix(web): possible error on change of context to a contextEditable (#7359) * chore(web): unit test polishing pass (#7381) ## 16.0.76 alpha 2022-10-06 * chore(linux): Cleanup unnecessary surrogate check (#7396) ## 16.0.75 alpha 2022-10-05 * chore(common): builder script maintenance (#7405) ## 16.0.74 alpha 2022-10-04 * chore(android/engine): Display Toast notifications on Sentry errors (#7390) * fix(android/engine): Dismiss subkeys on multi-touch (#7388) ## 16.0.73 alpha 2022-10-03 * fix(developer): handle invalid kps xml when loading project view (#7371) ## 16.0.72 alpha 2022-09-30 * fix(web): Only unhighlight suggestion if there's a pending one (#7383) * refactor(common): Split builder utilities to separate script (#7365) ## 16.0.71 alpha 2022-09-29 * fix(developer): generate valid js when using unquoted digits in stores (#7369) * fix(developer): ensure backslash in paths passed to kmcomp (#7370) * fix(web): Update spacebar caption when refreshing layout (#7348) * fix(common/web): mock deadkey handling after rules manipulating context (#7345) ## 16.0.70 alpha 2022-09-26 * fix(android): Add language name when installing default lexical-model (#7347) * chore(common): Add 15.0 stable entries to HISTORY.md :cherries: (#7350) ## 16.0.69 alpha 2022-09-21 * fix(android/engine): Check listview for setting keyboard selection (#7325) * refactor(common/web): reworks low-level module build scripts ️ (#7319) * refactor(common): `builder` script tweaks - "has action" vs "start action" ️ (#7333) * feat(common): builder trap-functionality testing ️ (#7334) * chore(common): builder extra params support (#7339) ## 16.0.68 alpha 2022-09-20 * chore(web): update `got` dependency for regression tests (#7315) * chore(developer): update multer dependency for server (#7314) * chore(developer): update node-windows-trayicon to update node-gyp to 9.1.0 (#7321) ## 16.0.67 alpha 2022-09-19 * fix(common/models): blocks full-text "corrections" ️ (#7241) * change(web): better fat-finger key weighting ️ (#7242) * fix(web): fixes unintended auto-acceptance of suggestion after reverting (#7305) * feat(common/models): wordbreaker customization (#7279) * fix(common/models): fixes reference dropped by git merge (#7313) * test(android): Add final keyboard to test K_ENTER rule (#7303) * chore(common): Update to Unicode 15.0 (#7302) * chore(common): update auto labeler configuration (#7316) * chore(common): make scripts executable and add pre-commit test (#7317) * chore(deps): bump nanoid and mocha (#7307) * chore(common): remove unused ncc dependency (#7318) ## 16.0.66 alpha 2022-09-17 * chore: improve auto labeling (#7288) ## 16.0.65 alpha 2022-09-16 * chore(linux): Remove unused IBusLookupTable (#7296) ## 16.0.64 alpha 2022-09-15 * fix(android/engine): Switch keyboard if uninstalling current one (#7291) * fix(common/models): fixes quote-adjacent pred-text suggestions (#7205) * fix(common/models): max prediction wait check (#7290) ## 16.0.63 alpha 2022-09-14 * chore(linux): Update debian changelog (#7281) * fix(linux): Fix ignored error (#7284) ## 16.0.62 alpha 2022-09-13 * fix(developer): hide key-sizes when in desktop layout in touch layout editor (#7225) * fix(developer): show more useful error if out of space during Setup (#7267) ## 16.0.61 alpha 2022-09-12 * docs(windows): add steps for using testhost debugging (#7263) * fix(developer): compiler mismatch on currentLine (#7190) * fix(developer): suppress repeated warnings about unreachable code (#7219) * chore: try disabling concurrency for browserstack tests (#7258) * chore(web): disable browserstack on non-web-specific builds (#7260) ## 16.0.60 alpha 2022-09-10 * fix(web): enhanced timer for prediction algorithm (#7037) * chore(core): fixup km_kbp_event docs (#7253) * fix(windows) Update unit tests for tsf bkspace (#7254) * fix(android): Standardize language ID in language picker menu (#7239) ## 16.0.59 alpha 2022-09-09 * chore: use keyman.com instead of keyman-staging.com (#7233) * feat(core): add `km_kbp_event` API endpoint (#7223) * fix(windows): Delete both code units when deleting surrogate pairs in TSF-aware apps (#7243) ## 16.0.58 alpha 2022-09-08 * fix(common/models): reconnects unit tests for worker-internal submodules (#7215) * feat(common/models): extra Unicode-based wordbreaker unit tests (#7217) ## 16.0.57 alpha 2022-09-07 * fix(android/engine): Fix Backspace key to delete without errant subkeys (#7156) ## 16.0.56 alpha 2022-09-05 * chore(linux): Fix ibus-keyman.postinst script (#7192) ## 16.0.55 alpha 2022-09-03 * chore(android): Reduce Toast notification noise (#7178) ## 16.0.54 alpha 2022-08-30 * chore(core): rename json.hpp to jsonpp.hpp (#6993) * chore(developer): remove unused dependencies from KeymanWeb compiler (#7000) * chore: update core/ label (#7138) * chore(linux): Update debian changelog (#7145) * fix(linux): Allow downgrades for installing build deps (#7147) * chore(core): emcc off path for linux (#7149) ## 16.0.53 alpha 2022-08-29 * feat(linux): Dockerfile for linux builder (#7133) ## 16.0.52 alpha 2022-08-26 * fix(android/engine): Lower the max height for landscape orientation (#7119) * fix(linux): Remove wrong `ok_for_single_backspace` method (#7123) ## 16.0.51 alpha 2022-08-24 * fix(android): verify browser before starting activity (#7001) * chore: Change platform advocates per discussion (#7096) * fix(windows): Add invalidate context action to non-updatable parse (#7089) * feat(common): add parameter variable support to `builder_` functions (#7103) ## 16.0.50 alpha 2022-08-23 * chore(core): Remove obsolete python keyboardprocessor (#7094) ## 16.0.49 alpha 2022-08-22 * fix: remove saving and restoring context kbd options (#7077) * chore(deps): bump @actions/core from 1.8.2 to 1.9.1 (#7087) ## 16.0.48 alpha 2022-08-16 * fix(web): button, float init timer cleanup (#7036) ## 16.0.47 alpha 2022-08-15 * chore(core): refactor kmx_file.h to common (#7062) * fix(developer): stack overflow when compiling non-web keyboard (#7031) * fix(developer): prevent crash attempting to compile ansi keyboard (#7033) * chore(linux): Refactor `jenkins.sh` (#7060) * fix(developer): compiler emitting garbage for readonly groups (#7013) ## 16.0.46 alpha 2022-08-12 * docs(core): cleanup in keyboardprocessor.h (#7065) ## 16.0.45 alpha 2022-08-09 * feat(linux): Replace deprecated distutils (#7051) * chore(linux): Adjust Linux source package to restructured code (#7056) ## 16.0.44 alpha 2022-08-08 * chore(linux): Update debian changelog (#7041) ## 16.0.43 alpha 2022-08-05 * chore(web): centralizes web-based modules' CI unit test configurations (#7024) * refactor(web): converts test_utils funcs to Promise use (#7027) * chore(core): get wasm core building again (#7023) * chore(common): build-utils.sh minor tweaks (#7018) * change(web): rotation polish - OSK reload no longer needed ️ (#6787) * change(web): updates mobile screen dimension detection code ️ (#6979) ## 16.0.42 alpha 2022-08-01 * feat(developer): add languageUsesCasing to Model Editor (#7008) * fix(developer): increase maximum file size for server (#7003) * fix(developer): rebuilding a model would not refresh it in server (#7015) * chore(common): GitHub issue template tweaks (#7022) ## 16.0.41 alpha 2022-07-29 * chore(common): builder script `:target` and `--option` support (#6986) * chore(linux): Add code comment (#7009) ## 16.0.40 alpha 2022-07-28 * chore(linux): Add script to upload to debian (#6997) ## 16.0.39 alpha 2022-07-27 * chore(linux): Update debian changelog (#6996) ## 16.0.38 alpha 2022-07-26 * feat(developer): Rework Touch Layout Editor to support flick and multitap (#6884) * fix(developer): improve error message for multi-part key ids on <15.0 (#6989) * fix(android): rework longpress movement trigger (#6984) * chore(linux): Update changelog (#6988) ## 16.0.37 alpha 2022-07-22 * fix(linux): Catch PermissionError exception (#6968) * chore(linux): Update Debian changelog :cherries: (#6973) * chore(linux): Add support for Ubuntu 22.10 "Kinetic Kudu" (#6975) * fix(developer): reduce timeouts if server shut down (#6943) * fix(linux): Implement refresh after keyboard installation (#6956) ## 16.0.36 alpha 2022-07-20 * chore(linux): Code cleanup (#6957) * fix(linux): Another attempt at fixing postinst script (#6960) * fix(linux): Fix uninstallation when using fcitx5 (#6963) ## 16.0.35 alpha 2022-07-19 * fix(common): Fix `delete` (#6965) ## 16.0.34 alpha 2022-07-15 * fix(developer): set contextDevice in web debugger ️ (#6906) * fix(web): postkeystroke processing should ignore key-event source (#6901) * fix(web): layer-setting ops should not trigger for hardware keystroke processing ️ (#6902) * fix(developer): kmdecomp virtual character key output (#6940) * fix(developer): crash on exit when checking for updates (#6941) * fix(developer): crash when switching back a tab (#6942) * chore(web): remove invalid warning msg (#6950) ## 16.0.33 alpha 2022-07-14 * feat(developer): Option to skip embed of compiler version (#6920) * feat(developer): compiler regression support (build kmcomp-$version.zip during release build) (#6918) * chore(ios): updates core internals for the in-app browser (#6838) ## 16.0.32 alpha 2022-07-13 * fix(ios): ignore CFBundleShortVersionString (#6934) ## 16.0.31 alpha 2022-07-12 * fix(developer): QR Code for Package Editor had wrong path (#6926) ## 16.0.30 alpha 2022-07-11 * fix(web): maps touch-layout chiral alt, ctrl to non-chiral when non-chiral keyboard is active (#6808) ## 16.0.29 alpha 2022-07-08 * fix(web): ncaps rules not matching on touch (#6911) ## 16.0.28 alpha 2022-07-08 * chore(android): disable sendError for js errors (#6905) * fix(developer): add no-ops for symbol builds for components (#6908) ## 16.0.27 alpha 2022-07-07 * fix(web): improve `console.error()` reporting (#6890) ## 16.0.26 alpha 2022-07-06 * fix(developer): Show full version number (#6866) * chore(developer): rename developer/js to developer/kmlmc (#6630) * feat(developer): .keyman-touch-layout schema for 15.0 (#6856) * feat(developer): add flick and multitap to touch layout schema and doc (#6877) * fix(linux): Fix post-install script (#6894) ## 16.0.25 alpha 2022-07-05 * chore(web): update readme (#6891) ## 16.0.24 alpha 2022-07-02 * fix(common): trigger builds correctly for stable builds (#6847) * fix(windows): show full version number (#6867) ## 16.0.23 alpha 2022-06-29 * fix(web): clears repeating bksp on keyboard reload ️ (#6786) * fix(web): null-guard for refreshLayout (#6854) ## 16.0.22 alpha 2022-06-28 * fix(ios): eliminates conditional height for banner image (#6855) ## 16.0.21 alpha 2022-06-27 * chore(ios): modernizes app-help's internals (#6836) * fix(linux): Deal with non-existing files (#6840) * fix(linux): Catch KeyboardInterrupt (#6841) ## 16.0.20 alpha 2022-06-26 * chore(web): shorten check/web/file-size check message (#6780) ## 16.0.19 alpha 2022-06-24 * change(web): drops old IE-related handling code (#6557) * chore(deps): bump got from 11.8.3 to 11.8.5 (#6821) * chore(ios): log script actions and fixup export settings to avoid version being clobbered (#6835) ## 16.0.18 alpha 2022-06-23 * chore(core): move common/core/desktop/ to core/ (#6629) ## 16.0.17 alpha 2022-06-22 * chore(web): updates error-reporting lib uploader (#6818) * fix(web): fixes doc-keyboard generation (#6793) ## 16.0.16 alpha 2022-06-21 * fix(web): key tip constraint logic requires .bottom CSS (#6784) * fix(ios): overzealous error about missing banner image (#6807) * chore(linux): Update Debian changelog (#6810) ## 16.0.15 alpha 2022-06-18 * fix(web): crash on custom modifier keys (#6790) * chore: add trigger definitions for stable-15.0 and fixup force param for increment-version.sh (#6776) ## 16.0.14 alpha 2022-06-17 * chore(web): add 'index.html' to parent links in test pages (#6791) ## 16.0.13 alpha 2022-06-15 * chore: beta to master merge A16S4 (#6771) ## 16.0.12 alpha 2022-06-14 * chore(web): replace lerna with npm workspaces and ts projects (#6525) * fix(common): update increment-version for new tsc, node versions (#6762) ## 16.0.11 alpha 2022-05-27 * chore: A16S2 beta to master (#6670) * chore(ios): FV certificate hash (#6674) ## 16.0.10 alpha 2022-05-15 * chore: beta to master A16S1 (#6614) ## 16.0.9 alpha 2022-04-29 * chore(common): merge beta to master B15S7 (Part 2) (#6579) ## 16.0.8 alpha 2022-04-17 * chore: merge beta to master B15S7 (#6537) ## 16.0.7 alpha 2022-04-07 * chore: beta to master B15S6 (#6490) * fix(ios): use CFBundleShortVersionString for version (#6496) ## 16.0.6 alpha 2022-04-05 * chore(deps): bump ansi-regex from 3.0.0 to 3.0.1 in /web/testing/regression-tests (#6470) * chore(deps-dev): bump minimist from 1.2.5 to 1.2.6 in /web/testing/regression-tests (#6471) * chore(deps): bump minimist from 1.2.5 to 1.2.6 in /developer/server (#6472) ## 16.0.5 alpha 2022-04-04 * chore(common): beta to master B15S6 (#6467) ## 16.0.4 alpha 2022-03-22 * chore: B15S4 beta->alpha (#6402) ## 16.0.3 alpha 2022-03-16 * chore: merge beta changes to alpha B15S4 (#6376) * chore(common/core/desktop): Improve meson build file ️ (#6183) ## 16.0.2 alpha 2022-03-03 * chore(deps-dev): bump karma from 6.3.14 to 6.3.16 in /web/testing/regression-tests (#6322) ## 16.0.1 alpha 2022-03-02 * chore(common): move to 16.0 (#6318) ## 15.0.270 stable 2022-09-12 * chore(linux): Add support for Ubuntu 22.10 "Kinetic Kudu" (#7143) * chore(linux): Update debian changelog (#7144) * fix(android/engine): Cleanup list of subkeys when dismissing window (#7176) * chore(linux): Fix ibus-keyman.postinst script (#7208) * fix(windows): Delete both code units when deleting surrogate pairs in TSF-aware apps (#7256) * fix(developer): compiler mismatch on currentLine (#7191) * fix(developer): suppress repeated warnings about unreachable code (#7265) ## 15.0.269 stable 2022-08-29 * chore(linux): Update debian changelog (#7040) * feat(linux): Replace deprecated distutils :cherries: (#7052) * fix(developer): compiler emitting garbage for readonly groups (#7014) * chore: Change platform advocates per discussion (#7114) * fix(windows): remove saving and restoring context kbd options (#7107) * fix(windows): Add invalidate context action to non-updatable parse (#7108) * fix(android/engine): :cherries: Lower the max height for landscape orientation (#7128) ## 15.0.268 stable 2022-08-04 * chore(linux): Update debian changelog (#6995) * fix(developer): increase maximum file size for server (#7004) * fix(developer): rebuilding a model would not refresh it in server (#7016) * chore(linux): Add script to upload to debian (#7017) * fix(developer): stack overflow when compiling non-web keyboard (#7034) * fix(developer): prevent crash attempting to compile ansi keyboard (#7035) ## 15.0.267 stable 2022-07-26 * fix(developer): QR Code for Package Editor had wrong path (#6927) * fix(ios): ignore CFBundleShortVersionString (#6935) * fix(web): context-only rule effects, set(&layer) from physical keystrokes ️ (#6949) * chore(web): remove invalid warning msg (#6951) * fix(common): Fix `delete` :cherries: (#6966) * fix(linux): Another attempt at fixing postinst script :cherries: (#6961) * fix(linux): Fix uninstallation when using fcitx5 :cherries: (#6964) * fix(linux): Catch PermissionError exception :cherries: (#6969) * chore(linux): Update Debian changelog (#6972) * fix(developer): kmdecomp virtual character key output (#6945) * fix(developer): crash on exit when checking for updates (#6946) * fix(developer): crash when switching back a tab (#6947) * fix(developer): reduce timeouts if server shut down (#6948) * fix(android): rework longpress movement trigger (#6992) * chore(linux): Update changelog (#6987) * fix(developer): improve error message for multi-part key ids on <15.0 (#6990) ## 15.0.266 stable 2022-07-08 * fix(linux): Fix post-install script :cherries: (#6895) * fix(web): improve `console.error()` reporting (#6904) * fix(web): ncaps rules not matching on touch (#6913) ## 15.0.265 stable 2022-07-04 * fix(common): trigger builds correctly for stable builds (#6879) * fix(web): post-keystroke processing after use of pred. text selection (#6886) ## 15.0.264 stable 2022-07-01 * fix(ios): eliminates conditional height for banner image (#6857) * fix(web): clears repeating bksp on keyboard reload ️ (#6863) * fix(web): better stability during transient OSK load state (#6861) * fix(developer): readonly groups should never emit output (#6873) * fix(web): Maintain separate Caps Lock states for touch and physical (#6874) ## 15.0.263 stable 2022-06-24 * chore(ios): add manageAppVersionAndBuildNumber=false (#6837) ## 15.0.262 stable 2022-06-23 * fix(web): key preview styling, positioning issues (#6795) * chore(linux): Update Debian changelog (#6809) * fix(linux): Deal with non-existing files (#6812) * fix(linux): Catch KeyboardInterrupt (#6814) * fix(ios): blocks known non-error "error" report (#6816) * fix(web): fixes doc-keyboard generation (#6817) * chore(web): updates error-reporting lib uploader (pseudo- ) (#6819) ## 15.0.261 stable 2022-06-18 * fix(web): crash on custom modifier keys (#6789) ## 15.0.260 stable 2022-06-15 * chore(common): Release version 15.0 ## 15.0.259 beta 2022-06-10 * fix(android/engine): Disable haptic feedback on hardware keystrokes (#6671) * fix(windows): Install TIP crash with inconsistent bcp47tag (#6727) * change(web): adjusts minimum distance needed for quick-display of subkeys (#6714) * change(web): browser test timeout tweaks (#6718) ## 15.0.258 beta 2022-06-06 * chore: add 14.0 entries to beta HISTORY.md (#6705) * chore(web): switch on additional BrowserStack reporting (#6707) * fix(web): fixes OSK-interaction issues in Float, Toolbar UI modules (#6689) ## 15.0.257 beta 2022-06-03 * fix(developer): kmcomp package compiler race condition (#6696) * fix(developer): install keyboard call should quote kmshell.exe path (#6691) ## 15.0.256 beta 2022-06-01 * chore(android,ios,mac): Update crowdin strings for Spanish (Latin America) (#6650) ## 15.0.255 beta 2022-05-31 * fix(web): osk shrinkage from rounding (#6658) ## 15.0.254 beta 2022-05-30 * fix(ios): missed i18n site (#6667) * fix(ios): keyboard height on app load (#6672) * feat(ios): adds back and forward navigation buttons for in-app help (#6654) * change(ios): modernization of the Keyman app main screen's layout logic (#6666) ## 15.0.253 beta 2022-05-27 * chore(ios): FV certificate hash (#6673) ## 15.0.252 beta 2022-05-25 * fix(ios): fixes OSK mispositioning bug in iOS 15 (#6631) ## 15.0.251 beta 2022-05-23 * fix(ios): stops leaking memory on system keyboard rotation (#6552) * fix(android/engine): Fix sticky long-press keys (#6637) ## 15.0.250 beta 2022-05-20 * feat(android/app): Provide haptic feedback when typing (#6626) * fix(ios): disables transparent nav bar for ios 15 (#6633) ## 15.0.249 beta 2022-05-19 * chore(common): improve PR reporting of changes (#6624) ## 15.0.248 beta 2022-05-17 * fix(windows): use GlobalGetAtomName to access global list (#6580) ## 15.0.247 beta 2022-05-16 * chore(common/resources): Update langtags.json (#6594) * fix(android/engine): Refresh OSK when changing spacebar text (#6620) ## 15.0.246 beta 2022-05-11 * chore(ios): Set transparent background on "more" icons (#6598) * chore(common): Add crowdin strings for Polish (#6593) ## 15.0.245 beta 2022-05-10 * chore(common): Add crowdin strings for Italian (#6592) ## 15.0.244 beta 2022-05-09 * fix(windows): Don't reset defaults on Keyman upgrade (#6491) ## 15.0.243 beta 2022-05-03 * chore(web): report on file size (#6584) * chore(android/engine): Ignore DownloadManager if ID not found (#6581) * fix(common/models): prevents preemptive tokenization of potential contractions (#6574) * fix(web): fixes fat-finger distrib when subkey selected (#6526) ## 15.0.242 beta 2022-04-29 * docs(windows): Update OS and whatsnew in help (#6560) * fix(android/engine): Check suggestion banner after setting keyboard (#6559) * chore(common): Update Crowdin strings for Fula (#6562) ## 15.0.241 beta 2022-04-27 * change(web): touch alias optimization followup (#6566) * fix(common/core/web): Fix forEach loop in SentryManager (#6569) * fix(linux): Fix shared keyboard (un-)installation in Bionic (#6565) ## 15.0.240 beta 2022-04-26 * feat(web): adds .getKeyboard().IsRTL, .HasLoaded (#6567) * fix(android): Don't show welcome.htm on keyboard package update (#6555) * fix(android/engine): Localize some Toast notifications (#6561) ## 15.0.239 beta 2022-04-22 * fix(web): optimizes, enhances caret placement within text on mobile devices (#6551) ## 15.0.238 beta 2022-04-21 * chore(linux): Fix failure in Debian reproducibility testing (#6548) * chore(linux): Update Linux dependencies (#6549) ## 15.0.237 beta 2022-04-20 * feat(linux): WIP - implement capslock handling with Wayland ️ (#6213) ## 15.0.236 beta 2022-04-19 * fix(android): key tip sticky with multitap (#6494) * fix(web): blocks modifier key fat-fingering (#6473) ## 15.0.235 beta 2022-04-18 * chore(android,windows): Update crowdin strings for bwr-NG (#6532) ## 15.0.234 beta 2022-04-14 * chore(common): Add Crowdin strings for Portuguese (pt-PT) (#6509) * chore(linux): Fix l10n language mappings (#6529) * chore(linux): Update Debian changelog (#6530) ## 15.0.233 beta 2022-04-13 * chore(android/app): Add description for referrer response error (#6524) * fix(linux): test fileVersion during package install (#6522) ## 15.0.232 beta 2022-04-11 * fix(linux): Remove tab completion warning (#6482) ## 15.0.231 beta 2022-04-09 * test(common/resources): Add Noto font to web_context_tests keyboard (#6488) ## 15.0.230 beta 2022-04-08 * fix(android/engine): Show keyboard after rotating (#6498) * fix(windows): don't log before checking nil when installing keyboard (#6505) * chore: Revert "feat(web): prediction casing follows current layer" (#6510) * chore(linux): Update changelog file (#6500) * fix(windows): framework for switching of pipeline (#6392) ## 15.0.229 beta 2022-04-07 * fix(iOS): check version during package install (#6479) * feat(ios): testflight builds for PRs (#6486) * chore(ios): Document minimum iOS version 12.1 (#6492) * fix(developer): handle exception on unpaired surrogate (#6487) * chore(mac): Update whatsnew for 15.0 (#6493) * fix(ios): use CFBundleShortVersionString for version (#6495) * fix(android/app): Simplify sharing intent (#6481) ## 15.0.228 beta 2022-04-05 * feat(web): prediction casing follows current layer (#6459) * fix(mac): check package fileVersion during install (#6415) ## 15.0.227 beta 2022-04-04 * fix(developer): improves More Help link for icon tool (#6464) * chore(android): Document minimum required version of Chrome (#6468) * chore(common): Update in-app help versions to 15.0 (#6469) * fix(web): rely on caller for unmatched keys (#6457) * feat(developer): hint on unreachable code (#6440) * feat(developer): check filename case consistency when compiling keyboard (#6445) * feat(developer): add Clear All button to icon editor (#6465) * fix(developer): icon editor font color now follows fgcolor (#6466) * fix(developer): validate kmconvert parameters (#6451) * feat(developer): check for duplicate store/group names (#6463) * docs(linux): Update testing section in readme (#6460) ## 15.0.226 beta 2022-04-01 * fix(web): track stateKeys changes with layer changes (#6453) ## 15.0.225 beta 2022-04-01 * fix(ios): reset context when osk is resized (#6428) * feat(developer): keep Virtual Key Identifier dialog open on Insert (#6449) * fix(oem/fv/ios): maintain consistent keyboard state between Keyman Engine and FV app (#6446) ## 15.0.224 beta 2022-03-29 * fix(android/engine): Clear WebView cache on package install (#6438) * feat(oem/fv/ios): Dictionary Support (#6197) ## 15.0.223 beta 2022-03-27 * fix(mac): invalid keyboard breaks configuration (#6421) * fix(windows): make long menus scroll in Configuration (#6424) * fix(web): ios popup positioning and style (#6383) ## 15.0.222 beta 2022-03-25 * fix(windows): put correct HK_ALT flag for modifier (#6425) ## 15.0.221 beta 2022-03-24 * fix(developer): structure sizes for kmcomp x64 (#6408) * fix(common): report more log detail in increment-version (#6418) ## 15.0.220 beta 2022-03-23 * fix(web): adjust touch alias element positioning (#6406) * fix(android/engine): Display longpress keys during a Move gesture (#6138) ## 15.0.219 beta 2022-03-22 * chore(common): Update Hausa strings (#6399) ## 15.0.218 beta 2022-03-21 * chore(android/engine): Remove visual gaps in keyboard picker menu (#6370) ## 15.0.217 beta 2022-03-19 * fix(web): bounding rect offset was incorrect (#6357) ## 15.0.216 beta 2022-03-18 * feat(linux): Allow to run ibus tests on Wayland ️ (#6202) ## 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) ## 15.0.209 beta 2022-03-08 * fix(windows): add null pointer checks imsample keyboard (#6187) * chore(linux): Debug why Beta build didn't get triggered (#6337) * fix(developer): project should not steal focus on load (#6325) * chore(android/engine): Remove bold styling in lists (#6341) * fix(linux): Fix trigger script (#6342) * chore: increment to 15.0.209 (#6343) ## 15.0.206 beta 2022-03-02 * change(web): tightens call signature for banner selection (#4966) * fix(windows): cleanup edge cases in k32_load (#5197) * feat(ios): refinement of spacebar-captioning PR (#5368) ## 15.0.205 alpha 2022-03-02 * fix(developer): move ngrok to Server/bin/ (#6304) * fix(linux): Gracefully handle keyboard download failure (#6285) * fix(linux): Gracefully handle makedirs failures (#6287) * chore(common): tweak CODEOWNERS (#6305) * fix(developer): rename Code to ID in Touch Layout Editor (#6309) * feat(developer): kmcomp -h and -help (#6312) * chore(developer): remove Package for Distribution action (#6313) * fix(web): error in floating osk view when no keyboard active (#6316) * chore(developer): disable upload for server except localhost (#6300) * fix(ios): tweak simulator builds to support M1 (#6317) * fix(developer): handle paste event in touch layout editor (#6295) * fix(developer): Improve active tab visibility (#6314) * fix(developer): font for Package and Model Editors (#6311) * fix(web): stop repeated CSS injection (#6310) * feat(developer): support commas in frequency in wordlists (#6315) * chore: release to beta ## 15.0.204 alpha 2022-03-01 * feat(android): Android web-based test harness (#6250) * fix(developer): server font support (#6298) * chore(windows): Remove core icon from system tray (#6302) ## 15.0.203 alpha 2022-02-26 * chore(common): remove rust (for now!) (#6291) ## 15.0.202 alpha 2022-02-24 * feat(common): echo in macos.sh setup script (#6246) * chore(common): Add CODEOWNERS file (#6262) * chore(oem/fv): Add keyboard version and languages (#6226) * fix(common/core/desktop): Add num and scroll lock mask to VKeyToChar (#6211) * fix(linux): Properly compare versions in km-package-install (#6278) ## 15.0.201 alpha 2022-02-21 * fix(developer): npm publish with correct tier (#6259) * fix(linux): Fix stray `[-vv]` in man pages (#6241) ## 15.0.200 alpha 2022-02-20 * chore(common): Update French strings (#6263) ## 15.0.199 alpha 2022-02-18 * fix(web): Non-integer OSK sizes (#6248) ## 15.0.198 alpha 2022-02-13 * fix(developer): compile package fileVersion from keyboard FileVersion (#6145) * chore(android/app): Clarify help on switching keyboards (#6234) ## 15.0.197 alpha 2022-02-12 * chore(deps): bump follow-redirects from 1.7.0 to 1.14.8 in /web/testing/regression-tests (#6247) * chore(deps-dev): bump karma from 6.3.4 to 6.3.14 in /web/testing/regression-tests (#6236) * fix(windows): create Keyman/Diag folder in redirected profile (#6225) * fix(developer): support KM_KBP_IT_CAPSLOCK (#6230) ## 15.0.196 alpha 2022-02-11 * fix(windows): add flag to track core process event (#6219) ## 15.0.195 alpha 2022-02-09 * chore(android): Upgrade gradle-wrapper version to 6.8 (#6223) ## 15.0.194 alpha 2022-02-08 * chore(android): Update Play publishing plugin to 3.5.0 (#6217) * feat(android/engine): Single tap globe switch to previous system IME (#6206) * feat(linux): Try to start ibus if not running (#6109) ## 15.0.193 alpha 2022-02-07 * chore(ios): certificate update again (#6208) ## 15.0.192 alpha 2022-02-04 * chore(oem/firstvoices): Add fv_haisla keyboard (#6181) * chore(linux): Improve dependencies in Linux package (#6198) * chore(linux): Remove obsolete Ubuntu 21.04 Hirsute (#6199) ## 15.0.191 alpha 2022-02-03 * fix(developer): remove keymanengine.msm (#6143) ## 15.0.190 alpha 2022-02-02 * fix(linux): Don't crash when installing keyboards in Wasta (#6159) ## 15.0.189 alpha 2022-02-01 * fix(linux): Don't crash if we lack permissions (#6179) * chore(linux): stop releasing KMFL together with Keyman (#6184) ## 15.0.188 alpha 2022-01-28 * fix(mac): Check for CODE_SETSYSTEMSTORE (#6169) * feat(developer): Keyman Developer Server (#6073) ## 15.0.187 alpha 2022-01-27 * fix(developer): handle Core failure to load (#6141) * feat(windows): Keyman Core Integration - Support for IMX DLLs (#5936) * chore(windows): testhost readme (#6164) * chore(ios): certificate update (#6165) * feat(linux): add support for Wayland (#6135) ## 15.0.186 alpha 2022-01-26 * feat(linux): Replace hirsute with impish (#6161) ## 15.0.185 alpha 2022-01-25 * feat(windows): testhost project for debugging keyman32 (#6154) * feat(windows): handle key output in testhost (#6157) * chore(deps): bump node-fetch from 2.6.1 to 2.6.7 in /resources/build/version (#6156) * fix(developer): prevent crash on build dblclicked file (#6151) * chore(linux): Add comment for clarification of code behaviour (#6152) ## 15.0.184 alpha 2022-01-24 * fix: only auto-merge if `auto:` prefix in title (#6146) ## 15.0.183 alpha 2022-01-21 * chore(linux): Update changelogs for 14.0.284 :cherries: (#6132) * chore(linux): Revert workaround for Python bug (#6133) ## 15.0.182 alpha 2022-01-21 * chore(linux): Add metadata file for packaging (#6127) * fix(web): crash in setTitleFromKeyboard when no keyboard active (#6129) ## 15.0.181 alpha 2022-01-19 * fix(linux): Add workaround for Python bug (#6124) * docs(linux): Add missing dependency (#6118) ## 15.0.180 alpha 2022-01-18 * feat(web): Caps Layer and double-tap gesture (#5989) * fix(web): Use regex to determine display layer and functional layers (#6100) ## 15.0.179 alpha 2022-01-17 * feat(web): Start of Sentence support - part 1 (#5963) * feat(developer): support for Caps Lock layer (#5988) * fix(web): call postKeystroke on banner touch (#6004) * chore(ios): project scripts should use /usr/bin/env bash (#6114) * chore: update docs (#6115) * chore(common): Check in crowdin strings for Kibaku (#6048) * fix(mac): externalize strings for package info window localization (#6088) * fix(developer): repatch #6074 (#6111) * fix(linux): Fix lintian errors (#6106) ## 15.0.178 alpha 2022-01-14 * chore(common): Check in crowdin strings for Waha (#6050) ## 15.0.177 alpha 2022-01-13 * chore(common): Check in crowdin strings for Marghi (#6049) ## 15.0.176 alpha 2022-01-12 * fix(windows): add x64 build fix invalid memory access (#6057) * feat(windows): method set context correctly truncates input buffer (#6080) * chore(common): Check in crowdin strings for Kanuri (#6047) * fix(linux): Update minimum sentry-sdk version (#6093) * docs: Enhance Linux build setup doc (#6094) ## 15.0.175 alpha 2022-01-11 * feat(linux): Don't create Sentry events for errors (#6070) * fix(linux): Fix attribute error (#6086) * fix(developer): bundle.sh must succeed (#6091) ## 15.0.174 alpha 2022-01-10 * chore(android/samples): Add -no-daemon flag to KMSample2 build script (#6082) * fix(linux): Fix installation of shared packages (#6015) ## 15.0.173 alpha 2022-01-05 * chore(common): Update crowdin strings for Amharic (#6040) * fix(linux): fix release version number for Sentry reporting (#6068) ## 15.0.172 alpha 2021-12-23 * fix(developer): work around devDependencies bug in npm (#6074) * chore(windows): nmake makefile cleanup (#6065) ## 15.0.171 alpha 2021-12-17 * feat(developer): remember test page preferences on reload (#6033) * feat(developer): tidy up package list in web test view (#6034) * feat(developer): live reload of web debugger (#6035) * feat(developer): cache web debug objects across sessions (#6036) * fix(developer): project_mru.xml path (#6061) * chore(developer): add browse4folder to components (#6062) * docs(windows): Add note on split user/admin accounts (#6059) * fix(mac): increase OSK character size by 50% (#6006) ## 15.0.170 alpha 2021-12-16 * docs(linux): Document how to disable error reporting (#6051) * fix(linux): fix release version number for Sentry reporting (#6052) * fix(linux): Fix package description (#6054) ## 15.0.169 alpha 2021-12-15 * fix(mac): display Unicode package name correctly instead of '????' (#6016) * fix(linux): Improve ibus-keyman tests (#6044) ## 15.0.168 alpha 2021-12-14 * feat(linux): Add support for Ubuntu 22.04 Jammy (#6037) ## 15.0.167 alpha 2021-12-13 * fix(windows): remove unused variable (#6039) ## 15.0.166 alpha 2021-12-11 * chore(windows): version.rc use macros instead of mkver (#6019) * chore(windows): move from Borland make to nmake (#6020) * chore(windows): use findstr instead of Borland grep (#6021) * chore(windows): replace mkver with mkver.sh (#6022) * chore(windows): build without delphi (#6030) ## 15.0.165 alpha 2021-12-08 * fix(web): font size was not consistently set (#5906) ## 15.0.164 alpha 2021-12-07 * refactor(common/core): Use defines in all xstring tests (#6002) ## 15.0.163 alpha 2021-12-06 * chore(common): buf now uses decxstr so remove comment (#6012) ## 15.0.162 alpha 2021-12-05 * chore(linux): Update changelogs for 14.0.283 :package: :cherries: (#6008) ## 15.0.161 alpha 2021-12-04 * chore(linux): Allow to specify debian revision :package: :cherries: (#5999) * chore(linux): Remove lintian warning :package: :cherries: (#6000) ## 15.0.160 alpha 2021-12-03 * fix(developer): building kmw keyboard had wrong message callback signature (#5972) * chore(common): add more description to Buf method (#6003) * chore(linux): add non-surrounding-text feature to tests (#5968) ## 15.0.159 alpha 2021-12-02 * fix(developer): debugger crash with empty group (#5995) * chore(android): Document switching to other system keyboard (#5991) * fix(android/engine): Fix font paths (#5987) ## 15.0.158 alpha 2021-12-01 * feat(android/engine): Add other IME's to the Keyboard Picker menu (#5973) * chore(android): Specify build tools version on other projects (#5979) ## 15.0.157 alpha 2021-11-29 * fix(web): remove obsolete popupBaseTarget (#5949) * fix(web): improve keyboard switch performance (#5958) * fix(web): support saving focus for custom OSK interactions (#5947) * fix(developer): render OSK nicely on touch devices (#5923) * chore(developer): move kcframe into its own folder (#5971) * fix(web): restore `dragEnd` function (#5977) * feat(common/core/desktop): Allow preserved key support (#5850) * chore(windows): Consolidate documentation for Windows devboxes (#5481) * chore(developer): tweak language metadata message (#5978) * fix(linux): Fix ibus-keyman integration tests (#5966) ## 15.0.156 alpha 2021-11-26 * fix(windows): fix loadkeyboardoptions core memory error (#5959) ## 15.0.155 alpha 2021-11-24 * fix(web): reset scroll anchor on touchend (#5919) * fix(web): shorten setFocusTimer() (#5946) * fix(web): clear longpress timeout if user does a flick up (#5952) ## 15.0.154 alpha 2021-11-22 * fix(web): simplify hide transition (#5910) * fix(web): inline osk keytip position (#5938) * feat(mac): i18n, support localization of Keyman for Mac (#5869) * chore(linux): Remove unused test methods (#5954) * chore(linux): Run ibus-keyman tests as part of the build (#5889) ## 15.0.153 alpha 2021-11-20 * fix(web): resolve unhandled exception in promise (#5902) ## 15.0.152 alpha 2021-11-19 * fix(common/core): Update decxstr to check all characters while decrementing (#5842) ## 15.0.151 alpha 2021-11-18 * fix(developer): use correct tike icon (#5925) * fix(android/engine): Support for U_xxxx_yyyy subkeys (#5913) * fix(mac): use xcframework to support m1 (#5933) * fix(developer): move web osk beneath text area (#5937) ## 15.0.150 alpha 2021-11-17 * fix(web): remove canvas use for iOS compatibility (#5915) ## 15.0.149 alpha 2021-11-17 * chore(developer): Update jszip version (#5770) * chore(common): Check in crowdin strings for Fulfulde Nigeria (#5841) ## 15.0.148 alpha 2021-11-16 * chore(common): Check in crowdin strings for Mandara (Wandala) (#5857) * chore(linux): Update method comments (#5883) ## 15.0.147 alpha 2021-11-15 * chore(android,linux,windows): Check in crowdin strings for Bura-Pabir (#5839) * chore: add keyman-local.com to iis https setup (#5892) * fix(web): avoid error if timerid not valid (#5908) ## 15.0.146 alpha 2021-11-14 * feat(developer): support for U_xxxx_yyyy (#5894) ## 15.0.145 alpha 2021-11-13 * fix(developer): crash exporting OSK on European keyboard (#5893) * feat(developer): validate .kps files during compile (#5895) ## 15.0.144 alpha 2021-11-12 * fix(android/engine): Truncate language name in list (#5878) * fix(android/app): Check KMP file exists before attempting to extract (#5849) * fix(web): Check parent element is defined before assigning (#5874) * fix(android/app): Revert test code (#5899) ## 15.0.143 alpha 2021-11-11 * fix(developer): handle shortcut keys in debugger (#5776) ## 15.0.142 alpha 2021-11-08 * chore(linux): Cleanup (#5886) * chore(linux): cleanup defunct tests (#5885) * chore(linux): fix failing ibus-keyman tests (#5884) ## 15.0.141 alpha 2021-11-05 * chore(linux): Add integration tests for ibus-keyman (#5881) ## 15.0.140 alpha 2021-11-03 * feat(android): Allow uninstall of sil_euro_latin keyboard (#5838) * chore(common/core): Compile test keyboards to .kmp (#5864) ## 15.0.139 alpha 2021-11-02 * chore(common/core): refactor kmx unit tests (#5862) * chore(linux): Extract keycode_to_vk[] to separate header file (#5863) ## 15.0.138 alpha 2021-10-29 * chore(linux): Set correct version number on ibus component (#5859) * chore(common/core): generate kmp.json (#5860) ## 15.0.137 alpha 2021-10-28 * chore(common): Don't check for conventional commit for fixups (#5858) ## 15.0.136 alpha 2021-10-23 * chore(android/engine): Address globe key TODO (#5836) ## 15.0.135 alpha 2021-10-20 * docs(windows): add note to caps-lock-stores test (#5837) ## 15.0.134 alpha 2021-10-19 * docs(windows): add install apps from anywhere instructions (#5829) ## 15.0.133 alpha 2021-10-16 * chore(common): Check in crowdin strings for Hausa (#5768) ## 15.0.132 alpha 2021-10-15 * feat(windows): manual keyboard caps tests (#5808) * feat(windows): Change caps to work with common core processor (#5803) ## 15.0.131 alpha 2021-10-13 * chore(windows): Add obj cod and pdb to gitignore (#5826) ## 15.0.130 alpha 2021-10-11 * fix(common/core): incxstr checks all character while incrementing (#5712) ## 15.0.129 alpha 2021-10-08 * chore: Create CODE_OF_CONDUCT.md (#5819) * chore: Add CONTRIBUTING documentation (#5821) * chore: Add link to SIL (#5823) ## 15.0.128 alpha 2021-10-07 * fix(ios): move sentry settings responsibility to build agent (#5805) ## 15.0.127 alpha 2021-10-06 * chore(web): disable registerstub test (#5800) ## 15.0.126 alpha 2021-10-05 * chore: sentry.io dsn ‍ ️ (#5787) ## 15.0.125 alpha 2021-10-05 * fix(android/engine): Remove unnecessary permissions from Manifest (#5752) * feat(developer): touch layout testing (#5723) * fix(web): popup positioning (#5742) * chore(linux): Update changelog files for 14.0.282 :cherries: (#5794) ## 15.0.124 alpha 2021-10-04 * fix(web): support variable stores with predictive text (#5749) * fix(windows): handle edge cases using default language (#5709) * fix(linux): Don't crash with non-keyboard package file (#5755) * fix(linux): Don't crash displaying keyboard details (#5758) ## 15.0.123 alpha 2021-10-01 * fix(common): Fix cherry-pick labeling (#5782) * chore(ios,android,windows): Update crowdin strings for Amharic (#5722) ## 15.0.122 alpha 2021-09-30 * fix(developer): move ampersand to shift+7 on touch (#5746) * feat(windows): Keyman Core integration (#5443) * chore(windows): Keyman Core UI and Settings (#5769) * fix(linux): Fix debian package script (#5771) * docs(mac): Add note about installing with homebrew (#5767) ## 15.0.121 alpha 2021-09-29 * fix(developer): remove empty touch rows on save (#5720) * chore(common): Check in crowdin strings for Shuwa Latin (#5734) * chore(windows): fix broken links in help (#5765) ## 15.0.120 alpha 2021-09-28 * fix: help.keyman.com script file cleanup (#5751) * chore(common): Enhance cherry-pick labeling (#5759) ## 15.0.119 alpha 2021-09-24 * chore(common): support forked repos when triggering test builds (#5738) ## 15.0.118 alpha 2021-09-23 * chore(deps): bump ansi-regex from 5.0.0 to 5.0.1 in /resources/build/version (#5741) * refactor(web): active element management in relation to OSK display control ️ (#5644) * refactor(web): osk activation and visibility modeling ️ (#5661) * chore(android/app): Remove runConfigruations.xml file (#5743) * feat(web): new OSK type - the inlined OSK (#5665) * chore(web): inline osk test page (#5728) * feat(web): enables mouse interactivity for the predictive banner (#5739) * fix(mac): add support for M1 processor (#5701) ## 15.0.117 alpha 2021-09-22 * fix(developer): run kmlmc from Keyman source path (#5727) ## 15.0.116 alpha 2021-09-21 * fix(common/core): insure list pntr is incremented (#5669) * chore(common): Check in crowdin strings for Simplified Chinese (#5681) * fix(web): Null check for calculating globe key position (#5724) ## 15.0.115 alpha 2021-09-20 * chore(common/core): cleanup version headers (#5719) * refactor(web): OSK modularization - specialized OSKView classes ️ (#5633) * feat(developer): track changes to option values better in debugger (#5696) * fix(developer): support chiral modifiers in debugger (#5697) ## 15.0.114 alpha 2021-09-17 * feat(developer): Debugger platform option (#5640) * feat(developer): Debugger keyboard options (#5647) * fix(developer): add version info to Core (#5711) * fix(common/core/web): layer reset on physical keystroke after OSK interaction (#5641) * fix(ios): prevents installation of packages without JS (#5698) ## 15.0.113 alpha 2021-09-16 * fix(ios): version-tagging for errors logged from the system keyboard (#5693) * fix(web): spacebar caption when functional layer differs from display layer (#5688) * refactor(web): OSK modularization - view components, layout cleanup ️ (#5619) * refactor(web): OSK modularization - common-path code -> OSKView ️ (#5620) * fix(common/core/web): Remove empty rows in OSK (#5699) ## 15.0.112 alpha 2021-09-14 * chore(common): Update to Unicode 14.0 (#5686) * chore(common): Add GitHub action to upload sources to crowdin (#5687) * fix(windows): fallback to filename if `&name` not set (#5684) ## 15.0.111 alpha 2021-09-13 * fix(developer): include Keyman Core in Keyman Developer (#5649) * fix(developer): ensure file modified after import from layout (#5676) * chore(android/engine): Fix dictionary selector and back arrow styling (#5667) * fix(web,android/app): Select numeric layer when entering a numeric field (#5664) ## 15.0.110 alpha 2021-09-10 * fix(android/engine): Fix localization on Android M (#5670) ## 15.0.109 alpha 2021-09-06 * fix(android/engine): Fix backspace on Android 5.0 (#5660) ## 15.0.108 alpha 2021-09-01 * fix(linux): Use first keyboard language if none given (#5655) ## 15.0.107 alpha 2021-08-31 * fix(linux): Fix launch of km-config (#5631) ## 15.0.106 alpha 2021-08-30 * fix(linux): Remove Linux workspace (#5654) ## 15.0.105 alpha 2021-08-27 * feat(android/app): Add navigation buttons to Info Activity (#5622) * fix(android): Fix Chrome version ranges for Keyman engine functionality (#5629) ## 15.0.104 alpha 2021-08-26 * chore(linux): Update changelog files (#5637) * fix(web): Check keyboard before marking layout calibrated (#5630) ## 15.0.103 alpha 2021-08-25 * chore(linux): Improve debian package script (#5626) * chore(linux): Fix uploading to Sentry (#5623) ## 15.0.102 alpha 2021-08-24 * fix(android/engine): UX improvement when 1 keyboard installed (#5570) * chore(windows): sentrytool param file support (#4172) * fix(developer): F6 in debugger and cef focus (#5597) * chore(common): add report-history.sh (#5527) * chore(common): more on report-history (#5603) * chore: fixup HISTORY.md (#5604) * chore(android/app): Add in-app help for adjusting keyboard height (#5621) ## 15.0.101 alpha 2021-08-23 * refactor(web): overhaul of OSK key layout calcs + styling, merges desktop & touch logic (#5462) * fix(android): keyboard's black bar bug (#5521) * refactor(web): prep work for mouse-based use of touch events (#5506) * refactor(web): mouse-based use of touch handlers (#5530) ## 15.0.100 alpha 2021-08-22 * fix(linux): Fix uploading to launchpad for legacy projects (#5612) ## 15.0.99 alpha 2021-08-21 * feat(android/app): Add menu to adjust keyboard height (#5606) ## 15.0.98 alpha 2021-08-20 * fix(windows): Ignore Access Denied error creating task (#4365) * fix(web): Have util.wait check useAlerts option (#5538) * fix(developer): debugger cleanup (#5588) * chore(developer): debug deadkey 1-based values (#5592) * chore(developer): refactor forcekeyboard in debug (#5593) * fix(developer): get Test Mode working again (#5594) * chore(developer): hide debug events panel (#5595) * fix(common/core/web): behavior with unmatched final group (#5553) * fix(ios): iOS 13 and 14 only - stuck settings toggles (#5548) * fix(linux): Fix lost context after pressing K_SHIFT (#5601) ## 15.0.97 alpha 2021-08-19 * fix(linux): Fix uploading to launchpad (#5607) ## 15.0.96 alpha 2021-08-19 * docs(linux): Fix readme for ibus-keyman (#5565) * chore(common/core): Add uninstall option to build script (#5564) * feat(web): setup build artifacts for manual tests (#5582) * feat(ios): adds option for Simulator-compatible testing artifact (#5557) * refactor(web): OSK layout hierarchy encapsulation (#5451) * refactor(web): reworks VisualKeyboard layout spec design (#5459) * refactor(web): overhaul of OSK key layout calcs + styling, merges desktop & touch logic (#5462) * fix(android): keyboard's black bar bug (#5521) * fix(android): removes duplicated line (#5587) * fix(linux): Check for valid kmp file (#5583) * fix(linux): Handle corrupt icon file (#5585) * fix(windows): handle restoring modal dialogs consistently (#5586) * chore(android): Remove runConfigurations.xml files (#5572) * fix(windows): Welcome should always show in front (#4657) ## 15.0.95 alpha 2021-08-06 * fix(windows): wrap text in keyboard installation dialog (#5559) * fix(windows): tsysinfo format grid correctly (#5556) * feat(android): Add API for checking Chrome version (#5520) * fix(android/app): Fix cleanup when progress dialog cancelled (#5541) * fix(common/core/desktop): split smp for context chars (#5562) * feat(developer): debugger uses Keyman Core (#5513) * fix(common/models): keep/suggestion diacritic sensitivity when de-duping (#5480) * fix(web): Blank spacebar text when displayName is empty string (#5555) * chore(linux): Consolidate Debian source packages (#5536) * chore(common/core): Linux side of caps-lock stores (#5497) ## 15.0.94 alpha 2021-08-05 * chore(ios,windows): Update crowdin strings for Azerbaijani (#5486) * chore(android): Update sentry-android-gradle-plugin to 2.1.0 (#5546) * fix(web): Have util.wait check useAlerts option (#5538) * fix(android): gracefully handle errors in KMW keyboards (#5423) * chore(linux): Remove compiler warning in ibus-keyman (#5549) ## 15.0.93 alpha 2021-08-04 * fix(linux): Improve uninstallation (#5505) * refactor(linux): Reformat keycode_to_vk table (#5508) * refactor(linux): Cleanup import of os.path (#5529) * chore(common/core): Allow shell script for kmcomp (#5498) * refactor(common/core): Move comment to where it belongs (#5518) ## 15.0.92 alpha 2021-08-03 * fix(android/app): Check Play Store release notes less than 500 chars (#5535) ## 15.0.91 alpha 2021-08-02 * chore(common): stable history update (#5515) * chore(android): log fontpath error (#5516) * chore(windows): fixup cef interfaces for CEF 90 (#5514) * chore(common/core): refactor backspace handling (#5512) * chore(windows): split keyman64 header to keymanengine (#5522) * fix(ios/engine): engine migration always precedes installs (#5484) * chore(common): Add C++ formatting rules (#5523) * fix(developer): compiler use and match behavior for Web should be same as Core (#5525) * fix(web): stuck key highlighting from touchpoint movement (#5490) ## 15.0.90 alpha 2021-07-28 * chore(windows): patches for Delphi 10.4 (#5496) * chore(common/core): additional debug tests (#5482) * chore(android): Update globe key help and whatsnew (#5495) * chore(common/core): handle deletion of markers in actions (#5489) * chore(linux): Remove Groovy and Impish builds (#5502) ## 15.0.89 alpha 2021-07-27 * feat(web): Update addKeyboards to return Promise (#5389) * fix(common/core/web): error from early fat-finger termination due to OS interruptions (#5479) * fix(common/core/web): OSK state-key management (#5456) * feat(android/engine): Improve globe key experience (#5437) ## 15.0.88 alpha 2021-07-23 * feat(common/core): debug action index (#5470) * refactor(web): osk inner-frame abstraction (help text vs std OSK) (#5430) * refactor(web): delayed OSK initialization (#5412) * chore(common/core): Implement capsAlwaysOff system store (#5432) ## 15.0.87 alpha 2021-07-22 * fix(ios): keyboard swapping (#5475) * refactor(linux): Refactor processing actions in separate methods (#5452) ## 15.0.86 alpha 2021-07-20 * chore(android): improve error reporting for kmw (#5468) ## 15.0.85 alpha 2021-07-19 * feat(common/core/desktop): kmx debugger basic infrastructure (#5425) * feat(common/core/desktop): add debug events (#5448) * chore(developer): fixup devtime paths (#5449) * refactor(web): partial encapsulation of the desktop title bar and resize bar (#5393) * refactor(web): osk move & resize handler encapsulation (#5409) ## 15.0.84 alpha 2021-07-09 * fix(web): Copy the keyboard stubs for registration (#5438) * fix(android/engine): register lexical model in switchToNextKeyboard (#5439) ## 15.0.83 alpha 2021-07-08 * chore(windows): remove backup build step (#5434) * refactor(common/core/desktop): Fix file and class names (#5445) * refactor(web): longpresses, groundwork for additional gestures (#5387) * fix(android/engine): Display dictionary help link (#5427) * refactor(common/core/desktop): Rename Load method (#5444) ## 15.0.82 alpha 2021-07-07 * fix(common/models/types): fixes test script config (#5441) ## 15.0.81 alpha 2021-07-06 * fix(android/engine): Fix font file path (#5424) * chore(common): npm audit fixes (#5419) * chore(web): updates regression test-deps to same versions as web (#5420) * chore(windows): make build paths consistent (#5405) ## 15.0.80 alpha 2021-07-02 * feat(web): spacebar text controls (#5348) * feat(android): Spacebar text controls (#5349) * feat(ios): add spacebar text controls (#5365) * fix(linux): Don't crash with corrupt keyboard (#5414) ## 15.0.79 alpha 2021-07-01 * docs: start consolidation of build config docs (#5324) * fix(developer): builder and editor commands were ignored (#5391) * chore(developer): remove obsolete InitClasses (#5403) * change(web): fat-finger-performance unit-test threshold (#5404) * fix(linux): Fix auto-generated help (#5399) * fix(linux): Improve bitmap conversion (#5401) ## 15.0.78 alpha 2021-06-30 * fix(web): console errors when using SHIFT w help-text 'osk' (#5392) ## 15.0.77 alpha 2021-06-29 * fix(windows): #5336 appcontext get to handle small buffer (#5383) * fix(common): get handle caller buffer size small than internal Fixes … (#5390) ## 15.0.76 alpha 2021-06-28 * chore(android): Add help on Settings option to change spacebar caption (#5375) * feat(android): hide textarea for perf (#5376) * chore: keyboard_info.source.json 1.0.6 (#5379) * refactor(android): setKeyboard and setKeymanLanguage (#5338) * feat(web): Merge keyboard stub with error stub (#5340) * feat(linux): Add reference index page (#5370) * fix(linux): Fix restarting ibus when running with sudo (#5371) * refactor(linux): Centralize paths (#5372) * fix(linux): Save QR code in temporary directory (#5373) ## 15.0.75 alpha 2021-06-25 * fix(windows): osk scaling mismatch on horz axis (#5341) * fix(linux): Don't add duplicate entries when reinstalling keyboard (#5363) * fix(linux): fix tab completion for command line tools (#5362) * feat(web): Update addLanguageKeyboards to return a Promise (#5260) * feat(web): Add option useAlerts to control alerts() (#5302) ## 15.0.74 alpha 2021-06-24 * fix(android): fixes application of nextlayer for subkeys with customized layer setting (#5350) * feat(common/core/web): engine correction-prep optimizations (#5319) * feat(linux): Add support for impish (Ubuntu 21.10) (#5334) * fix(linux): Add libglib2.0-bin to keyman Depends (#5360) ## 15.0.73 alpha 2021-06-23 * chore(windows): add engine test framework (#5337) * feat(linux): Auto-generate reference help (#5326) * fix(linux): Improve error handling if `lang_tags_map.py` is missing (#5345) ## 15.0.72 alpha 2021-06-22 * fix(mac): .kmx max file version is now 0x0E00 (14.0) (#5329) * fix(mac): kmp.inf is windows-1252 (#5328) * fix(windows): restore endpoints for interface stability (#5254) * chore(linux): Build also on riscv64 to facilitate migration on Ubuntu (#5323) * refactor(web): OSK key source-code reorganization (#5291) * refactor(web): osk key highlighting/preview behavior (#5292) * change(ios): setText now uses JSON serialization (#5321) ## 15.0.71 alpha 2021-06-18 * feat(common): keyboard_processor wasm build (#5233) * chore(linux): Update changelogs to match Debian (#5304) ## 15.0.70 alpha 2021-06-17 * fix(web): touch-move cancellation (#5290) * fix(developer): kmconvert help match reality (#5298) ## 15.0.69 alpha 2021-06-16 * refactor(web): OSK layout calculations - simplification (#5279) * refactor(web): VisualKeyboard - key event model (#5280) * refactor(web): OSK keytip abstraction (#5287) * refactor(web): encapsulation of browser-based subkey array popup (#5288) * chore(common): bash version for run-required-test-builds.sh (#5267) * fix(linux): Adjust version of dependency for ibus-keyman (#5281) ## 15.0.68 alpha 2021-06-15 * chore(common): Add YouTube links to Keyman 14 features (#5276) * chore(common): Check in crowdin strings for Spanish (Latin America) (#5269) * refactor(web): polishes management of OSK keys (#5257) * refactor(web): Visual Keyboard disentanglement - pass 1 (#5259) * refactor(web): VisualKeyboard height styling consistency (#5278) * fix(common/models): predictive-text engine use of NFD input (#5273) * chore(linux): Fix warnings (#5282) ## 15.0.67 alpha 2021-06-11 * feat(linux): Fix Linux packaging on i386 (#5250) ## 15.0.66 alpha 2021-06-11 * feat(android): silent install for referred kbd (#5240) * fix(android): rotation is not updating keyboard (#5247) ## 15.0.65 alpha 2021-06-10 * docs(ios): minor readme tweak regarding prerequisites (#5253) * fix(common/core/web): optimizes transform construction (#5248) ## 15.0.64 alpha 2021-06-09 * feat(android): Automatically install keyboard through Play Store (#5230) * fix(oem/fv/ios): app encryption flag for app store uploads (15.0) (#5244) * refactor(common/core/web, web): target-agnostic key events (#5181) * fix(linux): Fix packaging on ppa (#5249) ## 15.0.63 alpha 2021-06-08 * feat(common): Rust infrastructure (#5162) * fix(web): Always pass kill_browserstack (#5234) * chore(common): iis setup script for dev boxes (#5206) * fix(windows): support Esc key in Download Keyboard dialog (#5207) * fix(android/engine): Adjust default OSK landscape size (#5201) ## 15.0.62 alpha 2021-06-04 * fix(developer): support spaces in regression tests (#5217) ## 15.0.61 alpha 2021-06-03 * fix(linux): Exclude s390x from package builds for ibus-keyman (#5213) * feat(linux): Integrate with fcitx5 (#5215) ## 15.0.60 alpha 2021-06-01 * fix(windows): sentry.dll version handling (#5187) * fix(windows): start keymanx64 with ShellExecute (#5202) * fix(windows): fix size of splash (#5203) ## 15.0.59 alpha 2021-05-31 * fix(common): build script help param (#5175) * feat(ios): resource file validation before use (#5178) * fix(linux): Migrate from /usr/lib/ibus to /usr/libexec (#5183) * fix(linux): Don't crash on invalid metadata (#5185) * fix(android/samples): Set gradlew executable for Tests (#5198) * fix(windows): avoid cached hotkey state (#5190) * chore(windows): minor maintenance (#5192) * fix(common/core/desktop): Fix failing tests on armhf (#5169) ## 15.0.58 alpha 2021-05-28 * chore(android): Add -clean flag to build script (#5145) * feat(web): Add script to deploy KeymanWeb release to s.keyman.com (#5150) * feat(ios): partial conversion of internal logs to use of Sentry (#5153) * change(ios): workspace reorganization + cleanup (#5167) * fix(linux): Fix Makefile and instructions for building (#5170) ## 15.0.57 alpha 2021-05-28 * chore(ios): dependencies - update sentry-cocoa to 6.2.1 (#5120) * change(ios): minimum iOS version -> 12.1 (#5168) * chore(ios): renames problematic app selectors (#5173) ## 15.0.56 alpha 2021-05-27 * fix(ios): link, but NOT embed KeymanEngine.xcframework in app exs (#5164) * feat(common): offline help css (#5157) * change(ios): help always offline (#5158) ## 15.0.55 alpha 2021-05-27 * fix(ios): artifact upload preparation (#5160) ## 15.0.54 alpha 2021-05-26 * chore(windows): Update Sentry to 0.4.9 (#5144) * chore(web): Add CI script to kill BrowserStack tunnel (#5136) * docs(linux): Update readme (#5147) * chore(linux): Update changelogs (#5146) * fix(ios): re-enable SKIP_INSTALL (#5155) ## 15.0.53 alpha 2021-05-25 * feat(android/app): Auto-generate Play Store release notes (#5132) * fix(web): active element selection in multi-touch scenarios (#5134) * chore(windows): cleanup old .dof, .bdsproj and .cfg files (#5131) * chore(ios): shift to use of XCFrameworks (#5107) * chore(ios): imports iOS artifact-upload script for CI use (#5140) * refactor(ios/engine): "should reload keyboard" now a property of the keyboard (#4847) * docs(windows): Initial commit - README.md (#5119) * chore(windows): move to vc++ 2019 (#5143) ## 15.0.52 alpha 2021-05-24 * chore(windows): Chromium 89.0.18 (#5128) * chore(android/samples,oem/fv/android) Update dependencies (#5127) * feat(web): basic promise wrapper on cloud api call (#5121) ## 15.0.51 alpha 2021-05-21 * chore(windows): reorganise tests (#5084) * feat(developer): Add 'full copyright' field to templates (#5085) * fix(developer): TframeTextEditor.SetText was not synchronous (#5096) * chore(android): Update Gradle and other dependencies (#5098) * chore(web): add test page for playing with CKEditor (#5089) * chore(ios): update fv cert ref (#5123) * chore(mac): Add help links for installing Keyman and keyboards (#5108) * chore(android): Update targetSDKVersion to 30 (#5126) ## 15.0.50 alpha 2021-05-20 * chore(common): Check in crowdin strings for Amharic (#5102) * chore(common): resolve audit issues in Web-related repo NPM packages (#5092) * refactor(linux): Refactor `install_kmp.py` (#4932) * chore(linux): Swap order of dependency (#5113) * chore(linux): Remove unnecessary dependency on kmflcomp (#5115) ## 15.0.49 alpha 2021-05-19 * refactor(linux): Remove obsolete SCIM kmfl imengine (#5093) * fix(common/core/desktop): Fix warnings when compiling for armhf (#5099) * fix(common/core/desktop): Don't segfault on invalid .kmx file (#5101) ## 15.0.48 alpha 2021-05-17 * chore(common): Update stable history for 14.0.274 (#5087) * fix(web): position popups correctly in landscape mode on Android and during Chrome emulation (#5075) ## 15.0.47 alpha 2021-05-14 * fix(developer): kmconvert commandline and deploy (#5082) ## 15.0.46 alpha 2021-05-13 * chore(windows): remove unused keymanx64 parameter (#5062) * fix(android/engine): Check lexical-model file exists before using (#5071) * chore(web/resources): bump lodash from 4.17.19 to 4.17.21 in /web/testing/regression-tests (#5037) ## 15.0.45 alpha 2021-05-12 * fix(windows): refactor controller windows (#5060) * chore(windows): remove KMC_CHANGEUISTATE (#5061) * fix(linux): Swap order of dependencies for Debian package (#5064) * fix(linux): Fix Caps Lock (#5054) ## 15.0.44 alpha 2021-05-11 * chore(windows): FixupMissingFile needed current component code (#5057) * chore(windows): remove unused utilrun unit (#5056) * fix(developer): two small issues in kmdecomp (#5031) * fix(common/core): Add values for Caps and Nocaps modifiers (#5053) ## 15.0.43 alpha 2021-05-10 * chore(mac): update requirements to include Big Sur (#5030) * feat(android/app): Add telemetry for launching WebBrowserActivity (#5046) * chore(android/app): Always use offline help (#5047) * fix(windows): avoid disabling Keyman when speech recognition starts (#5000) * chore(windows): add telemetry to trace crash on exit (#5007) * fix(windows): make keymanx64 responsible for its own lifecycle (#5002) ## 15.0.42 alpha 2021-05-07 * chore(common): Check in crowdin files for Azerbaijani (#4992) ## 15.0.41 alpha 2021-05-06 * chore(linux): Add support for Ubuntu 21.04 (hirsute) (#5033) ## 15.0.40 alpha 2021-05-02 * chore(common): update stable history for 14.0.273 (#5003) ## 15.0.39 alpha 2021-04-30 * chore: support for xcode 12 (#4995) ## 15.0.38 alpha 2021-04-29 * fix(android/engine): Fix toHex() for null string (#4991) ## 15.0.37 alpha 2021-04-28 * fix(windows): handle errors starting keymanx64 (#4989) ## 15.0.36 alpha 2021-04-26 * docs(ios): tweaks prereqs in readme (#4977) * fix(linux): Fix crash with incomplete metadata (#4908) (#4971) * chore(android/engine): Don't use localized string for Sentry errors (#4978) * fix(web): Make banner initialization more robust (#4961) * chore: disable findTouchAliasElement logging (#4981) * chore(common): update stable history for 14.0.272 (#4975) * chore: Add cherry-pick label for cherry-pick PRs (#4973) ## 15.0.35 alpha 2021-04-23 * chore(ios): prep for CI transition to Xcode 12, build script tweak (#4967) * chore(linux): Fix triggering of Jenkins builds for stable branch (#4969) * fix(linux): Don't crash if kmp file vanishes (fixes #4907) (#4970) ## 15.0.34 alpha 2021-04-22 * No changes made ## 15.0.33 alpha 2021-04-22 * fix(oem/fv/android): Migrate keyboard list from 12.0 to 14.0 (#4951) * fix(web): publish restorePosition() function (#4946) * fix(web): fixes subkey lookup for fat-finger processing (#4954) * feat(linux): Improve Sentry crash reporting (#4914) * fix(web, ios): better SMP, emoji handling with frequent keyboard swaps (#4938) ## 15.0.32 alpha 2021-04-21 * fix(windows): handle invalid package names during install (#4887) * fix(windows): crash when installing TIP in some rare situations (#4890) * chore(windows): disable profile repair (#4899) * fix(windows): access violation closing text editor (#4920) * fix(windows): help contents broken from tray menu (#4922) * fix(developer): avoid crash if .kpj.user file is malformed (#4918) * fix(developer): chiral mismatch warning is disruptive (#4934) * fix(windows): avoid error if keyman32.dll renamed (#4940) * change(web): adds error + console logs usable for Sentry reporting targeting #4797 (#4821) ## 15.0.31 alpha 2021-04-20 * fix(android/engine): Don't load woff fonts on Android N (#4905) * fix(android/engine): Change getList() to return an empty list instead of null (#4926) * fix(android/engine): Don't set lexical model list to null (#4927) * fix(linux): don't crash on legacy non-Unicode files (#4906) * fix(linux): Don't crash on network problem (fixes #4911) (#4912) * chore(linux): Remove experimental scripts (#4913) ## 15.0.30 alpha 2021-04-19 * chore(android/engine): Rename "Pulaar" to "Pulaar-Fulfulde" (#4865) * fix(developer): Reduce non-canonical BCP 47 tag warning in PackageInfo to "Info" (#4863) * chore(common): Update crowdin for French (#4895) * chore(android,windows): Check in crowdin for Indonesian (#4829) ## 15.0.29 alpha 2021-04-05 * chore(android/engine): Rename "Fula" to "Pulaar" (#4859) ## 15.0.28 alpha 2021-04-02 * fix(linux): Fix crash if `.json` doesn't contain description (#4851) ## 15.0.27 alpha 2021-04-01 * docs(android): Update installing-keyboards.md (#4837) * chore(deps): bump y18n from 4.0.0 to 4.0.1 in /web/testing/regression-tests (#4817) * fix(android): ensure keyboard is always set after pageLoaded (#4840) * chore(deps): bump y18n from 4.0.0 to 4.0.1 in /resources/build/version (#4818) * fix(developer): buffer size for range expansions (#4831) * chore(common): Check in crowdin for Fulah (#4846) * docs(android): Update image for enabling-system-keyboards (#4844) * chore: history from 14.0.271 (#4849) ## 15.0.26 alpha 2021-03-31 * fix(android/engine): Add KMString wrapper for formatting Strings (#4813) ## 15.0.25 alpha 2021-03-30 * fix(developer): requote font names (#4814) ## 15.0.24 alpha 2021-03-29 * fix(ios): ensures JS keyboard set after page load (#4808) * fix(developer): open containing folder was not opening correct folder (#4776) * fix(linux): Fix crash if query doesn't contain bcp47 tag (#4800) (#4811) ## 15.0.23 alpha 2021-03-26 * fix(ios): fixes sys-kbd setup help link for iOS 9 and 10 (#4774) * fix(android): Fix NullPointerException in package installation (#4790) ## 15.0.22 alpha 2021-03-25 * fix(ios/samples): samples should use package-oriented API (#4771) * fix(android/engine): Sanitize embedded KMW Sentry error (#4782) ## 15.0.21 alpha 2021-03-23 * chore: beta to alpha A15S1 (#4759) ## 15.0.20 alpha 2021-03-22 * chore: B14S8 beta to alpha (#4739) * chore: merge beta to master (A15S1) (#4745) ## 15.0.19 alpha 2021-03-09 * chore: beta to alpha merge, B14S7 (#4624) ## 15.0.18 alpha 2021-02-25 * fix(linux): Set help-keyman.com.sh executable (#4530) ## 15.0.17 alpha 2021-02-22 * chore: merge B14S6 beta to alpha (#4503) ## 15.0.16 alpha 2021-02-11 * chore: B14S6 beta to master merge (#4473) * chore: manual version increment (#4478) ## 15.0.15 alpha 2021-02-11 * chore: merge B14S5 beta to master (#4432) ## 15.0.14 alpha 2021-02-02 * docs(linux): Improve packaging doc (#4389) ## 15.0.13 alpha 2021-02-01 * chore(linux): Don't report on Sentry when running unit tests (#4374) * chore(linux): Pass second tag parameter to Jenkins build (#4376) ## 15.0.12 alpha 2021-01-28 * chore(linux): Improve launchpad.sh script (#4355) ## 15.0.11 alpha 2021-01-27 * chore: Enhance PR labeling based on PR title (#4226) ## 15.0.10 alpha 2021-01-27 * fix(ios): renew distribution certificate (#4342) ## 15.0.9 alpha 2021-01-25 * chore(windows): help for 14.0, part 1 (#4109) * chore: merge B14S4 beta to master (#4320) ## 15.0.8 alpha 2021-01-18 * chore(linux): Allow to push to the `keyman-beta` ppa (#4271) ## 15.0.7 alpha 2021-01-12 * chore(linux): Update debian metadata (#4223) ## 15.0.6 alpha 2021-01-07 * fix(linux): only pass tag if we just created one (#4220) ## 15.0.5 alpha 2021-01-05 * chore(linux): pass tag to Jenkins build (#4160) (#4215) ## 15.0.4 alpha 2020-12-23 * feat(common/models): naive backspace workaround, naive multi-char Transform mitigation (#4206) * fix(web): supplies missing (optional) argument to prevent warnings (#4208) * fix(ios): moves Settings notification UI code to main thread (#4210) ## 15.0.3 alpha 2020-12-21 * fix(web): Solving kmwosk color inconsistency (#4154) ## 15.0.2 alpha 2020-12-16 * fix(common): increment version needs to check base (#4156) ## 15.0.1 alpha 2020-12-14 * chore: prepare 15.0 alpha (#4129) ## 14.0.292 stable 2022-05-24 * fix(windows): sentry debuglogging for DoInstall (#6648) ## 14.0.291 stable 2022-05-07 * fix(windows): don't log before checking nil when installing keyboard (#6506) * fix(windows): put correct HK_ALT flag for modifier (#6587) ## 14.0.290 stable 2022-03-31 * chore(oem/fv/android): Update dependencies (#6452) ## 14.0.289 stable 2022-03-30 * chore(linux): Remove versions that are no longer supported (#6388) * chore(windows): move crash metadata to extra (#6398) * fix(android/engine): Test fileVersion during package install (#6423) * fix(mac): invalid keyboard breaks configuration (#6420) * chore(android): Update Play publishing plugin to 3.5.0 and other plugins (#6224) * fix(web): track load error detail (#6443) ## 14.0.288 stable 2022-03-15 * chore(linux): Update changelogs for 14.0.287 (#6373) ## 14.0.287 stable 2022-03-04 * chore(ios): certificate update (#6210) * fix(windows): create Keyman/Diag folder in redirected profile (#6222) * fix(web): stop masking error (#6332) ## 14.0.286 stable 2022-01-27 * chore(linux): Update changelogs for 14.0.284 (#6131) * chore(linux): Revert workaround for Python bug (#6134) * fix: only auto-merge if `auto:` prefix in title (#6148) * fix(developer): work around devDependencies bug in npm (#6142) * chore(ios): certificate update (#6166) * fix(mac): Check for CODE_SETSYSTEMSTORE (#6170) ## 14.0.285 stable 2022-01-20 * fix(linux): Fix lintian errors :cherries: (#6107) * fix(linux): Add workaround for Python bug :cherries: (#6125) * fix(web): Use regex to determine display layer and functional layers (#6123) ## 14.0.284 stable 2022-01-11 * chore(android,oem/fv/android): Update targetSDKVersion to 30 (#5934) * fix(web): popupBaseKey null check (#5948) * fix(linux): Add test targets to Makefile (#5975) * fix(android/engine): Fix font paths (#5990) * chore(linux): Remove lintian warning (#5993) * chore(linux): Allow to specify debian revision (#5998) * chore(linux): Update changelogs for 14.0.283 :package: (#6007) * fix(linux): fix release version number for Sentry reporting :cherries: (#6053) * chore(common): Check in crowdin strings for Spanish (Latin America) (#6060) * fix(linux): fix release version number for Sentry reporting :cherries: (#6069) * chore(android/samples): Add -no-daemon flag to KMSample2 build script (#6083) * fix(linux): Fix attribute error :cherries: (#6087) ## 14.0.283 stable 2021-11-17 * chore(windows): fix broken links in help (#5766) * chore(linux): copy Keyman for Linux 15 reference to 14 (#5764) * fix(linux): Fix debian package script (#5772) * chore(common): Enhance cherry-pick labeling (#5773) * fix(common): Fix cherry-pick labeling (:cherries:) (#5783) * fix(linux): Don't crash displaying keyboard details (#5757) * chore(linux): Update changelog files for 14.0.282 (#5793) * fix(linux): Don't crash with non-keyboard package file (#5754) * chore: sentry.io dsn ‍ ️ (#5788) * fix(windows): handle edge cases using default language (#5775) * fix(ios): move sentry settings responsibility to build agent ‍ ️ (#5806) * fix(web): remove canvas use for iOS compatibility (#5916) ## 14.0.282 stable 2021-09-27 * fix(mac): add support for M1 processor (#5737) * chore(mac): Add help links for installing Keyman and keyboards (#5748) * fix: help.keyman.com script file cleanup (#5750) ## 14.0.281 stable 2021-09-17 * fix(common/models): keep/suggestion diacritic sensitivity when de-duping (#5552) * feat(ios): adds option for Simulator-compatible testing artifact (#5569) * chore(ios,windows): Update crowdin strings for Azerbaijani (#5487) * fix(oem/fv/ios): build configuration for 14.0's test-oriented simulator artifact (#5596) * fix(linux): Handle corrupt icon file (#5589) * fix(linux): Check for valid kmp file (#5590) * chore: fixup stable HISTORY.md (#5605) * chore(linux): Improve debian package script (#5624) * chore(linux): Fix uploading to Sentry (#5625) * chore(linux): Update changelog files (#5636) * fix(ios): iOS 13 and 14 only - stuck settings toggles (#5611) * fix(web): Fix layers for embedded longpress keys (#5651) * fix(linux): Use first keyboard language if none given (#5657) * fix(android/engine): Fix backspace on Android 5.0 (#5674) * chore(common): report-history (#5678) * fix(developer): ensure file modified after import from layout (#5677) * test(windows): investigate TIP crash (#5679) * fix(common/core/web): Remove empty rows in OSK (#5703) * fix(windows): fallback to filename if `&name` not set (#5685) ## 14.0.280 stable 2021-08-02 * fix(android): displayName for keyboard was not optional (#5492) * chore(linux): Remove Groovy builds (#5503) * chore(linux): Fix dependency versions (#5504) * fix(common/core/web): error from early fat-finger termination due to OS interruptions (#5491) * chore(android): log fontpath error (#5517) * fix(ios/engine): engine migration always precedes installs (#5501) * fix(common/core/web): OSK state-key management (#5494) * fix(linux): fix crash trying to display QR code (#5528) * fix(android): avoid error with empty font data (#5534) ## 14.0.279 stable 2021-07-22 * fix(ios): keyboard swapping (#5476) ## 14.0.278 stable 2021-07-20 * change(common/core/web): fat-finger-performance unit-test threshold (#5417) * fix(linux): Improve bitmap conversion (#5410) * fix(linux): Save QR code in temporary directory (#5411) * fix(linux): Fix restarting ibus when running with `sudo` (#5413) * fix(linux): Don't crash with corrupt keyboard (#5421) * fix(web): fixes osk resize-popping effect (#5428) * fix(android/engine): register lexical model in switchToNextKeyboard (#5447) * feat(web): spacebar text controls (#5406) * feat(android): Spacebar text controls (#5407) * feat(ios): add spacebar text controls (#5408) * chore(android): improve error reporting for kmw (#5469) ## 14.0.277 stable 2021-06-29 * chore(common): bash version for run-required-test-builds.sh (#5268) * chore(common): Add YouTube links to Keyman 14 features (#5285) * fix(common/models): predictive-text engine use of NFD input (#5286) * fix(developer): kmconvert help match reality (#5299) * chore(linux): Update changelogs to match Debian (#5303) * fix(mac): .kmx max file version is now 0x0E00 (14.0) (#5331) * fix(mac): kmp.inf is windows-1252 (#5330) * fix(windows): improve keymanx64 start stability (#5222) * chore(linux): Build also on riscv64 to facilitate migration on Ubuntu (#5322) * fix(android): fixes application of nextlayer for subkeys with customized layer setting (#5351) * feat(common/core/web): engine correction-prep optimizations (#5352) * fix(linux): Add libglib2.0-bin to keyman Depends (#5359) * fix(windows): osk scaling mismatch on horz axis (#5342) * fix(linux): Don't add duplicate entries when reinstalling keyboard (#5369) * chore: keyboard_info.source.json 1.0.6 (#5380) * feat(android): hide textarea for perf (#5377) * change(ios): setText now uses JSON serialization (#5333) ## 14.0.276 stable 2021-06-11 * fix(linux): Exclude s390x from package builds for ibus-keyman (#5220) * fix(web): Always pass kill_browserstack (#5235) * feat(android): Automatically install keyboard through Play Store (#5231) * fix(oem/fv/ios): app encryption flag for app store uploads (14.0) (#5243) * fix(common/core/web): optimizes transform construction (#5255) * fix(android): rotation is not updating keyboard (#5262) * feat(android): silent install for referred kbd (#5266) * fix(windows): disable new hotkey modifier check (#5270) ## 14.0.275 stable 2021-06-04 * fix(linux): Swap order of dependencies for Debian package (#5070) * fix(android/engine): Check lexical-model file exists before using (#5080) * fix(developer): kmconvert commandline and deploy (#5083) * fix(web): position popups correctly in landscape mode on Android and during Chrome emulation (#5090) * fix(common/core/desktop): Fix warnings when compiling for armhf (#5109) * fix(common/core/desktop): Don't segfault on invalid .kmx file (#5110) * chore(common): Check in crowdin strings for Amharic (#5117) * chore(linux): Swap order of dependency (#5114) * fix(developer): TframeTextEditor.SetText was not synchronous (#5097) * chore(ios): update fv cert ref (#5124) * chore(ios): works around wrong-workspace Carthage 0.38 lookup issue (#5135) * fix(web): multi touch handling (#5142) * chore(ios): artifact prep script now in-repo (#5141) * chore(web): Add CI script to kill BrowserStack tunnel (#5152) * fix(ios): artifact upload preparation (#5161) * chore(android): Add -clean flag to build script (#5177) * fix(windows): avoid cached hotkey state (#5189) * fix(android/samples): Set gradlew executable for Tests (#5199) * fix(common/core/desktop): Fix failing tests on armhf (#5204) * feat(web): Add script to deploy KeymanWeb release to s.keyman.com (#5179) * chore(ios): renames problematic app selectors (#5174) * fix(developer): support spaces in regression tests (#5218) ## 14.0.274 stable 2021-05-11 * fix(android/engine): Fix toHex() for null string (#4997) * chore: support for xcode 12 (#4996) * chore(linux): Add support for Ubuntu 21.04 (hirsute) (#5035) * chore(ios): prep for CI transition to Xcode 12, build script tweak (#5048) * chore(windows): add telemetry to trace crash on exit (#5008) * fix(windows): avoid disabling Keyman when speech recognition starts (#5038) * chore(android/app): Always use offline help (#5051) * chore(common): Check in crowdin files for Azerbaijani (#5039) * feat(android/app): Add telemetry for launching WebBrowserActivity (#5050) * fix(linux): Enable caps lock support (#5058) ## 14.0.273 stable 2021-04-26 * chore(linux): Fix triggering of Jenkins builds for stable branch (#4968) * fix(linux): Don't crash if kmp file vanishes (fixes #4907) (#4972) * fix(linux): Fix crash with incomplete metadata (#4908) (#4979) * chore(android/engine): Don't use localized string for Sentry errors (#4980) * chore: disable findTouchAliasElement logging (#4982) * fix(web): Make banner initialization more robust (#4983) * chore: Add cherry-pick label for cherry-pick PRs (#4984) ## 14.0.272 stable 2021-04-23 * chore(linux): Debug triggering Jenkins build (#4852) * chore(android/engine): Rename "Fula" to "Pulaar" (#4860) * chore(android/engine): Rename "Pulaar" to "Pulaar-Fulfulde" (#4891) * fix(developer): Reduce non-canonical BCP 47 tag warning in PackageInfo to Info (#4892) * chore(common): Update crowdin for French (#4903) * chore(android,windows): Check in crowdin for Indonesian (#4904) * fix(linux): don't crash on legacy non-Unicode files (#4878) * fix(android/engine): Don't load woff fonts on Android N (#4924) * fix(linux): Don't crash on network problem (fixes #4911) (#4931) * fix(android/engine): Change getList() to return an empty list instead of null (#4928) * fix(windows): handle invalid package names during install (#4888) * fix(windows): crash when installing TIP in some rare situations (#4901) * fix(windows): access violation closing text editor (#4921) * fix(windows): help contents broken from tray menu (#4923) * fix(developer): avoid crash if .kpj.user file is malformed (#4919) * fix(developer): chiral mismatch warning is disruptive (#4935) * chore(windows): disable profile repair (#4900) * fix(windows): avoid error if keyman32.dll renamed (#4941) * change(web): adds error + console logs usable for Sentry reporting targeting (#4929) * fix(web): fixes subkey lookup for fat-finger processing (#4955) * fix(oem/fv/android): Migrate keyboard list from 12.0 to 14.0 (#4952) * fix(web): publish restorePosition() function (#4957) * fix(web, ios): better SMP, emoji handling with frequent keyboard swaps (#4958) * feat(linux): Improve Sentry crash reporting (#4960) ## 14.0.271 stable 2021-04-01 * fix(android/engine): Sanitize embedded KMW Sentry error (#4786) * fix(ios/samples): samples should use package-oriented API (#4772) * fix(ios): fixes sys-kbd setup help link for iOS 9 and 10 (#4775) * fix(android): Fix NullPointerException in package installation (#4796) * fix(ios): ensures JS keyboard set after page load (#4809) * fix(developer): open containing folder was not opening correct folder (#4777) * fix(linux): Fix crash if query doesn't contain bcp47 tag (#4800) (#4801) * fix(android/engine): Add KMString wrapper for formatting Strings (#4820) * fix(developer): requote font names (#4815) * fix(android): ensure keyboard is always set after pageLoaded (#4841) * fix(linux): Fix crash if `.json` doesn't contain description (#4835) * fix(developer): buffer size for range expansions (#4832) * chore(common): Check in crowdin strings for Fulah (#4822) * docs(android): Update installing-keyboards and enabling-system-keyboards (#4842) ## 14.0.270 stable 2021-03-23 * chore: stable tier (#4763) ## 14.0.269 beta 2021-03-23 * chore: history: (#4760) * fix: support new branches in increment-version (#4761) ## 14.0.268 beta 2021-03-23 * fix(windows): Change TLangSwitchRefreshWatcher ownership from thread to form (#4752) * fix(common/models): prediction threshold when count is low, unintentional aliasing (#4754) ## 14.0.267 beta 2021-03-22 * docs(ios): Help for 14.0 features (#4741) * chore: increment-version.sh for stable (#4742) ## 14.0.266 beta 2021-03-19 * chore(android/app): Migrate launcher icon to adaptive (#4720) * fix(common/core/web): predictive banner activation logic (#4713) * fix(web): allows refresh of currently-loaded model (#4728) * fix(ios): kbd search now caches publishing data for result (#4729) * fix(linux): Fix switching to keyboard in middle of line (#4678) (#4721) * fix(windows): ensure profiles are reinstalled during setup (#4727) * fix(windows): Avoid double start during setup (#4726) ## 14.0.265 beta 2021-03-18 * fix(common/core/web): disambiguation of keys sharing same base key ID (#4703) * fix(windows): Download keyboard dialog TLS protocol support (#4714) * fix(web): first-pass workaround for popup-key corrections (#4704) * fix(developer): use var not let in definitions (#4718) * chore(windows): finalize help (#4717) ## 14.0.264 beta 2021-03-17 * fix(android/app): Load system keyboard before checking overrides (#4696) * fix(android): Update styling and set text to black (#4662) ## 14.0.263 beta 2021-03-16 * fix(ios): keyboard search did not alert for lack of net (#4693) * chore(android/engine): Send KMW console errors to Sentry (#4692) * fix(windows): start Keyman after setup only if not running (#4681) * fix(developer): &CasedKeys and &MnemonicLayout are not compatible together (#4690) * fix(android/engine): Fix crash when download file fails to copy to cache (#4697) * fix(developer): validate keyboard_info should give info on non-canonical bcp47 (#4689) * chore(developer): upgrade bcp 47 canonicalisation to warning (#4699) * fix(developer): support named character codes at end of line (#4691) ## 14.0.262 beta 2021-03-16 * fix(android): Update styling and set text to black (#4662) * fix(mac): prevent duplicate keyboards in list (#4674) ## 14.0.261 beta 2021-03-15 * fix(windows): Trigger language sync after changes (#4663) * chore(linux): Ignore buildtools in keyman-config tarball (#4675) ## 14.0.260 beta 2021-03-15 * chore(windows): fully disable auto start task (#4658) * fix(windows): keep online update in focus (#4661) * fix(windows): setup must save install state for restarts (#4649) * fix(ios): removal of default keyboard respected when updating app (#4651) * feat(ios): auto-bundles the most recent version of default resources (#4656) * fix(mac): register configuration window on load (#4667) * chore(ios): Set Localizable.strings to UTF-8 (#4670) * fix(android/app): Fix crash when clicking QR code (#4664) * fix(android): fixes errors within lists used for UI (#4666) * chore(common): Update crowdin for km (#4671) * chore(android/app,ios/app): Update crowdin for de (#4672) * fix(mac): release window resources on close (#4669) * fix(mac): show local help in app (#4673) * chore(windows): Update whatsnew.md (#4665) ## 14.0.259 beta 2021-03-12 * chore(developer): add B11 ISO code for ABNT2 keyboard (#4654) * fix(web): better check for missing MutationObserver type (#4646) * fix(android/engine): Reset in-app context when selection changes (#4636) * chore(linux): Move signature files as well (#4653) ## 14.0.258 beta 2021-03-11 * fix(windows): context help links (#4626) * fix(windows): hotkeys correctly ignore right modifier keys (#4628) * fix(windows): Handle disabled profiles and invalid language ids (#4635) * fix(web): event handling for TouchAliasElement's blinking caret (#4638) * fix(common/models): prevents "undefined" reversion display string (#4648) * docs(common): Update npm-packages readme (#4644) ## 14.0.257 beta 2021-03-10 * fix(common/core/web): Add keyboard check for scriptObject (#4640) * docs(common): Update readme (#4642) ## 14.0.256 beta 2021-03-10 * chore(linux): Update readme (#4633) ## 14.0.255 beta 2021-03-09 * chore(common): Update readme (#4631) ## 14.0.254 beta 2021-03-09 * fix(web): use language code correctly in toolbar (#4620) * chore(linux): Fix some lintian warnings for Debian package (#4621) * docs(ios): adds supported l10ns to help/about/whatsnew (#4625) * fix(windows): represerve keys on setfocus (#4622) * fix(windows): show version selector for Keyman in installer (#4623) * fix(windows): ensure valid base layout on install (#4627) ## 14.0.253 beta 2021-03-05 * fix(android/app): Fix welcome.htm responsiveness (#4531) * feat(developer): &CasedKeys system store (#4586) * fix(android): Localize Toast notifications (#4588) * fix(windows): PreservedKeyMap::MapUSCharToVK line order bug (#4595) * fix(developer): tidy up expansions tests (#4592) * fix(ios): adds i18n for some error alerts (#4577) * fix(windows): incxstr could run over buffer with malformed data (#4596) * chore(android/app): Update whatsnew with available display languages (#4610) * chore(linux): Improve Sentry environment setting (#4589) * fix(developer): Expand filenames before load (#4606) ## 14.0.252 beta 2021-03-04 * feat(ios): enables de, fr, and km localizations (#4585) * fix(developer): improve CEF location search stability (#4571) * fix(developer): Support all fonts in Keyboard Fonts dialog (#4574) * feat(developer): Add different Open Containing Folder buttons (#4576) * feat(developer): Range expansions (#4584) * fix(web): fixes lack of respect for underlying-key display settings (#4572) * fix(common/models): fixes application of suggestions immediately after a backspace (#4587) * fix(linux): Improve version number (#4582) * chore(linux): Don't report to Sentry in dev environment (#4581) ## 14.0.251 beta 2021-03-03 * fix(developer): Improve stability of named code constants (#4547) * fix(developer): schema conformance for model package compiler (#4548) * fix(developer): touch layout osk import handling of multiple modifiers (#4552) * fix(developer): require language tag when compiling keyboard package (#4563) * fix(developer): Avoid blank keys when importing KMX to KVKS (#4564) * feat(developer): isRTL support for lexical model editor (#4559) * fix(developer): track modified state in wordlist editor better (#4562) * chore(ios): better visual feedback for keyboard search during poor internet connectivity (#4573) * chore(common): Update crowdin files for `de` (#4578) * chore(common/core/desktop): write debug output to console (#4569) ## 14.0.250 beta 2021-03-02 * fix(common/resources): Fix help.keyman.com path for CI (#4565) ## 14.0.249 beta 2021-03-01 * fix(web): mnemonic keystrokes w FF keymapping (#4540) * chore(ios/app): Adjust help titles for installing custom dictionaries (#4550) ## 14.0.248 beta 2021-02-26 * fix(common/models): predictions after context reset / caret shift (#4411) * change(oem/fv/ios): FV keyboards now package-based (#4471) * fix(windows): Handle Caps Lock event correctly from TIP (#4536) * fix(developer): run even if sentry unavailable (#4537) * fix(developer): UTF-8 messages in LM compiler (#4539) * feat(common/models): mid-context suggestions & reversions, fix(common/models): correction-search SMP issues (#4427) * fix(ios): package installer completion requires welcome dismissal (#4543) * fix(windows): Refresh settings on 64-bit apps (#4378) * fix(windows): prevent re-registration of TIPs on 14.0 upgrade (#4535) ## 14.0.247 beta 2021-02-25 * fix(web): keyboard documentation patch-up (#4512) * fix(web): removes package namespacing from kbd's CSS class (#4516) ## 14.0.246 beta 2021-02-24 * chore(common): allow forced version increment (#4522) ## 14.0.245 beta 2021-02-24 * fix(common/core/web): core key-processing now always returns RuleBehavior type. (#4508) * fix(common/resources): Set help-keyman.com.sh executable (#4510) * fix(developer/compilers): fixes error when "constructor" is in wordlist (#4504) * fix(web): hides touch-alias caret when keystroke causes focus change (#4514) ## 14.0.244 beta 2021-02-22 * fix(common/models): merges identical suggestions after casing (#4502) * fix(web): macOS 11 agent string parsing (#4497) * fix(ios): app logging messages were transient, never stored (#4500) * chore(ios): web-side sentry enablement try-catch (#4492) ## 14.0.243 beta 2021-02-12 * change(ios/app): Generate offline help from markdown (#4470) * fix(windows): tsysinfox64 not signed (#4486) * chore(android/app): Update help formatting and images (#4485) * fix(android/engine): Display welcome.htm help within the app (#4477) * fix(ios): tutorial's link to "Add a Keyboard" links directly to keyboard search (#4491) * feat(linux): Improve output of km-package-list-installed (#4481) ## 14.0.242 beta 2021-02-11 * fix(android/engine): Display online keyboard help (#4462) * fix(windows): Track modifier changes in UWP apps (#4468) * fix(common/resources): Fix help.keyman.com path for commit (#4469) * fix(common): create GitHub comments serially (#4472) * fix(linux): Fix dependencies on packages (#4464) ## 14.0.241 beta 2021-02-10 * fix(common/resources): Just use master branch for help.keyman.com (#4459) * fix(windows): hotkeys offset in config list (#4454) * chore(ios): Settings case-statement cleanup (#4443) * fix(linux): Also use staging site for beta versions (#4455) ## 14.0.240 beta 2021-02-09 * fix(windows): When uninstalling, exit Keyman (#4383) * fix(common/models): predictions after context reset / caret shift (#4411) * modify(common): Refactor help-keyman-com.sh script for uploading help files (#4433) * fix(linux): improve BCP 47 canonicalization (#4439) ## 14.0.239 beta 2021-02-08 * fix(developer): debug information with unicode identifiers (#4408) * fix(developer): Compiler check for if and nul at start of context (#4410) * feat(developer): improve BCP 47 canonicalization (#4425) * chore(linux): Check in markdown help for Linux (#4414) ## 14.0.238 beta 2021-02-08 * fix(android/engine): Remove WRITE_EXTERNAL_STORAGE from manifest (#4434) * chore(common): Check in crowdin files for French (#4420) ## 14.0.237 beta 2021-02-06 * fix(linux): Fix packaging (#4428) ## 14.0.236 beta 2021-02-04 * chore(windows/resources): Fix typo about Community Forum link (#4412) * change(android/app): Separate displaying welcome.htm from keyboard installation (#4413) * fix(linux): Improve fix for #3399 (#4418) ## 14.0.235 beta 2021-02-03 * fix(windows): Ensure UAC window comes to foreground (#4384) * fix(windows): setup should ignore cert revocation (#4392) * fix(developer): don't check both setup.exe and setup-redist.exe (#4398) * fix(windows): Show balloon when Keyman is already running (#4386) * fix(developer): Generate platforms correctly from template (#4399) * fix(developer): Import Keyboard support for Targets (#4400) * fix(ios): fixes unit test mocking, test init (#4394) * fix(ios): fixes app crash on network/install error during resource updates (#4395) * fix(ios): fixes package-install/update event concurrency management (#4396) * fix(common/models): bksp workaround now works beyond first word (#4401) * chore(windows): tests should be case-sensitive (#4405) * fix(windows): crash deleting wordlist (#4406) * fix(windows): Use forward slashes in wordlist paths (#4407) * modify(android/app): Change build-help.sh to generate offline help from Markdown files (#4397) * fix(linux): Don't crash if uninstalling last keyboard (#4402) ## 14.0.234 beta 2021-02-02 * fix(windows): remove Show Keyboard Usage hotkey (#4379) * fix(windows): avoid invalid language codes in Add Language dialog (#4381) ## 14.0.233 beta 2021-02-01 * fix(windows): SMP-aware deletion in TSF-aware apps (#4360) * fix(common): tweak surrogate pair deletions (#4361) * fix(windows): Enter and Spacebar handling in Configuration (#4349) * fix(web): removes stylesheets from unloaded keyboards (#4371) * fix(android, ios): eliminates OSK layout flashing from predictive text banner display (#4370) * fix(windows): crash for Sinhala mitigation (#4380) * chore(linux): Pass second tag parameter to Jenkins build (#4388) ## 14.0.232 beta 2021-01-29 * chore(linux): Don't report on Sentry when running unit tests (#4356) * fix(windows): Ignore Access Denied error creating task (#4365) * chore(windows/resources): Fix more titles and TODOs in help (#4367) ## 14.0.231 beta 2021-01-28 * chore(common): Enhance PR labeling based on PR title (#4357) * change(web): set -eu for web scripts (#4353) * fix(ios): accidental duplicated line from merge (#4366) ## 14.0.230 beta 2021-01-28 * fix(android/app): Wrap preference screen titles (#4326) * fix(ios): better handling of scoped vs non-scoped package URLs (#4327) * fix(web): bulk renderer using video stream capture (#4316) * change(android/engine): Allow swipe to dismiss update notifications (#4329) * fix(windows): improve support for strings.xml (#4323) * fix(windows): invalid character in text content opening help (#4330) * fix(windows): align title to top in Install Keyboard (#4331) * chore(windows/resources): Cherry-pick 14.0 help from #4109 (#4335) * fix(ios): renew distribution certificate (#4344) * fix(ios): reloads keyboard after package updates (#4347) * fix(ios): fixes accidental logo / cancel button overlap during package installation (#4332) * fix(ios): resolves rough edges with installation view transitions (#4338) * fix(web/ui): propagates UI module build failures (#4352) * chore(linux): Fix typo (#4341) * chore(windows/resources): Address more TODO links for help (#4351) * fix(windows): setup strings comment for language (#4362) * fix(windows): Splash button sizes (#4348) * chore: manual version increment (#4363) ## 14.0.228 beta 2021-01-22 * fix(web): uses CSS line-height to vertically center oversized OSK keycaps (#4255) * fix(web): OSK loading efficiency (#4279) * fix(web): default popup key selection, space highlight after popup (#4306) * fix(web): language menu key highlighting (#4308) * fix(web): dynamic font downscaling for OSK keys (#4270) * chore(windows/resources): Cleanup Notes and Tips in help (#4307) * fix(developer): Debug character grid performance (#4237) * chore(android/samples): Remove old sample keyboard loaded code (#4315) ## 14.0.227 beta 2021-01-21 * fix(web): dynamic font downscaling for OSK keys (#4270) * fix(web): toolbar and loading optimisations (#4304) * chore(web): updates MTNT for pred-text testing page to 0.1.5 (casing) (#4305) * fix(android/samples): Add dependency on androidx.preference (#4310) ## 14.0.226 beta 2021-01-20 * fix(windows, common/core/desktop): context mismatch with if and dk (#4276) * chore(common): Check in crowdin files for de (German) (#4295) * feat(android/app): Add option to change display language (#4261) * fix(developer/compilers): fixes developer build breakage from #4291 (#4299) * fix(android/app): Handle keyman protocol from external browser (#4292) ## 14.0.225 beta 2021-01-19 * fix(android/samples): Fix Sentry dependencies (#4267) * fix(web): better font-wait null guards (#4286) * fix(web): uses CSS line-height to vertically center oversized OSK keycaps (#4255) * fix(developer): disable TSentryClient on WINE (#4274) * fix(web): no key previews for special keys reliant on keyboard-specific OSK font (#4282) * fix(web): default kbd ui name is now generic (#4293) * fix(developer/compilers): fixes dependency versioning on alpha, beta tiers (#4291) ## 14.0.224 beta 2021-01-18 * fix(android): Popup misalignments and compatibility with WeChat, Telegram (#4254) * chore(web): sample pages now wait on init's promise for keyboard loading (#4253) ## 14.0.223 beta 2021-01-15 * fix(windows): typo in font helper string (#4251) * chore(android/app): Add Obolo language from crowdin (#4256) * fix(web): unexpected errors in OSK / banner position calculations (#4238) * chore(linux): Improve version number for debian package (#4258) ## 14.0.222 beta 2021-01-14 * chore(common): Check in crowdin files for km (Khmer) (#4228) * fix(web): OSK key preview positioning (#4241) * fix(web): disables predictive text on Opera mini (#4243) ## 14.0.221 beta 2021-01-13 * fix(windows): fix menu popup position (#4175) * fix(windows): Update mitigation for Keyman 14 and Windows 10 19597 (#4180) * fix(developer): Allow unhandled keys to go through to debugger memo (#4209) ## 14.0.220 beta 2021-01-13 * fix(android/engine): Remove usage of WRITE_EXTERNAL_STORAGE permission (#4170) * fix(web): osk size & position after focus changes (#4232) * chore(linux): Update debian metadata based on Debian repos (#4233) ## 14.0.219 beta 2021-01-12 * chore: bugfix cherrypick (#4208, #4210) (#4230) * fix(common/core/web): mnemonic modifier key-up handling (#4231) ## 14.0.218 beta 2021-01-08 * chore(linux): pass tag to Jenkins build (#4160) (#4224) ## 14.0.217 beta 2021-01-05 * chore(linux): Allow to push to the `keyman-beta` ppa (#4214) ## 14.0.216 beta 2020-12-23 * fix(developer): make touch layout editor source view fonts consistent (#4198) * fix(developer): Respect tab editor option (#4200) * fix(web): Solving kmwosk color inconsistency (#4187) ## 14.0.215 beta 2020-12-22 * fix(windows): create task fails (#4181) * fix(windows): prevent modifier key from navigating in download dialog (#4182) * fix(windows): keyboard help missing (#4177) * fix(windows): Proxy Configuration window size (#4159) * chore(common): update copyright year in various locations (#4197) * fix(windows): Settings refresh management (#4164) * fix(windows): Improve refresh performance (#4165) * fix(windows): exception handling list error (#4166) * fix(windows): OSK toolbar sync (#4167) * fix(windows): Show full version with tag in Setup (#4169) * fix(windows): Improve refresh reliablilty (#4171) * fix(developer): debug.log created unexpectedly (#4189) * chore(windows): Remove silent exception in task cleanup (#4191) * fix(windows/config): keyboard icons missing (#4193) * fix(developer): Map symbols for *LTREnter* and *LTRBkSp* (#4190) * fix(developer): Encoding for .model.ts files (#4199) * feat(common): annotate PRs with build links (#4202) ## 14.0.214 beta 2020-12-20 * fix(windows): Text editor font bugs (#4149) * fix(windows): Warn if we reach maximum transient languages (#4157) ## 14.0.213 beta 2020-12-18 * fix(windows): sentrytool should fail build on exception and access violation when rewriting executables (#4158) ## 14.0.212 beta 2020-12-17 * fix(windows): uninstall language button z-index (#4145) * fix(windows): exit button position on setup (#4150) * fix(windows): Online Update dialog layout was messy (#4152) ## 14.0.211 beta 2020-12-16 * chore(windows): remove obsolete importkeyboard app (#4138) * fix(windows): glitch in keyboard menu (#4139) * fix(windows): menu scroll positions need reset at popup (#4140) * fix(windows): remove obsolete option 'Switch to OSK/Help' (#4141) * fix(windows): Canonicalize BCP 47 tag on keyboard download (#4144) * fix(windows): help window centred on load (#4147) * fix(windows): Text editor font bugs (#4149) * chore(common): Update history for 14.0 beta release (#4148) * fix(common): increment version needs to check base (#4155) ## 14.0.210 beta 2020-12-15 * fix(windows): beta uses wrong server (#4142) ## 14.0.209 beta 2020-12-14 * chore(common): fix trigger for beta branches (#4135) ## 14.0.208 beta 2020-12-14 * chore: re-trigger beta (#4133) ## 14.0.207 beta 2020-12-14 * fix: build trigger definitions (#4131) ## 14.0.206 beta 2020-12-14 * feat(ios/app): adds error reporting toggle (#4106) * chore(android): rework versionCode system (#4128) ## 14.0.205 alpha 2020-12-14 * fix(web): sporadic blank keyboard on Android (#4117) * chore(common/models): predictive-text "semi-fill" for iOS 9 use (#4118) ## 14.0.204 alpha 2020-12-11 * chore(windows): apply eberhard's suggestions to docs (#4105) * fix(ios): prevents crash from failed legacy-resource-wrapping attempt (#4100) * chore(deps): bump ini from 1.3.5 to 1.3.7 in /web/testing/regression-tests (#4108) ## 14.0.203 alpha 2020-12-10 * fix(web/ui): Add null check for calculations when canceling touch (#4098) ## 14.0.202 alpha 2020-12-09 * fix(ios): fixes nav bar issues when using "Install From File" (#4099) * fix(web/ui): Fix check on indexOf (#4103) * fix(ios): autosets + autodisplays keyboard after a package install (#4101) ## 14.0.201 alpha 2020-12-08 * chore(ios): pbxproj file compat for Xcode 12 & Simulator (#4094) * refactor(ios/engine): changes "install from file" to better match Apple guidelines (#4089) * fix(ios/engine): requests security for imported files (#4095) * fix(android/app) Change UX to ensure package installation finishes (#4088) * chore(windows): help titles and missing files (#4091) ## 14.0.200 alpha 2020-12-07 * fix(web/ui): Add check for suggestion.tag (#4085) ## 14.0.199 alpha 2020-12-07 * chore(windows): also build web help (#4086) ## 14.0.198 alpha 2020-12-07 * fix(windows): help deployment (#4083) ## 14.0.197 alpha 2020-12-04 * fix(windows): bootstrap installer not signed (#4067) * fix(common/core/web): Sanitize embedded KMW Sentry events (#4071) * fix(windows): keyman: link with = sign is mishandled (#4069) * chore(android/app,oem/fv/android): Revert #4025 (#4076) * chore(oem/fv/windows): update oem firstvoices product name (#4052) * feat(windows): convert Keyman for Windows help to Markdown (#4074) * chore(windows): remove docbook and libxslt (#4075) * fix(android/engine): Remove in-app keyboard Sentry log about fallback keyboard (#4078) * fix(web/engine): findNearestKey erroneously returned key child (#4077) * fix(common/core/web): predictive context reset (#4072) * fix(ios/engine): deletion for selected text at the context start (#4080) ## 14.0.196 alpha 2020-12-03 * fix(common): improve increment-version robustness (#4062) * fix(ios/engine): preserves early context-setting effects (#4070) * feat(linux): Rename onboard package (#4059) ## 14.0.195 alpha 2020-12-02 * chore(windows): remove obsolete newhelp folder (#4048) * feat(ios/engine): keyboard-menu scroll indicator now flashes when opened (#4043) * fix(ios): better meta viewport consistency (#4045) * fix(windows): Rename to Keyman in help files (#4049) * chore(common/resources): Fix dest paths for crowdin strings (#3995) * fix(windows): Rename to Keyman (#4050) * fix(ios/engine): adds check for keyboard load success, auto-reset on load failure (#4054) ## 14.0.194 alpha 2020-12-01 * fix(android/app,oem/fv/android): Sanitize Sentry navigation breadcrumbs (#4025) * fix(windows): Task creation and deletion cleanup (#4033) * fix(windows): crash with package online update (#4034) * fix(windows): Keep language associations when updating keyboard (#4035) * fix(windows): Handle network errors when downloading keyboards (#4036) * chore(windows): disable Sentry 'Started' event (#4037) * fix(ios): package-internal links should be considered internal (#4022) ## 14.0.193 alpha 2020-11-30 * chore: refresh github templates (#3999) ## 14.0.192 alpha 2020-11-28 * chore(linux/resources): Cleanup formatting in history.md (#3983) ## 14.0.191 alpha 2020-11-27 * fix(mac): improve robustness of altool call (#3959) * fix(mac): Handle duplicate filenames for packages (#3961) * chore(common/resources): Document keeping scopes in sync (#3974) * fix(common/models): proper RTL quote ordering (#3897) * chore(mac): englishspanish test keyboard (#3976) * chore(mac/resources): Catch up mac history for 13.0 releases (#3977) * fix(android/engine,android/app) Notify when invalid keyboard package fails to install (#3964) * chore(windows): cleanup unused variable (#3978) ## 14.0.190 alpha 2020-11-26 * fix(oem/fv/android): Check keyboard selected before allowing setup (#3923) * chore(common): fixup missing history (#3957) ## 14.0.189 alpha 2020-11-25 * fix(mac): re-sign files post plist update (#3932) * fix(mac/engine): wrong variable type (#3933) * feat(mac): Add support for "ISO" keyboard layouts (#3924) * fix(mac): turn on legacy mode for Java apps (#3944) * feat(developer): add new touch layout special tags (#3878) * fix(web): default attachment behavior (#3948) * fix(mac): arrow keys now reset context (#3946) * feat(mac): user-controllable legacy app list (#3949) * chore(mac): fix iso section key code (#3952) * chore(common/resources): Part 3 of additional HISTORY.md cleanup (#3947) ## 14.0.188 alpha 2020-11-24 * chore(mac): Update README.md (#3880) * fix(windows): sentry range check error (#3921) * chore(common/resources): Clean up commit types in HISTORY.md (#3926) * fix(android/engine): adds null guard to refreshLayouts call (#3927) * fix(ios/engine): adds null guard to refreshLayouts call (#3927) * fix(ios/engine): banner inconsistency (#3925) * chore(web): adds LTREnter, LTRBkSp, and associated layout mapping (#3937) * fix(web): adds null guards for two Sentry errors (#3941) * chore(common/resources): additional cleanup to HISTORY.md (#3942) ## 14.0.187 alpha 2020-11-23 * chore(mac): use new keyboard install page (#3908) * fix(ios/engine): allows some language-code incomplete matches during package installation (#3884) * feat(ios/engine): launches external links outside the app (#3889) * chore(linux): Fix launchpad build (closes #3875) (#3913) * fix(linux): Don't fail installation if restarting ibus fails (#3915) ## 14.0.186 alpha 2020-11-20 * feat(mac): Sentry support (#3886) * chore(mac): rewrite plists after build (#3891) * fix(mac): add icon for Keyman.app (#3892) * fix(mac): codesign resilience (#3893) * fix(mac): support page and copyright (#3904) * fix(oem/fv/android): Update Sentry library in FV app (#3905) * fix(android/app): Install keyboard packages w/o welcome.htm (#3874) * fix(web/engine): fixes OSK rotation (#3909) * feat(common/core/web): integrated suggestion casing tests (#3887) * fix(ios/engine): changes image-banner display logic (#3911) ## 14.0.185 alpha 2020-11-19 * feat(web/engine): allows touch aliasing away from blank keys (#3858) * chore(linux): Additionally build packages for Ubuntu 20.10 (Groovy) (#3876) * fix(linux): Remove version.sh and get tier/version from .md files (#3686) * fix(android/samples): Remove use of version.gradle in Sample projects (#3899) * feat(android/engine): Add embedded KeymanWeb engine crash reporting to Sentry (#3825) ## 14.0.184 alpha 2020-11-18 * feat(developer/compilers): compiler-side groundwork for applyCasing (#3770) * feat(common/models): use of applyCasing for suggestions (#3824) * feat(common/models): casing for suggestions with partial replacement (#3845) * fix(common/core/web): Add environment to web Sentry reports (#3888) * fix(android/engine): Update in-app TextView context on pageLoaded (#3867) ## 14.0.183 alpha 2020-11-17 * feat(windows): major version upgrades (#3866) * feat(developer): support major version upgrades (#3868) * docs(windows): Update Delphi version requirement note (#3871) * feat(web/engine): updates osk font, adds layout codes for new glyphs (#3851) * fix(common/core/web): meta key handling (#3847) * feat(common/core/web): input processor unit tests (#3836) ## 14.0.182 alpha 2020-11-16 * fix(web/engine): blocks key previews for blank/hidden keys (#3857) * fix(common/core/web): Fixes engine-level context tests, adds notany cases (#3860) ## 14.0.181 alpha 2020-11-13 * fix(common/core/web): fixes no-output logic check, arrow keys (#3848) * fix(common/core/web): adds missing null-check (#3859) ## 14.0.180 alpha 2020-11-12 * fix(windows): makefile format error (#3854) ## 14.0.179 alpha 2020-11-12 * fix(windows): Import OSK wrong for European layouts (#3830) * fix(windows): SizeOfImage header was wrong for dbg (#3833) * chore(windows): symbol server support (#3834) * fix(windows): sporadic 8087 control word corruption (#3842) ## 14.0.178 alpha 2020-11-10 * fix(developer): Remove IE dependency from Developer Setup (#3839) ## 14.0.177 alpha 2020-11-07 * fix(developer): support for notany() and context() (#3816) * fix(web): support for notany() and context() (#3817) * fix(developer): debug window inherits editor font (#3829) ## 14.0.176 alpha 2020-11-05 * fix(developer): remove obsolete NRSIAllTags (#3819) * fix(developer): Incorrect script:language map (#3818) * fix(android/app): Remove network check on "Get Started" menu (#3823) ## 14.0.175 alpha 2020-11-04 * feat(android/engine): Add check for associated model on ModelPickerActivity (#3808) ## 14.0.174 alpha 2020-11-03 * chore(common/resources): improve build README.md (#3812) ## 14.0.173 alpha 2020-10-30 * fix(windows): Cleanup setup.inf processing and CompareVersions function (#3790) * fix(windows): setup now allows choice of source (#3794) * fix(windows): show bootstrap progress in setup (#3792) * fix(windows): cleanup setup action list (#3793) * chore(android/engine): Remove use of lexical-model catalog (#3803) * fix(windows): disabling/enabling a profile could have wrong association (#3799) * fix(windows): keyboard menu could get out of sync (#3800) * fix(windows): crash installing package with a race (#3805) * fix(windows): Handle failure on task creation (#3804) ## 14.0.172 alpha 2020-10-29 * fix(windows): Start Keyman on Demand - keyman32 (#3772) * fix(windows): Start Keyman on Demand - tasks (#3773) * fix(windows): remove msctf free from DllMain (#3779) * fix(windows): error reading kmp.inf in setup (#3781) * chore(web): Update keymanweb-osk.ttf to v. 2.100 (#3782) * fix(android/engine): Fix issues when re-installing lexical-models (#3731) ## 14.0.171 alpha 2020-10-28 * fix(android/browser): Fix slow input in embedded browser (WebViews) (#3768) * chore(common/models): fixes context tracking with accepted suggestions (#3767) * chore(windows): small cleanups (#3774) ## 14.0.170 alpha 2020-10-27 * fix(windows): Remove double refresh (#3754) * fix(windows): Keyman Configuration changes apply instantly (#3753) * fix(windows): Make help button work (#3760) * fix(windows): use new windows url for online update check (#3761) * fix(windows): Community button had wrong link (#3764) * fix(windows): Crash in Keep in Touch external link (#3763) * fix(windows): Fix multiple issues with UI locales (#3766) * fix(android/engine): Only get keyboard version for cloud/ (#3740) ## 14.0.169 alpha 2020-10-26 * feat(common/core/web): simplify corrective distribution (#3726) * fix(windows): restore Setup after minimize (#3739) * fix(windows): buffer overrun in debug function (#3745) * fix(windows): download error dialog could be blank (#3747) * feat: Keyman Settings Manager base classes (#2456) * feat(windows): kmconfig console app (#3732) * feat(windows): kmconfig GUI (in kmshell) (#3733) * feat(windows): Apps for Controlling Browser TSF integration (#3734) ## 14.0.168 alpha 2020-10-24 * chore(android): Update dependencies (#3738) ## 14.0.167 alpha 2020-10-23 * fix(android/browser): Improve how embedded browser handles input (#3722) ## 14.0.166 alpha 2020-10-22 * fix(web): disable U+25CC for diacritics (#3039) * refactor(common/models): Common tokenization and wordbreaking functions (#3706) * fix(windows): setup status showed only 'removing older versions' (#3735) * fix(windows): improve tsysinfo upload messages (#3727) * chore(windows): update msgping to Winsdk 10 (#3728) * fix(android/engine): Improve KMManager robustness (#3721) * feat(common/core/web): fat-finger ignores inputs that beep (#3701) ## 14.0.165 alpha 2020-10-21 * fix(web): K_SPACE handling for embedded mode, hardware keystrokes (#3707) ## 14.0.164 alpha 2020-10-20 * feat(common/models): context tracking of accepted Suggestions (#3663) * feat(common/models): context reversion modeling (#3685) * fix(windows): RefreshKeyboards loses some profiles (#3714) * fix(windows): icons missing in Configuration (#3717) * fix(windows): tweak scrolling in keyboard menu (#3719) * fix(developer): crash creating basic project (#3716) ## 14.0.163 alpha 2020-10-19 * fix(web): Remove base key from popup keys (#3718) ## 14.0.162 alpha 2020-10-18 * fix(web): Let embedded device handle K_TAB or K_ENTER (#3664) ## 14.0.161 alpha 2020-10-16 * fix(common/core/web): fixes revert event bug (#3709) ## 14.0.160 alpha 2020-10-14 * feat(common/models): disables "keep" when word is not suggestion otherwise (#3700) * feat(common/core/web): selective wordbreak swallowing after accepting suggestions (#3702) * refactor(common/models): extract Outcome type (#3705) ## 14.0.159 alpha 2020-10-12 * fix(web): unit test script failure on compilation failures (#3597) ## 14.0.158 alpha 2020-10-09 * feat(common/models): 'revert' now uses model's punctuation (#3647) * fix(windows): launch configuration non-elevated (#3691) * fix(windows): disabled keyboards listed in hotkeys (#3693) ## 14.0.157 alpha 2020-10-08 * fix(windows): show version with tag in setup (#3682) * fix(windows): keyman desktop setup filename (#3684) ## 14.0.156 alpha 2020-10-08 * chore(windows): Move to Windows SDK 10.0.17763.0 (#3654) * fix(windows): Some registry keys could have incorrect permissions (#3668) * fix(developer): ci uses repo tier and version (#3670) * fix(windows): update CI for publishing desktop help (#3671) * fix(web): ci uses repo tier and version (#3672) * fix(windows): improve version numbers (#3678) * chore: don't add tag to version in filenames (#3681) ## 14.0.155 alpha 2020-10-07 * refactor(common/models): centralizes suggestion & keep inits (#3645) * fix(common/models): predictions after typed whitespace (#3657) * fix(web): Fix how layer is separated from key name (#3659) ## 14.0.154 alpha 2020-10-05 * fix(windows): Upgrading keyboards with transient profiles (#3637) * fix(windows): upgrading disabled keyboards (#3638) * fix(developer): coverity reports for compiler (#3640) * fix(windows): coverity reports for mcompile (#3641) * fix(windows): coverity reports for kmtip (#3642) * fix(windows): coverity reports for keyman32 (#3649) * chore: exclude parens if no scope in commit msg (#3653) ## 14.0.153 alpha 2020-10-02 * chore(common/resources): bump @actions/core from 1.2.2 to 1.2.6 in /resources/build/version (#3646) * fix(android/app): Switch system keyboard in KMPBrowserActivity (#3648) ## 14.0.152 alpha 2020-09-30 * fix(ios/engine): package installation language-picker improvements (#3623) ## 14.0.151 alpha 2020-09-29 * fix(windows): Buffer overrun in firstrun (#3634) * fix(windows): upgrading transitional profiles (#3635) * fix(android/engine): Fix undetermined lexical model package ID (#3624) ## 14.0.150 alpha 2020-09-28 * feat(windows): overflow menu for osk toolbar (#3626) * feat(windows): scrollable keyboard menu (#3627) * fix(android/app): Allow uninstalling sil_euro_latin for non-default languages (#3628) * feat(ios/engine): Utilizes packages' welcome pages (#3622) * fix(android/app): Only copy asset .kmp file if it doesn't exist (#3629) ## 14.0.149 alpha 2020-09-25 * fix(windows): add back support for disabling keyboards (#3607) * fix(windows): bootstrap package install specified language bugs (#3609) * fix(windows): bootstrap should skip install of failed downloads (#3610) * refactor(android/app): Move Settings activities from KMEA to KMAPro (#3614) * fix(android/app): Change install intent to MainActivity (#3615) * fix(windows): cleanup pointer to int typecasts (#3612) * fix(developer): hardcoded urls in debugger (#3613) * fix(developer): Project window and About window hardcoded urls (#3618) * fix(windows): cleanup hardcoded urls in tsysinfo (#3619) ## 14.0.148 alpha 2020-09-24 * fix(windows): external links should open externally (#3602) * fix(windows): hint dialog was blank when elevated (#3604) * fix(android): Log errors for crashes involving Keyboard Picker (#3499) ## 14.0.147 alpha 2020-09-23 * feat(common/models): context + input tracking for predictive text (#3549) * feat(common/models): initial integration for enhanced corrections (#3555) * feat(common/models): correction thresholding, acceptance (#3556) * refactor(common/models): distance modeler cleanup (#3565) * change(common/models): context tracker cleanup, optimizations, fixes (#3573) * feat(common/models): Correction improvement (#3575) * feat(common/models): naive correction-algorithm timer (#3581) * fix(common/models): Android API compat for upgraded correction-search (#3601) * fix(android/app): Query api.keyman.com for downloading associated dictionary (#3606) * refactor(web/engine): application of predictive suggestions (#3582) * fix(windows): simplify profile repair (#3559) ## 14.0.146 alpha 2020-09-22 * chore(web): bump http-proxy from 1.17.0 to 1.18.1 in /web/testing/regression-tests (#3568) * feat(ios/engine): go/package use for model pkg downloads (#3603) ## 14.0.145 alpha 2020-09-21 * feat(windows): improve keyboard language dialog (#3557) * fix(windows): lookup language name on create (#3558) ## 14.0.144 alpha 2020-09-18 * feat(developer): add viewport to html templates (#3531) * fix(windows): use new signtime.bat on build agents (#3586) * fix(developer): Touch font size should be string (#3585) * fix(android/app): Fix Info page title size (#3571) * fix(linux/config): Check if file exists before creating hard links (#3592) * fix(windows): remove obsolete releaseCapture calls (#3594) * fix(linux/config): Catch if kmp.json is invalid JSON (#3593) ## 14.0.143 alpha 2020-09-16 * fix(android/app): Validate language selection for "INSTALL" button (#3579) ## 14.0.142 alpha 2020-09-15 * chore(common/resources): bump node-fetch from 2.6.0 to 2.6.1 in /resources/build/version (#3578) ## 14.0.141 alpha 2020-09-11 * fix(web): default layout shift not changing layer (#3574) ## 14.0.140 alpha 2020-09-09 * feat(common/models): core edit-distance calculation class (#3526) * feat(common/models): Edit path derivation (#3547) * feat(common/models): low-level correction-algorithm infrastructure (#3527) * feat(common/models): correction-search algorithm core (#3534) ## 14.0.139 alpha 2020-09-04 * fix(windows): BCP 47 tag canonicalization (#3545) * fix(windows): upgrade of profiles from 13.0 (#3552) ## 14.0.138 alpha 2020-09-02 * feat(windows): map installed bcp47 (#3542) * fix(windows): simplify profile uninstall (#3543) * fix(android/app): Remove unused intent ACTION_GET_USERDATA (#3551) * fix(android/engine): Remove notification after installing kbd package (#3546) * fix(android): Re-enable monitoring of Application Not Responding (ANR) (#3550) ## 14.0.137 alpha 2020-08-31 * fix(android/engine): Fix package filename when downloading from cloud (#3541) * feat(windows): select language at keyboard install (#3524) * feat(windows): add langtags.json data (#3529) * fix(windows): add transient profile support to keyman32 (#3539) ## 14.0.136 alpha 2020-08-28 * fix(android/app): Inject meta viewport tag for viewing help (#3523) * fix(android/app): Fix overflow menu for hdpi devices (#3532) * feat(windows): Rework of profile installation - Engine (#3509) * feat(windows): profile installation - Keyman for Windows (#3510) * feat(windows): profile installation - Support Tool (#3511) * chore(windows): remove stockeditor (#3516) * fix(windows): refresh configuration after changes (#3517) * feat(windows): split language registration on app install (#3520) * fix(linux): Improve robustness when installing ibus-keyman (#3535) ## 14.0.135 alpha 2020-08-27 * feat(common/models): override script defaults: spaces break words (#3506) * fix(android/engine): Check asset package version before installing (#3514) * feat(android): Use Stepper for navigating package installation steps (#3498) ## 14.0.134 alpha 2020-08-26 * fix(linux): Add packaging of Linux localization files (#3504) ## 14.0.133 alpha 2020-08-25 * feat(common/models): lexicon traversal (#3479) * feat(common/models): actual priority queue for Trie models (#3480) * feat(common/models): efficient batch-enqueue (#3486) ## 14.0.132 alpha 2020-08-24 * feat(linux): Add link to share online (#3494) * docs(common): Clarify l10n readme (#3496) * feat(linux): Add i18n for Linux (#3492) * feat(linux): Small UI improvements (#3495) ## 14.0.131 alpha 2020-08-21 * feat(android/app): Add language picker for keyboard package installation (#3481) ## 14.0.130 alpha 2020-08-19 * fix(android): Fix util to getting the tier on CI builds (#3491) ## 14.0.129 alpha 2020-08-17 * feat(windows): rework download keyboard dialog style (#3463) * chore(common/resources): Add sample vscode settings files (#3249) * fix(linux): Lookup language tag from keyboard (#3408) ## 14.0.128 alpha 2020-08-13 * feat(linux): Hook up Sentry for km-config (#3378) * chore(linux): Use new staging site names and use variable for downloads.keyman.com (#3406) ## 14.0.127 alpha 2020-08-12 * refactor(common/models): LMLayer state management tweak, persistent ModelCompositor (#3477) ## 14.0.126 alpha 2020-08-10 * fix(android): Add CI script to publish to Play Store (#3469) * fix(android): Update sentry plugin to remove obsolete API use (#3471) * feat(ios/app): universal links for keyboard installation (#3466) * fix(ios/engine): Proper associating-installer deinitialization, cancellation tests (#3468) * refactor(ios): error definitions, i18n (#3470) * chore(common/core/desktop): cleanup keyboardprocessor.h.in (#3473) ## 14.0.125 alpha 2020-08-07 * fix(android): Update Gradle wrapper to 5.6.4 (#3467) * feat(ios/engine): Associating package installer (#3458) * feat(ios/app): Associating package installer use within existing install paths (#3465) ## 14.0.124 alpha 2020-08-06 * feat(windows): set default UI language at install (#3438) * feat(windows): i18n for Setup (#3444) * feat(windows): add globe icon to Configuration UI (#3446) * feat(windows): set UI language from Setup preference on first install (#3447) * feat(windows): docs on editing translations (#3448) * change(android): Improve string context to help crowdin translators (#3457) * fix(android/app): Fix environment portion of app version string (#3462) ## 14.0.123 alpha 2020-08-05 * feat(android): Use staging help site for pre-release builds (#3453) * fix(android): Cleanup string formatting with strings.xml (#3452) * chore(android): Add script to find unused strings. Manually remove them (#3456) * feat(ios/engine): LanguagePickAssociator progress tracking, base integration with package lang picker (#3455) ## 14.0.122 alpha 2020-08-04 * feat(android/app): Associate app with /keyboards/install links (#3449) * fix(android): Update KMPBrowser to pass external links to user browser (#3439) * feat(ios/engine): Language-pick associator (#3451) ## 14.0.121 alpha 2020-08-03 * fix(android): Fix KMTextView to compile on Linux (#3442) ## 14.0.120 alpha 2020-07-31 * feat(android): Use api.keyman-staging.com for pre-release builds (#3423) * refactor(ios/engine): merges keyboard & lexical model info views, fixes QR code logic (#3432) * feat(android): Add app association to keyman.com (#3431) * chore(windows): cleanup comments in strings.xml (#3434) * feat(ios/engine): language selection during (file-based) package installation (#3416) * feat(ios/engine) Package-installer layout optimizations (#3437) ## 14.0.119 alpha 2020-07-30 * feat(windows): convert locale.xml to strings.xml format (#3424) * refactor(windows): add translations to windows install (#3428) * refactor(windows): remove old locale links (#3429) * chore(windows): remove old locale tools (#3430) * feat(ios): Start of engine and app internationalization (#2745) ## 14.0.118 alpha 2020-07-29 * chore(common): unify crowdin.yml (#3418) * fix(windows): more i18n cleanup: (#3415) * feat(windows): generate message consts at build time (#3413) * fix(android/app): Use go/android/ links to download cloud keyboards (#3343) * fix(windows): i18n of strings in Font Helper (#3414) * refactor(windows): refactor Dialog elements (#3421) * chore(windows): Remove usage page resources (#3422) ## 14.0.117 alpha 2020-07-28 * feat(windows): i18n groundwork (#3411) * feat(windows): Removes unused strings from locale.xml (#3412) * refactor(ios/engine): package installer tweaks (#3410) * chore(ios/engine): more obsoletions (#3407) ## 14.0.116 alpha 2020-07-24 * refactor(ios/engine): builds package download links (#3383) * refactor(ios/engine): chained lexical model install callback, fix (#3388) * feat(ios/engine): download queue concurrency (#3395) * feat(ios/engine): keyboard search core (#3384) * feat(ios/engine): support for deferred chaining of lexical model downloads (#3401) * docs(linux): Update readme (#3397) * feat(ios/engine): use of Keyman staging sites (#3405) * feat(linux): keyman:// protocol handler (#3398) * chore(ios/engine): dead code removal + deprecations (#3402) ## 14.0.115 alpha 2020-07-23 * fix(windows): proxy configuration from system (#3389) * fix(windows): hide unavailable options in Setup (#3392) * fix(windows): make sure silent is actually silent for setup (#3391) * chore(windows): staging site hostnames (#3387) * feat(windows): cleanup server names (#3325) * feat(windows): keyman: protocol handler (#3382) * feat(developer/compilers): logging errors and warnings in the lexical model compiler (#3385) ## 14.0.114 alpha 2020-07-22 * chore(web): bump lodash from 4.17.15 to 4.17.19 in /web/testing/regression-tests (#3360) ## 14.0.113 alpha 2020-07-21 * refactor(ios/engine): update detection now based upon packages (#3362) * refactor(ios/engine): package download notifications (#3363) * refactor(ios/engine): package-based resource updates, cloud resource migration (#3372) * fix(ios/engine): engine tier enum, proper detection (#3373) * refactor(ios/engine): Centralized Keyman domain definitions (#3381) * fix(linux): Use language from search when installing keyboard (#3290) * refactor(linux): Small refactorings (#3376) * refactor(developer/compilers): reading from a wordlist (#3380) ## 14.0.112 alpha 2020-07-20 * feat(windows): disable defaults options when Keyman already installed (#3371) * feat(windows): setup will retry if offline during initial install steps (#3370) * feat(windows): setup select tier from filename or parameter (#3369) * fix(windows): re-add license to setup (#3368) * feat(windows): strip ' (1)' from filename in setup (#3367) * fix(windows): remove large dependencies (#3346) * refactor(ios/engine): package-version query caching + package state properties (#3335) * refactor(ios/engine): keyboard downloads now retrieve KMPs (#3341) * refactor(ios/engine): download queue & download state detection cleanup (#3342) * chore(developer): cleanup test constants (#3350) * change(common/models/wordbreakers): update word boundary props to 13.0 (#3365) * feat(linux): Use staging URLs for alpha version (#3364) ## 14.0.111 alpha 2020-07-16 * fix(android/engine): Update deprecated call to switch system keyboard for Android P (#3353) ## 14.0.110 alpha 2020-07-15 * fix(developer/compilers): merge duplicate words during compile (#3338) * refactor(developer): hashmap-based wordlist compilation (#3340) * chore(linux): Add license details for kmpdetails.* (#3355) ## 14.0.109 alpha 2020-07-14 * feat(windows): New Keyboard Search and Download (#3326) * refactor(ios/engine): lexical model query & download rework (#3327) * refactor(ios/engine): hashable package keys (#3333) * fix(ios/engine): version equality (#3334) * refactor(linux): make some methods protected (#3291) * feat(oem/fv/android): Add nrc.str.sencoten model and update SystemKeyboard from KMAPro (#3332) ## 14.0.108 alpha 2020-07-09 * refactor(windows): PackagesOnly parameter (#3321) * chore(windows): code cleanup (#3320) * chore(windows): update setup i18n (#3317) * chore(windows): Cleanup logging in Windows Setup (#3316) * feat(windows): Keyman Setup online bootstrap (#3304) * chore: cleanup global ExtPath (#3315) * feat(android/app): Use build-download-resources.sh for KMApro app (#3322) * feat(oem/fv/android): Use build-download-resources.sh for FV app (#3322) * refactor(ios/engine): Centralized package download utility function (#3299) * fix(oem/fv/android): Add a fallback keyboard to FV Android app (#3323) ## 14.0.107 alpha 2020-07-08 * feat(android/engine): Add additional info on installed keyboards exceptions (#3319) ## 14.0.106 alpha 2020-07-04 * fix(android/app) Download associated dictionary when installing cloud keyboard package (#3307) ## 14.0.105 alpha 2020-07-03 * feat(android): Download default resources at build time (#3300) * fix(android/engine): Fix unbound variable in build script (#3308) ## 14.0.104 alpha 2020-07-01 * fix(android): Resize PackageActivity title text (#3297) ## 14.0.103 alpha 2020-06-30 * fix(common/core/web): fixes transcription buffer cap (#3301) ## 14.0.102 alpha 2020-06-29 * fix(android): Use tier to determine keyboard search host (#3296) * refactor(ios/engine): Resource download cleanup and mocking prep (#3292) * refactor(ios/engine): ID-based download tracking, update notification rework (#3295) ## 14.0.101 alpha 2020-06-26 * feat(linux): address code review comments of #3278 (#3281) * fix(linux): Always restart IBus when installing keyboard (#3284) * refactor(linux): cleanup code (#3286) * fix(linux): Fix crash converting kvk into LDML (#3288) * feat(ios/engine): package-version query implementation (#3280) ## 14.0.100 alpha 2020-06-25 * refactor(ios/engine): Download notifications via completion blocks (#3274) * refactor(ios/engine): better resource type links (#3276) * refactor(ios/engine): Resource-download installation closures (#3277) * feat(linux): Install keyboard on Gnome (#3278) ## 14.0.99 alpha 2020-06-24 * feat(ios/engine): adds getInstalledPackage(for:) (#3270) * refactor(linux): address code review comments of #3272 (#3275) ## 14.0.98 alpha 2020-06-23 * refactor(ios/engine): reworks download queue objects (#3267) * feat(linux): Improve Linux package description (#3268) ## 14.0.97 alpha 2020-06-22 * feat(android): Implement menu to add language for installed keyboard pkg (#3255) * fix(mac/resources): altool is failing but we lose the log in CI (#3264) * refactor(ios/engine): more notification rework prep (#3262) * fix(mac): altool second call report ci errors (#3265) * refactor(ios/engine): more dead code removal (#3266) ## 14.0.96 alpha 2020-06-19 * fix(ios/engine): fixes keyboard swapping (#3259) * fix(common/resources): shebang for lerna-based Linux builds (#3260) * refactor(ios/engine): Notification rework prep, simplification (#3261) ## 14.0.95 alpha 2020-06-19 * feat(android/app): Consolidate install menus (#3245) * change(ios/engine): migrates legacy cloud resources to KMP format (#3237) * change(ios/engine): Default resource update (#3244) * fix(ios/engine): migration of preload-sourced resources (#3247) * refactor(common/resources): web-environment package (#3248) * chore(linux): Add some unit tests for keyman_config (#3250) * chore(linux): Update automatically installed dependencies (#3254) * fix(common/resources): web-environment package-lock.json (#3256) ## 14.0.94 alpha 2020-06-16 * feat(linux): Add onboard as recommended package (#3241) ## 14.0.93 alpha 2020-06-15 * fix(developer/ide): double click to change layer update combo (#3240) * fix(developer/ide): fix copy and paste in touch editor (#3238) ## 14.0.92 alpha 2020-06-12 * change(ios/engine): Package migration prep (#3229) * chore: labeler (#3233) * feat(android/engine): Migrate cloud keyboards when updating keyboard package (#3221) * refactor(ios/engine): explicitly synchronous Package processing (#3230) * feat(ios/engine): KeymanPackage now parses its ID (#3234) * fix(windows): sentry exception reports (#3235) ## 14.0.91 alpha 2020-06-11 * chore(android): Remove google-services and update readme (#3228) ## 14.0.90 alpha 2020-06-10 * refactor(ios/engine): Language resource + keying polymorphism (#3220) * refactor(ios): Selective resource installation via abstraction (#3207) * feat(ios/engine): Generation of kmp.json for non-package resources (#3212) ## 14.0.89 alpha 2020-06-09 * fix(android/engine): Revise updateOldKeyboardsList (#3216) * feat(ios/engine): embedded KeymanWeb engine Sentry use (#3218) * feat(android): Handle model picker updates (#3209) ## 14.0.88 alpha 2020-06-08 * change(android/samples): Update addKeyboard syntax for Sample and Test apps (#3213) * fix(linux): Restart km-config after installing keyboard (#3214) ## 14.0.87 alpha 2020-06-05 * fix(developer/compilers): normalise touch layout on compile (#3203) * feat(android): Add utility to check BCP47 equivalence (#3210) * refactor(ios/engine): KMP installation now relies on KeymanPackage class, parses (#3205) * refactor(ios/engine): Abstraction of KMP installation methods (#3206) * feat(linux): Make two windows modal dialogs (#3211) ## 14.0.86 alpha 2020-06-02 * fix(ios): fixes lerna concurrency workaround and missing func reference (#3192) * fix(android/engine): Use available models for ModelPickerActivity() (#3191) * feat(android): Add system globe action to show system keyboards (#3197) * feat(linux): Open a .kmp file in km-config (#3183) * refactor(ios/engine): kmp.json - Keyboard info deserialization (#3193) * refactor(ios/engine): kmp.json - Lexical model info deserialization (#3195) * feat(ios/engine): kmp.json - full deserialization (#3198) * fix(android): Add wrapper for logging errors & exceptions (#3196) * fix(oem/fv/ios): new certificate (#3201) ## 14.0.85 alpha 2020-05-30 * change(android/engine): Clean up naming for formatting QR code URL (#3187) ## 14.0.84 alpha 2020-05-29 * change(developer): packs ModelCompiler via npm pack, 7-zip (#3166) * change(web): Selective Sentry uploads (#3163) * refactor(ios/engine): Polishes HTTPDownloader to prep for unit testing (#3179) * feat(ios/engine): HTTPDownloader unit testing (#3180) * fix(linux): Disable buttons if no keyboard installed (#3184) * change(ios/engine): Removes unused, deprecated JS/JSON-based adhoc install code (#3186) * change(common/models,developer/compilers): move joiner from LMLayer to model compiler (#3071) ## 14.0.83 alpha 2020-05-28 * change(ios): Selective Sentry uploads (#3162) * change(android/engine): Handle keyboard package updates (#3175) * fix(common/models/types): fixes models-types build script, sets std header (#3182) ## 14.0.82 alpha 2020-05-27 * fix(ios): fixes build warning on Error coersion, fixes logged error for intermediate embedded state (#3173) * fix(linux): Don't fail (un-)install if running multiple ibus (#3169) * chore(linux): Update maintainer in package metadata (#3168) * feat(linux): Improve appstream metadata (#3176) ## 14.0.81 alpha 2020-05-27 * refactor(resources): convert gosh into npm package 🙃 (#3159) * chore(common,web): use consistent TypeScript dep on all packages (#3158) * chore(common/resources): add `common/models` to build trigger definitions (#3144) * fix(common/resources): adds package-lock.json for gosh package (#3171) ## 14.0.80 alpha 2020-05-25 * fix(android/engine): Remove LanguageListUtil (#3155) * refactor(common/models/templates): create package: @keymanapp/models-templates (#3128) ## 14.0.79 alpha 2020-05-22 * fix(android): Fix system keyboard globe button override (#3140) * fix(common/core/web): use build script to generate environment.inc.ts (#3146) * change(common/core/web,web): update dependencies to @keymanapp/models-types (#3147) ## 14.0.78 alpha 2020-05-21 * refactor(common/models): factor out word breakers to their own package (#3125) * fix(developer): crash when developer starts (#3138) * chore(android): Refactor KeyboardPickerActivity (#3113) * chore(common/resources): cleanup scopes (#3139) * feat(web): starts proper KMW Sentry integration (#3122) * refactor(common/models/types): rename @keymanapp/lexical-model-types => @keymanapp/models-types (#3143) * change(common/core/web): add and distribute type declaration (#3145) * fix(common/models/types): drops version updates for deprecated common/lexical-model-types (#3148) ## 14.0.77 alpha 2020-05-19 * refactor(web/engine): Moves common utility functions into separate `web-utils` package (#3130) * refactor(web/engine): renames DeviceSpec, moves to utils (#3132) * fix(ios): Fixes keyboard metadata decoding, tweaks to project files (#3137) * feat(windows): Use http: instead of file: for Configuration UI (#3127) ## 14.0.76 alpha 2020-05-15 * fix(windows): use correct name for Sentry in C++ (#3129) * chore: Allow to override hook defs (#3112) ## 14.0.75 alpha 2020-05-13 * feat(android/samples): Add Tamil lexical model to KMSample2 (#3123) ## 14.0.74 alpha 2020-05-11 * fix(windows): kmbrowserhost was missing debug info (#3117) ## 14.0.73 alpha 2020-05-11 * fix(windows): force output keystroke failure (#3083) * fix(windows): kmshell title and kmbrowserhost sentry (#3115) ## 14.0.72 alpha 2020-05-08 * fix(oem/fv/ios): Fixes FV app's system keyboard (#3105) * fix(oem/fv/ios): FV light mode lock and basic banner fix (#3108) * fix(windows): sentry cef shutdown interactions (#3107) * feat(android): Migrate installed keyboards list to keyboards_list.json (#3091) ## 14.0.71 alpha 2020-05-08 * fix(windows): use consistent sentry db location (#3100) ## 14.0.70 alpha 2020-05-07 * fix(android/app): Fix back button after System Keyboard dismissed (#3093) * fix(android/samples): Back button to dismiss KMSample2 system keyboard (#3095) * fix(oem/fv/android): Back button to dismiss FV Android system keyboard (#3096) ## 14.0.69 alpha 2020-05-06 * fix(common/resources): npm install required for auto inc lerna versions (#3089) * fix(windows): sentry x64 stacks truncated pointers (#3087) ## 14.0.68 alpha 2020-05-06 * fix(common/core/desktop): enable build for win x64, use global VERSION.md and fix decxstr() bug (#3076) * change(android): Add methods to go between LanguageResource and JSON (#3079) * feat(common): auto-update for package versioning (#3078) ## 14.0.67 alpha 2020-05-05 * fix(oem/fv/ios): Additional libraries for FirstVoices SWKeyboard (#3080) ## 14.0.66 alpha 2020-05-04 * feat(web): test Recorder overhaul, Node-based tests using Recorder for KeyboardProcessor (#3060) * fix(oem/fv/ios): add sentry framework to carthage build step (#3074) ## 14.0.65 alpha 2020-05-03 * fix(oem/fv/ios): try embed of sentry again for fv (#3072) ## 14.0.64 alpha 2020-05-01 * fix(oem/fv/ios): add sentry framework to fv keyboards (#3069) ## 14.0.63 alpha 2020-05-01 * fix(android): Fix FileUtilsTest to be cross-platform (#3061) * fix(windows): add LARGEADDRESSAWARE flag for all CEF processes (#3064) * fix(android): Remove more custom keyboard fields(#3051) * fix(oem/fv/ios): FV settings bundle for SWKeyboard (#3066) * change(common/models/wordbreakers): single-pass join word breaker decorator (#3059) ## 14.0.62 alpha 2020-05-01 * change(oem/fv/android): Update DSN for FV Android app (#3050) * feat(web/engine): Basic KeyboardProcessor tests (#2994) * fix(oem/fv/android): Update FirstVoices build_keyboards.sh script (#3045) * fix(oem/fv/ios): Update FirstVoices build_keyboards.sh script (#3045) ## 14.0.61 alpha 2020-04-30 * chore(common/resources): bump @actions/http-client from 1.0.3 to 1.0.8 in /resources/build/version (#3047) * fix(oem/fv/ios): firstvoices icon and version info (#3044) * feat(windows): Sentry integration fixes and polish (#3006) * feat(developer/compilers): compile joinWordsAt property (#3032) ## 14.0.60 alpha 2020-04-29 * feat(common/resources): initial use of lerna (in-repo package links only) (#2997) * change(web/engine): spins core/web/keyboard-processor package off from KeymanWeb (#3001) * change(web/engine): spins core/web/input-processor package off from KeymanWeb (#3008) * chore(common/models): change author from personal to work affiliation (#3046) ## 14.0.59 alpha 2020-04-29 * chore: merge stable history (#3037) * feat(common/models/wordbreakers): create join word breaker decorator (#3021) * fix(oem/fv/ios): download fv keyboards (#3040) * change(android): Refactor LanguageResource() and remove "Custom" property (#3033) ## 14.0.58 alpha 2020-04-28 * change(developer/compilers): improvements to default searchTermToKey (#3024) ## 14.0.57 alpha 2020-04-27 * change(common/resources): Update to Unicode 13.0 (#3029) * change(android): Refactor Keyboard class to not use Map (#3020) ## 14.0.56 alpha 2020-04-24 * fix(android): Clarify label that shows "Get Started" on startup (#3025) * feat(developer/compilers): allow for verbose word breaker specification (#3023) ## 14.0.55 alpha 2020-04-23 * change(android): Convert LanguageListActivity to utility (#3018) * change(android): Change "Get Started" keyboard picker to bring up embedded keyboard search (#3013) * feat(common): lerna now npm-installed locally (#3012) * refactor(web/engine): successful web-core compilation (#2992) * change(common/models,developer/compilers): always bundle searchTermToKey() with model (#2971) * change(common/models): remove NFD table (#3014) ## 14.0.54 alpha 2020-04-22 * refactor(developer/compilers): word breaker compilation (#3016) ## 14.0.53 alpha 2020-04-21 * refactor(common/models): Abstracted connection between LMLayer and Worker initialization (#2986) * refactor(common/models): starts a formal 'headless' mode (#2987) * fix(android): predictive banner display bugfix (#3010) * fix(android): Fix system keyboard alignment (#3009) ## 14.0.52 alpha 2020-04-17 * refactor(web/engine): precomputation for OSK key events, headless production thereof (#2969) * refactor(web/engine): initial ModelManager split (#2974) * refactor(web/engine): LMLayer enablement state management rework (#2975) * refactor(web/engine): predictive data routing, LanguageProcessor as EventEmitter (#2976) * refactor(web/engine): web-core build prep (#2982) ## 14.0.51 alpha 2020-04-16 * change(android): Update minimum SDK to 21 (#2993) ## 14.0.50 alpha 2020-04-15 * feat(android): Add KMPBrowserActivity for cloud keyboard searches (#2961) * fix(android): Handle default font DejaVuSans.ttf (#2981) * feat(android): Download cloud keyboards from https://keyman.com/keyboards (#2953) * fix(ios): iOS 13.4 subkey menu workaround (#2959) * change(ios): Web-based popup key longpresses (#2968) * fix(web): repairs Web regression test suite (#2973) * feat(android): Dismiss system keyboard on Back press (#2984) ## 14.0.49 alpha 2020-04-11 * chore(common/models): do not run tests in IE11 in Windows (#2978) ## 14.0.48 alpha 2020-04-07 * feat(windows): Testing Sentry integration (#2923) * feat(windows): use crashpad and better call stacks (#2931) ## 14.0.47 alpha 2020-04-07 * fix(common/models): use searchTermToKey() on input (#2954) * refactor(web/engine): proper split-off of DOM-reliant code (#2939) * refactor(web/engine): InputProcessor/KeyboardProcessor split (#2940) * fix(ios): prevents in-app keyboard resets (#2951) * refactor(web/engine): headless KeyboardProcessor (#2941) ## 14.0.46 alpha 2020-04-06 * fix(android): Add check for WRITE_EXTERNAL_STORAGE permission (#2946) ## 14.0.45 alpha 2020-04-05 * chore(web): bump minimist from 1.2.2 to 1.2.3 in /web/testing/regression-tests (#2947) ## 14.0.44 alpha 2020-04-03 * refactor(web/engine): relocates DOM-only parts of Processor (#2922) * refactor(web/engine): begins formally removing DOM-aware keyboard API functions from web-core KeyboardInterface (#2915) * refactor(web/engine): start of system store abstraction (#2919) * refactor(web/engine): Processor now manages current layer; OSK listens via callback (#2920) * refactor(web/engine): RuleBehavior now headless (#2925) * refactor(web/engine): variable store storage abstraction (#2926) * fix(web): fixes activeElement typing (#2927) * refactor(web/engine): relocates DOM-only parts of Processor (#2938) * fix(android): Change KeyboardHarness/build.sh to not rebuild KMEA (#2943) * feat(android): Propagate languageID when downloading kmp (#2944) ## 14.0.43 alpha 2020-04-02 * fix(web/engine): default layout fix for chiral keyboards (#2936) * fix(android): Fix exception in ResourcesUpdateTool (#2933) * change(android/samples): Update sample and test projects to install asset kmp's (#2935) ## 14.0.42 alpha 2020-04-01 * fix(android): Fix globe button crash on 3rd party apps (#2930) * change(android) Install default asset kmp's (#2928) ## 14.0.41 alpha 2020-03-31 * refactor(web/engine): KeyboardInterface/Processor cleanup and prep (#2901) * refactor(web/engine): Preps keyboard layouts definitions for web-core (#2902) * refactor(web/engine): layouts now full property of Keyboard wrapper (#2903) * feat(android): Specify optional language ID for installing kmp (#2921) ## 14.0.40 alpha 2020-03-30 * fix(developer): use correct registry types for sentry options (#2912) * fix(windows): replaces empty eventid with underscore when autoreport errors off (#2913) * refactor(web): namespacing DOM-focused management (#2891) * refactor(web/engine): starts DOM pre-processor (#2892) * refactor(web): starts OSK preprocessor (#2893) * refactor(web): headless device representation (#2894) * refactor(web): cleanup for Processor.processKeyEvent (#2899) * chore(common/resources): Cleanup unused folders and update README (#2916) ## 14.0.39 alpha 2020-03-29 * feat(windows): sentry x64 support (#2898) * feat(windows): user control for upload to sentry (#2900) ## 14.0.38 alpha 2020-03-28 * feat(ios): Add Crowdin CLI for iOS strings (#2905) ## 14.0.37 alpha 2020-03-27 * feat(windows): crash reports in CEF (#2887) * feat(common/resources): Use Crowdin CLI (v3) for handling l10n files (#2895) * fix(windows): show error if tsysinfo fails to start; kmcomapi reporting (#2897) ## 14.0.36 alpha 2020-03-26 * fix(web/engine): Fixes default key lookup returns (#2890) ## 14.0.35 alpha 2020-03-25 * feat(windows): new error notification dialog (#2875) * feat(windows): sentry c++ wrappers (#2886) * refactor(web/engine): activeKeyboard now tracked on Processor (#2864) * refactor(web/engine): Initial definition of typed Keyboard wrapper (#2868) * refactor(web/engine): More Keyboard wrapper properties (#2869) * refactor(web/engine): headless-friendly keymapping (#2870) * refactor(web/engine): relocates keyboard tag code, adds typing (#2883) * fix(web): fixes variable stores (#2884) ## 14.0.34 alpha 2020-03-24 * fix(web): fixes embedded kbd initialization (#2879) * fix(ios): popup keys over base keys no longer emit base char. (#2881) ## 14.0.33 alpha 2020-03-23 * fix(android/samples): Update min SDK versions for sample apps (#2872) * refactor(web/engine): Modularize default key output handling (#2853) * refactor(web/engine): extended abstraction with OutputTarget (#2849) * refactor(web/engine): reworks use of embedded's keyman['oninserttext'] (#2850) * refactor(web/engine): reworks default output handling to return RuleBehaviors (#2854) * refactor(web/engine): removes shiftState parameter (#2859) * refactor(web/engine): moves new RuleBehavior type & behaviors to own file (#2861) * refactor(web/engine): doInputEvent moved to OutputTarget (#2862) * refactor(web/engine): KeyboardInterface now property of Processor (#2863) * fix(windows): some sentry symbolication was not working (#2871) * fix(linux): Use __release_version__ for downloadkeyboard window (#2877) ## 14.0.32 alpha 2020-03-20 * fix(windows): include sources for sentry (#2866) ## 14.0.31 alpha 2020-03-20 * fix(android/samples): Fix min SDK version for Sample and Test apps (#2860) ## 14.0.30 alpha 2020-03-19 * docs(common/resources): minor updates to readme (#2856) ## 14.0.29 alpha 2020-03-19 * feat(windows): Add Sentry reports to Delphi apps (#2848) ## 14.0.28 alpha 2020-03-18 * fix(web): fixes design mode and content editable issues (#2838) * fix(ios): corrects OSK height adjustment, banner display issues. (#2840) * feat(windows): add sentry tooling (#2806) * refactor(web/engine): new RuleBehavior return type from keyboard calls, utilization (#2830) * refactor(web/engine): KeyEvent object now refers to outputTarget over element (#2846) * fix(linux): Fix failing Linux package builds (#2843) * feat(linux): Add focal as platform to build packages for (#2842) ## 14.0.27 alpha 2020-03-17 * chore(web): bump minimist from 1.2.0 to 1.2.2 in /web/testing/regression-tests (#2829) ## 14.0.26 alpha 2020-03-16 * fix(oem): Disable monitoring of ANR for oem Android app (#2828) ## 14.0.25 alpha 2020-03-13 * feat(common/resources): sentry release control (#2794) * chore(windows): improve build script tests (#2680) * fix(web): enhanced sourcemaps + proper sourcemaps for minified KMW (#2809) * feat(common/resources): Add script to parse crowdin translation file (#2801) * fix(linux): Fix how keyboardprocessor version is set in dist.sh (#2814) * feat(android): Additional Sentry integration (#2810) * fix(web): applies base key layer property to unassigned subkeys (#2808) * feat(android): Start adding RTL to layouts (#2816) * fix(common/models): fixes word lookup from Tries for SMP script-based languages (#2815) * feat(common/resources): add release finalization for Sentry (#2819) * fix(web): further fixes BuildVisualKeyboard. Fixes #2818 (#2822) * fix(web): fixes internal reference for validation tool (#2824) ## 14.0.24 alpha 2020-03-11 * fix(linux): Fix CI dist path to common/core/desktop (#2795) * fix(web): fixes build number reference of API call (#2796) * fix(web): updating BuildVisualKeyboard (#2802) ## 14.0.23 alpha 2020-03-10 * fix(ios): fixes Carthage framework copy for Sentry (#2800) * feat(android): Start of Sentry-based crash reporting (#2778) ## 14.0.22 alpha 2020-03-09 * fix(common/resources): parameter order incorrect in git diff (#2787) * feat(ios): compilations within Xcode now properly set version (#2775) * fix(ios/engine): Fixes context bug for certain keyboard rules after newlines (#2770) * feat(android): Update additional main app strings for crowdin (#2793) * feat(ios): Start of Sentry-based crash reporting (#2771) * feat(ios): Improved Sentry integration (first pass) (#2782) ## 14.0.21 alpha 2020-03-08 * fix(common/resources): builds were never triggered (#2790) ## 14.0.20 alpha 2020-03-08 * feat(windows): Chromium replacement for embedded MSHTML in for Keyman Desktop (#1720) * refactor(common/core/desktop): Rename keyboard core (#2735) ## 14.0.19 alpha 2020-03-06 * fix(web): support otf extension for truetype fonts (#2780) ## 14.0.18 alpha 2020-03-04 * feat(windows): etl2log support tool (#2758) * feat(developer): allow use of ISO9995 in key ids (#2741) * feat(android): Handle keyman:// protocol to download kmp keyboard (#2734) * change(android): Cleanup UI strings (#2751) * fix(ios): fixes broken online-help versioned link (#2773) ## 14.0.17 alpha 2020-02-26 * feat(ios): KeymanEngine version migration unit tests (#2692) * feat(ios): starts iOS unit testing (#2649) * fix(android) Fix crash on kbdMapList (#2719) * fix(developer): crash when switching layout templates (#2726) * feat(developer): always save options (#2731) * feat(common/resources): Support git worktree when configuring local hooks (#2722) * docs(linux): Add linux packaging documentation (#2720) * fix(developer): insert from charmap into touch editor (#2737) * fix(developer): debugger breaking smp with bksp (#2739) * feat(ios): Adds keyboard-scale unit tests, fixes unknown-device bug (#2695) ## 14.0.16 alpha 2020-02-25 * fix(android) Fix crash on kbdMapList (#2719) * fix(developer): crash when switching layout templates (#2726) ## 14.0.15 alpha 2020-02-24 * fix(android): Sanitize app version string for api query (#2715) * chore(common/resources): Improve output when triggering Jenkins jobs (#2706) * fix(common/resources): Fix increment-version.sh script (#2714) ## 14.0.14 alpha 2020-02-21 * chore(linux): allow to trigger Jenkins build from script (#2697) * fix(ios): Resource update issues (#2703) * fix(web): Web CI target reversion (#2693) * refactor(common/resources): Simplify and improve getting hook directory (#2701) ## 14.0.13 alpha 2020-02-19 * fix(linux): setup gschema (#2675) * fix(ios): Responsive predictive toggles (#2674) * chore(windows): cleanup documentation (#2681) * chore: merge p9s2 beta part 2 to master (#2683) ## 14.0.12 alpha 2020-02-18 * fix(android/samples): Fix build for KMSample1 project (#2669) * fix(developer): crash in context help (#2661) * fix(developer): crash importing blank OSK (#2663) * fix(common/core/desktop, linux): Misc keyboard processor fixes for Xenial (#2648) * fix(linux): Fix tier used in debian watch files (#2664) * fix(ios): Engine demo fix (#2662) * docs(ios): Updates offline help for new 13.0 content (#2671) * fix(developer): upgrade removes preferences (#2672) * fix(developer): upgrade removes preferences (#2668) * chore(common/resources): Rename trigger-definitions.sh to *.config (#2665) ## 14.0.11 alpha 2020-02-17 * fix(web): Fat-finger complication fixes (#2647) * feat(web): restyles prediction banner (#2629) * chore(oem/fv/ios): FV iconography update (#2650) * feat(mac): install script rather than drag+drop (#2537) * fix(common): Update configure-repo.sh to ln commit-msg-defs (#2652) * change(web): Testing resources update (#2651) * fix(android): Add ability to reinitialize `CloudDownloadMgr` (#2635) * chore: merge beta changes to master (#2659) * fix(mac): invalid build script params removed (#2660) ## 14.0.10 alpha 2020-02-14 * fix(common/core): buffer overrun in context api (#2616) * fix(web): patches Float and Toggle UI issues (#2622) * change(web): build.sh recompilation of LMLayer only performed when needed (#2623) * fix(ios): Fixes in-app use of KMSample2 (#2626) * fix(developer): touch layout editor character map integration (#2619) * fix(developer/compilers): package: version mismatch (#2620) * fix(developer/compilers): compiler sometimes merges touch platform support wrongly in .keyboard_info (#2621) * fix(ios): Fixes lexical model url generation for updates (#2627) * fix(linux): Cherrypick linux packaging fixes (#2624) * fix(developer/ide): model debugger mime type mismatch (#2633) * fix(ios): Fixes invalid keyboard display when backing out of sharing text (#2631) * fix(oem/fv/android): Update version of androidx.appcompat (#2640) * change(android): Update in-app help (#2641) * fix(developer/ide): Model editor various bugs (#2634) * fix(web): fixes positioning of native-mode language menu (#2642) * change(android): Update app dependencies (#2644) * fix(ios): initial-install check within Migrations (#2646) * fix(mac): Modifier keys were resetting cached context (#2588) * refactor(mac): initial steps of input pathway (#2643) ## 14.0.9 alpha 2020-02-10 * fix(common/core/desktop): buffer overrun in context api (#2614) * fix(common/resources): refactor trigger of test builds (#2611) * fix(ios): fixes installation of default resources and updates them (#2578) * chore(android): Update default nrc.en.mtnt.model to 0.1.4 (#2608) * chore(common/resources): add build scripts for beta tests (#2612) * fix(common/resources): don't include build-utils.sh (#2615) * fix(common/resources): Fix setting context when >= 64 characters (#2607) * fix(ios): Icon image change on light/dark mode transition (#2593) * fix(ios): Keyboard banner light/dark transitions (#2594) * fix(linux): Fix packaging of keyman-config on Xenial (#2609) ## 14.0.8 alpha 2020-02-07 * chore(common/resources): Tweak history management (#2602) * chore(common/resources): Update README.md (#2598) * chore: update history (#2605) * chore: merge beta P9S1 changes to master (#2606) * chore(common/resources): Add script that checks if build is required (#2603) * fix(linux): Install requirements before packaging (#2599) ## 14.0.7 alpha 2020-02-07 * chore(common/resources): Tweak history management (#2602) * chore(common/resources): Update README.md (#2598) ## 14.0.6 alpha 2020-02-06 * fix(windows): Windows touch keyboard would cancel on each keystroke (#2580) * fix(linux): Fix 'About' keyboard when missing copyright (#2583) * feat(linux): Keyboard options configuration dialog (#2566) * feat(common): prepare-commit-msg hook for autogenerated conventional commit messages (#2581) * fix(linux): cherry-pick packaging changes from beta branch (#2589) * fix(linux): Display the script name in log output (#2591) ## 14.0.5 alpha 2020-02-04 * chore(common/resources): support test builds on master/beta/stable-x.y (#2576) * fix(web): default BKSP output targeting (#2561) * fix(linux): Remove cosmic and disco releases (#2574) ## 14.0.4 alpha 2020-02-03 * chore(common/resources): trigger builds after version increment (#2572) * fix(ios): keyboard stability (#2545) * fix(web): dev_resource compile fix (#2557) * fix(linux): Update launchpad PPA by tier (#2551) * fix(android): Fix cancelling ConfirmDialogFragment (#2547) * fix(web): Fix K_TAB from external keyboard (#2546) * fix(ios): Now (eventually) uses sys pref for kbd clicks (#2550) * feat(ios): Deeplink into Keyman settings for system keyboard setup (#2548) * fix(common/models): RTL model specification (#2554) * fix(web): Suggestion reordering for RTL languages (#2553) * fix(ios): Fixes margins on keyboard in iOS 9/10 (#2560) ## 14.0.3 alpha 2020-02-03 * chore(common/resources): increment version final (#2568) * chore(common/resources): add version tags (#2570) ## 14.0.2 alpha 2020-01-29 * chore(common/resources): version tags (#2562) ## 14.0.1 alpha 2020-01-29 * chore(common/resources): Starting 14.0 release keyman/LICENSE.md0000664000000000000000000000273714600607066010654 0ustar # License Copyright (c) 2017-2022 SIL International. All rights reserved. Licensed under the MIT License. [Keyman for Linux](./linux) is licensed under the MIT License apart from [ibus-kmfl](./linux/ibus-kmfl) which is licensed under the GNU General Public License as published by the Free Software Foundation; either [version 2](./linux/ibus-kmfl/COPYING) of the License, or (at your option) any later version. --- The MIT License 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 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.keyman/README.md0000664000000000000000000000240714600607066010521 0ustar ![Keyman](https://keyman.com/cdn/dev/img/logo2.png) [Keyman](https://keyman.com) makes it possible for you to type in any language on Windows, macOS, Linux, iPhone, iPad, Android tablets and phones, and even instantly in your web browser. Create keyboard layouts with Keyman Developer and share them with the community in the [keyboards repository](https://github.com/keymanapp/keyboards). The [Keyman Community](https://community.software.sil.org/c/keyman) have already contributed keyboard layouts for over 2,000 languages! # License Copyright (c) SIL International. Keyman is an open source project distributed under the [MIT license](LICENSE.md). # Get Involved * [Code of Conduct](CODE_OF_CONDUCT.md) * [Contributing to the Keyman App](CONTRIBUTING.md) * [Localize Keyman](https://translate.keyman.com/project/keyman) * [Other Ways of Getting Involved](https://keyman.com/about/get-involved) # Development Status * [Development Status Site](https://status.keyman.com) # Important Links * [Keyman Home](https://keyman.com) * [Downloads](https://keyman.com/downloads) * [Keyboards](https://keyman.com/keyboards) * [Documentation](https://help.keyman.com/) * [Online Keyboard](https://keymanweb.com/) * [SIL Language Technology - software.sil.org](https://software.sil.org/) keyman/TIER.md0000664000000000000000000000000514600607066010317 0ustar beta keyman/VERSION.md0000664000000000000000000000001014600607066010675 0ustar 17.0.295keyman/common/0000775000000000000000000000000014600607066010527 5ustar keyman/common/build.sh0000775000000000000000000000114114600607066012162 0ustar #!/usr/bin/env bash ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE builder_describe "Keyman common and resources modules" \ ":resources=../resources" \ ":linux" \ ":mac" \ ":web" \ ":windows" \ clean \ configure \ build \ test builder_parse "$@" #------------------------------------------------------------------------------------------------------------------- builder_run_child_actions clean configure build test keyman/common/include/0000775000000000000000000000000014600607066012152 5ustar keyman/common/include/build.sh0000775000000000000000000000224014600607066013606 0ustar #!/usr/bin/env bash # # Creates keymanversion_build.h # # Exit on command failure and when using unset variables: set -eu ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE cd "$THIS_SCRIPT_PATH" builder_describe "Build keymanversion_build.h" configure build clean builder_describe_outputs \ configure /common/include/.keymanversion_build.configured \ build /common/include/keymanversion_build.h builder_parse "$@" #------------------------------------------------------------------------------------------------------------------- if builder_start_action clean; then rm -f keymanversion_build.h .keymanversion_build.configured builder_finish_action success clean fi if builder_start_action configure; then # no-op, keeping 'configure' for deps touch .keymanversion_build.configured builder_finish_action success configure fi if builder_start_action build; then replaceVersionStrings_Mkver keymanversion_build.in keymanversion_build.h builder_finish_action success build fi keyman/common/include/keymanversion_build.in0000664000000000000000000000352514600607066016560 0ustar #pragma once // This file is transformed from keymanversion_build.in to keymanversion_build.h by /common/include/build.sh // Legacy version number defines #define KEYMANVERSION "$RELEASE" #define KEYMANVERSIONW L"$RELEASE" // Current version number defines #define KEYMAN_Version "$Version" #define KEYMAN_Version_W L"$Version" #define KEYMAN_VersionWin "$VersionWin" #define KEYMAN_VersionWin_W L"$VersionWin" #define KEYMAN_VersionWin_W16 u"$VersionWin" #define KEYMAN_VersionRelease "$VersionRelease" #define KEYMAN_VersionRelease_W L"$VersionRelease" #define KEYMAN_VersionMajor $VersionMajor #define KEYMAN_VersionMinor $VersionMinor #define KEYMAN_VersionPatch $VersionPatch #define KEYMAN_Tier "$Tier" #define KEYMAN_Tier_W L"$Tier" #define KEYMAN_Tag "$Tag" #define KEYMAN_Tag_W L"$Tag" #define KEYMAN_VersionWithTag "$VersionWithTag" #define KEYMAN_VersionWithTag_W L"$VersionWithTag" #define KEYMAN_VersionRc "$VersionRc" #define KEYMAN_VersionRc_W L"$VersionRc" #define KEYMAN_Environment "$Environment" #define KEYMAN_Environment_W L"$Environment" #define KEYMAN_VersionGitTag "$VersionGitTag" #define KEYMAN_VersionGitTag_W L"$VersionGitTag" // // Version macros for .rc files /// #define kv_version_stringify(x) kv_version_to_string(x) #define kv_version_to_string(x) #x // Product versioning #define KV_VERSION_MAJOR $VersionMajor #define KV_VERSION_MINOR $VersionMinor #define KV_VERSION_PATCH $VersionPatch #define KV_VERSION_STRING kv_version_stringify($VersionMajor ## . ## $VersionMinor ## . ## $VersionPatch ## .0) "\0" #define KV_FILEVERSION KV_VERSION_MAJOR, KV_VERSION_MINOR, KV_VERSION_PATCH, 0 #define KV_PRODUCTVERSION KV_VERSION_MAJOR, KV_VERSION_MINOR, KV_VERSION_PATCH, 0 keyman/common/include/km_types.h0000664000000000000000000000460614600607066014164 0ustar #pragma once #include #include /* #if defined(_WIN32) || defined(_WIN64) #define snprintf _snprintf #define vsnprintf _vsnprintf #define strcasecmp _stricmp #define strncasecmp _strnicmp #endif */ #if defined(__LP64__) || defined(_LP64) /* 64-bit, g++ */ #define KMX_64BIT #endif #if defined(_WIN64) && !defined(USE_64) /* 64-bit, Windows */ #define KMX_64BIT #endif typedef uint32_t KMX_DWORD; typedef int32_t KMX_BOOL; typedef uint8_t KMX_BYTE; typedef uint16_t KMX_WORD; #if defined(__cplusplus) typedef char16_t km_core_cp; typedef char32_t km_core_usv; #else typedef uint16_t km_core_cp; // code point typedef uint32_t km_core_usv; // Unicode Scalar Value #endif typedef km_core_cp KMX_WCHAR; // wc, 16-bit UNICODE character typedef KMX_WCHAR* PKMX_WCHAR; typedef char KMX_CHAR; typedef char* PKMX_STR; typedef KMX_CHAR* PKMX_CHAR; typedef uint32_t KMX_UINT; typedef KMX_BYTE* PKMX_BYTE; typedef KMX_WORD* PKMX_WORD; typedef KMX_DWORD* PKMX_DWORD; #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif // Macros and types to support char16_t vs wchar_t depending on project #ifdef USE_CHAR16_T #define lpuch(x) u ## x typedef km_core_cp KMX_UCHAR; #else #define lpuch(x) L ## x typedef wchar_t KMX_UCHAR; #endif typedef KMX_UCHAR* KMX_PUCHAR; // Alignment /* When we read .kmx files, they have no alignment guarantees, so we need to tell the compiler to generate unaligned-safe code for accesses to COMP_ structure members. Note we are assuming that COMP_KEYBOARD is aligned because it is always the start of the file, so will be at the start of any buffer which will automatically be aligned correctly. TODO: consider using c++11 alignas */ #if defined(__EMSCRIPTEN__) || defined (__GNUC__) || defined (__clang__) typedef KMX_DWORD __attribute__((aligned(1))) KMX_DWORD_unaligned; typedef KMX_BOOL __attribute__((aligned(1))) KMX_BOOL_unaligned; typedef KMX_WORD __attribute__((aligned(1))) KMX_WORD_unaligned; #elif defined(_MSC_VER) typedef KMX_DWORD __declspec(align(1)) KMX_DWORD_unaligned; typedef KMX_BOOL __declspec(align(1)) KMX_BOOL_unaligned; typedef KMX_WORD __declspec(align(1)) KMX_WORD_unaligned; #else // TODO: consider other platforms #define KMX_DWORD_unaligned KMX_DWORD #define KMX_BOOL_unaligned KMX_BOOL #define KMX_WORD_unaligned KMX_WORD #endif keyman/common/include/kmx_file.h0000664000000000000000000002752014600607066014127 0ustar /* Copyright: Copyright (C) 2003-2018 SIL International. Authors: mcdurdin */ #pragma once #include #ifdef KM_CORE_LIBRARY // TODO: move this to a common namespace keyman::common::kmx_file or similar in the future namespace km { namespace core { namespace kmx { #endif #define KMX_MAX_ALLOWED_FILE_SIZE (128 * 1024 * 1024) /* 128MB */ /* */ #define KEYMAN_LAYOUT_DEFAULT 0x000005FE #define KEYMANID_NONKEYMAN 0xFFFFFFFF #define KEYMANID_IGNORE 0xFFFFFFFE #define KEYMANID_INVALID 0xFFFFFFFD /* Shift flags for hotkeys (version 1.0) */ #define SHIFTFLAG 0x2000 #define CTRLFLAG 0x4000 #define ALTFLAG 0x8000 /* Miscellaneous flags and defines */ #define MAXGROUPS 128 /* File version identifiers */ #define VERSION_30 0x00000300 #define VERSION_31 0x00000301 #define VERSION_32 0x00000302 #define VERSION_40 0x00000400 #define VERSION_50 0x00000500 #define VERSION_501 0x00000501 #define VERSION_60 0x00000600 #define VERSION_70 0x00000700 #define VERSION_80 0x00000800 #define VERSION_90 0x00000900 #define VERSION_100 0x00000A00 #define VERSION_140 0x00000E00 #define VERSION_150 0x00000F00 #define VERSION_160 0x00001000 #define VERSION_170 0x00001100 #define VERSION_MIN VERSION_50 #define VERSION_MAX VERSION_170 // // Backspace types // #define BK_DEFAULT 0 #define BK_DEADKEY 1 // Different begin types #define BEGIN_ANSI 0 #define BEGIN_UNICODE 1 #define BEGIN_NEWCONTEXT 2 #define BEGIN_POSTKEYSTROKE 3 #define TSS_NONE 0 #define TSS_BITMAP 1 #define TSS_COPYRIGHT 2 #define TSS_HOTKEY 3 #define TSS_LANGUAGE 4 #define TSS_LAYOUT 5 #define TSS_MESSAGE 6 #define TSS_NAME 7 #define TSS_VERSION 8 #define TSS_CAPSONONLY 9 #define TSS_CAPSALWAYSOFF 10 #define TSS_SHIFTFREESCAPS 11 #define TSS_LANGUAGENAME 12 #define TSS_CALLDEFINITION 13 #define TSS_CALLDEFINITION_LOADFAILED 14 #define TSS_ETHNOLOGUECODE 15 #define TSS_DEBUG_LINE 16 #define TSS_MNEMONIC 17 #define TSS_INCLUDECODES 18 #define TSS_OLDCHARPOSMATCHING 19 #define TSS_COMPILEDVERSION 20 #define TSS_KEYMANCOPYRIGHT 21 #define TSS_CUSTOMKEYMANEDITION 22 #define TSS_CUSTOMKEYMANEDITIONNAME 23 /* Keyman 7.0 system stores */ #define TSS__KEYMAN_60_MAX 23 #define TSS_VISUALKEYBOARD 24 #define TSS_KMW_RTL 25 #define TSS_KMW_HELPFILE 26 #define TSS_KMW_HELPTEXT 27 #define TSS_KMW_EMBEDJS 28 #define TSS_WINDOWSLANGUAGES 29 #define TSS__KEYMAN_70_MAX 29 /* Keyman 8.0 system stores */ #define TSS_COMPARISON 30 #define TSS__KEYMAN_80_MAX 30 /* Keyman 9.0 system stores */ #define TSS_PLATFORM 31 #define TSS_BASELAYOUT 32 #define TSS_LAYER 33 #define TSS_PLATFORM_NOMATCH 0x8001 // Reserved for internal use - after platform statement is run, set to either TSS_PLATFORM_NOMATCH or TSS_PLATFORM_MATCH #define TSS_PLATFORM_MATCH 0x8002 // Reserved for internal use - as the result will never change for the lifetime of the process. #define TSS_VKDICTIONARY 34 // Dictionary of virtual key names for v9 dynamic layouts #define TSS_LAYOUTFILE 35 // Keyman 9 layer-based JSON OSK #define TSS_KEYBOARDVERSION 36 // &keyboardversion system store // I4140 #define TSS_KMW_EMBEDCSS 37 #define TSS_TARGETS 38 #define TSS__KEYMAN_90_MAX 38 /* Keyman 14.0 system stores */ #define TSS_CASEDKEYS 39 #define TSS__KEYMAN_140_MAX 39 /* Keyman 15.0 system stores */ #define TSS_BEGIN_NEWCONTEXT 40 #define TSS_BEGIN_POSTKEYSTROKE 41 #define TSS_NEWLAYER 42 #define TSS_OLDLAYER 43 #define TSS__KEYMAN_150_MAX 43 /* Keyman 17.0 system stores */ #define TSS_DISPLAYMAP 44 #define TSS__KEYMAN_170_MAX 44 #define TSS__MAX 44 /* wm_keyman_control_internal message control codes */ #define KMCI_SELECTKEYBOARD 3 // I3933 #define KMCI_SELECTKEYBOARD_TSF 4 // I3933 #define KMCI_GETACTIVEKEYBOARD 5 // I3933 #define KMCI_SETFOREGROUND 6 // I3933 #define KMCI_SELECTKEYBOARD_BACKGROUND 7 // I4271 #define KMCI_SELECTKEYBOARD_BACKGROUND_TSF 8 // I4271 #define FILEID_COMPILED 0x5354584B #define SZMAX_LANGUAGENAME 80 #define SZMAX_KEYBOARDNAME 80 #define SZMAX_COPYRIGHT 256 #define SZMAX_MESSAGE 1024 #define UC_SENTINEL 0xFFFF #define UC_SENTINEL_EXTENDEDEND 0x10 // was ((CODE_LASTCODE)+1)... what was I thinking? #define U_UC_SENTINEL u"\uFFFF" /* * VK__MAX defines the highest virtual key code defined in the system = 0xFF. Custom VK codes start at 256 */ #define VK__MAX 255 #define CODE_ANY 0x01 #define CODE_INDEX 0x02 #define CODE_CONTEXT 0x03 #define CODE_NUL 0x04 #define CODE_USE 0x05 #define CODE_RETURN 0x06 #define CODE_BEEP 0x07 #define CODE_DEADKEY 0x08 // 0x09 = bkspace.-- we don't need to keep this separate though with UC_SENTINEL #define CODE_EXTENDED 0x0A //#define CODE_EXTENDEDEND 0x0B deprecated #define CODE_SWITCH 0x0C #define CODE_KEY 0x0D #define CODE_CLEARCONTEXT 0x0E #define CODE_CALL 0x0F // UC_SENTINEL_EXTENDEDEND 0x10 #define CODE_CONTEXTEX 0x11 #define CODE_NOTANY 0x12 #define CODE_KEYMAN70_LASTCODE 0x12 #define CODE_SETOPT 0x13 #define CODE_IFOPT 0x14 #define CODE_SAVEOPT 0x15 #define CODE_RESETOPT 0x16 #define CODE_KEYMAN80_LASTCODE 0x16 /* Keyman 9.0 codes */ #define CODE_IFSYSTEMSTORE 0x17 #define CODE_SETSYSTEMSTORE 0x18 #define CODE_LASTCODE 0x18 #define U_CODE_ANY u"\u0001" #define U_CODE_INDEX u"\u0002" #define U_CODE_CONTEXT u"\u0003" #define U_CODE_NUL u"\u0004" #define U_CODE_USE u"\u0005" #define U_CODE_RETURN u"\u0006" #define U_CODE_BEEP u"\u0007" #define U_CODE_DEADKEY u"\u0008" #define U_CODE_EXTENDED u"\u000A" #define U_CODE_SWITCH u"\u000C" #define U_CODE_CLEARCONTEXT u"\u000E" #define U_CODE_CALL u"\u000F" #define U_CODE_EXTENDEDEND u"\u0010" #define U_CODE_CONTEXTEX u"\u0011" #define U_CODE_NOTANY u"\u0012" #define U_CODE_SETOPT u"\u0013" #define U_CODE_IFOPT u"\u0014" #define U_CODE_SAVEOPT u"\u0015" #define U_CODE_RESETOPT u"\u0016" #define U_CODE_IFSYSTEMSTORE u"\u0017" #define U_CODE_SETSYSTEMSTORE u"\u0018" #define C_CODE_ANY(store) U_UC_SENTINEL U_CODE_ANY store #define C_CODE_INDEX(val1, val2) U_UC_SENTINEL U_CODE_INDEX val1 val2 #define C_CODE_CONTEXT() U_UC_SENTINEL U_CODE_CONTEXT #define C_CODE_NUL() U_UC_SENTINEL U_CODE_NUL #define C_CODE_USE(val) U_UC_SENTINEL U_CODE_USE val #define C_CODE_RETURN() U_UC_SENTINEL U_CODE_RETURN #define C_CODE_BEEP() U_UC_SENTINEL U_CODE_BEEP #define C_CODE_DEADKEY(deadkey) U_UC_SENTINEL U_CODE_DEADKEY deadkey #define C_CODE_EXTENDED(varargs) U_UC_SENTINEL U_CODE_EXTENDED varargs #define C_CODE_SWITCH(val) U_UC_SENTINEL U_CODE_SWITCH val #define C_CODE_CLEARCONTEXT() U_UC_SENTINEL U_CODE_CLEARCONTEXT #define C_CODE_CALL(val) U_UC_SENTINEL U_CODE_CALL val #define C_CODE_CONTEXTEX(val) U_UC_SENTINEL U_CODE_CONTEXTEX val #define C_CODE_NOTANY(val) U_UC_SENTINEL U_CODE_NOTANY val #define C_CODE_SETOPT(val1, val2) U_UC_SENTINEL U_CODE_SETOPT val1 val2 #define C_CODE_IFOPT(opt, val1, val2) U_UC_SENTINEL U_CODE_IFOPT opt val1 val2 #define C_CODE_SAVEOPT(opt) U_UC_SENTINEL U_CODE_SAVEOPT opt #define C_CODE_RESETOPT(opt) U_UC_SENTINEL U_CODE_RESETOPT opt #define C_CODE_IFSYSTEMSTORE(store, val1, val2) U_UC_SENTINEL U_CODE_IFSYSTEMSTORE store val1 val2 #define C_CODE_SETSYSTEMSTORE(store, val) U_UC_SENTINEL U_CODE_SETSYSTEMSTORE store val #define KF_SHIFTFREESCAPS 0x0001 #define KF_CAPSONONLY 0x0002 #define KF_CAPSALWAYSOFF 0x0004 #define KF_LOGICALLAYOUT 0x0008 #define KF_AUTOMATICVERSION 0x0010 // 16.0: Support for LDML Keyboards in KMXPlus file format #define KF_KMXPLUS 0x0020 #define HK_ALT 0x00010000 #define HK_CTRL 0x00020000 #define HK_SHIFT 0x00040000 #define LCTRLFLAG 0x0001 // Left Control flag #define RCTRLFLAG 0x0002 // Right Control flag #define LALTFLAG 0x0004 // Left Alt flag #define RALTFLAG 0x0008 // Right Alt flag #define K_SHIFTFLAG 0x0010 // Either shift flag #define K_CTRLFLAG 0x0020 // Either ctrl flag #define K_ALTFLAG 0x0040 // Either alt flag //#define K_METAFLAG 0x0080 // Either Meta-key flag (tentative). Not usable in keyboard rules; // Used internally (currently, only by KMW) to ensure Meta-key // shortcuts safely bypass rules // Meta key = Command key on macOS, Windows key on Windows #define CAPITALFLAG 0x0100 // Caps lock on #define NOTCAPITALFLAG 0x0200 // Caps lock NOT on #define NUMLOCKFLAG 0x0400 // Num lock on #define NOTNUMLOCKFLAG 0x0800 // Num lock NOT on #define SCROLLFLAG 0x1000 // Scroll lock on #define NOTSCROLLFLAG 0x2000 // Scroll lock NOT on #define ISVIRTUALKEY 0x4000 // It is a Virtual Key Sequence #define VIRTUALCHARKEY 0x8000 // Keyman 6.0: Virtual Key Cap Sequence NOT YET #define K_MODIFIERFLAG 0x007F #define K_NOTMODIFIERFLAG 0xFF00 // I4548 struct COMP_STORE { KMX_DWORD_unaligned dwSystemID; KMX_DWORD_unaligned dpName; KMX_DWORD_unaligned dpString; }; struct COMP_KEY { KMX_WORD_unaligned Key; KMX_WORD_unaligned _reserved; KMX_DWORD_unaligned Line; KMX_DWORD_unaligned ShiftFlags; KMX_DWORD_unaligned dpOutput; KMX_DWORD_unaligned dpContext; }; struct COMP_GROUP { KMX_DWORD_unaligned dpName; KMX_DWORD_unaligned dpKeyArray; // [LPKEY] address of first item in key array KMX_DWORD_unaligned dpMatch; KMX_DWORD_unaligned dpNoMatch; KMX_DWORD_unaligned cxKeyArray; // in array entries KMX_BOOL_unaligned fUsingKeys; // group(xx) [using keys] <-- specified or not }; struct COMP_KEYBOARD { KMX_DWORD dwIdentifier; // 0000 Keyman compiled keyboard id KMX_DWORD dwFileVersion; // 0004 Version of the file - Keyman 4.0 is 0x0400 KMX_DWORD dwCheckSum; // 0008 As stored in keyboard. DEPRECATED as of 16.0 KMX_DWORD KeyboardID; // 000C as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts KMX_DWORD IsRegistered; // 0010 KMX_DWORD version; // 0014 keyboard version KMX_DWORD cxStoreArray; // 0018 in array entries KMX_DWORD cxGroupArray; // 001C in array entries KMX_DWORD dpStoreArray; // 0020 [LPSTORE] address of first item in store array KMX_DWORD dpGroupArray; // 0024 [LPGROUP] address of first item in group array KMX_DWORD StartGroup[2]; // 0028 index of starting groups [2 of them] KMX_DWORD dwFlags; // 0030 Flags for the keyboard file KMX_DWORD dwHotKey; // 0034 standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey) KMX_DWORD dpBitmapOffset; // 0038 offset of the bitmaps in the file KMX_DWORD dwBitmapSize; // 003C size in bytes of the bitmaps }; struct COMP_KEYBOARD_KMXPLUSINFO { KMX_DWORD dpKMXPlus; // 0040 offset of KMXPlus data, header is first KMX_DWORD dwKMXPlusSize; // 0044 size in bytes of entire KMXPlus data }; /** * Only valid if comp_keyboard.dwFlags&KF_KMXPLUS */ struct COMP_KEYBOARD_EX { COMP_KEYBOARD header; // 0000 see COMP_KEYBOARD COMP_KEYBOARD_KMXPLUSINFO kmxplus; // 0040 see COMP_KEYBOARD_EXTRA }; typedef COMP_KEYBOARD *PCOMP_KEYBOARD; typedef COMP_STORE *PCOMP_STORE; typedef COMP_KEY *PCOMP_KEY; typedef COMP_GROUP *PCOMP_GROUP; extern const int CODE__SIZE[]; #define CODE__SIZE_MAX 5 #define KEYBOARDFILEHEADER_SIZE 64 #define KEYBOARDFILESTORE_SIZE 12 #define KEYBOARDFILEGROUP_SIZE 24 #define KEYBOARDFILEKEY_SIZE 20 static_assert(sizeof(COMP_STORE) == KEYBOARDFILESTORE_SIZE, "COMP_STORE must be KEYBOARDFILESTORE_SIZE bytes"); static_assert(sizeof(COMP_KEY) == KEYBOARDFILEKEY_SIZE, "COMP_KEY must be KEYBOARDFILEKEY_SIZE bytes"); static_assert(sizeof(COMP_GROUP) == KEYBOARDFILEGROUP_SIZE, "COMP_GROUP must be KEYBOARDFILEGROUP_SIZE bytes"); static_assert(sizeof(COMP_KEYBOARD) == KEYBOARDFILEHEADER_SIZE, "COMP_KEYBOARD must be KEYBOARDFILEHEADER_SIZE bytes"); #ifdef KM_CORE_LIBRARY } // namespace kmx } // namespace core } // namespace km #endif keyman/common/include/test_assert.h0000664000000000000000000000374714600607066014676 0ustar /* * Keyman is copyright (C) SIL International. MIT License. * * Keyman Core - test assertion macros */ #pragma once #include #include #include #include #include "test_color.h" #ifdef _assert_failed #undef _assert_failed #endif #define _assert_failed(result, exprText) { \ std::wcerr << console_color::fg(console_color::BRIGHT_RED) \ << "Test failed with " << (result) \ << " at " << __FILE__ << ":" << __LINE__ << ":" \ << console_color::reset() \ << std::endl \ << " " << (exprText) << std::endl; \ std::exit(EXIT_FAILURE); \ } #ifdef try_status #undef try_status #endif #define try_status(expr) { \ auto __s = (expr); \ if (__s != KM_CORE_STATUS_OK) { \ _assert_failed(__s, u ## #expr); \ } \ } #ifdef assert #undef assert #endif #define assert(expr) { \ if (!(expr)) { \ _assert_failed(0, u ## #expr); \ } \ } #ifdef assert_equal #undef assert_equal #endif #define assert_equal(actual, expected) { \ if ((actual) != (expected)) { \ std::wcerr << console_color::fg(console_color::BRIGHT_RED) \ << "Test failed at " << __FILE__ << ":" << __LINE__ << ":" \ << console_color::reset() \ << std::endl \ << "expected: " << (expected) << std::endl \ << "actual: " << (actual) << std::endl; \ std::exit(EXIT_FAILURE); \ } \ } #ifdef assert_string_equal #undef assert_string_equal #endif #define assert_string_equal(actual, expected) { \ if (u16cmp((actual), (expected)) != 0) { \ std::wcerr << console_color::fg(console_color::BRIGHT_RED) \ << "Test failed at " << __FILE__ << ":" << __LINE__ << ":" \ << console_color::reset() \ << std::endl \ << "expected: " << Debug_UnicodeString((PKMX_WCHAR)(expected)) << std::endl \ << "actual: " << Debug_UnicodeString((PKMX_WCHAR)(actual)) << std::endl; \ std::exit(EXIT_FAILURE); \ } \ } keyman/common/include/test_color.h0000664000000000000000000000315114600607066014500 0ustar /* * Keyman is copyright (C) SIL International. MIT License. * * Keyman Core - test console color helpers */ #pragma once #include namespace console_color { enum ansi_code { BLACK = 0, RED = 1, GREEN = 2, YELLOW = 3, BLUE = 4, MAGENTA = 5, CYAN = 6, WHITE = 7, GREY = 8, BRIGHT_RED = 196 }; bool enabled = false; // TODO: move to test_color.c because test_color.h cannot be #included in more than 1 file in a project otherwise. class fg { ansi_code code; public: fg(ansi_code pCode) : code(pCode) {} inline friend std::wostream& operator<<(std::wostream& os, const fg& mod) { if(!enabled) return os; return os << "\033[38;5;" << mod.code << "m"; } }; class bg { ansi_code code; public: bg(ansi_code pCode) : code(pCode) {} inline friend std::wostream& operator<<(std::wostream& os, const bg& mod) { if(!enabled) return os; return os << "\033[48;5;" << mod.code << "m"; } }; #define __define_ansi_code__(name,value) class name { \ inline friend std::wostream& \ operator<<(std::wostream& os, const name& mod) { \ if(!enabled) return os; \ return os << "\033[" value "m"; \ } \ } __define_ansi_code__(reset, "0"); __define_ansi_code__(bold, "1"); __define_ansi_code__(underline, "4"); __define_ansi_code__(reversed, "7"); #undef __define_ansi_code__ #ifdef _MSC_VER #include inline bool isaterminal() { return _isatty(_fileno(stdout)); } #else #include inline bool isaterminal() { return isatty(STDOUT_FILENO); } #endif } keyman/common/linux/0000775000000000000000000000000014600607066011666 5ustar keyman/common/linux/build.sh0000775000000000000000000000132714600607066013327 0ustar #!/usr/bin/env bash ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE if [[ $BUILDER_OS != linux ]]; then builder_echo grey "Platform is not linux; skipping common/linux" exit 0 fi # # TODO: when we have linux-specific tests, add them here # as child modules # builder_describe "Keyman common Linux modules" \ clean \ configure \ build \ test builder_parse "$@" #------------------------------------------------------------------------------------------------------------------- builder_run_child_actions clean configure build test keyman/common/test/0000775000000000000000000000000014600607066011506 5ustar keyman/common/test/keyboards/0000775000000000000000000000000014600607066013471 5ustar keyman/common/test/keyboards/baseline/0000775000000000000000000000000014600607066015253 5ustar keyman/common/test/keyboards/baseline/README.md0000664000000000000000000000153714600607066016540 0ustar # Keyboard baseline fixtures This folder contains a set of keyboards that are used by multiple projects to verify behaviour, both for compilation, and for runtime tests. The following projects are known to use these keyboards: * core -- .kmn files only, compiled with kmc during tests * developer/kmcmplib -- .kmn files, compiled for tests, and .kmx as reference * linux -- .kmn files for test steps only, .kmx files The .kmx files were built with kmcomp, not kmc, in order to ensure that developer/kmcmplib gets a valid baseline reference. Once kmc is stable, it is possible that we will be able to use the kmc npm module to build .kmx for all projects that need them. ## Build parameters Keyboards were built with debug information and no compiler version embedded, with kmcomp 16.0.138: ```bat for %d in (*.kmn) do kmcomp -no-compiler-version -d %d ``` keyman/common/test/keyboards/baseline/baseline.kpj0000664000000000000000000002724414600607066017554 0ustar $PROJECTPATH\build False False True keyboard id_k_000___null_keyboard k_000___null_keyboard.kmn k_000___null_keyboard.kmn 1.0 .kmn id_k_001___basic_input_unicodei k_001___basic_input_unicodei.kmn k_001___basic_input_unicodei.kmn 1.0 .kmn id_k_002___basic_input_unicode k_002___basic_input_unicode.kmn k_002___basic_input_unicode.kmn 1.0 .kmn id_k_003___nul k_003___nul.kmn k_003___nul.kmn 1.0 .kmn id_k_004___basic_input__shift_2_ k_004___basic_input__shift_2_.kmn k_004___basic_input__shift_2_.kmn 1.0 .kmn id_k_005___nul_with_initial_context k_005___nul_with_initial_context.kmn k_005___nul_with_initial_context.kmn 1.0 .kmn id_k_006___vkey_input__shift_ctrl_ k_006___vkey_input__shift_ctrl_.kmn k_006___vkey_input__shift_ctrl_.kmn 1.0 .kmn id_k_007___vkey_input__ctrl_alt_ k_007___vkey_input__ctrl_alt_.kmn k_007___vkey_input__ctrl_alt_.kmn 1.0 .kmn id_k_008___vkey_input__ctrl_alt_2_ k_008___vkey_input__ctrl_alt_2_.kmn k_008___vkey_input__ctrl_alt_2_.kmn 1.0 .kmn id_k_012___ralt k_012___ralt.kmn k_012___ralt.kmn 1.0 .kmn id_k_013___deadkeys k_013___deadkeys.kmn k_013___deadkeys.kmn 1.0 .kmn id_k_014___groups_and_virtual_keys k_014___groups_and_virtual_keys.kmn k_014___groups_and_virtual_keys.kmn 1.0 .kmn id_k_015___ralt_2 k_015___ralt_2.kmn k_015___ralt_2.kmn 1.0 .kmn id_k_017___space_mnemonic_kbd k_017___space_mnemonic_kbd.kmn k_017___space_mnemonic_kbd.kmn 1.0 .kmn id_k_018___nul_testing k_018___nul_testing.kmn k_018___nul_testing.kmn 1.0 .kmn id_k_019___multiple_deadkeys k_019___multiple_deadkeys.kmn k_019___multiple_deadkeys.kmn 1.0 .kmn id_k_020___deadkeys_and_backspace k_020___deadkeys_and_backspace.kmn k_020___deadkeys_and_backspace.kmn 1.0 .kmn id_k_021___options k_021___options.kmn k_021___options.kmn 1.0 .kmn id_k_022___options_with_preset k_022___options_with_preset.kmn k_022___options_with_preset.kmn 1.0 .kmn id_k_023___options_with_save k_023___options_with_save.kmn k_023___options_with_save.kmn 1.0 .kmn id_k_024___options_with_save_and_preset k_024___options_with_save_and_preset.kmn k_024___options_with_save_and_preset.kmn 1.0 .kmn id_k_025___options_with_reset k_025___options_with_reset.kmn k_025___options_with_reset.kmn 1.0 .kmn id_k_026___system_stores k_026___system_stores.kmn k_026___system_stores.kmn 1.0 .kmn id_k_027___system_stores_2 k_027___system_stores_2.kmn k_027___system_stores_2.kmn 1.0 .kmn id_k_028___smp k_028___smp.kmn k_028___smp.kmn 1.0 .kmn id_k_029___beep k_029___beep.kmn k_029___beep.kmn 1.0 .kmn id_k_030___multiple_groups k_030___multiple_groups.kmn k_030___multiple_groups.kmn 1.0 .kmn id_k_031___caps_lock k_031___caps_lock.kmn k_031___caps_lock.kmn 1.0 .kmn id_k_032___caps_control k_032___caps_control.kmn k_032___caps_control.kmn 1.0 .kmn id_k_033___caps_always_off k_033___caps_always_off.kmn k_033___caps_always_off.kmn 1.0 .kmn id_k_034___options_double_set_reset k_034___options_double_set_reset.kmn k_034___options_double_set_reset.kmn 1.0 .kmn id_k_035___options_double_set_staged k_035___options_double_set_staged.kmn k_035___options_double_set_staged.kmn 1.0 .kmn id_k_036___options___double_reset_staged k_036___options___double_reset_staged.kmn k_036___options___double_reset_staged.kmn 1.0 .kmn id_k_037___options___double_reset k_037___options___double_reset.kmn k_037___options___double_reset.kmn 1.0 .kmn id_k_038___punctkeys k_038___punctkeys.kmn k_038___punctkeys.kmn 1.0 .kmn id_k_039___generic_ctrlalt k_039___generic_ctrlalt.kmn k_039___generic_ctrlalt.kmn 1.0 .kmn id_k_040___long_context k_040___long_context.kmn k_040___long_context.kmn 1.0 .kmn id_k_041___long_context_and_deadkeys k_041___long_context_and_deadkeys.kmn k_041___long_context_and_deadkeys.kmn 1.0 .kmn id_k_042___long_context_and_split_deadkeys k_042___long_context_and_split_deadkeys.kmn k_042___long_context_and_split_deadkeys.kmn 1.0 .kmn id_k_043___output_and_keystroke k_043___output_and_keystroke.kmn k_043___output_and_keystroke.kmn 1.0 .kmn id_k_044___if_and_context k_044___if_and_context.kmn k_044___if_and_context.kmn 1.0 .kmn id_k_045___deadkey_and_context k_045___deadkey_and_context.kmn k_045___deadkey_and_context.kmn 1.0 .kmn id_k_046___deadkey_and_contextex k_046___deadkey_and_contextex.kmn k_046___deadkey_and_contextex.kmn 1.0 .kmn id_k_047___caps_always_off_initially_on k_047___caps_always_off_initially_on.kmn k_047___caps_always_off_initially_on.kmn 1.0 .kmn id_k_048___modifier_keys_keep_context k_048___modifier_keys_keep_context.kmn k_048___modifier_keys_keep_context.kmn 1.0 .kmn id_k_049___enter_invalidates_context k_049___enter_invalidates_context.kmn k_049___enter_invalidates_context.kmn 1.0 .kmn keyman/common/test/keyboards/baseline/k_000___null_keyboard.kmn0000664000000000000000000000034314600607066022003 0ustar store(&NAME) '000 - null keyboard' c Description: Tests null keyboard c keys: [K_A][RALT K_B][SHIFT K_C] c expected: aC c expected context: C c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys keyman/common/test/keyboards/baseline/k_000___null_keyboard.kmx0000664000000000000000000000047414600607066022022 0ustar KXTS-@<0Keyman000 - null keyboard&NAME6.0&version12G0 Main10BUnicode2<Mainkeyman/common/test/keyboards/baseline/k_001___basic_input_unicodei.kmn0000664000000000000000000000057514600607066023340 0ustar store(&NAME) '001 - basic input UnicodeI' c Description: Tests basic input with simple context rules, ANSI characters used only c keys: [SHIFT K_A][SHIFT K_B][SHIFT K_C][SHIFT K_SPACE][SHIFT K_D][SHIFT K_E][SHIFT K_F] c expected: abc def c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys + 'A' > 'a' + 'B' > 'b' + 'C' > 'c' 'DE' + 'F' > 'def' keyman/common/test/keyboards/baseline/k_001___basic_input_unicodei.kmx0000664000000000000000000000067014600607066023346 0ustar KXTSo7@&0Keyman001 - basic input UnicodeI&NAME6.0&version11G0 Main9BUnicode>HMainA BCFabcdefDEkeyman/common/test/keyboards/baseline/k_002___basic_input_unicode.kmn0000664000000000000000000000064514600607066023166 0ustar store(&NAME) '002 - basic input Unicode' c Description: Tests basic input with simple context rules (Unicode) c keys: [SHIFT K_A][SHIFT K_B][SHIFT K_C][SHIFT K_SPACE][SHIFT K_D][SHIFT K_E][SHIFT K_F] c expected: \u0E01\u0E02\u0E03\u0020\u0E04\u0E05\u0E06 c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys + 'A' > U+0E01 + 'B' > U+0E02 + 'C' > U+0E03 'DE' + 'F' > U+0E04 U+0E05 U+0E06 keyman/common/test/keyboards/baseline/k_002___basic_input_unicode.kmx0000664000000000000000000000066614600607066023203 0ustar KXTSs]!@$0Keyman002 - basic input Unicode&NAME6.0&version11G0 Main9BUnicode<FMainA BCFDEkeyman/common/test/keyboards/baseline/k_003___nul.kmn0000664000000000000000000000034414600607066017753 0ustar store(&NAME) '003 - nul' c Description: Tests nul context c keys: [K_A][K_A][K_A] c expected: cd c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys nul + 'a' > 'b' 'b' + 'a' > 'c' + 'a' > 'd' keyman/common/test/keyboards/baseline/k_003___nul.kmx0000664000000000000000000000057214600607066017770 0ustar KXTS她@z0Keyman003 - nul&NAME6.0&version11G0 Main9BUnicode&Maina bfalpatxbcbdkeyman/common/test/keyboards/baseline/k_004___basic_input__shift_2_.kmn0000664000000000000000000000071414600607066023373 0ustar store(&NAME) '004 - basic input (shift 2)' c Description: Tests basic vkey input with shift only (Unicode) c keys: [SHIFT K_A][SHIFT K_B][SHIFT K_C][SHIFT K_SPACE][SHIFT K_D][SHIFT K_E][SHIFT K_F] c expected: \u0E01\u0E02\u0E03\u0020\u0E04\u0E05\u0E06 c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys + [SHIFT K_A] > U+0E01 + [SHIFT K_B] > U+0E02 + [SHIFT K_C] > U+0E03 'DE' + [SHIFT K_F] > U+0E04 U+0E05 U+0E06 keyman/common/test/keyboards/baseline/k_004___basic_input__shift_2_.kmx0000664000000000000000000000067214600607066023410 0ustar KXTS3[@(0Keyman004 - basic input (shift 2)&NAME6.0&version11G0 Main9BUnicode@JMainA @B@C@F@DEkeyman/common/test/keyboards/baseline/k_005___nul_with_initial_context.kmn0000664000000000000000000000042714600607066024267 0ustar store(&NAME) '005 - nul with initial context' c Description: Tests nul context with an initial context supplied c keys: [K_A][K_A] c expected: xdd c context: x store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys nul + 'a' > 'b' 'b' + 'a' > 'c' + 'a' > 'd' keyman/common/test/keyboards/baseline/k_005___nul_with_initial_context.kmx0000664000000000000000000000064414600607066024302 0ustar KXTS?@.0Keyman005 - nul with initial context&NAME6.0&version11G0 Main9BUnicodeFPMaina aabcbdkeyman/common/test/keyboards/baseline/k_006___vkey_input__shift_ctrl_.kmn0000664000000000000000000000074214600607066024076 0ustar store(&NAME) '006 - vkey input (shift ctrl)' c Description: Tests basic vkey input with shift and control (Unicode) c keys: [LCTRL SHIFT K_A][SHIFT K_B][RCTRL SHIFT K_C][K_SPACE][SHIFT K_D][SHIFT K_E][SHIFT K_F] c expected: \u0E01\u0E02\u0E03\u0020\u0E04\u0E05\u0E06 c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys + [SHIFT CTRL K_A] > U+0E01 + [SHIFT K_B] > U+0E02 + [SHIFT CTRL K_C] > U+0E03 'DE' + [SHIFT K_F] > U+0E04 U+0E05 U+0E06 keyman/common/test/keyboards/baseline/k_006___vkey_input__shift_ctrl_.kmx0000664000000000000000000000067614600607066024116 0ustar KXTS.@,0Keyman006 - vkey input (shift ctrl)&NAME6.0&version11G0 Main9BUnicodeDNMainA 0@B@C0@F@DEkeyman/common/test/keyboards/baseline/k_007___vkey_input__ctrl_alt_.kmn0000664000000000000000000000071314600607066023540 0ustar store(&NAME) '007 - vkey input (ctrl alt)' c Description: Tests basic vkey input with control and alt (Unicode) c keys: [LCTRL LALT K_A][K_B][RCTRL RALT K_C][K_SPACE][K_D][K_E][LCTRL LALT K_F] c expected: \u0E01\u0E02\u0E03\u0020\u0E04\u0E05\u0E06 c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys + [CTRL ALT K_A] > U+0E01 + [K_B] > U+0E02 + [CTRL ALT K_C] > U+0E03 'de' + [CTRL ALT K_F] > U+0E04 U+0E05 U+0E06 keyman/common/test/keyboards/baseline/k_007___vkey_input__ctrl_alt_.kmx0000664000000000000000000000067214600607066023556 0ustar KXTSZ@(0Keyman007 - vkey input (ctrl alt)&NAME6.0&version11G0 Main9BUnicode@JMainA `@B@C`@F`@dekeyman/common/test/keyboards/baseline/k_008___vkey_input__ctrl_alt_2_.kmn0000664000000000000000000000055114600607066023762 0ustar store(&NAME) '008 - vkey input (ctrl alt 2)' c Description: Tests basic vkey input with control and alt (Unicode) c keys: [LCTRL LALT K_A][LCTRL LALT K_B][LCTRL LALT K_C] c expected: \u0E01\u0E03 c expected context: \u0E03 c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys + [CTRL ALT K_A] > U+0E01 + [CTRL ALT K_C] > U+0E03 keyman/common/test/keyboards/baseline/k_008___vkey_input__ctrl_alt_2_.kmx0000664000000000000000000000060414600607066023773 0ustar KXTS0m@.0Keyman008 - vkey input (ctrl alt 2)&NAME6.0&version12G0 Main10BUnicodeFPMainA`@x|C`@~keyman/common/test/keyboards/baseline/k_012___ralt.kmn0000664000000000000000000000062414600607066020120 0ustar store(&NAME) '012 - ralt' c Description: Tests Right Alt processing: requires Ctrl+Alt simulation off. c env.simulate_altgr: 0 c keys: [RALT K_A][RALT K_O][LCTRL LALT K_A][LCTRL LALT K_O] c expected: \u05d6\u05e8\u0062\u0063 c context: store(&VERSION) '9.0' begin Unicode > use(main) group(main) using keys + [RAlt K_A] > U+05D6 + [RAlt K_O] > U+05E8 + [Ctrl Alt K_A] > "b" + [Ctrl Alt K_O] > "c" keyman/common/test/keyboards/baseline/k_012___ralt.kmx0000664000000000000000000000062214600607066020130 0ustar KXTS D@0Keyman012 - ralt&NAME9.0&VERSION12G0 main10BUnicode *mainA@z~O@A`@O`@bckeyman/common/test/keyboards/baseline/k_013___deadkeys.kmn0000664000000000000000000000040014600607066020740 0ustar store(&NAME) '013 - deadkeys' c Description: Tests a simple deadkey rule in Unicode c keys: [SHIFT K_6][K_A] c expected: \u00E2 c context: store(&VERSION) '9.0' begin unicode > use(main) group(main) using keys + '^' > deadkey(1) dk(1) + 'a' > U+00E2 keyman/common/test/keyboards/baseline/k_013___deadkeys.kmx0000664000000000000000000000061214600607066020757 0ustar KXTS [@* 0Keyman013 - deadkeys&NAME9.0&VERSION11G0 main9BUnicode15D0 1BLmain^ t|a~keyman/common/test/keyboards/baseline/k_014___groups_and_virtual_keys.kmn0000664000000000000000000000120614600607066024117 0ustar store(&NAME) '014 - groups and virtual keys' c Description: Tests multiple groups and virtual keys with mnemonic layout c keys: [K_A][SHIFT K_2][K_A][LCTRL K_2][K_A] c expected: \u03B1\u1FB0\u1FB1 store(&VERSION) '9.0' begin Unicode > use(UMain) store(&MnemonicLayout) "0" c ---------------------------------------------- group(UMain) using keys + [K_A] > U+03B1 + [CTRL K_2] > deadkey(MacronBug) + [ALT K_2] > deadkey(MacronBug) + [SHIFT K_2] > deadkey(BreveBug) match > use(DK1) c ---------------------------------------------- group(DK1) deadkey(MacronBug) U+03B1 > U+1FB1 deadkey(BreveBug) U+03B1 > U+1FB0 keyman/common/test/keyboards/baseline/k_014___groups_and_virtual_keys.kmx0000664000000000000000000000137414600607066024137 0ustar KXTS - @*"@<f`~x0Keyman014 - groups and virtual keys&NAME9.0&VERSION0&MnemonicLayout14G0 UMain24G1 DK18BUnicode20M0 UMain26D0 MacronBug26D1 BreveBug0<(UMain2 @2@@2@A@DK1keyman/common/test/keyboards/baseline/k_015___ralt_2.kmn0000664000000000000000000000035614600607066020346 0ustar store(&NAME) '015 - ralt 2' c Description: Tests Right Alt processing with non-US kbds. c keys: [K_A][K_B][K_C][RALT K_A] c expected: abcd store(&VERSION) '9.0' begin Unicode > use(main) group(main) using keys 'c' + [RAlt K_A] > "cd" keyman/common/test/keyboards/baseline/k_015___ralt_2.kmx0000664000000000000000000000051214600607066020352 0ustar KXTS h8@ J0Keyman015 - ralt 2&NAME9.0&VERSION10G0 main8BUnicode",mainA @@Fcdckeyman/common/test/keyboards/baseline/k_017___space_mnemonic_kbd.kmn0000664000000000000000000000070514600607066022763 0ustar store(&NAME) '017 - space mnemonic kbd' c Description: Tests Space handling in mnemonic keyboards (failed with Win 98) c keys: [K_A][K_B][K_SPACE][K_C][K_SPACE][K_D][K_SPACE][K_D][K_E] c expected: XYZ store(&VERSION) '9.0' store(&HOTKEY) "[CTRL SHIFT K_A]" store(&mnemoniclayout) "1" begin Unicode > use(main) group(main) using keys 'ab' + ' ' > 'X' C bug: space ignored 'c ' + 'd' > 'Y' C bug: space ignored ' d' + 'e' > 'Z' C works OK keyman/common/test/keyboards/baseline/k_017___space_mnemonic_kbd.kmx0000664000000000000000000000077214600607066023001 0ustar KXTS H1@~A0,VPlf0Keyman017 - space mnemonic kbd&NAME9.0&VERSION393281&HOTKEY1&mnemoniclayout12G0 main10BUnicodemain deXabYc Z dkeyman/common/test/keyboards/baseline/k_018___nul_testing.kmn0000664000000000000000000000040714600607066021516 0ustar store(&NAME) '018 - nul testing' c Description: Tests the processing of nul in LHS of rules c keys: [K_A][K_A] c expected: OKa store(&VERSION) "9.0" store(&HOTKEY) "[CTRL SHIFT K_N]" begin unicode > use(main) group(Main) using keys nul + 'a' > 'OK' c EOF keyman/common/test/keyboards/baseline/k_018___nul_testing.kmx0000664000000000000000000000060014600607066021523 0ustar KXTS ,O)@>N,(0Keyman018 - nul testing&NAME9.0&VERSION393294&HOTKEY11G0 Main9BUnicodeV`Maina tzOKkeyman/common/test/keyboards/baseline/k_019___multiple_deadkeys.kmn0000664000000000000000000000340014600607066022664 0ustar store(&NAME) '019 - multiple deadkeys' c Description: Tests deadkey scenarios c 1. One deadkey in context dk(1) + '1' c 2. One char and one deadkey in context 'a' dk(2) + '2' c 3. One deadkey and one char in context dk(3) 'a' + '3' c 4. Two deadkeys in a row in context dk(4a) dk(4b) + '4' c 5. One char and two deadkeys in context 'a' dk(5a) dk(5b) + '5' c 6. One char and two deadkeys and one char in context 'a' dk(6a) dk(6b) 'b' + '6' c 7. Two deadkeys and one char in context dk(7a) dk(7b) 'a' + '7' c 8. Three deadkeys in context dk(8a) dk(8b) dk(8c) + '8' c 9. Replacing deadkeys in context via rule [9][x][x] c keys: [K_1][K_X][K_2][K_X][K_3][K_X][K_4][K_X][K_5][K_X][K_6][K_X][K_7][K_X][K_8][K_X][K_9][K_X][K_X] c expected: 1=OK 2=OK 3=OK 4=OK 5=OK 6=OK 7=OK 8=OK 9=OK c context: store(&VERSION) '9.0' begin unicode > use(main) group(main) using keys + '1' > dk(1) dk(1) + 'x' > '1=OK ' + '2' > 'a' dk(2) 'a' dk(2) + 'x' > '2=OK ' + '3' > dk(3) 'a' dk(3) 'a' + 'x' > '3=OK ' + '4' > dk(4a) dk(4b) dk(4a) dk(4b) + 'x' > '4=OK ' + '5' > 'a' dk(5a) dk(5b) 'a' dk(5a) dk(5b) + 'x' > '5=OK ' + '6' > 'a' dk(6a) dk(6b) 'b' 'a' dk(6a) dk(6b) 'b' + 'x' > '6=OK ' + '7' > dk(7a) dk(7b) 'a' dk(7a) dk(7b) 'a' + 'x' > '7=OK ' dk(7a) 'a' + 'x' > '7=Fail1 ' dk(7b) 'a' + 'x' > '7=Fail2 ' + '8' > dk(8a) dk(8b) dk(8c) dk(8a) dk(8b) dk(8c) + 'x' > '8=OK ' dk(8a) + 'x' > '8=Fail1 ' dk(8b) + 'x' > '8=Fail2 ' dk(8c) + 'x' > '8=Fail3 ' dk(8a) dk(8b) + 'x' > '8=Fail4 ' dk(8a) dk(8c) + 'x' > '8=Fail5 ' dk(8b) dk(8c) + 'x' > '8=Fail6 ' c [K_9] [K_X] [K_X] -> test that + '9' > '{' dk(9a) dk(9b) '}' dk(9c) dk(9d) dk(9b) '}' dk(9c) dk(9d) + 'x' > dk(9e) '}' dk(9f) dk(9g) '{' dk(9a) dk(9e) '}' dk(9f) dk(9g) + 'x' > '9=OK' keyman/common/test/keyboards/baseline/k_019___multiple_deadkeys.kmx0000664000000000000000000000422014600607066022677 0ustar KXTS |b|@ $4.D>TNf`xr"60JD^Xrl0Keyman019 - multiple deadkeys&NAME9.0&VERSION20G0 main18BUnicode59D0 159D1 259D2 359D3 4a59D4 4b59D5 5a59D6 5b59D7 6a59D8 6b59D9 7a59D10 7b59D11 8a59D12 8b59D13 8c59D14 9a59D15 9b59D16 9c59D17 9d59D18 9e59D19 9f59D20 9gmain12345"(6%*<7(>N8-Pd98fx;x&x:x#x) x.0<xP\xfrx |x*x+x2x3x4 x.:x/BTx0\nx1vaaaa b  a  {}9=OK{}6=OK a b}}5=OK a7=OK   a8=OK   2=OK a3=OK a4=OK 7=Fail1  a7=Fail2  a8=Fail4   8=Fail5  8=Fail6  1=OK 8=Fail1  8=Fail2  8=Fail3 keyman/common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmn0000664000000000000000000000232214600607066023561 0ustar store(&NAME) '020 - deadkeys and backspace' c Description: Tests deadkey backspacing c 1. One deadkey in context dk(1) + BKSP = nul c 2. One char and one deadkey in context 'a' dk(2) + BKSP = nul c 3. One deadkey and one char in context dk(3) 'a' + BKSP = nul c 4. Two deadkeys in a row in context dk(4a) dk(4b) + BKSP = nul c 5. One char and two deadkeys in context 'a' dk(5a) dk(5b) 'b' + BKSP = 'a' c 6. One char and two deadkeys and one char and two deadkeys in context: c 'a' dk(6a) dk(6b) 'b' dk(6c) dk(6d) + BKSP = 'a' c 7. Tests behaviour when deleting two characters with deadkey prior to first character, c verifying that deadkeys are preserved with the first backspace event: c 'c' (dk7) 'de' + BKSP + BKSP = 'ok' c keys: [K_1][K_BKSP][K_2][K_BKSP][K_3][K_BKSP][K_4][K_BKSP][K_5][K_BKSP][K_6][K_BKSP][K_7][K_BKSP][K_BKSP] c expected: wxaa ok c context: wxyz store(&VERSION) '9.0' begin unicode > use(main) group(main) using keys + '1' > dk(1) + '2' > 'a' dk(2) + '3' > dk(3) 'a' + '4' > dk(4a) dk(4b) + '5' > 'a' dk(5a) dk(5b) 'b' + '6' > 'a' dk(6a) dk(6b) 'b' dk(6c) dk(6d) + '7' > 'c' dk(7) 'd' 'e' 'c' 'd' + [K_BKSP] > ' fail' 'c' dk(7) 'd' + [K_BKSP] > ' ok' keyman/common/test/keyboards/baseline/k_020___deadkeys_and_backspace.kmx0000664000000000000000000000200214600607066023566 0ustar KXTS @,h.|t(":4LF^Xpj~0Keyman020 - deadkeys and backspace&NAME9.0&VERSION22G0 main20BUnicode32D0 132D1 232D2 332D3 4a32D4 4b32D5 5a32D6 5b32D7 6a32D8 6b32D9 6c32D10 6d32D11 7 main @fn@z1234567 okc d failcdaaaba b  c dekeyman/common/test/keyboards/baseline/k_021___options.kmn0000664000000000000000000000053114600607066020646 0ustar store(&NAME) '021 - options' c Description: Tests basic option rules c keys: [K_A][K_1][K_A][K_0][K_A] c expected: no foo.foo.no foo. c context: store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' + '1' > set(foo = '1') + '0' > set(foo = '0') keyman/common/test/keyboards/baseline/k_021___options.kmx0000664000000000000000000000105414600607066020661 0ustar KXTS QlW0 @p, "0*F@\Xb^hdnj0Keyman021 - options&NAME10.0&version0foo13G0 Main11BUnicode1010Main01aa   foo.no foo. keyman/common/test/keyboards/baseline/k_022___options_with_preset.kmn0000664000000000000000000000071414600607066023267 0ustar store(&NAME) '022 - options with preset' c Description: Tests basic option rules with a preset supplied c keys: [K_A][K_1][K_A][K_0][K_A] c expected: foo.foo.no foo. c context: c option: foo=1 c expected option: foo=0 c saved option: foo=0 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' + '1' > set(foo = '1') save(foo) + '0' > set(foo = '0') save(foo) keyman/common/test/keyboards/baseline/k_022___options_with_preset.kmx0000664000000000000000000000112014600607066023271 0ustar KXTS ,7 @P$:6HB^Xtpzv|0Keyman022 - options with preset&NAME10.0&version0foo16G0 Main14BUnicode1010Main0 1 a(a4D  foo.no foo. keyman/common/test/keyboards/baseline/k_023___options_with_save.kmn0000664000000000000000000000066314600607066022727 0ustar store(&NAME) '023 - options with save' c Description: Tests basic option rules with save c keys: [K_A][K_1][K_A][K_0][K_A][K_2] c expected: no foo.foo.no foo. c context: c expected option: foo=0 c saved option: foo=0 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' + '1' > set(foo = '1') + '0' > set(foo = '0') + '2' > save(foo) keyman/common/test/keyboards/baseline/k_023___options_with_save.kmx0000664000000000000000000000113614600607066022735 0ustar KXTS Q @^  62D>ZTplvr|x~0Keyman023 - options with save&NAME10.0&version0foo15G0 Main13BUnicode1010Main0 1 2"*a,6aBR  foo.no foo. keyman/common/test/keyboards/baseline/k_024___options_with_save_and_preset.kmn0000664000000000000000000000073114600607066025130 0ustar store(&NAME) '024 - options with save and preset' c Description: Tests basic option rules with save c keys: [K_A][K_1][K_A][K_0][K_A][K_2] c expected: foo.foo.no foo. c context: c option: foo=1 c expected option: foo=0 c saved option: foo=0 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' + '1' > set(foo = '1') + '0' > set(foo = '0') if(foo = '0') + '2' > save(foo) keyman/common/test/keyboards/baseline/k_024___options_with_save_and_preset.kmx0000664000000000000000000000122014600607066025134 0ustar KXTS , @,B8XTf`|v0Keyman024 - options with save and preset&NAME10.0&version0foo16G0 Main14BUnicode10100Main02<1>H2JRa^hat   foo.no foo. keyman/common/test/keyboards/baseline/k_025___options_with_reset.kmn0000664000000000000000000000065514600607066023116 0ustar store(&NAME) '025 - options with reset' c Description: Tests basic option rules with reset c keys: [K_A][K_1][K_A][K_0][K_A][K_3] c expected: foo.foo.no foo. c context: c option: foo=1 c expected option: foo=1 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' + '1' > set(foo = '1') + '0' > set(foo = '0') + '3' > reset(foo) keyman/common/test/keyboards/baseline/k_025___options_with_reset.kmx0000664000000000000000000000114014600607066023116 0ustar KXTS %겢 @` "84F@\Vrnxt~z0Keyman025 - options with reset&NAME10.0&version0foo15G0 Main13BUnicode1010Main0 1"3$,a.8aDT  foo.no foo. keyman/common/test/keyboards/baseline/k_026___system_stores.kmn0000664000000000000000000000152514600607066022107 0ustar store(&NAME) '026 - system stores' c Description: Tests platform and baselayout system store rules c keys: [K_1][K_2][K_3][K_4][K_A][K_B] c expected: windows.desktop.hardware.native.en-US.kbdus.dll. c context: c (default) option: &platform=windows desktop hardware native <-- ignored by test c (default) option: &baseLayout=kbdus.dll <-- ignored by test c (default) option: &baseLayoutAlt=en-US <-- ignored by test store(&version) '10.0' store(digit) '1234567890' store(letter) 'abcdefghij' begin Unicode > use(Main) group(Main) using keys platform('windows') + '1' > 'windows.' platform('desktop') + '2' > 'desktop.' platform('hardware') + '3' > 'hardware.' platform('native') + '4' > 'native.' + any(digit) > 'platform-fail.' baselayout('en-US') + 'a' > 'en-US.' baselayout('kbdus.dll') + 'b' > 'kbdus.dll.' + any(letter) > 'baselayout-fail.' keyman/common/test/keyboards/baseline/k_026___system_stores.kmx0000664000000000000000000000366414600607066022127 0ustar KXTS nT@.&<2dNp ,0Keyman026 - system stores&NAME10.0&version1234567890digitabcdefghijletter17G0 Main15BUnicodewindowsdesktophardwarenativeen-USkbdus.dllFPMain0Xv1x12233244D4Pn5p6789aa*LbNdbpcdef"g$FhHjiljplatform-fail.windows.  platform-fail.desktop.  platform-fail.hardware.  platform-fail.native.  platform-fail.platform-fail.platform-fail.platform-fail.platform-fail.platform-fail.en-US.! baselayout-fail.kbdus.dll.!baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.keyman/common/test/keyboards/baseline/k_027___system_stores_2.kmn0000664000000000000000000000136514600607066022333 0ustar store(&NAME) '027 - system stores 2' c Description: Tests platform and baselayout system store rules c keys: [K_1][K_2][K_3][K_4][K_A][K_B] c expected: linux.desktop.hardware.native.fr-FR.kbdfr.dll. c context: c option: &platform=linux desktop hardware native c option: &baseLayout=kbdfr.dll c option: &baseLayoutAlt=fr-FR store(&version) '10.0' store(digit) '1234567890' store(letter) 'abcdefghij' begin Unicode > use(Main) group(Main) using keys platform('linux') + '1' > 'linux.' platform('desktop') + '2' > 'desktop.' platform('hardware') + '3' > 'hardware.' platform('native') + '4' > 'native.' + any(digit) > 'platform-fail.' baselayout('fr-FR') + 'a' > 'fr-FR.' baselayout('kbdfr.dll') + 'b' > 'kbdfr.dll.' + any(letter) > 'baselayout-fail.' keyman/common/test/keyboards/baseline/k_027___system_stores_2.kmx0000664000000000000000000000366014600607066022345 0ustar KXTS hO@.*@6hRt ,0Keyman027 - system stores 2&NAME10.0&version1234567890digitabcdefghijletter17G0 Main15BUnicodelinuxdesktophardwarenativefr-FRkbdfr.dllFPMain0Xv1x12233.40@4Lj5l6789 a a&HbJ`blcdefg BhDfihjplatform-fail.linux.  platform-fail.desktop.  platform-fail.hardware.  platform-fail.native.  platform-fail.platform-fail.platform-fail.platform-fail.platform-fail.platform-fail.fr-FR.! baselayout-fail.kbdfr.dll.!baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.baselayout-fail.keyman/common/test/keyboards/baseline/k_028___smp.kmn0000664000000000000000000000070314600607066017762 0ustar store(&NAME) '028 - smp' c Description: Tests SMP characters; see #4361 [1-4], #5561 [5] c keys: [K_1][K_2][K_3][K_4][K_5] c expected: \U0001F601yx c context: store(&version) '10.0' begin Unicode > use(Main) group(Main) using keys c Tests #4361: + [K_1] > U+1F642 U+1F642 + [K_2] > context 'hi' U+1F600 U+1F600 + [K_3] > 'x' U+1F642 'hix' + [K_4] > U+1F601 'y' c Tests #5561 (#5465): + [K_5] > U+10333 use(second) group(second) U+10333 > 'x' keyman/common/test/keyboards/baseline/k_028___smp.kmx0000664000000000000000000000107614600607066020000 0ustar KXTS Q@,>0Keyman028 - smp&NAME10.0&version11G0 Main24G1 second9BUnicode\f Main1@2@3@4@5@=Bhi==Bx==y=Bhix3second48x3keyman/common/test/keyboards/baseline/k_029___beep.kmn0000664000000000000000000000027014600607066020076 0ustar store(&NAME) '029 - beep' c Description: Tests beep c keys: [K_1] c expected: \b c context: store(&version) '10.0' begin Unicode > use(Main) group(Main) using keys + [K_1] > beep keyman/common/test/keyboards/baseline/k_029___beep.kmx0000664000000000000000000000050614600607066020112 0ustar KXTS u@F0Keyman029 - beep&NAME10.0&version11G0 Main9BUnicode *Main1 @>Dkeyman/common/test/keyboards/baseline/k_030___multiple_groups.kmn0000664000000000000000000000057714600607066022417 0ustar store(&NAME) "030 - multiple groups" c Description: Tests multiple groups. Purpose here is to interleave output and backspaces from kmx processor to consumer c keys: [K_1][K_2] c expected: abc c context: store(&version) '10.0' begin Unicode > use(Main) group(Main) using keys + [K_1] > 'a' 'b' + [K_2] > context use(b) match > use(a) group(a) 'a' > 'b' group(b) 'b' > 'abc' keyman/common/test/keyboards/baseline/k_030___multiple_groups.kmx0000664000000000000000000000112414600607066022416 0ustar KXTS use(Main) group(Main) using keys + [NCAPS K_1] > 'fail.' + [CAPS K_1] > 'pass.' + [NCAPS SHIFT K_2] > 'fail.' + [CAPS SHIFT K_2] > 'pass.' + '#' > 'pass.' + '3' > 'fail.' + 'a' > 'fail.' + 'A' > 'pass.' + 'b' > 'pass.' + 'B' > 'fail.' keyman/common/test/keyboards/baseline/k_031___caps_lock.kmx0000664000000000000000000000121214600607066021121 0ustar KXTS 1(b@0Keyman031 - caps lock&NAME10.0&version12G0 Main10BUnicode,6 Main# 1B 1A&3(42B6B2ADPAR^B`lanzb|pass.fail.pass.fail.fail.pass.pass.fail.fail.pass.keyman/common/test/keyboards/baseline/k_032___caps_control.kmn0000664000000000000000000000155414600607066021651 0ustar store(&NAME) '032 - caps control' c Description: Tests Caps Lock env set c keys: [K_1][K_CAPS][K_2][SHIFT K_3][K_4][K_CAPS][K_5][K_CAPS][K_6][K_SHIFT][K_7] c expected: pass.pass.pass.pass.pass.pass.pass. c capsLock: 0 c context: store(&version) '10.0' store(&shiftfreescaps) '1' store(&capsononly) '1' begin Unicode > use(Main) group(Main) using keys + [CAPS K_1] > 'fail.' + [NCAPS K_1] > 'pass.' + [NCAPS K_2] > 'fail.' + [CAPS K_2] > 'pass.' c Shift will free caps lock when it is released, so this test should still have Caps Lock on. + [NCAPS SHIFT K_3] > 'fail.' + [CAPS SHIFT K_3] > 'pass.' + [CAPS K_4] > 'fail.' + [NCAPS K_4] > 'pass.' + [NCAPS K_5] > 'fail.' + [CAPS K_5] > 'pass.' + [NCAPS K_6] > 'fail.' + [CAPS K_6] > 'pass.' c Shift was pressed and released ([K_SHIFT]) so Caps should be off before this + [CAPS K_7] > 'fail.' + [NCAPS K_7] > 'pass.' keyman/common/test/keyboards/baseline/k_032___caps_control.kmx0000664000000000000000000000156014600607066021660 0ustar KXTS p@rp  ,(JD`Z0Keyman032 - caps control&NAME10.0&version1&shiftfreescaps1&capsononly15G0 Main13BUnicodeMain3B3A1A1B2B2A4A 4B5B(5A*66!B8D6"AFR7%AT`7&Bbnfail.pass.fail.pass.fail.pass.fail.pass.fail.pass.fail.pass.fail.pass.keyman/common/test/keyboards/baseline/k_033___caps_always_off.kmn0000664000000000000000000000064214600607066022321 0ustar store(&NAME) '033 - caps always off' c Description: Tests Caps Lock always off c keys: [K_1][K_CAPS][K_2][K_CAPS][K_3] c expected: pass.pass.pass. c capsLock: 0 c context: store(&version) '10.0' store(&capsalwaysoff) '1' begin Unicode > use(Main) group(Main) using keys + [CAPS K_1] > 'fail.' + [NCAPS K_1] > 'pass.' + [CAPS K_2] > 'fail.' + [NCAPS K_2] > 'pass.' + [CAPS K_3] > 'fail.' + [NCAPS K_3] > 'pass.' keyman/common/test/keyboards/baseline/k_033___caps_always_off.kmx0000664000000000000000000000107414600607066022333 0ustar KXTS U @N< & <60Keyman033 - caps always off&NAME10.0&version1&capsalwaysoff14G0 Main12BUnicodefpMain1A1B2A2B3A ,3B.:fail.pass.fail.pass.fail.pass.keyman/common/test/keyboards/baseline/k_034___options_double_set_reset.kmn0000664000000000000000000000072014600607066024261 0ustar store(&NAME) '034 - options double set reset' c Description: Tests basic option rules with save reset+set+reset c keys: [K_A][K_A] c expected: foo.foo. c context: c option: foo=1 c expected option: foo=1 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' set(foo='2') reset(foo) set(foo='3') reset(foo) if(foo = '2') + 'a' > 'bar.' if(foo = '3') + 'a' > 'baz.' if(foo = '0') + 'a' > 'no foo.' keyman/common/test/keyboards/baseline/k_034___options_double_set_reset.kmx0000664000000000000000000000124214600607066024273 0ustar KXTS ֩ @0F<\Xjdz0Keyman034 - options double set reset&NAME10.0&version0foo15G0 Main13BUnicode123230Maina(NaZdapzafoo.  bar. baz. no foo. keyman/common/test/keyboards/baseline/k_035___options_double_set_staged.kmn0000664000000000000000000000074414600607066024415 0ustar store(&NAME) '035 - options double set staged' c Description: Tests basic option rules with save reset+set+reset c keys: [K_A][K_B][K_C][K_B][K_A] c expected: foo.foo. c context: c option: foo=1 c expected option: foo=2 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' set(foo='2') + 'b' > reset(foo) + 'c' > set(foo='3') if(foo = '2') + 'a' > 'bar.' if(foo = '3') + 'a' > 'baz.' if(foo = '0') + 'a' > 'no foo.' keyman/common/test/keyboards/baseline/k_035___options_double_set_staged.kmx0000664000000000000000000000131614600607066024423 0ustar KXTS = @2H>^Zlf|0Keyman035 - options double set staged&NAME10.0&version0foo15G0 Main13BUnicode123230MainaRdapzaabcfoo. bar. baz. no foo.  keyman/common/test/keyboards/baseline/k_036___options___double_reset_staged.kmn0000664000000000000000000000065514600607066025244 0ustar store(&NAME) '036 - options - double reset staged' c Description: Tests basic option rules with save reset+reset c keys: [K_A][K_B][K_B][K_A] c expected: foo.foo. c context: c option: foo=1 c expected option: foo=2 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' set(foo='2') + 'b' > reset(foo) if(foo = '2') + 'a' > 'bar.' if(foo = '0') + 'a' > 'no foo.' keyman/common/test/keyboards/baseline/k_036___options___double_reset_staged.kmx0000664000000000000000000000115014600607066025245 0ustar KXTS  @h"8.NJ\Vrl0Keyman036 - options - double reset staged&NAME10.0&version0foo15G0 Main13BUnicode1220Maina a,6aBRb^ffoo. bar. no foo. keyman/common/test/keyboards/baseline/k_037___options___double_reset.kmn0000664000000000000000000000064014600607066023710 0ustar store(&NAME) '037 - options - double reset' c Description: Tests basic option rules with save reset+reset c keys: [K_A][K_A] c expected: foo.foo. c context: c option: foo=1 c expected option: foo=1 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' set(foo='2') reset(foo) reset(foo) if(foo = '2') + 'a' > 'bar.' if(foo = '0') + 'a' > 'no foo.' keyman/common/test/keyboards/baseline/k_037___options___double_reset.kmx0000664000000000000000000000111014600607066023713 0ustar KXTS 8 @H* @<NHd^zv|0Keyman037 - options - double reset&NAME10.0&version0foo15G0 Main13BUnicode1220Maina a a,<foo. bar. no foo. keyman/common/test/keyboards/baseline/k_038___punctkeys.kmn0000664000000000000000000000120614600607066021210 0ustar store(&NAME) '038 - punctkeys' c Description: Tests punctuation keys (Unicode) c keys: [K_A][K_COLON][K_A][K_EQUAL][K_A][K_COMMA][K_A][K_HYPHEN][K_A][K_PERIOD][K_A][K_SLASH][K_A][K_BKQUOTE][K_A][K_LBRKT][K_A][K_BKSLASH][K_A][K_RBRKT][K_A][K_QUOTE][K_A][K_oE2] c expected: efghijklmnop c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys 'a' + [K_COLON] > 'e' 'a' + [K_EQUAL] > 'f' 'a' + [K_COMMA] > 'g' 'a' + [K_HYPHEN] > 'h' 'a' + [K_PERIOD] > 'i' 'a' + [K_SLASH] > 'j' 'a' + [K_BKQUOTE] > 'k' 'a' + [K_LBRKT] > 'l' 'a' + [K_BKSLASH] > 'm' 'a' + [K_RBRKT] > 'n' 'a' + [K_QUOTE] > 'o' 'a' + [K_oE2] > 'p' keyman/common/test/keyboards/baseline/k_038___punctkeys.kmx0000664000000000000000000000120214600607066021216 0ustar KXTSBp@0Keyman038 - punctkeys&NAME6.0&version11G0 Main9BUnicode(2 Main@"&@*.@26@:>@BF@JN @RV@Z^@bf@jn@rv@z~paoagahaiajaeafalamanakakeyman/common/test/keyboards/baseline/k_039___generic_ctrlalt.kmn0000664000000000000000000000047614600607066022335 0ustar store(&NAME) '039 - generic ctrlalt' c Description: Tests generic alt and control (Unicode) c keys: [K_A][K_A][LCTRL K_B][K_A][LALT K_C][K_A][RCTRL K_B][K_A][RALT K_C] c expected: abcbc c context: store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys 'a' + [CTRL K_B] > 'b' 'a' + [ALT K_C] > 'c' keyman/common/test/keyboards/baseline/k_039___generic_ctrlalt.kmx0000664000000000000000000000056614600607066022347 0ustar KXTS&n(@v 0Keyman039 - generic ctrlalt&NAME6.0&version11G0 Main9BUnicode4>MainB @fjC@@nrbacakeyman/common/test/keyboards/baseline/k_040___long_context.kmn0000664000000000000000000000064714600607066021667 0ustar store(&NAME) '040 - long context' c Description: Tests context longer than 64 chars c keys: [K_SPACE][K_F] c expected: 012345678901234567890123456789012345678901234567890123456789012\u0020 c context: 012345678901234567890123456789012345678901234567890123456789012 store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys + [K_SPACE] > U+0020 c prevent entering symbols after space U+0020 + 'f' > U+0020 keyman/common/test/keyboards/baseline/k_040___long_context.kmx0000664000000000000000000000055614600607066021700 0ustar KXTSTڙ@n0Keyman040 - long context&NAME6.0&version11G0 Main9BUnicode.8Main @`dffj keyman/common/test/keyboards/baseline/k_041___long_context_and_deadkeys.kmn0000664000000000000000000000300414600607066024351 0ustar store(&NAME) '041 - long context and deadkeys' c Description: Tests that we don't split a dk in context:set. Note that we start with a context c with length MAXCONTEXT-1 (abc...fgh is 60 characters/bytes long + 3 bytes for dk(1)). c keys: [K_Z][K_1][K_2][K_3][K_4] c context: c expected: PASS store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys c Setup + [K_Z] > dk(1) 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh' c Test 1 dk(1) 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh' + '1' > context '1' c Test 2: Test that we haven't split a deadkey code: UC_SENTINEL CODE_DEADKEY c because: CODE_DEADKEY = U+0008; deadkey_number = U+0001 U+0008 U+0001 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh1' + '2' > 'FAIL TEST 2' U+0001 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh1' + '2' > 'FAIL TEST 2' 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh1' + '2' > context '2' c Test 3: Test that we haven't split a deadkey code: UC_SENTINEL CODE_DEADKEY c because: CODE_DEADKEY = U+0008; deadkey_number = U+0001 U+0008 U+0001 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12' + '3' > 'FAIL TEST 3' U+0001 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12' + '3' > 'FAIL TEST 3' 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12' + '3' > 'abcdefghijklmnopqrstuvwxyz123' c Convert to a visible result: dk(1) 'abcdefghijklmnopqrstuvwxyz123' + '4' > 'PASS' keyman/common/test/keyboards/baseline/k_041___long_context_and_deadkeys.kmx0000664000000000000000000000343014600607066024366 0ustar KXTS@N,&D>0Keyman041 - long context and deadkeys&NAME6.0&version12G0 Main10BUnicode33D0 1fp Main1$,22D\23^v334!JTZ@1abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghFAIL TEST 2abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh1FAIL TEST 2abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh1FAIL TEST 3abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12FAIL TEST 3abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12abcdefghijklmnopqrstuvwxyz123abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh12PASSabcdefghijklmnopqrstuvwxyz123abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghkeyman/common/test/keyboards/baseline/k_042___long_context_and_split_deadkeys.kmn0000664000000000000000000000155714600607066025600 0ustar store(&NAME) '042 - long context and split deadkeys' c Description: Tests that we don't split a dk in context. Note that we start with a context with length MAXCONTEXT. c keys: [K_Z][K_SPACE][K_1][K_2] c context: c expected: PASS store(&version) '6.0' begin Unicode > use(Main) group(Main) using keys c Setup + [K_Z] > dk(1) 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk' c Test 1: Test that we haven't split a deadkey code: UC_SENTINEL CODE_DEADKEY c Here, looking at last char only: deadkey_number = U+0001 U+0001 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk' + ' ' > 'FAIL' dk(1) 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk' + ' ' > 'UNEXPECTED' c Convert to a visible result: 'defghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk ' + '1' > 'def' dk(1) 'abcdef' + '2' > 'PASS' keyman/common/test/keyboards/baseline/k_042___long_context_and_split_deadkeys.kmx0000664000000000000000000000206014600607066025600 0ustar KXTS# &@X0 "62NH0Keyman042 - long context and split deadkeys&NAME6.0&version11G0 Main9BUnicode23D0 1pzMain  j12Z@.FAILabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkUNEXPECTEDabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkdefdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijk PASSabcdefabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkkeyman/common/test/keyboards/baseline/k_043___output_and_keystroke.kmn0000664000000000000000000000067614600607066023453 0ustar store(&NAME) '043 - output and keystroke' c Description: Tests the 'emit default key' function by having an empty 'using keys' final group c keys: [K_1][K_2][K_3] c expected: abd3 c context: store(&version) '10.0' begin Unicode > use(Main) group(Main) using keys + [K_1] > 'a' 'b' + [K_2] > context use(b) 'abc' + [K_3] > context(1) context(2) 'd' use(emit) match > use(a) group(a) 'a' > 'b' group(b) 'b' > 'abc' group(emit) using keys keyman/common/test/keyboards/baseline/k_043___output_and_keystroke.kmx0000664000000000000000000000132414600607066023454 0ustar KXTS e^ @2,HBXRhb|x0Keyman043 - output and keystroke&NAME10.0&version11G0 Main19G1 a23G2 b27G3 emit9BUnicode17M0 Main Main1 @RV2@Xd3@h~abdabcabababcbemitkeyman/common/test/keyboards/baseline/k_044___if_and_context.kmn0000664000000000000000000000065114600607066022147 0ustar store(&NAME) '044 - if and context' c Description: Tests that context(x) takes if() statements into account. See #4275. c keys: [K_A][K_B] c expected: ex c context: store(&version) '10.0' begin Unicode > use(Main) group(Main) using keys store(nfc) '0' store(diaeresisBase) 'ae' + 'a' > 'exay' c Test #1 for if() with context(n) if(nfc = "0") any(diaeresisBase) 'x' any(diaeresisBase) 'y' + 'b' > context(2) context(3) keyman/common/test/keyboards/baseline/k_044___if_and_context.kmx0000664000000000000000000000076414600607066022166 0ustar KXTS  @t.*<6\Xrn0Keyman044 - if and context&NAME10.0&version11G0 Main0nfcaediaeresisBase9BUnicode0Mainabexay xykeyman/common/test/keyboards/baseline/k_045___deadkey_and_context.kmn0000664000000000000000000000064714600607066023165 0ustar store(&NAME) '045 - deadkey and context' c Description: Tests that context emits deadkeys correctly. See #4275. c keys: [K_Y][K_Z][SHIFT K_SLASH] c expected: correct c context: store(&version) '10.0' begin Unicode > use(Main) group(Main) using keys + 'y' > dk(1) 'a' dk(2) 'b' dk(3) c Test #2 for dk(d) and context dk(1) 'a' dk(2) 'b' dk(3) + 'z' > '<' context '>' '<' dk(1) 'a' dk(2) 'b' dk(3) '>' + '?' > 'correct' keyman/common/test/keyboards/baseline/k_045___deadkey_and_context.kmx0000664000000000000000000000110014600607066023160 0ustar KXTS 0< @z@ $84PJ`Zpj0Keyman045 - deadkey and context&NAME10.0&version11G0 Main9BUnicode18D0 118D1 218D2 3Main?y z(correct<ab>ab<>abkeyman/common/test/keyboards/baseline/k_046___deadkey_and_contextex.kmn0000664000000000000000000000064314600607066023517 0ustar store(&NAME) '046 - deadkey and contextex' c Description: Tests that context() emits deadkeys correctly. See #4275. c keys: [K_Y][SHIFT K_M][SHIFT K_SLASH] c expected: correct c context: store(&version) '10.0' begin Unicode > use(Main) group(Main) using keys + 'y' > dk(1) 'a' dk(2) 'b' dk(3) c Test #3 for dk(d) and context(n) dk(1) 'a' dk(2) 'b' dk(3) + 'M' > '<' context(1) '>' '<' dk(1) '>' + '?' > 'correct' keyman/common/test/keyboards/baseline/k_046___deadkey_and_contextex.kmx0000664000000000000000000000106614600607066023531 0ustar KXTS g{= @~6("<8TNd^tn0Keyman046 - deadkey and contextex&NAME10.0&version11G0 Main9BUnicode18D0 118D1 218D2 3Main?My 4correct<><>ababkeyman/common/test/keyboards/baseline/k_047___caps_always_off_initially_on.kmn0000664000000000000000000000104114600607066025072 0ustar store(&NAME) '047 - caps always off initially on' c Description: Tests Caps Lock always off, entry to the test has Caps Lock c on to test that it is then switched off on first keystroke event. c keys: [K_1][K_CAPS][K_2][K_CAPS][K_3] c expected: pass.pass.pass. c capsLock: 1 c context: store(&version) '10.0' store(&capsalwaysoff) '1' begin Unicode > use(Main) group(Main) using keys + [CAPS K_1] > 'fail.' + [NCAPS K_1] > 'pass.' + [CAPS K_2] > 'fail.' + [NCAPS K_2] > 'pass.' + [CAPS K_3] > 'fail.' + [NCAPS K_3] > 'pass.' keyman/common/test/keyboards/baseline/k_047___caps_always_off_initially_on.kmx0000664000000000000000000000112614600607066025110 0ustar KXTS \.@hV @:VP0Keyman047 - caps always off initially on&NAME10.0&version1&capsalwaysoff15G0 Main13BUnicodeMain1A1B2A*2B,83A:F3BHTfail.pass.fail.pass.fail.pass.keyman/common/test/keyboards/baseline/k_048___modifier_keys_keep_context.kmn0000664000000000000000000000051214600607066024564 0ustar store(&NAME) '048 - modifier keys keep context' c Description: Tests that modifier keys don't reset context (#5591) c keys: [K_A][K_SHIFT][K_B][K_A][K_ALT][K_B][K_A][K_CAPS][K_B] c expected: pass.pass.pass. c context: store(&VERSION) '9.0' begin unicode > use(main) group(main) using keys + [K_A] > 'a' 'a' + [K_B] > 'pass.' keyman/common/test/keyboards/baseline/k_048___modifier_keys_keep_context.kmx0000664000000000000000000000062214600607066024600 0ustar KXTS &E@2  0Keyman048 - modifier keys keep context&NAME9.0&VERSION11G0 main9BUnicodeJTmainA @|B@apass.akeyman/common/test/keyboards/baseline/k_049___enter_invalidates_context.kmn0000664000000000000000000000066414600607066024440 0ustar store(&NAME) '049 - enter_invalidates_context' c Description: Tests that core context is cleared when kb processor c determines its invalid. eg Enter key See #10182. c keys: [K_A][K_B][K_ENTER][K_C] c expected: abc c expected context: c c context: store(&version) '10.0' begin Unicode > use(Main) group(Main) using keys c Test if context was not invalidated by [K_ENTER] context will be 'abd' 'a' 'b' + [K_C] > 'abd' keyman/common/test/keyboards/baseline/k_049___enter_invalidates_context.kmx0000664000000000000000000000057014600607066024446 0ustar KXTS #[@4x "0Keyman049 - enter_invalidates_context&NAME10.0&version13G0 Main11BUnicodeLVMainC@jrabdabkeyman/common/test/keyboards/caps_lock_layer_3620/0000775000000000000000000000000014600607066017275 5ustar keyman/common/test/keyboards/caps_lock_layer_3620/HISTORY.md0000664000000000000000000000015214600607066020756 0ustar Caps Lock Layer 3620 Change History ==================== 1.0 (2021-11-30) ---------------- * Created by keyman/common/test/keyboards/caps_lock_layer_3620/LICENSE.md0000664000000000000000000000203714600607066020703 0ustar The MIT License (MIT) © 2021 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. keyman/common/test/keyboards/caps_lock_layer_3620/README.md0000664000000000000000000000057114600607066020557 0ustar Caps Lock Layer 3620 keyboard ============== Version 1.0 Description ----------- Caps Lock Layer 3620 generated from template Links ----- Copyright --------- See [LICENSE.md](LICENSE.md) Supported Platforms ------------------- * Windows * macOS * Linux * Web * iPhone * iPad * Android phone * Android tablet * Mobile devices * Desktop devices * Tablet devices keyman/common/test/keyboards/caps_lock_layer_3620/binary/0000775000000000000000000000000014600607066020561 5ustar keyman/common/test/keyboards/caps_lock_layer_3620/binary/caps_lock_layer_3620.kmx0000664000000000000000000001035214600607066025107 0ustar KXTS L -@8DTP$rj&#Rtj|' & 0Keyman10.0&VERSIONCaps Lock Layer 3620&NAME&COPYRIGHT1.0&KEYBOARDVERSIONany&TARGETScaps_lock_layer_3620.kvk&VISUALKEYBOARDcaps_lock_layer_3620.keyman-touch-layout&LAYOUTFILE @A @B @C @D @E @F @G @H @I @J @K @L @M @N @O @P @Q @R @S @T @U @V @W @X @Y @Z @A @B @C @D @E @F @G @H @I @J @K @L @M @N @O @P @Q @R @S @T @U @V @W @X @Y @ZkeyabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZout @A @B @C @D @E @F @G @H @I @J @K @L @M @N @O @P @Q @R @S @T @U @V @W @X @Y @Z&CasedKeys17G0 main11BUnicodePZhmainAAz~ABBABBCACBDADBEAEBFAFBGAGBHAHBIAIBJAJBKAKBLALBMA MBNANB OA"&OB(,PA.2PB48QA:>QB@DRAFJRBLPSARVSBX\TA^bTBdhUAjnUBptVAvzVB|WAWBXAXBYAYBZAZBAAABBABBCACBDADBEAEBFAFBGAGBHA HB IAIBJA"JB$(KA*.KB04LA6:LB<@MABFMBHLNANRNBTXOAZ^OB`dPAfjPBlpQArvQBx|RA~RBSASBTATBUAUBVAVBWAWBXAXBYAYBZAZBAABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXXYYZZaabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzzkeyman/common/test/keyboards/caps_lock_layer_3620/binary/caps_lock_layer_3620.kvk0000664000000000000000000000014514600607066025102 0ustar KVKFcaps_lock_layer_3620ArialArialkeyman/common/test/keyboards/caps_lock_layer_3620/caps_lock_layer_3620.kpj0000664000000000000000000000641614600607066023616 0ustar $PROJECTPATH\build True True True keyboard id_ae750e073bdf1a73f961466813e93a67 caps_lock_layer_3620.kmn source\caps_lock_layer_3620.kmn 1.0 .kmn
Caps Lock Layer 3620 ©
id_8572983c5fa67dc8f3e31da0333521b5 caps_lock_layer_3620.kps source\caps_lock_layer_3620.kps .kps
Caps Lock Layer 3620 ©
id_ede98e4633e239f933cbfd1f4e1b766c HISTORY.md HISTORY.md .md id_53e892b8b41cc4caece1cfd5ef21d6e7 LICENSE.md LICENSE.md .md id_0730bb7c2e8f9ea2438b52e419dd86c9 README.md README.md .md id_6beb4ed096b4f0d03913a0cf0dc1c10b caps_lock_layer_3620.kmx source\..\build\caps_lock_layer_3620.kmx .kmx id_8572983c5fa67dc8f3e31da0333521b5 id_85da30900c1f778b42f47770aa7d67ae caps_lock_layer_3620.js source\..\build\caps_lock_layer_3620.js .js id_8572983c5fa67dc8f3e31da0333521b5 id_456ab3d34c321e614773101797d2a54f caps_lock_layer_3620.kvk source\..\build\caps_lock_layer_3620.kvk .kvk id_8572983c5fa67dc8f3e31da0333521b5 id_356e5d149c1e539356d72698c1e401a6 welcome.htm source\welcome.htm .htm id_8572983c5fa67dc8f3e31da0333521b5 id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_8572983c5fa67dc8f3e31da0333521b5
keyman/common/test/keyboards/caps_lock_layer_3620/source/0000775000000000000000000000000014600607066020575 5ustar keyman/common/test/keyboards/caps_lock_layer_3620/source/caps_lock_layer_3620.keyman-touch-layout0000664000000000000000000005141414600607066030247 0ustar { "tablet": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "a", "pad": 70 }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "id": "T_new_54", "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": 70 }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "id": "T_new_190", "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "text": "$", "pad": 70, "layer": "shift" }, { "id": "K_2", "text": "@", "layer": "shift" }, { "id": "K_3", "text": "#", "layer": "shift" }, { "id": "K_5", "text": "%", "layer": "shift" }, { "id": "K_7", "text": "&", "layer": "shift" }, { "id": "K_HYPHEN", "text": "_", "layer": "shift" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "text": "|", "layer": "shift" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "id": "T_new_536", "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1", "nextlayer": "shift" }, { "id": "K_LBRKT", "text": "[", "sk": [ { "id": "U_00AB", "text": "«" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "text": "(", "layer": "shift" }, { "id": "K_0", "text": ")", "layer": "shift" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "»" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "text": "+", "layer": "shift" }, { "id": "K_HYPHEN", "text": "-", "layer": "default" }, { "id": "K_8", "text": "*", "layer": "shift" }, { "id": "K_SLASH", "text": "/", "layer": "default" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "140", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "caps", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": 70 }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "id": "T_new_190", "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*ShiftedLock*", "width": "110", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] } ], "displayUnderlying": false } }keyman/common/test/keyboards/caps_lock_layer_3620/source/caps_lock_layer_3620.kmn0000664000000000000000000000105714600607066025113 0ustar c caps_lock_layer_3620 generated from template at 2021-11-30 14:58:52 c with name "Caps Lock Layer 3620" store(&VERSION) '10.0' store(&NAME) 'Caps Lock Layer 3620' store(©RIGHT) '©' store(&KEYBOARDVERSION) '1.0' store(&TARGETS) 'any' store(&VISUALKEYBOARD) 'caps_lock_layer_3620.kvks' store(&LAYOUTFILE) 'caps_lock_layer_3620.keyman-touch-layout' begin Unicode > use(main) store(key) [K_A] .. [K_Z] [SHIFT K_A] .. [SHIFT K_Z] store(out) 'a' .. 'z' 'A' .. 'Z' store(&CasedKeys) [K_A] .. [K_Z] group(main) using keys + any(key) > index(out, 1) keyman/common/test/keyboards/caps_lock_layer_3620/source/caps_lock_layer_3620.kps0000664000000000000000000000330214600607066025116 0ustar 15.0.114.0 7.0 readme.htm Caps Lock Layer 3620 © ..\build\caps_lock_layer_3620.kmx 0 .kmx ..\build\caps_lock_layer_3620.js 0 .js ..\build\caps_lock_layer_3620.kvk 0 .kvk welcome.htm 0 .htm readme.htm 0 .htm Caps Lock Layer 3620 caps_lock_layer_3620 1.0 English keyman/common/test/keyboards/caps_lock_layer_3620/source/caps_lock_layer_3620.kvks0000664000000000000000000000026614600607066025305 0ustar
10.0 caps_lock_layer_3620
keyman/common/test/keyboards/caps_lock_layer_3620/source/readme.htm0000664000000000000000000000076314600607066022552 0ustar Caps Lock Layer 3620

Caps Lock Layer 3620

Caps Lock Layer 3620 1.0 generated from template.

©

keyman/common/test/keyboards/caps_lock_layer_3620/source/welcome.htm0000664000000000000000000000111614600607066022741 0ustar Start Using Caps Lock Layer 3620

Start Using Caps Lock Layer 3620

Caps Lock Layer 3620 1.0 generated from template.

Keyboard Layout

keyman/common/test/keyboards/full_caps_3620_3621/0000775000000000000000000000000014600607066016566 5ustar keyman/common/test/keyboards/full_caps_3620_3621/HISTORY.md0000664000000000000000000000015114600607066020246 0ustar full_caps_3620_3621 Change History ==================== 1.0 (2021-12-01) ---------------- * Created by keyman/common/test/keyboards/full_caps_3620_3621/LICENSE.md0000664000000000000000000000203714600607066020174 0ustar The MIT License (MIT) © 2021 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. keyman/common/test/keyboards/full_caps_3620_3621/README.md0000664000000000000000000000056714600607066020055 0ustar full_caps_3620_3621 keyboard ============== Version 1.0 Description ----------- full_caps_3620_3621 generated from template Links ----- Copyright --------- See [LICENSE.md](LICENSE.md) Supported Platforms ------------------- * Windows * macOS * Linux * Web * iPhone * iPad * Android phone * Android tablet * Mobile devices * Desktop devices * Tablet devices keyman/common/test/keyboards/full_caps_3620_3621/full_caps_3620_3621.kpj0000664000000000000000000000640214600607066022373 0ustar $PROJECTPATH\build True True True keyboard id_48789b910029398efc8e93b3cf8ead67 full_caps_3620_3621.kmn source\full_caps_3620_3621.kmn 1.0 .kmn
full_caps_3620_3621 ©
id_0a20f9a938ef015f88d1e10294793d49 full_caps_3620_3621.kps source\full_caps_3620_3621.kps .kps
full_caps_3620_3621 ©
id_ede98e4633e239f933cbfd1f4e1b766c HISTORY.md HISTORY.md .md id_53e892b8b41cc4caece1cfd5ef21d6e7 LICENSE.md LICENSE.md .md id_0730bb7c2e8f9ea2438b52e419dd86c9 README.md README.md .md id_3087832d59de33f9903fc21ba620b576 full_caps_3620_3621.kmx source\..\build\full_caps_3620_3621.kmx .kmx id_0a20f9a938ef015f88d1e10294793d49 id_5ac2d34b9f02b291dd03055796f14de3 full_caps_3620_3621.js source\..\build\full_caps_3620_3621.js .js id_0a20f9a938ef015f88d1e10294793d49 id_74e4dcbb99594bddbe39b1fcac0ea24f full_caps_3620_3621.kvk source\..\build\full_caps_3620_3621.kvk .kvk id_0a20f9a938ef015f88d1e10294793d49 id_356e5d149c1e539356d72698c1e401a6 welcome.htm source\welcome.htm .htm id_0a20f9a938ef015f88d1e10294793d49 id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_0a20f9a938ef015f88d1e10294793d49
keyman/common/test/keyboards/full_caps_3620_3621/source/0000775000000000000000000000000014600607066020066 5ustar keyman/common/test/keyboards/full_caps_3620_3621/source/full_caps_3620_3621.keyman-touch-layout0000664000000000000000000005130114600607066027024 0ustar { "tablet": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "a", "pad": 70 }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "id": "T_new_54", "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": 70 }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "id": "T_new_88", "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "text": "$", "layer": "shift", "pad": 70 }, { "id": "K_2", "text": "@", "layer": "shift" }, { "id": "K_3", "text": "#", "layer": "shift" }, { "id": "K_5", "text": "%", "layer": "shift" }, { "id": "K_7", "text": "&", "layer": "shift" }, { "id": "K_HYPHEN", "text": "_", "layer": "shift" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "text": "|", "layer": "shift" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1" }, { "id": "K_LBRKT", "text": "[", "sk": [ { "id": "U_00AB", "text": "«" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "text": "(", "layer": "shift" }, { "id": "K_0", "text": ")", "layer": "shift" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "»" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "text": "+", "layer": "shift" }, { "id": "K_HYPHEN", "text": "-", "layer": "default" }, { "id": "K_8", "text": "*", "layer": "shift" }, { "id": "K_SLASH", "text": "/", "layer": "default" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "140", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "caps", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": 70 }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "id": "T_new_88", "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*ShiftedLock*", "width": "110", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] } ], "displayUnderlying": false } }keyman/common/test/keyboards/full_caps_3620_3621/source/full_caps_3620_3621.kmn0000664000000000000000000000364114600607066023676 0ustar c full_caps_3620_3621 generated from template at 2021-12-01 08:45:15 c with name "full_caps_3620_3621" store(&VERSION) '15.0' store(&NAME) 'full_caps_3620_3621' store(©RIGHT) '©' store(&KEYBOARDVERSION) '1.0' store(&TARGETS) 'any' store(&VISUALKEYBOARD) 'full_caps_3620_3621.kvks' store(&LAYOUTFILE) 'full_caps_3620_3621.keyman-touch-layout' begin Unicode > use(main) begin NewContext > use(NewContext) begin PostKeystroke > use(PostKeystroke) store(key) [K_A] .. [K_Z] [SHIFT K_A] .. [SHIFT K_Z] store(out) 'a' .. 'z' 'A' .. 'Z' store(&CasedKeys) [K_A] .. [K_Z] store(caps) 'A'..'Z' store(digit) '0'..'9' group(NewContext) readonly c Any time we get a new context, by mouse click, tap, c cursor movement, new document, etc, we'll try and c determine the best layer to use nomatch > use(nextLayer) group(PostKeystroke) readonly c this is a heuristic: if we find two+ characters in capitals, leave c us in shift layer, assuming the user hasn't just switched layer c themselves. Not sure if this is a good idea! c if(&newLayer = "") if(&layer = 'shift') any(caps) any(caps) > layer('caps') c ??? is this a good idea? c stay on the numeric layer if we are there already if(&newLayer = "") if(&layer = 'numeric') any(digit) > context c don't cancel caps lock layer if(&layer = 'caps') > context c no other changes, so detect sentence or layer change, as long c as the user hasn't attempted to change layer themselves if(&newLayer = "") > use(nextLayer) group(nextLayer) readonly store(sentencePunctuation) '.?!' nul > layer('shift') c note that 'readonly' layers do not need to use 'context' unless there is c no other content on output of rule (empty output is illegal) any(sentencePunctuation) ' ' > layer('shift') any(sentencePunctuation) ' ' > layer('shift') nomatch > layer('default') group(main) using keys + any(key) > index(out, 1) keyman/common/test/keyboards/full_caps_3620_3621/source/full_caps_3620_3621.kps0000664000000000000000000000327414600607066023710 0ustar 15.0.114.0 7.0 readme.htm full_caps_3620_3621 © ..\build\full_caps_3620_3621.kmx 0 .kmx ..\build\full_caps_3620_3621.js 0 .js ..\build\full_caps_3620_3621.kvk 0 .kvk welcome.htm 0 .htm readme.htm 0 .htm full_caps_3620_3621 full_caps_3620_3621 1.0 English keyman/common/test/keyboards/full_caps_3620_3621/source/full_caps_3620_3621.kvks0000664000000000000000000000636614600607066024076 0ustar
10.0 full_caps_3620_3621
` 1 2 3 4 5 6 7 8 9 0 - = q w e r t y u i o p [ ] \ a s d f g h j k l ; ' \ z x c v b n m , . / ~ ! @ # $ % ^ & * ( ) _ + Q W E R T Y U I O P { } | A S D F G H J K L : " | Z X C V B N M < > ?
keyman/common/test/keyboards/full_caps_3620_3621/source/readme.htm0000664000000000000000000000076014600607066022040 0ustar full_caps_3620_3621

full_caps_3620_3621

full_caps_3620_3621 1.0 generated from template.

©

keyman/common/test/keyboards/full_caps_3620_3621/source/welcome.htm0000664000000000000000000000111314600607066022227 0ustar Start Using full_caps_3620_3621

Start Using full_caps_3620_3621

full_caps_3620_3621 1.0 generated from template.

Keyboard Layout

keyman/common/test/keyboards/invalid/0000775000000000000000000000000014600607066015117 5ustar keyman/common/test/keyboards/invalid/README.md0000664000000000000000000001670614600607066016410 0ustar # **Tests for kmcompxtest()**
This folder contains several kmn-files that are used for testing resulting error codes. Most of these tests are copied from balochi_phonetic and contain alterations of the data to produce (at least) 1 error.

## Naming Convention of kmn-files for using with kmcompxtest() CERR_404D_balochi_phonetic.kmn The naming convention of the files is as follows: * All Files **MUST** start with CERR_ followed by 4 characters and an underscore. * After the second underscore all combination of char can be used. * The 4 characters following CERR_ correspond to the last 4 digits of the error code which is expected to be produced by this file. ( e.g. CERR_404D_balochi_phonetic.kmn should produce error 0x0000404D).

While running, kmcompxtest extracts those 4 characters from the Filename (e.g. 404D for CERR_404D_balochi_phonetic) and compares those to the actual error found. * If these 4 characters correspond to the actual error given, the test will be marked as OK. (Code 0)
* If these 4 characters signify an error but **no error** does occur, the test will be marked as FAILED (Code 1)
* If these 4 characters signify an error but this **specific error** does not occur, the test will be marked as FAILED (Code 4)
* If these 4 characters signify an error number that is **not correct**, the test will be marked as FAILED (Code 5)
* If more than 1 error is produced, only the error coded in the Filename will be detected

### Tests are available for the following CERR_: | | Error Number | CERR_ | :-: | :-----------:| :------------------------------------- | | 00000800 | CERR_LEXICAL_MODEL_MIN | | 000008FF | CERR_LEXICAL_MODEL_MAX | | 00000800 | CERR_LEXICAL_MODEL_MIN | | 000008FF | CERR_LEXICAL_MODEL_MAX | | 00000000 | CERR_None | | 00000001 | CERR_EndOfFile | | 00008002 | CERR_BadCallParams | | 00008004 | CERR_CannotAllocateMemory | | 00004005 | CERR_InfileNotExist | | 00004006 | // CERR_CannotCreateOutfile | | 00008007 | CERR_UnableToWriteFully | | 00004008 | CERR_CannotReadInfile | | 00008009 | CERR_SomewhereIGotItWrong |**X**| 0000400A | CERR_InvalidToken | | 0000400B | CERR_InvalidBegin | | 0000400C | CERR_InvalidName |**X**| 0000400D | CERR_InvalidVersion |**X**| 0000400E | CERR_InvalidLanguageLine | | 0000400F | CERR_LayoutButNoLanguage | | 00004010 | CERR_InvalidLayoutLine | | 00004011 | CERR_NoVersionLine | | 00004012 | CERR_InvalidGroupLine |**X**| 00004013 | CERR_InvalidStoreLine | | 00004014 | CERR_InvalidCodeInKeyPartOfRule |**X**| 00004015 | CERR_InvalidDeadkey |**X**| 00004016 | CERR_InvalidValue |**X**| 00004017 | CERR_ZeroLengthString | | 00004018 | CERR_TooManyIndexToKeyRefs |**X**| 00004019 | CERR_UnterminatedString | | 0000401A | CERR_StringInVirtualKeySection | | 0000401B | CERR_AnyInVirtualKeySection | | 0000401C | CERR_InvalidAny |**X**| 0000401D | CERR_StoreDoesNotExist | | 0000401E | CERR_BeepInVirtualKeySection | | 0000401F | CERR_IndexInVirtualKeySection | | 00004020 | CERR_InvalidIndex | | 00004021 | CERR_OutsInVirtualKeySection | | 00004022 | CERR_InvalidOuts | | 00004024 | CERR_ContextInVirtualKeySection | | 00004025 | CERR_InvalidUse |**X**| 00004026 | CERR_GroupDoesNotExist | | 00004027 | CERR_VirtualKeyNotAllowedHere | | 00004028 | CERR_InvalidSwitch |**X**| 00004029 | CERR_NoTokensFound | | 0000402A | CERR_InvalidLineContinuation |**X**| 0000402B | CERR_LineTooLong | | 0000402C | CERR_InvalidCopyright |**X**| 0000402D | CERR_CodeInvalidInThisSection | | 0000402E | CERR_InvalidMessage | | 0000402F | CERR_InvalidLanguageName | | 00004030 | CERR_InvalidBitmapLine |**X**| 00004031 | CERR_CannotReadBitmapFile | | 00004032 | CERR_IndexDoesNotPointToAny | | 00004033 | CERR_ReservedCharacter |**X**| 00004034 | CERR_InvalidCharacter | | 00004035 | CERR_InvalidCall | | 00004036 | CERR_CallInVirtualKeySection | | 00004037 | CERR_CodeInvalidInKeyStore |**X**| 00004038 | CERR_CannotLoadIncludeFile |**X**| 00004039 | CERR_60FeatureOnly_EthnologueCode |**X**| 0000403A | CERR_60FeatureOnly_MnemonicLayout | | 0000403B | CERR_60FeatureOnly_OldCharPosMatching | | 0000403C | CERR_60FeatureOnly_NamedCodes | | 0000403D | CERR_60FeatureOnly_Contextn |**X**| 0000403E | CERR_501FeatureOnly_Call | | 0000403F | CERR_InvalidNamedCode |**X**| 00004040 | CERR_InvalidSystemStore |**X**| 00004044 | CERR_60FeatureOnly_VirtualCharKey |**X**| 00004045 | CERR_VersionAlreadyIncluded |**X**| 00004046 | CERR_70FeatureOnly |**X**| 00004047 | CERR_80FeatureOnly | | 00004048 | CERR_InvalidInVirtualKeySection |**X**| 00004049 | CERR_InvalidIf |**X**| 0000404A | CERR_InvalidReset |**X**| 0000404B | CERR_InvalidSet |**X**| 0000404C | CERR_InvalidSave |**X**| 0000404D | CERR_InvalidEthnologueCode | | 0000804E | CERR_CannotCreateTempfile |**X**| 0000404F | CERR_90FeatureOnly_IfSystemStores | | 00004050 | CERR_IfSystemStore_NotFound | | 00004051 | CERR_90FeatureOnly_SetSystemStores | | 00004052 | CERR_SetSystemStore_NotFound | | 00004053 | CERR_90FeatureOnlyVirtualKeyDictionary | | 00004054 | CERR_NotSupportedInKeymanWebContext | | 00004055 | CERR_NotSupportedInKeymanWebOutput | | 00004056 | CERR_NotSupportedInKeymanWebStore | | 00004057 | CERR_VirtualCharacterKeysNotSupportedInKeymanWeb | | 00004058 | CERR_VirtualKeysNotValidForMnemonicLayouts | | 00004059 | CERR_InvalidTouchLayoutFile | | 0000405A | CERR_TouchLayoutInvalidIdentifier | | 0000405B | CERR_InvalidKeyCode |**X**| 0000405C | CERR_90FeatureOnlyLayoutFile |**X**| 0000405D | CERR_90FeatureOnlyKeyboardVersion |**X**| 0000405E | CERR_KeyboardVersionFormatInvalid | | 0000405F | CERR_ContextExHasInvalidOffset |**X**| 00004060 | CERR_90FeatureOnlyEmbedCSS |**X**| 00004061 | CERR_90FeatureOnlyTargets | | 00004062 | CERR_ContextAndIndexInvalidInMatchNomatch | | 00004063 | CERR_140FeatureOnlyContextAndNotAnyWeb |**X**| 00004064 | CERR_ExpansionMustFollowCharacterOrVKey |**X**| 00004065 | CERR_VKeyExpansionMustBeFollowedByVKey |**X**| 00004066 | CERR_CharacterExpansionMustBeFollowedByCharacter |**X**| 00004067 | CERR_VKeyExpansionMustUseConsistentShift |**X**| 00004068 | CERR_ExpansionMustBePositive |**X**| 00004069 | CERR_CasedKeysMustContainOnlyVirtualKeys |**X**| 0000406A | CERR_CasedKeysMustNotIncludeShiftStates |**X**| 0000406B | CERR_CasedKeysNotSupportedWithMnemonicLayout |**X**| 0000406C | CERR_CannotUseReadWriteGroupFromReadonlyGroup | | 0000406D | CERR_StatementNotPermittedInReadonlyGroup |**X**| 0000406E | CERR_OutputInReadonlyGroup |**X**| 0000406F | CERR_NewContextGroupMustBeReadonly |**X**| 00004070 | CERR_PostKeystrokeGroupMustBeReadonly |**X**| 00004071 | CERR_DuplicateGroup |**X**| 00004072 | CERR_DuplicateStore |**X**| 00004073 | CERR_RepeatedBegin |**X**| 000080C0 | CERR_BufferOverflow keyman/common/test/keyboards/invalid/source/0000775000000000000000000000000014600607066016417 5ustar keyman/common/test/keyboards/invalid/source/CERR_400A_balochi_phonetic.kmn0000664000000000000000000000542014600607066023720 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' c ***** CERR_InvalidToken 0x0000400A ******************************** + [CTRL B10] > L'1234' c ******************************************************************* + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا' keyman/common/test/keyboards/invalid/source/CERR_400D_balochi_phonetic.kmn0000664000000000000000000000541614600607066023730 0ustar  c ***** CERR_InvalidVersion 0x0000400D ***************************** store(&VERSION) '127.0' c ******************************************************************* store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_400E_balochi_phonetic.kmn0000664000000000000000000000544614600607066023734 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' c ***** CERR_InvalidLanguageLine 0x0000400E ************************ store(&LANGUAGE) 'abc123' c ******************************************************************* begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4013_balochi_phonetic.kmn0000664000000000000000000000541214600607066023704 0ustar c ***** CERR_InvalidStoreLine 0x00004013 *************************** store(&VERSION '10.0' c ****************************************************************** store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4015_k_014___groups_and_virtual_keys.kmn0000664000000000000000000000146614600607066026557 0ustar store(&NAME) '014 - groups and virtual keys' c Description: Tests multiple groups and virtual keys with mnemonic layout c keys: [K_A][SHIFT K_2][K_A][LCTRL K_2][K_A] c expected: \u03B1\u1FB0\u1FB1 store(&VERSION) '9.0' begin Unicode > use(UMain) store(&MnemonicLayout) "0" c ---------------------------------------------- group(UMain) using keys + [K_A] > U+03B1 c ***** CERR_InvalidDeadkey 0x00004015 ****************************** + [CTRL K_q] > deadkey('–') c ******************************************************************* + [ALT K_2] > deadkey(MacronBug) + [SHIFT K_2] > deadkey(BreveBug) match > use(DK1) c ---------------------------------------------- group(DK1) deadkey(MacronBug) U+03B1 > U+1FB1 c won't work deadkey(BreveBug) U+03B1 > U+1FB0 c workskeyman/common/test/keyboards/invalid/source/CERR_4016_k_014___groups_and_virtual_keys.kmn0000664000000000000000000000146614600607066026560 0ustar store(&NAME) '014 - groups and virtual keys' c Description: Tests multiple groups and virtual keys with mnemonic layout c keys: [K_A][SHIFT K_2][K_A][LCTRL K_2][K_A] c expected: \u03B1\u1FB0\u1FB1 store(&VERSION) '9.0' begin Unicode > use(UMain) store(&MnemonicLayout) "0" c ---------------------------------------------- group(UMain) using keys + [K_A] > U+03B1 + [CTRL K_2] > deadkey(MacronBug) + [ALT K_2] > deadkey(MacronBug) + [SHIFT K_2] > deadkey(BreveBug) match > use(DK1) c ---------------------------------------------- group(DK1) deadkey(MacronBug) U+03B1 > U+1FB1 c won't work c ***** CERR_InvalidValue 0x00004016 ***************************** deXadkey(BreveBug) U+03B1 > U+1FB0 c works c *******************************************************************keyman/common/test/keyboards/invalid/source/CERR_4017_balochi_phonetic.kmn0000664000000000000000000000540514600607066023712 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.bmp' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' c ***** CERR_ZeroLengthString 0x00004017 *************************** + [CTRL B10] > c ****************************************************************** + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4019_balochi_phonetic.kmn0000664000000000000000000000541014600607066023710 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' c ***** CERR_UnterminatedString 0x00004019 ************************* store(&BITMAP)CERR__balochi_phonetic.ico' c ****************************************************************** begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_401D_k_034___options_double_set_reset.kmn0000664000000000000000000000115014600607066026726 0ustar store(&NAME) '034 - options double set reset' c Description: Tests basic option rules with save reset+set+reset c keys: [K_A][K_A] c expected: foo.foo. c context: c option: foo=1 c expected option: foo=1 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys c ***** CERR_StoreDoesNotExist 0x0000401D *********************************** if(foo = '1') + 'a' > 'foo.' set(foo='2') reset(ffoo) set(foo='3') reset(foo) c ******************************************************************* if(foo = '2') + 'a' > 'bar.' if(foo = '3') + 'a' > 'baz.' if(foo = '0') + 'a' > 'no foo.' keyman/common/test/keyboards/invalid/source/CERR_4026_balochi_phonetic.kmn0000664000000000000000000000123014600607066023702 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) c ***** CERR_GroupDoesNotExist 0x00004026 ************************** c ******************************************************************keyman/common/test/keyboards/invalid/source/CERR_4029_balochi_phonetic.kmn0000664000000000000000000000534414600607066023717 0ustar store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' c ***** CERR_NoTokensFound 0x00004029 ******************************* begin c ******************************************************************* group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '§' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا' keyman/common/test/keyboards/invalid/source/CERR_402B_balochi_phonetic.kmn0000664000000000000000000002611414600607066023726 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' c ***** CERR_LineTooLong 0x0000402B ******************************** store(©RIGHT) '© 2017-2021 SIL InternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxInternationalxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' c ****************************************************************** store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_402D_balochi_phonetic.kmn0000664000000000000000000000536414600607066023734 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) c ***** CERR_CodeInvalidInThisSection 0x0000402D ******************* c ****************************************************************** + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4031_balochi_phonetic.kmn0000664000000000000000000000540414600607066023705 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' c ***** CERR_CannotReadBitmapFile 0x00004031 *********************** store(&BITMAP) 'balochi_phonetic.ico' c ****************************************************************** begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4034_balochi_phonetic.kmn0000664000000000000000000000541714600607066023714 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' c ***** CERR_InvalidCharacter 0x00004034 *************************** store(©RIGHT) ' 2012 U+1234 -2020 SIL International' c ****************************************************************** store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4038_balochi_phonetic.kmn0000664000000000000000000000545014600607066023715 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' c ***** CERR_CannotLoadIncludeFile 0x00004038 ********************** store(&INCLUDECODES) 'XX.txt' c ****************************************************************** begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4039_balochi_phonetic.kmn0000664000000000000000000000614214600607066023715 0ustar c ***** This test will produce XXXX Error: *************************** c ***** 1) it will be marked as FAIL when run in kmcompxtest ******* c ***** as a XXXXXXX non-existing ErrorNr (0x00040733) is specified ***** c ******************************************************************store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' c ***** CERR_60FeatureOnly_EthnologueCode 0x00004039 **************** store(&version) '3.0' store(ÐNOLOGUECODE) 'eng' c ******************************************************************* begin Unicode > use(main) group (main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '§' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا' keyman/common/test/keyboards/invalid/source/CERR_403A_014_groups_and_virtual_keys.kmn0000664000000000000000000000211714600607066025757 0ustar c RegressionTest: Multiple groups and virtual keys c Font: Arial Unicode MS c Encoding: Unicode c Description: Tests multiple groups and virtual keys -- bug Ixxx c Procedure: Press A, Shift+2, A, Ctrl+2, A c AutoProc: K_A S+ K_2 S- K_A C+ K_2 C- K_A c FinalOutput: U+03B1 U+1FB0 U+1FB1 c ***** CERR_60FeatureOnly_MnemonicLayout 0x0000403A **************** store(&VERSION) '3.0' c ******************************************************************* NAME "AltGr Deadkeys Test" begin Unicode > use(UMain) c Substitute UMain1 or UMain2 c ***** CERR_60FeatureOnly_MnemonicLayout 0x0000403A **************** store(&MnemonicLayout) "1" c ******************************************************************* c ---------------------------------------------- group(UMain) using keys + ['a'] > U+03B1 + [CTRL '2'] > deadkey(MacronBug) + [ALT '2'] > deadkey(MacronBug) + [SHIFT '2'] > deadkey(BreveBug) match > use(DK1) c ---------------------------------------------- group(DK1) deadkey(MacronBug) U+03B1 > U+1FB1 c won't work deadkey(BreveBug) U+03B1 > U+1FB0 c works keyman/common/test/keyboards/invalid/source/CERR_403E_imsample.kmn0000664000000000000000000000077214600607066022251 0ustar c ***** CERR_501FeatureOnly_Call 0x0000403E ************************* store(&VERSION) '3.0' c ******************************************************************* store(&NAME) 'IMTest' store(DLLFunction) "imsample.dll:DF" begin Unicode > use(main) group(main) using keys c ***** CERR_501FeatureOnly_Call 0x0000403E ************************* + [K_BKSP] > call(DLLFunction) + [K_ESC] > call(DLLFunction) nomatch > call(DLLFunction) c *******************************************************************keyman/common/test/keyboards/invalid/source/CERR_4040_balochi_phonetic.kmn0000664000000000000000000000541514600607066023707 0ustar store(&VERSION) '10.0' c ***** CERR_InvalidSystemStore 0x00004040 ************************* store(&NXXAME) 'Balochi Phonetic' c ****************************************************************** store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4044_014_groups_and_virtual_keys.kmn0000664000000000000000000000211614600607066025742 0ustar c RegressionTest: Multiple groups and virtual keys c Font: Arial Unicode MS c Encoding: Unicode c Description: Tests multiple groups and virtual keys -- bug Ixxx c Procedure: Press A, Shift+2, A, Ctrl+2, A c AutoProc: K_A S+ K_2 S- K_A C+ K_2 C- K_A c FinalOutput: U+03B1 U+1FB0 U+1FB1 c ***** CERR_501FeatureOnly_Call 0x0000403E ************************* store(&VERSION) '3.0' c ******************************************************************* NAME "AltGr Deadkeys Test" begin Unicode > use(UMain) c Substitute UMain1 or UMain2 store(&MnemonicLayout) "1" c ---------------------------------------------- c ***** CERR_60FeatureOnly_VirtualCharKey 0x00004044 **************** group(UMain) using keys + ['a'] > U+03B1 + [CTRL '2'] > deadkey(MacronBug) + [ALT '2'] > deadkey(MacronBug) + [SHIFT '2'] > deadkey(BreveBug) c ******************************************************************* match > use(DK1) c ---------------------------------------------- group(DK1) deadkey(MacronBug) U+03B1 > U+1FB1 c won't work deadkey(BreveBug) U+03B1 > U+1FB0 c works keyman/common/test/keyboards/invalid/source/CERR_4045_balochi_phonetic.kmn0000664000000000000000000000546114600607066023715 0ustar store(&VERSION) '10.0' c ***** CERR_VersionAlreadyIncluded 0x00004045 ****************************** store(&VERSION) '110.0' c ******************************************************************* store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا' keyman/common/test/keyboards/invalid/source/CERR_4046_balochi_phonetic.kmn0000664000000000000000000000541214600607066023712 0ustar c ***** CERR_70FeatureOnly 0x00004046 ****************************** store(&VERSION) '4.0' c ****************************************************************** store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4047_k_022___options_with_preset.kmn0000664000000000000000000000134614600607066025726 0ustar store(&NAME) '022 - options with preset' c Description: Tests basic option rules with a preset supplied c keys: [K_A][K_1][K_A][K_0][K_A] c expected: foo.foo.no foo. c context: c option: foo=1 c expected option: foo=0 c saved option: foo=0 c ***** CERR_80FeatureOnly 0x00004047 ******************************* store(&VERSION) '3.0' c ******************************************************************* store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' c ***** CERR_80FeatureOnly 0x00004047 ******************************* + '1' > set(foo = '1') save(foo) + '0' > set(foo = '0') save(foo) c *******************************************************************keyman/common/test/keyboards/invalid/source/CERR_4049_k_022___options_with_preset.kmn0000664000000000000000000000113114600607066025720 0ustar store(&NAME) '022 - options with preset' c Description: Tests basic option rules with a preset supplied c keys: [K_A][K_1][K_A][K_0][K_A] c expected: foo.foo.no foo. c context: c option: foo=1 c expected option: foo=0 c saved option: foo=0 store(&VERSION) '8.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys c ***** CERR_InvalidIf 0x00004049 *********************************** if(foo '1') + 'a' > 'foo.' c ******************************************************************* if(foo = '0') + 'a' > 'no foo.' + '1' > set(foo = '1') save(foo) + '0' > set(foo = '0') save(foo)keyman/common/test/keyboards/invalid/source/CERR_404A_k_025___options_with_reset.kmn0000664000000000000000000000106714600607066025563 0ustar store(&NAME) '025 - options with reset' c Description: Tests basic option rules with reset c keys: [K_A][K_1][K_A][K_0][K_A][K_3] c expected: foo.foo.no foo. c context: c option: foo=1 c expected option: foo=1 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' + '1' > set(foo = '1') + '0' > set(foo = '0') c ***** CERR_InvalidReset 0x0000404A ******************************** + '3' > reset c ******************************************************************* keyman/common/test/keyboards/invalid/source/CERR_404B_k_025___options_with_reset.kmn0000664000000000000000000000105114600607066025555 0ustar store(&NAME) '025 - options with reset' c Description: Tests basic option rules with reset c keys: [K_A][K_1][K_A][K_0][K_A][K_3] c expected: foo.foo.no foo. c context: c option: foo=1 c expected option: foo=1 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' c ***** CERR_InvalidReset 0x0000404B ******************************** + '1' > set( + '0' > set c ******************************************************************* + '3' > reset(foo) keyman/common/test/keyboards/invalid/source/CERR_404C_k_023___options_with_save.kmn0000664000000000000000000000107514600607066025376 0ustar store(&NAME) '023 - options with save' c Description: Tests basic option rules with save c keys: [K_A][K_1][K_A][K_0][K_A][K_2] c expected: no foo.foo.no foo. c context: c expected option: foo=0 c saved option: foo=0 store(&version) '10.0' store(foo) '0' begin Unicode > use(Main) group(Main) using keys if(foo = '1') + 'a' > 'foo.' if(foo = '0') + 'a' > 'no foo.' + '1' > set(foo = '1') + '0' > set(foo = '0') c ***** CERR_InvalidSave 0x0000404C ********************************* + '2' > save c ******************************************************************* keyman/common/test/keyboards/invalid/source/CERR_404D_balochi_phonetic.kmn0000664000000000000000000000545014600607066023732 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' c ***** CERR_InvalidEthnologueCode 0x0000404D ********************** store(&EthnologueCode) "xxxx" c ****************************************************************** begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_404F_k_026___system_stores.kmn0000664000000000000000000000174314600607066024565 0ustar store(&NAME) '026 - system stores' c Description: Tests platform and baselayout system store rules c keys: [K_1][K_2][K_3][K_4][K_A][K_B] c expected: windows.desktop.hardware.native.en-US.kbdus.dll. c context: c (default) option: &platform=windows desktop hardware native <-- ignored by test c (default) option: &baseLayout=kbdus.dll <-- ignored by test c (default) option: &baseLayoutAlt=en-US <-- ignored by test c ***** CERR_90FeatureOnly_IfSystemStores 0x0000404F **************** store(&version) '3.0' c ******************************************************************* store(digit) '1234567890' store(letter) 'abcdefghij' begin Unicode > use(Main) group(Main) using keys platform('windows') + '1' > 'windows.' platform('desktop') + '2' > 'desktop.' platform('hardware') + '3' > 'hardware.' platform('native') + '4' > 'native.' + any(digit) > 'platform-fail.' baselayout('en-US') + 'a' > 'en-US.' baselayout('kbdus.dll') + 'b' > 'kbdus.dll.' + any(letter) > 'baselayout-fail.' keyman/common/test/keyboards/invalid/source/CERR_405C_balochi_phonetic.kmn0000664000000000000000000000541214600607066023730 0ustar c ***** CERR_90FeatureOnlyLayoutFile 0x0000405C ******************** store(&VERSION) '4.0' c ****************************************************************** store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_405D_balochi_phonetic.kmn0000664000000000000000000000541214600607066023731 0ustar c ***** CERR_90FeatureOnlyKeyboardVersion 0x0000405D *************** store(&VERSION) '4.0' c ****************************************************************** store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_405E_balochi_phonetic.kmn0000664000000000000000000000541114600607066023731 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' c ***** CERR_KeyboardVersionFormatInvalid 0x0000405E *************** store(&KEYBOARDVERSION) 'abc' c ****************************************************************** store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4060_balochi_phonetic.kmn0000664000000000000000000000545614600607066023716 0ustar store(&VERSION) '4.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' c ***** CERR_90FeatureOnlyEmbedCSS 0x00004060 ********************** store(&KMW_EMBEDCSS) 'naijatype.css' c ****************************************************************** begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4061_balochi_phonetic.kmn0000664000000000000000000000541214600607066023707 0ustar c ***** CERR_90FeatureOnlyTargets 0x00004061 *********************** store(&VERSION) '4.0' c ****************************************************************** store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا'keyman/common/test/keyboards/invalid/source/CERR_4064_caps_lock_layer_3620.kmn0000664000000000000000000000127014600607066024222 0ustar c caps_lock_layer_3620 generated from template at 2021-11-30 14:58:52 c with name "Caps Lock Layer 3620" store(&VERSION) '10.0' store(&NAME) 'Caps Lock Layer 3620' store(©RIGHT) '©' store(&KEYBOARDVERSION) '1.0' store(&TARGETS) 'any' store(&VISUALKEYBOARD) 'caps_lock_layer_3620.kvks' store(&LAYOUTFILE) 'caps_lock_layer_3620.keyman-touch-layout' begin Unicode > use(main) store(key) [K_A] .. [K_Z] [SHIFT K_A] .. [SHIFT K_Z] c ***** CERR_ExpansionMustFollowCharacterOrVKey 0x00004064 ********** store(out) .. 'z' 'A' .. 'Z' c ******************************************************************* store(&CasedKeys) [K_A] .. [K_Z] group(main) using keys + any(key) > index(out, 1) keyman/common/test/keyboards/invalid/source/CERR_4065_test_expansion_invalid.kmn0000664000000000000000000000150214600607066025166 0ustar c This file tests that invalid expansions are caught store(&NAME) 'Test Invalid Expansions' begin Unicode > use(main) group(main) using keys c Backward ranges store(char_range_backward) 'c' .. 'a' store(key_range_backward) [K_E] .. [K_A] store(char_range_empty) 'c' .. 'c' store(key_range_empty) [K_E] .. [K_E] c Incomplete ranges store(range_open) .. store(char_range_open_end) 'a' .. store(char_range_open_start) .. 'z' store(key_range_open_end) [K_A] .. store(key_range_open_start) .. [K_Z] c Inconsistent ranges store(char_range_to_key) 'a' .. [K_Z] store(key_range_to_char) [K_A] .. 'z' store(char_range_to_statement) 'a' .. nul store(key_range_to_statement) [K_A] .. nul store(char_range_from_statement) nul .. 'a' store(key_range_from_statement) nul .. [K_A] store(key_range_shift_inconsistent) [SHIFT K_A] .. [K_Z] keyman/common/test/keyboards/invalid/source/CERR_4066_test_expansion_invalid.kmn0000664000000000000000000000150214600607066025167 0ustar c This file tests that invalid expansions are caught store(&NAME) 'Test Invalid Expansions' begin Unicode > use(main) group(main) using keys c Backward ranges store(char_range_backward) 'c' .. 'a' store(key_range_backward) [K_E] .. [K_A] store(char_range_empty) 'c' .. 'c' store(key_range_empty) [K_E] .. [K_E] c Incomplete ranges store(range_open) .. store(char_range_open_end) 'a' .. store(char_range_open_start) .. 'z' store(key_range_open_end) [K_A] .. store(key_range_open_start) .. [K_Z] c Inconsistent ranges store(char_range_to_key) 'a' .. [K_Z] store(key_range_to_char) [K_A] .. 'z' store(char_range_to_statement) 'a' .. nul store(key_range_to_statement) [K_A] .. nul store(char_range_from_statement) nul .. 'a' store(key_range_from_statement) nul .. [K_A] store(key_range_shift_inconsistent) [SHIFT K_A] .. [K_Z] keyman/common/test/keyboards/invalid/source/CERR_4067_test_expansion_invalid.kmn0000664000000000000000000000150214600607066025170 0ustar c This file tests that invalid expansions are caught store(&NAME) 'Test Invalid Expansions' begin Unicode > use(main) group(main) using keys c Backward ranges store(char_range_backward) 'c' .. 'a' store(key_range_backward) [K_E] .. [K_A] store(char_range_empty) 'c' .. 'c' store(key_range_empty) [K_E] .. [K_E] c Incomplete ranges store(range_open) .. store(char_range_open_end) 'a' .. store(char_range_open_start) .. 'z' store(key_range_open_end) [K_A] .. store(key_range_open_start) .. [K_Z] c Inconsistent ranges store(char_range_to_key) 'a' .. [K_Z] store(key_range_to_char) [K_A] .. 'z' store(char_range_to_statement) 'a' .. nul store(key_range_to_statement) [K_A] .. nul store(char_range_from_statement) nul .. 'a' store(key_range_from_statement) nul .. [K_A] store(key_range_shift_inconsistent) [SHIFT K_A] .. [K_Z] keyman/common/test/keyboards/invalid/source/CERR_4068_test_expansion_invalid.kmn0000664000000000000000000000150214600607066025171 0ustar c This file tests that invalid expansions are caught store(&NAME) 'Test Invalid Expansions' begin Unicode > use(main) group(main) using keys c Backward ranges store(char_range_backward) 'c' .. 'a' store(key_range_backward) [K_E] .. [K_A] store(char_range_empty) 'c' .. 'c' store(key_range_empty) [K_E] .. [K_E] c Incomplete ranges store(range_open) .. store(char_range_open_end) 'a' .. store(char_range_open_start) .. 'z' store(key_range_open_end) [K_A] .. store(key_range_open_start) .. [K_Z] c Inconsistent ranges store(char_range_to_key) 'a' .. [K_Z] store(key_range_to_char) [K_A] .. 'z' store(char_range_to_statement) 'a' .. nul store(key_range_to_statement) [K_A] .. nul store(char_range_from_statement) nul .. 'a' store(key_range_from_statement) nul .. [K_A] store(key_range_shift_inconsistent) [SHIFT K_A] .. [K_Z] keyman/common/test/keyboards/invalid/source/CERR_4069_test_casedkeys_invalid_1.kmn0000664000000000000000000000026714600607066025370 0ustar c Tests cased keys - invalid codes store(&NAME) 'Test &CasedKeys' begin Unicode > use(main) group(main) using keys store(&CasedKeys) U+1000 + [K_A] > 'aaah' + [SHIFT K_A] > 'AAAH' keyman/common/test/keyboards/invalid/source/CERR_406A_test_casedkeys_invalid_2.kmn0000664000000000000000000000027414600607066025377 0ustar c Tests cased keys - invalid codes store(&NAME) 'Test &CasedKeys' begin Unicode > use(main) group(main) using keys store(&CasedKeys) [SHIFT K_1] + [K_A] > 'aaah' + [SHIFT K_A] > 'AAAH' keyman/common/test/keyboards/invalid/source/CERR_406B_test_casedkeys_mnemonic_1.kmn0000664000000000000000000000040714600607066025554 0ustar c Tests cased keys - invalid with mnemonic layout store(&NAME) 'Test &CasedKeys' store(&mnemoniclayout) '1' begin Unicode > use(main) group(main) using keys store(&CasedKeys) [K_A] [K_E] [K_I] [K_O] [K_U] [K_1] .. [K_4] + [K_A] > 'aaah' + [SHIFT K_A] > 'AAAH' keyman/common/test/keyboards/invalid/source/CERR_406C_test_5963_readonlygroup_usenonreadonly.kmn0000664000000000000000000000025314600607066030201 0ustar c should fail to compile, readonly group uses() non-readonly group begin Unicode > use(main) group(main) using keys group(foo) readonly 'a' > use(bar) group(bar) keyman/common/test/keyboards/invalid/source/CERR_406E_test_5963_readonlygroup_misplacedcontext.kmn0000664000000000000000000000031114600607066030477 0ustar c Should fail to compile, `context` must be omitted or first statement in output begin Unicode > use(main) group(main) using keys group(foo) readonly 'a' > use(bar) context group(bar) readonly keyman/common/test/keyboards/invalid/source/CERR_406F_test_5963_newcontext_2.kmn0000664000000000000000000000023514600607066024604 0ustar c Should fail to compile, group is not readonly begin Unicode > use(main) begin NewContext > use(NewContext) group(NewContext) group(main) using keys keyman/common/test/keyboards/invalid/source/CERR_4070_test_5963_postkeystroke_2.kmn0000664000000000000000000000024514600607066025310 0ustar c Should fail to compile, group is not readonly begin Unicode > use(main) begin PostKeystroke > use(PostKeystroke) group(PostKeystroke) group(main) using keys keyman/common/test/keyboards/invalid/source/CERR_4071_balochi_phonetic.kmn0000664000000000000000000000544514600607066023716 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) c ***** CERR_DuplicateGroup 0x00004071 ****************************** group(main) using keys c ******************************************************************* group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا' keyman/common/test/keyboards/invalid/source/CERR_4072_balochi_phonetic.kmn0000664000000000000000000000545314600607066023716 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' c ***** DuplicateStore 0x00004072 *********************************** store(©RIGHT) '© ABC' c ******************************************************************* store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا' keyman/common/test/keyboards/invalid/source/CERR_4073_balochi_phonetic.kmn0000664000000000000000000000545114600607066023715 0ustar store(&VERSION) '10.0' store(&NAME) 'Balochi Phonetic' store(&TARGETS) 'any' store(&KMW_RTL) '1' store(&LAYOUTFILE) 'balochi_phonetic.keyman-touch-layout' store(&KEYBOARDVERSION) '1.4.2' store(©RIGHT) '© 2017-2021 SIL International' store(&MESSAGE) 'The Balochi Phonetic keyboard is distributed under The MIT License (MIT).' store(&KMW_HELPTEXT) 'This is a phonetically organized Balochi keyboard.' store(&VISUALKEYBOARD) 'balochi_phonetic.kvks' store(&BITMAP) 'CERR__balochi_phonetic.ico' begin Unicode > use(main) c ***** CERR_RepeatedBegin 0x00004073 ******************************* begin Unicode > use(main) c ******************************************************************* group(main) using keys + [CTRL B08] > '‎' + [CTRL B09] > '‏' + [CTRL B10] > '–' + [SHIFT CTRL E11] > '“' + [SHIFT CTRL E12] > '”' + [CTRL E11] > '‘' + [CTRL E12] > '’' + [CTRL K_K] > 'ء' + [CTRL K_D] > 'ذ' + [K_EQUAL] > '=' + [SHIFT K_8] > '*' + [SHIFT K_7] > '&' + [SHIFT K_5] > '%' + [SHIFT K_4] > '$' + [SHIFT K_3] > '#' + [SHIFT K_2] > '@' + [SHIFT K_1] > '!' + [SHIFT K_N] > 'ں' + [K_BKSLASH] > '۔' + [K_LBRKT] > ']' + [K_RBRKT] > '[' + [K_F] > 'َ' + [K_V] > 'ِ' + [K_X] > 'ش' + [SHIFT K_H] > 'ح' + [SHIFT K_G] > 'ص' + [SHIFT K_Y] > 'ي' + [CTRL K_0] > '۰' + [CTRL K_9] > '۹' + [CTRL K_8] > '۸' + [CTRL K_7] > '۷' + [CTRL K_6] > '۶' + [CTRL K_5] > '۵' + [CTRL K_4] > '۴' + [CTRL K_3] > '۳' + [CTRL K_2] > '۲' + [CTRL K_1] > '۱' + [K_SLASH] > '/' + [K_HYPHEN] > '-' + [SHIFT K_COLON] > ':' + [SHIFT K_QUOTE] > '"' + [K_QUOTE] > U+0027 + [K_O] > 'ُ' + [SHIFT K_O] > 'ْ' + [K_BKQUOTE] > 'ء' + [SHIFT K_W] > 'أ' + [SHIFT K_P] > 'ّ' + [SHIFT K_BKQUOTE] > 'ٔ' + [SHIFT K_J] > 'ض' + [SHIFT K_9] > ')' + [SHIFT K_RBRKT] > '{' + [SHIFT K_LBRKT] > '}' + [SHIFT K_0] > '(' + [SHIFT K_SLASH] > '؟' + [SHIFT K_K] > 'ع' + [SHIFT K_EQUAL] > '«' + [SHIFT K_HYPHEN] > '»' + [SHIFT K_I] > 'ً' + [SHIFT K_PERIOD] > '‹' + [SHIFT K_COMMA] > '›' + [SHIFT K_L] > 'ـ' + [SHIFT K_U] > 'ۀ' + [SHIFT K_B] > 'ة' + [SHIFT K_M] > 'غ' + [SHIFT K_F] > 'ف' + [SHIFT K_E] > 'ۓ' + [SHIFT K_Q] > 'ق' + [K_0] > '0' + [K_9] > '9' + [K_8] > '8' + [K_7] > '7' + [K_6] > '6' + [K_5] > '5' + [K_4] > '4' + [K_3] > '3' + [K_2] > '2' + [K_1] > '1' + [K_I] > 'ێ' + [SHIFT K_D] > 'ڈ' + [K_G] > 'گ' + [K_U] > 'ۆ' + [SHIFT K_R] > 'ڑ' + [SHIFT K_6] > '‌' + [SHIFT K_T] > 'ٹ' + [SHIFT K_V] > 'ظ' + [SHIFT K_C] > 'ط' + [SHIFT K_X] > 'خ' + [SHIFT K_Z] > 'ژ' + [SHIFT K_S] > 'ث' + [SHIFT K_A] > 'آ' + [K_PERIOD] > '.' + [K_COMMA] > '،' + [K_M] > 'م' + [K_N] > 'ن' + [K_B] > 'ب' + [K_C] > 'چ' + [K_Z] > 'ز' + [K_P] > 'پ' + [K_Y] > 'ی' + [K_T] > 'ت' + [K_R] > 'ر' + [K_E] > 'ے' + [K_W] > 'و' + [K_Q] > 'ئ' + [K_COLON] > '؛' + [K_L] > 'ل' + [K_K] > 'ک' + [K_J] > 'ج' + [K_H] > 'ه' + [K_D] > 'د' + [K_S] > 'س' + [K_A] > 'ا' keyman/common/test/keyboards/invalid/source/CERR_80C0_test_expansion_absurd.kmn0000664000000000000000000000024314600607066025035 0ustar c This file tests absurdly long expansions store(&NAME) 'Test Expansions' begin Unicode > use(main) group(main) using keys store(schar_range) U+0020 .. U+10FFFF keyman/common/test/keyboards/invalid/source/CERR__balochi_phonetic.ico0000664000000000000000000000217614600607066023365 0ustar  h(  keyman/common/test/keyboards/issue/0000775000000000000000000000000014600607066014621 5ustar keyman/common/test/keyboards/issue/6254-invalid-version-99/0000775000000000000000000000000014600607066020567 5ustar keyman/common/test/keyboards/issue/6254-invalid-version-99/README.md0000664000000000000000000000106414600607066022047 0ustar 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 keyman/common/test/keyboards/issue/6254-invalid-version-99/build.sh0000775000000000000000000000214214600607066022224 0ustar #!/usr/bin/env bash set -e set -u ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../../../../../resources/build/build-utils.sh" # . "$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 cd "$THIS_DIR" 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 fikeyman/common/test/keyboards/issue/6254-invalid-version-99/the_99.kmp0000664000000000000000000000727214600607066022411 0ustar PKfjT1,kmp.infuN@$ٓ& &(&h[IcV6ˠ#Kk7?f+7yZp VFFH:O -pC d) P=X H!ӔYQU:m+4fzd/ΰ/؄1:{SrKQ)hGgc g>nB?I6d辀3"tkܱ OᦳXxi'wҟB,rvիiU#mBXO;Ow dž`)cocm17ixAMbUuW7PKfjTITkmp.jsonJ0zRXJWPo +‚]$mMRZw7M6.^M3}z'kzW,u bvBtb芷$" uIJgCc wZOuUm#a]@ 2Dۦ* :UċZ$USҷ2C^=S n28߇R\L"vJSXF7f&ժt׃藷CsỲ|B3(fC2Zڋge8VPs$gGQuF2ܐ#yC",)?9]N{nYZ`daM/߿PKvfjT the_99.kmxmjAD&JA FL!ha'G"$h,)>O cvٝu;JK?a Evl\/%Q<?7Sa\S lj978o/?'|jh O2zY虳1- q)\v,q-nY㓾#6 MqujJߩ4d?95=E=N#%Ǘ&jJWyF HhYrYQjGW O )ES˴QB5Rz:OWQ -X^M]W&#J)5ǚ9cڶ:h}s ĵiI"_ԑj}|`2ٺ&Ԅ׳>W-YAr]k6qn^2zJ&k_/VK.mQ(g[m"+TQ#ѩ"')KiG8Xy?*EXl zCPv,j=o"u,o`&%jg,nU(YVcJVw`!ŁquʐOg|BS5A^@^B܇cț!/qnA^܅C2aku=pށ.o98r[˜s~gulg3'mU\o$VQ;٪>!=!?|ykȏ9w pHVfӻqqPT@8E]~ Gtڬ6JĵD!n./:{ravX'bp[l ڬ4hܬƺ.RpArdmV3 WMjA1*NQkoW.9>@9 !9n $@OK9 @rV G9~'cC G1? rk@ @ gA.X ȕ,=dD Ha}69M=B$gI #a =.$[VlRI5Wg)=ӚV7r[pϫ/Z׷|(dyiQan=zxv7Tu9PKfjTA2I the_99.kvkvc`c```g(a`HegB#CC&C"C  PKejT')F= welcome.htm}MK@m)"MzQbEzM~#MRayMwϷ{,i-0E [ Y)\M[ބ7Mi5LgeeNfv%, L(J#%+pZ\&$.F|7GY]@l|)QXj1gI^[#YeWe ZBpmb\N/LWD9=o Ý\w㈇#d g5t;l H c)o 05rТaDI}YtكPKejT( readme.htm}QN@ #&\ID68TB^zt6nҾ1}A_ATq`/^{l~޼>AZ-//6B+"2QW!B517E>:C j*#0yEE{)(FD7Ò-&:" LGND3>`Nkq=Z#\ZUAzw#~׷~'M\Zf琹Hf{tka2x:غkkWr>}vd#S[o50iB:i9aYZjA2?PKfjT1, kmp.infPK?fjTIT$ Qkmp.json ;C4;C4] C4PKvfjT the_99.kmxPKvfjTwxJ( the_99.jsPKfjTA2I the_99.kvkPKejT')F= > welcome.htmPKejT( readme.htmPK keyman/common/test/keyboards/obolo_chwerty_6347/0000775000000000000000000000000014600607066017033 5ustar keyman/common/test/keyboards/obolo_chwerty_6347/HISTORY.md0000664000000000000000000000257114600607066020523 0ustar 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 keyman/common/test/keyboards/obolo_chwerty_6347/LICENSE.md0000664000000000000000000000207214600607066020440 0ustar 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. keyman/common/test/keyboards/obolo_chwerty_6347/README.md0000664000000000000000000000175614600607066020323 0ustar 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 keyman/common/test/keyboards/obolo_chwerty_6347/obolo_chwerty_6347.kpj0000664000000000000000000001512414600607066023106 0ustar $PROJECTPATH\build True True True keyboard id_78ef9463d8d3c51a0dae86c2e065bdc5 obolo_chwerty_6347.kmn source\obolo_chwerty_6347.kmn 1.2.1 .kmn
Obolo Chwerty #6347 © 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_7746b99d6a71e8104ece237d08c78aeb 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_8ec79e2ed4a2ffef6c8f0645d5ff022f obolo_chwerty_6347.ico source\obolo_chwerty_6347.ico .ico id_78ef9463d8d3c51a0dae86c2e065bdc5 id_4ff5fcfce1ae50bc814203248053112b obolo_chwerty_6347.kvk source\..\build\obolo_chwerty_6347.kvk .kvk id_7746b99d6a71e8104ece237d08c78aeb id_4ab379e52544d45e5dfcdc1e6e5c3c8c obolo_chwerty_6347.kmx source\..\build\obolo_chwerty_6347.kmx .kmx id_7746b99d6a71e8104ece237d08c78aeb id_3d23e18f28a458b590852120a16ce2bc obolo_chwerty_6347.js source\..\build\obolo_chwerty_6347.js .js id_7746b99d6a71e8104ece237d08c78aeb id_f6212220adf6c5eb0ae25c33cb973c64 chwerty_default.png source\welcome\chwerty_default.png .png id_7746b99d6a71e8104ece237d08c78aeb id_cd62e578000692c9966c069950904d06 chwerty_keycombi.png source\welcome\chwerty_keycombi.png .png id_7746b99d6a71e8104ece237d08c78aeb id_2d29737f21e65a75ca98a9c3ab1f4a6f chwerty_mobi_alt.png source\welcome\chwerty_mobi_alt.png .png id_7746b99d6a71e8104ece237d08c78aeb id_2d856489cc6083c4b74a1b8c2b528785 chwerty_mobi_default.png source\welcome\chwerty_mobi_default.png .png id_7746b99d6a71e8104ece237d08c78aeb id_ee5bdb44f34cd08e1c6012f91790c302 chwerty_mobi_shift.png source\welcome\chwerty_mobi_shift.png .png id_7746b99d6a71e8104ece237d08c78aeb id_743e9cd02f1d4004a5320b9faa355587 chwerty_shift.png source\welcome\chwerty_shift.png .png id_7746b99d6a71e8104ece237d08c78aeb id_a81a3f903e8ce052259e09e4a6fbabb0 chwertyftkey1.png source\welcome\chwertyftkey1.png .png id_7746b99d6a71e8104ece237d08c78aeb id_cb8167846a4ac07edd78e5a39a7cc587 chwertyftkey2.png source\welcome\chwertyftkey2.png .png id_7746b99d6a71e8104ece237d08c78aeb id_7325a11eaf4f66357aa7185056091802 chwertyftkey3.png source\welcome\chwertyftkey3.png .png id_7746b99d6a71e8104ece237d08c78aeb id_724e5b4c63f10bc0abf7077f7c3172fc welcome.htm source\welcome\welcome.htm .htm id_7746b99d6a71e8104ece237d08c78aeb id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_7746b99d6a71e8104ece237d08c78aeb
keyman/common/test/keyboards/obolo_chwerty_6347/source/0000775000000000000000000000000014600607066020333 5ustar keyman/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.css0000664000000000000000000000071714600607066024414 0ustar /* 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;} keyman/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.ico0000664000000000000000000000217614600607066024377 0ustar  h(  333fff333333ffffffffffffffffff333333keyman/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.keyman-touch-layout0000664000000000000000000014270714600607066027551 0ustar { "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": "" } }keyman/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kmn0000664000000000000000000001605514600607066024413 0ustar 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(&newLayer = "") if(&layer = 'numeric') any(digit) > context if(&layer = 'caps') > context if(&newLayer = "") > 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) keyman/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kps0000664000000000000000000000712014600607066024414 0ustar 15.0.211.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 #6347 obolo_chwerty_6347 1.2.1 Obolo (Andoni) keyman/common/test/keyboards/obolo_chwerty_6347/source/obolo_chwerty_6347.kvks0000664000000000000000000000655014600607066024603 0ustar
10.0 obolo_chwerty_6347
` 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 v b n m , . / ' ¬ ! @ # $ % & * ( ) _ + CH W E R T Y U I O P { } " A S D F G SH J K L : Z V B N M < > ?
keyman/common/test/keyboards/obolo_chwerty_6347/source/readme.htm0000664000000000000000000000150014600607066022276 0ustar 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:

  • Files renamed
  • Font and PHP help have been removed (reduce distribution size)
keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/0000775000000000000000000000000014600607066021766 5ustar keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_default.png0000664000000000000000000005142114600607066025670 0ustar PNG  IHDRH9UsRGBgAMA a pHYsodRIDATx^݊lu[obúO`Xue~۠zB1 $tDJdْm|;Gdh9fDf][>G!B!B0!Cn!B!2B!B!Cn!B!2B!Ba/xӟ=|w=-fO{#go/xgv~}վkt~>>HL?o?O`O3܎/rہ@D&{3"oH韾H R4`1l/@,avmpTofOk_#:ӿ? Vq,i)Cn{:+:[꽙%oH韲m>ICU%Osgܶpޛ)le׾FOsUIr*[?]=2+[YI2V|kO9W)窲3C. VnVnVBg8PY2*qV eUhzm|kqr[[;PY2*qV eU(BgvC?}[̐{=2+TwBuw+TwBuw+TwV eU(Bg8PY2*4Lk`7~ܭfȽr[[;PY2*qV eU(Bg.ri!X[[ eU(Bg8PY2*qVajj=OW|rs<~ OS>÷ϮO[~c߾wާ=2+TwBuw+TwBuw+TwV eU(Bg8PY2*4L톼:ޮ݇~vȴW{tpqw}iӀzlz_w{GbVnVn*qV eU(Bg8PY Y zgIgxXyR{Ͼ§.v: O|=#CnBuw+TwBuw+TwBug8PY2*qV eU(BPs4 |}gCnj};{=2+TwBuw+TwBuw+TwV eU(Bg8PY2*4L]=}"gtϾgɐ8> 'm,{ϲg3~!X[[ eU(Bg8PY2*qVal(aW| OXN1P,ׂ>|:fέP}Dћ}1BuXޛ eFKK*ډkyQRWʌ- eU(BT~=^74Upwno{B\NB M!ۃrr\'B1dW(3k eU(BTxxѻin{6lkȽ߰-*Tιus卞kr!wYS*޹C2upȭ^φ } eF~c{?ۇ7m.U(BgroB1z%w#CVC^c㺧T_훇7WެP}D3oTʬ2- |OA׮]~n( 8^i*qV SqL{d-V>r.5+T_W70ʢޛև sz/ ZpSho3z/v=a~=PY2*4L1!X*\xQ'+T_O52.WxT 0KT(:ON*m)w3 [%U(BTr ō?-7xN,d2.Wp>Z*Y_%׷LjB\8.)ew_R2*4L1!X*̐{r+CY,Y6+TE̶\r5@hꀏcAUYSܦB=M=ˠ߹+˥C;ʌo/BgȐ[P}f=Z.> &CB}BǷN{SܦBQ<ڽmPf,ː;۟됷t*y.סBTr O֧ 9 GwkCno;mY/8ʌeYNnPj)nS̸P\xS(3z?3fP}!7=2+T_rۡBuy6P}$O7vCns1Pf,.r;3(Yu/; ezzI~}!zz\!&0ǴGb0C"皿ZfЫP}$o}Uwn[*]TOXްȝ9ʬ²o5(3e^u/r2^!VȐ[P}n|ȽumVJ9 G2CB;A2ct2l'ʌ~lE̸pt>u/}wKC*qVa*i Wᆇܳgg҅CNBySfv]OkB)nSX.}cPfI_V(BgȐ[P}nt}۬P}^P}mf}tW(3s~Z8P(3?m*˥]x+=#DŽB\t*yߞ񮲿Vhc#CnBU!^}QP}mv%f]|Tp.ZnxT(3Kt[ esSr^=~Iʼo3FGbpcCK Go{ צx˟v)&{T(3}w1Pf<{/`,{PY2*4L1!X*АnB< q{۬P}mna=ߋl_J6el\k΋ܹ` eƳ~Le c= ecubjPY2*4L1!XWlg\9 G귯\Хh֛KfksKC׾Ѡ̰Co*?m*StvQ(3ĄvW}qV SqL{d-V>rk6vjk~_ux2<, evb?wq5(3bPY2*4L1!X[[ eU(Bg8PY2*qVa*i ݭP ݭP ՝U(Bg8PY2*qV SqL{d-VnVnVBg8PY2*qV eUhc#CnBuw+TwBuw+TwBug8PY2*qV eU(BTr[[;PY2*qV eU(BgȐO 82nA9WW(jO \iϿ&C^=)lO8\M_?+s*糇ܶp?wĖzo_I۽5?+ቆ8_4C/ G[-L鿒{kOYGW*%;evmlO}?{kOdOSmc_~Or嗻ۉz${o\u0^m+_ srhA&[Ku7zo57O?>* _um}X<B!B!7B! rC!B!pgr>o_yA4g;_ʖw齙fH7m?wCn Vn_Wzվr7OFO?휟mXگg{`v" dM?}SofOD?}cx!=Z,5:1M_r[꽙%oH韲rX.^˳Cn( f大tR8JhOYG-L鿒{kOYG|@/]4wvgq~:)\UެOg+[5J>{=2=SUeof%8[򵯑?\U2^o!X۲ *qV eP ݭP ݭPY2*qV qqW !uP|1,oKNg8PY2VnVnVBg8PY8oW}.S|GUdpV eU(lVnVn*qV eUhxݷ+7 TdpV eU(lVnVn*qV eUhx!i>?dBg8P ݭP ݭP ՝U(Bg8rC. Kܧ?B+WdpV eU(lVnVn*qV eUhx!?|{{7۾vᩦB' eU(Bg+TwBuw+TwBuw+TwV eU(BC\Nj~&~2䶷3 ;:U(Bg8[[[ eU(Bg=nr˩Bg8P ݭP ݭP ՝U(Bg8!w:U(Bg8[[[ eU(Bg=2B' eU(Bg+TwBuw+TwBuw+TwV eU(BC\GTdpV eU(lVnVn*qV eUhȐ; *qV eP ݭP ݭPY2*qV qqrPY2*qV[[;PY2*qV!.#C*t28PY2*qBuw+TwBuw+TwBug8PY2*4y{d@Ng8PY2VnVnVBg8PY-|=|#{d@NGoۏ~ eU(Bg+TwBuw+TwBuw+TwV eoC{|[9{S!yy=2B'pf}18P ݭP ݭP}~qoqfo*qV:̐{mM8w|cΫ=2B'pf}18P i[W+TwBuw+T_rPY2tf=Pf ~_]ڌ=2B'pf}18P c[P WiE*qV:̐{fN?=~FwtȐ; Ù!T(Bg+T_roBuw+TwBug8Pff=3C!w:3CPY2V3bVn*qV:̐{fܻ#C*t2Vo͒!'A2o|f_+޲N13BUHB.o>G+To=|aO!|ߓgq~3gV0s~w'+T_[*Nطu2䞛!nȐ; X=jBBfoR_xe}bG̸.phʬB/dE+TrO. Շ3Cn_ gݷc7(3䞙!nȐ; MK/·; Oʂgv~{6P .v eF7E~2m܃w-שq[pfkZᢿк>y_:̐{fܻ#C*t24@}![8]Yofq q9v?lqKCn}2˷EÙ!q^\xTp};[Y̼I:̐{fܻ#C*t2+Gˍn§P}:DM=靶ݍῸ`APf!wnm ׷ ՇsIorM_VXS(3 `O*Yr<^#3侶=2B'ztɅ~@{pvЗ]ʌ›ڂc@*\xǍ u!//j ^4P}839\ es᾵]ʬ wGTdxUoY/?W.vȔڱk/tʲo:u (YGV6NPpf5׸ljB\ \G3䞙!nȐ; -%߳*y^5[yRspiB,vSǀBUxyhq{C. gܾ_s;'Y2ùtdPffȽ=2B'ëz͍Ysʼou`=bpagtRprLPf޸M*T_r᳇/uP}83uk됷tdPffȽ=2B'ztɅ~@{Ka[cBm!ʬk G/*T }m_~~&u2Pf^k*Yrf ^>\qɅ~@\۪EPf޸~EнҭkB}U͐{fܻ#C*t28PY2*qBuw+T_׾UP ݭPY2T20Crf Bg8P ݭP}|ͅ۸ ݭP ՝U(3r gfȽ=2B' eU(Bg+TwB=.hS+TwBuw+TwVpf3䞙!nȐ; *qV eP ?8uBuw+TwBug g\AOezo*4y{d@Ng8PY2VnC[K ݭP ՝U(3r ThȐ; *qV eP ݭP ݭPY2*qV qqr߳ot2ɧ?w}r_?W(s58'~M!=!7:r)lO8\M_A.N! `4ŗW>~:)}]H韲j[꽙%oH韲rX.^r ٶҾF'?+[K7^?SQk; +!@{>?چ* pqڶm Sl{~;1tҬCOKrn7O?oz?ߏ%6X!7B!B !B!lȐB!B>fLip,C}>#]zo-7Z6ʺy /XND|?vl)_Kڿ{6jW@1m'B@'ۅ|{LBk_#v*Cn{,L?<j 'bBg8PY2*qBuw+TwBuw+TwBugZgǕCSރO}fg?~vso/gN8fNCOq|.*qV eU(Bg+TwBuw+TwBuw+TwVqo6h6zbvx"g'saٚqݐ<S_h}/w~(>;9P'o OXO8PY2*qV eP ݭP ݭPYs8g7'ߺU Csw +'uX[οu]G|vS eU(Bg8P ݭP ݭP ՝Uh}|4Tfѐ6=ė+ EC  <@<~}ī4=އ ] U(Bg8PY2VnVnVBޠIhF}0TO9 ɽ聆;be;P_s}]~<M2*qV eU(lVnVn*> _r&r4{hϾywѧu߃ ] U(Bg8PY2VnVnVB޼BaYgnhώ/o[i;tVwnS eU(Bg8P ݭP ݭP ՝Uh}!w*t1pV eU(Bg8[[[ =2\.*qV eU(Bg+TwBuw+TwBuw+TwVq{r˩Y2*qV eU(lVnVn*>Ȑr8PY2*qV eP ݭP ݭPYrWBg8PY2*qV[[;8#CUbBg8PY2*qBuw+TwBuw+TwBugZG{d] ] U(Bg8PY2VnVnVBo +W eU(J?>xW eV7?zx$8Pf8˾}1ԯBuw+T:*T_Wl ݭP}~7{ޛBo +W eU(J7<֛| eU(3rg1?7+T f]lxϐȐr8PY2tCnY}棇oPPY2Ù!w ˭P}f]lꫴ s_qGܕY2*YrOOq?|:U2* f]n4Cb+T_ Bo +W eU(J7: 68Pf83侘ki3.BUzi}!w*t1pV eV&o=|.C2 gBa͐;mVN?~xrcrWBQ=- "|: en~cC칰C>2CK7OET_mu~7+T wv,߬P}nt=Buz_ZG{d] ] &נؖwN_ʌ钾rtrp]ĿI! Gv*T_r3CطGܕ`H72~RY<](3u^ cm OaEN2#:Ϟb>/^k Wqmpȭ~5BU:m dTh}!w*t1X ot e4ͽ-o͆2Lۅ ]2q#Cnj A]?WVz\q r8#CUbN-ʌT(3'_s PThz%BJ79䞎nBU!+TwVqGܕ`|?Ӷ!wɂT(3 PTXc~% Wf4Cb+TwVqGܕ`Xӊ9}\yRws?Pf(&C!p_}/Y/\WJ76V^VJ ݭPYrWB\N=S(3S'͆ PTP%`vP}nxEBUhVBo +WxַMԷ3䞜z۶2r^ GWKT*ؐgr^#P ՝Uh}!w*t1NSfC6P(3k\na9dp_*ؐ{ؿg*͐ ՝Uh}!w*t1E7 KB\8eȅ erk ntmo. PYrWB,71rv[/N eFbz$T(0օ._ː nxȭ/X?cY{BugZG{d] ] Ƴ,/n;cFYo~!EƐ[[% W馇ܵY*]x7+T_u/\v*>Ȑr ٍ|q!wΥe WFz_PYrWBg8PY2*YAg5qBU!P cyo ՝Uh}!w*t1pV eU(B5z|Y)qB5z ݭP Wuj*>Ȑr8PY2*qVxߖ=U eP}uַ}/xU[Z<~w:X =2\.*qV eU(3Y|yBg+Tߩca+TwBuw+T_s`5Z =2\.*qV eU(3SygqB!7I\lV]VBo +W eU(Bg8P ݭP ݭP ՝Uh}!w/eNO>پs5r)lO84)rWl \M_82nAk1տzN. OOYGlfOk_#HrE)ޛ?Wv}5Z'G_8PfF^__{-^?}?[轙?{kd^َs3P;/w?~l'r/SZv!Oڿ{6jW@{=nn?J@|^x@˶. C.kRjn7O-KJqwqX<B!B!7B! rC!B!ذx?{6__õ|.>q#ڿK6FOgn/-3Xwo~Tlm9\lůڿ{6뽑nktktٺ.tp]ȧr[轙?{kOd?sC|m`!={lAG+[K7^?Sx/uyvͫ1ν>@G-ޛ?Wv})h?sCKCS. *[k7+?Sʖ})窲ik#C3"ޛ)le׾FOsUzNCwbmN93SY2VnVnVBg8PY2*N!=nrp`5Rﯙ}et1pV[[;PY2*qV 37ײǕC@?yځV棷so eP ݭP ݭPY2*qV eU.ə!~w5z,CU(lVnVn*qV eU(rN_W>ӇDlwޚ Ӂu搛R䑜.*qBuw+TwBuw+TwBug8PY2*qV\'gng?{:Spw >kWq}Ȕ8OrׯBg+TwBuw+TwBuw+TwV eU(BgZ'gneԣZ:kNt1pV[[;PY2*qV wfn`ۆ܃ǃtn`.*qBuw+TwBuw+TwBug8PY2*qVu yCns>Tu 8P ݭP ݭP ՝U(Bg8PYn|n/g t 8P ݭP ݭP ՝U(Bg8PYfȍ/d\߶jzہ|mD eP ݭP ݭPY2*qV eU.ə+'k~tzz1SY2VnVnVBg8PY2*N_Ɲ.*qBuw+TwBuw+TwBug8PY2*qVure t 8P ݭP ݭP ՝U(Bg8PY1=2>)bBg+TwBuw+TwBuw+TwV eU(BgZ'ZȐL eP ݭP ݭPY2*qV eUhk#C3.*qBuw+TwBuw+TwBug8PY2*qVure t 8P ݭP ݭP ՝U(Bg8PY1=2>)bBg+TwBuw+TwBuw+TwV eU(BgZ'ZȐL eP ݭP ݭPY2*qV eUhk#C3.*qBuw+TwBuw+To~>xP ՝U(Bg8Pf~uGºB_rt1pV[~v?OVnÙ!T(Bg8PfoM_O_rt1pV[f})+T /Bg8PY2o>zUhk#C3.*qBuw+TwBuw+T /Bg8PY2kVB_rt1pV[[pf}18PY2*Y*7Z'ZȐL eP ݭP Շ3CPY2*qV*=Uq1=2>)bBq]qC[Kz%+TNro:, dzo?o|=ެP}8a<8ZpP^sEG8PfB_rt1pV̸nuȅ߅/>uVeN#zjaBO}`ǿBv]WU(By:'<Z'ZȐL eiY/ Tō>՘`YOboA`j!s<mP_nСpP^wBS{}1cuPY2*Y"B_rt1pV==ZE^?ͪP}8"x i9; x_Чp.=nV>/x+|ߪ eU(6~Thk#C3.*YeȻ-;T˲^ed'!E}->u_] 8PY2t c|-{d}SY2rSfc|xiՇs" ԬP}XKE~B\osBwk*qV̪<*7Z'ZȐL e'8+Tʅ7<͠p.Wl ui{ѥ6w) ~ /Bgʬ {woThk#C3.*Y ߦWP}(. EfCisB\o3vBwϐ2*qVz<{A1=2>)bBUX6K`P}(.vfh;U>~7|'CsF e=C˨PY2p/UZ'ZȐL eƷus`c"Y*7+T΅toOy[g}8Pf5^[VB_rt1pVB\W/oV>gO,{rB\osv[g}8Pf-ΉoUn*N!NAg mY\s?Xh.菃OT>/oV>HB\oo_W(swrj+Ycy7Bux[ c|-{d}SY2͔ggSKIfkѼ|gٷs{[gȝ5ooPfmnr=\\)N!NAg k]vZW>.?Շ.*T<{=q3O2Onq=0Thk#C3.*{' v Շ hP}8iקͭ<~P.3N{:/v)Yr; Z'ZȐL eP ݭP ݭPY2*Y׽إPY2{|AUB_rt1pV[[;PY2r eU(3'WU:9ײGg:] U(lk>٬P ݭP ՝U(BUyAgʌoUn*N!NAg8[̐{[;PY2kpXt2*gU:9ײGg:] U(lk0CVnVBgʬS2*qVure t 8P ݭP ݭP ՝U(Bg8PY1=2>)b'l ʹS+qvk ʹӿB9WZ'ZȐL ПOgP-7(jO \ikcv;ɿoKOG}'zo_I۽5 ^`fܟ>mL/WeofOk_#:/ v`vmUv+[xEwdok_#'tkdkt_7FVm'p.=~嗻 ] l[߽fOH?o 5]:5CXxm۰K+- Фƚl=Trn7O?!`B!Bat2B!B!Cn!B!LnbZ[>r-c}Vs?1ӗ}fyf ̬GAerzȭ;~M֡mrx\|]1ZU^xX4XsyF} 2'ݱ01=C.4&Gw6c'kFWB1ƸV/, zZ5Ƞk0o>zgrw޹:MvX"gOWB cq*t/ܭ [/7dIk[ V}qо c=rp!";Vut{A節ұAVThc1U/y2xʂ|rqwƀ 7'ǚz8k:Mm*@1תBk=9x>pn0o5t!:Mm*@1תBklL_s7k1!wmx -b1Ƶн(ր c@~LȐ{mx -b1Ƶн0f7z{dȽ[IM1ZU^o3x=2C$ަB cq*t/ƀMr֡moSB1ƸV c@&^o wp6!c\ m1}G;uhThc1U6о#C:Mm*@1תBxa h!n&6Z ckU{a0oȐ{mx -b1Ƶн0f7z{dȽ[IM1ZU^o3x=2C$ަB cq*t/ƀMr֡moSB1ƸV c@&^o wp6!c\ m1}G;uhThc1U6о#C:Mm*@1תBxa h!n&6Z ckU{a0oȐ{mx -b1Ƶн0f7z{dȽ[IM1ZU^o3x=2C$ަB cq*t/ƀMr֡moSB1ƸV c@&^o wp6!c\ m1}G;uhThc1U6о#C:Mm*@1תBxa h!n&6Z ckU{a0oȐ{mx -b1Ƶн0f7z{dȽ[IM1ZU^o3x=2C$ަB cq*t/ƀMr֡moSB1ƸV c@&^o wp6!c\ m1}G;uhThc1U6о#C:Mm*@1תBxa h!n&6Z ckU{a0oȐ{mx -b15ɧ?Nн0f7z{dȽ[IM 1͐1}7wCrz5K B1Ƹ6D/c֣c.9gܟ>.murt,/pc1vOSxw<;6jU9ܱ1>.yf=:9owr~#qvmqtc_~[Т!cbmM5f=:&9o;h3LhKm^LmRb$c| }ޢKrL˫ﱦe3˿|ߺ|ewkS&')^zy;#grY Ϲ=_0mvO{?C kT(D߾?K/k׏x,/>|qr|/.z@ d5?ӥ1~adt.Nwo^ vz͗Q;?cl @ [RJ.Zqj.IK.]Ktmkno_!Zcuo\@%&=B۾vtI+/1k /φ4_^ ^TS?rm_^@_zLuƟv~/U@ _B9&5^Fӟ m L6[o^%y@ kU=_^/N'li ̶.@ &HrLߜoZ7O%䠋/YG@ dWς -kK:4.'uױ/1/l˗|L_8?V, R^L_u@ U W@_ۤBy?ɗY@^Cpy@  .-B W@\^!q>W@^Spy@  .-B W@֖×W@ @+p'Ppk+@mW . X\^j66`mpym\ry Y2 iYwƚx)ݐb0KhQl&ի]p`RCPsjM&Up`RCPsjM&Up`RCPsjM&Up`RCPsjM&Up`RCPsjM&Up`RCPsjM&{kO?_GEQ=W!<5(Zg\8-?֤zUoW>mh6\,אc̷kڶ*6Qsl(ZUI~|Y=W!ए__qo|L">~>,3 jyx]նU1|ѹcΫxew-?֤zU]!tJHn𗔃vB65.u!'a\^coyIk;pm\Xx]^S>vZ-?mA6ӮG9E EӍ_&ν:j:# -ξ^5Y׭9.G5g-UGˏb-$wx5eף ͓|_t;jožWڬNh><V[sLo\b$I9x"̴ޫ-%?zA`z\I4Φ{Wm\JxHqi:%ɚkL "~#Xq.Wͳk{--55*GlV3?^=}lp7~x|MK);MND_c8?lCσc̩!)גJm2ǮǙ6Nw%l?okur"jPnR7ouV>E {cuvNeSYሯ7 b_fzxs}zrñPZoPGՖT7.dopܘvғTH$ D?ʼnڝY;GiCBi핏ɆVynkYUAԅy Of{koW`Aˏb5W|`>&]ߐԅy OVWdek,+Z~[I(w|K A]b Eˏb5W|K A]b Eˏb5W|K A]b Eˏb5W|K A]b Eˏb5Wi,4,;cs+G՚TWMe> ܥyxe(Z~U,X5o;VkR]5ӍQݿ>ϟq]/cTfGu9hQl&ի|>ݘ1C|q/r+ ŏKuogX9f!ݨpZ~[I$<ۮP܍E31Ho.K68S5~X>p8!O^k*/ζ+3@϶+.~NPsԂGkیz5J~p6Z~[I$|,C(:3߅?IU} n6zq ?οtFCk[5ZWP š>4r1;8PWf˧3.3th=]>+8'b>ʝ|G՚MCBs$aa310xY)֝~A6Zshd<گeS6oN0{3_ulmmn}^]WI4+u=KE;E^Τ)gsjH<|/8ݮ1E:Wy#en<3G:\MlK{0#WIVsZ]Ӌyudoсq9wRf<-Gk~m aMڼz/V[R~2QC@Lfγjl, >NV-">a VM)'nsDVD$uEѯƿDˈ}Ko9591n ?^ǴZ)v1\$PƻZ䟯`C|Pb gVgв6y|=aDGcLp,FM'$>E9O~lNnS}Ht]%/~ӺKqQyz'̩,Yڤ "~\^̿5 {4qĮ#̜gHkވ9?]G!K!滠oKkܑSߏy$7K٘T#~cG|`}O1t8|y#|z PN`14ǮǙ9ϒ Nmӡ/OIK^w0_Y&,#gMUj*u֭틦?wL۾"f3kidCA>sjE {ٸ\{2jԴ7|d_ 5*Sa1mWƋ7_kϗS}9g~Pl&{MĦy <ka+Զ`cQ\af359.ڤ\H%;:\Z_)|srUjks?bly07v'CG̹}g>V_C{|=ӯ1>dӡX!_sU1#HcILfc}al=ClxV;asyچ&ݨUkpY`Q(ZUI.vY`]OZs{͟Ȗ?|@=K 9b.cp(Z~U,2!~0LK\c}'MH~jYR7%c}Kdynksq+7.b,/<^^gׯ9YW~-Gˏb5y 5j̜ǤƤC? yDŽèvU1xzBU׉X-~VW;.!NhQl%UCQ]_RDӻuf׃ ͓6mH? (F+ .ǖ|4Gv}q\|/!Il$u,{)&Y\s5WWw+6N1v[9ǻ'Mڻ儕>>0ww<^Vl5loX۟܎6MIOzI_{GG1s}tͅaJEFh;Gnc:[6W3ch*\m8::zb61i}us3.ijkC8?MUHجu]3s%ct'i:ɘn?9ؙ~zdkOyLHϬ{x\k&jzmbKaT:s"V7'|cURiksi]ur=Ik'nw bK_Cygd Vv\^N]盒^qTOSݚֽ؇6wm}q( :I[4%Z 61t\ɨ؏[cԾ+?c*{Yp58nwg,ޭM^ϠFˏb-O?6VX25b ̜g؆$%)A1 *pZ 16R"(K,n!6~'onǖjTG%#Qxl&>k?*{a"~PSjHXkۑrdWg5ʗB-yZ}eTޓt~ vlvE(msu~qЇݰ?^8VgݾԷYH[U}WThQl,K+l2uCݡ$"%ʐc:C RL4Jdaq zq-!6TںdY7-\Wr>eu Hqi:%I_aiYsͅkZ-7h CsX4WٜSkM:\]b_%z܆ihYǎj}RֱݷnWc*E9zڤ*.Ǵت O ~O*2s5c+$

; XV:l^$J#JjTGnG(tJ$zaR6D<ҙmzk5c ] ۡrǼ s1+Z7!]ɟnR7ouIho^BC%U?ӊekp=ųnbubߐ)νo3>H[U}WThQl%qA v83Y5$&n/9Y'҇ 2>D2{v\u`G ds\3wۡ~y4ߕS{o]vRl5l_VϛXO!zƜB:'a/ucW GyeV];GsvA7%ɯݭ=,o0Eރe{[RE"b_%o+nqq[ǖ4SGb4:Ż^@Fˏb5 *k1ˮG9Ϩc7) 9)/±| 93'%m^'y  a.hĦet\(?뉶XOc~ɫK<8\؃W_k W\pxfܓg!am6 G7?S^{Ÿܻ91';6|ޜ``_%y.VRgG:::ԜGY;EXOa=x>s}ޝC>u*? K{cClqLf+]hSzt_[#%POaGg(`k3&|Xu8>b5l Gˏb5^b;^OAi0 ^^u#ܥ+G՚TWMe> ܥyxe(Z~U,X5o;VkR]5[;>|}O3?ϧTZCx3k#.3FjMW%v w{Aҙ1~|:F5g1 BM05lE(29tҌ>lZ\Ͽt=ߧ)G.U~`s_Ka}\3+ԏcgl]bQ#Y^\"*[Q =dmٵqcFb~(Zh߉|̲Qfγjl݄n X#83 a>V Ƅ8M[hΪ!ֶn1ߌEyvxY05oeQvSΰbwvxܟmbhQl5QcQ3qmlyfm=t l/=Rh{O+Fmb'bڗrİ3ww<.3Z'mAIWn'v֛5-Y]Ri~jst J.zn4}h L:}a^mvu}y(p:>:Ni|ƢD&Ʊ+/sq)6#s@U6# St;.m+E)Lį's5}kٔ.&;a>T0\UPTVנD_ϛ|"sj6Ks6i6Go0ÆzAhjc&=Vmg բJG9Ϛ?ga,iϔEKD.vmo-#TWr{;l4K;&UP%RL/]OaNfX "~<4k^3{OFGW#vNah]J>#\1\o^1pr]!۔rjX¯O޶lC$7/*NE,JӨ?8ZԡxTjFZ &m_k12`-?:?lhiR0sUc磉ӿ sd,%xoݒ5]rQm{:s*Wno SuP<ܩ},}):h6 r1Y} YfՐ_kOѸ<8U󯵿'Gt+"|u8>E7j.XYzG^[MjMW%e>?]-4^qrĮ/6fL%W \^5^[=jM&UpZ~buXUyv٘9| .:-hQl&Uk. wV.5v͛>+G՚TWMe> ܥyxe(Z~U,X5o;VkR]5ٯj;+psjMUbA?Kf!5KXϑ3ł4~XϒYHs5Z~[T 6`mpym 8Ppk+@m˫XϒYHs3 ܥ.G՚T~>\__?ӫ?_U7N7gN}xf.jxSkHsAg]+նUw-G՚To[ŔwVC[{]pyqI 5W*10VkRm.BZz] ?Ӿ{e*kCI63&{\1՘k*x+s]j۪\uܘR:u]87ܯvc H4gV쾵ts{ř{Clq?Hnៅ? m ~1]wؕ` xX`ys֥ڂI7iaI9;ah:8doL(>*b0/Øc1k<ԶU1|[ׅsj1[ſf^[!UF==fw(Z/s5+/)UU:N˓-b\I2dW3}Bf~!Š7S~x !)<7ߊ8z)vgJ>؎'ѳ[_/jWON z3X{l0=_luo퇸#u{'H(f?ְ>'=N+r[}Զ13K\>QUXɞjd`ĜWx]ףU_?OlGG€t~$e_|C+TӨݭu;O͛|mx=VmG7&I Oa׶8F!eaLwçG6d-1yME(;c$eB [Hpq1bwpm>YǺ^;Zmhz]{IK`{U|qz^tnKO\Ҟr Ω! |]8ǮzM9qkuim 1{ۡӈПtvra771ck{w}=tsIm6}T|ީuo"11N[{qu}e7X, E|N|E[k|3FIJl&v(Z;6ȩp>ƠO`za3V,IC8,n.)^.Ea%'za96w:vإ||ꝪGSs'myU}]cJ>mtT6J$=.WV`\}X@A {B׌{̂]Ŷ)v*mU|g5Q %9{r%hMy|XZ)Q_op| b_Lhzl)v+B0wn/JYֵmx{ ;!58oq߰"" +MQ3;tu!?S|q S=6Ҏ}nG{.UT=z9hXߢ:Z!<MymzuAa#}$wݥ{}kde5b@{cy8Ž3pc~p]{؆ت S K,ktQZ]t f}_2Q WB_ 099\w؟3k'z4m>Y_NգSsG軡 vy7>5|n;?!bV9kJ-Ρh}I_3vÚ< 4.6JvWe5bQܼPxLNK>emϭ1b[G՚Ti\p@kq!.4j1 B/.-@]"ooҜn, qyɴ/9d}x]=?wQ|N9v׻X|緬6qk~7~.Wvα+#{!sgF^!0jDolmOƶoɮs̺9UWuj'vC}Jw|/y/흣hQl&V~=rP+8ˮi&+mb{X0)o,'Z=Vk>ͬ--oaQ_V" Otӳ;nel9$}==3?yDt=m`& Y<%|ﱵ{׏? cyNSoF~cOs;{6 <}βK ~~ܶDŽyg*JXc[cM,9}$):Vߞoj׈bΩɺu縳:Zzzkn6$9Ax[1<7ci~HvtC7=l!j8B>@forW*'oh#hQa5 фbΛ`ǚq]RV\p1^Aˏb5v Kkq+%pS:<WpOOsqk 뙼t]8c> f뙼+|3hQl&US_9ݮ9cqyw%]8>jưCyח1qy3\5(ZpP2DׂQfnRL!/py}U5Eˏb5^b;+p0VkR]5ٯj;+p0VkR]5ٯj;+p0VkR Y2 iYwƚx)ݐb0KhQlERp7Ppk+@mW . XK.UbA?Kf!5KXϑ3ł4~R f -?֤zU]]j<[x.Z~[Iud]]j<[x.Z~[Iud]]j<[x.Z~[Iud]]j<[x.Z~[Iud]]j<[x.Z~[Iud]]j<[x.Z~[Iudoχwz5L-}>~~7?>~C> XV?אUb Eˏb5.U~|?]Pjqc.cj#jskHӍ[zmͽW(Z?\ ~a߲,+@~<wrA^:ax-yP^\Յu@l=yWϗVkR]5ٯje}h$?7phˆGȘk{:GxDzɳ9s^ҬpݘRJuxHN=;fO7s\w7?똍ogq[A0O\Qf3ئkߣns<#gM| 1C$Cpyb.!\Xsg9zƇD]+qVpvVo89w[~W:shQl&1׷,݈zyx  v\pZCP¡$^~LQ]/-E|?>={zk}Gk4A|\l*^Ԡ(ъݞ񱭷^.ڼ~R ze6H,cZ}#tsڞ[Әe׾f=*|Ng?3bycS>.1|QҪXɞ52bzIK_u_Vcжc|ʺt}W kXHܷ3j0!F\0)vQB D׬#{ރr*󎖷g/ֱ=o:^G>*>ԺC7etCf\8ƾZMO9ɳRcZ_ʷ>~ u%6oiEˏb5k1ˮG9Ϫåmp#&9!I'ρGt&:J~m㔑u=:DZ 6jGWK/m`{gCvt|m}-yPnqHYvV  $ ߍ%kJ``Z#Ma󎠻U]lG~f5}3>9xLjXmt7w+=dOX}!j8cUppx]24_d׏ E͐nձ-snpQQa  ~h>\1?9yH7Vn@3Ayzudfs,W^l?mŁTmx#kњ[HJa]!<.*>0Fklϝ~V/ H{Uj9fxK[u|t{?Gk $]Y wr3fuab63?TΈóz[e ,# В>=˜x,J~m VKtȉލcUKKv\MUqݐĢIkCyu8YvP(!ĨI,C{9$Ϯ?9'絮Igh`U5Ҕ|t{ƅ}ʹlq<RL2w )ciFD b϶kjMcUpb@Feף̜gȡ eOusO6O*jiLwڠl@ DKrt|MOz?g_m|iw$ۨsث5CoA׌0Gג|sI > gš{}rW>zҜ|V1$wZE}O+ե\b sX^sϒ;Qw)Q;i qRc80wC- r!f$7/!~}^ }KGˏb5S,esz]eTzӣM@|ۘ/g_q6E2Y75]`G~f5}7Y L# ]w|qn:>sza6b63Bj[s /<&~ sI 7<eCpz1(u5Z~[I$|, iHuԐ.u뙼{ݭ_-?֤j_. w"̝,ÚE\^_.u7{Iˏb5Z.vYSkH \(Z~U,Xԅy \(Z~U,Xԅy \(Z~U,Xԅy \(ZXϒYHs3B__?Û_?_;F؊ nXkx?_Ԭ0>Odkծ;0؆KlǯOע(oRh)|')>?wgٶU1Em}W9ׯ_Zۮ3 5}y!|~|q]lmG"ߟ.wrA^:ߟGu,ɚ~,Y?&}pf-ͫ}>/<՗\mߜifFX m}<=Vc]jێQj؟r%V]dļpnF \\(82zY{:Gx+ߓg1K/:TR?Bvy{mDi^#QΈj:s+}/J>={zk}e6dZchΊFls9l;ǯzRG+6v{ZǶ^{hInm> 5ek}َ%RឯsUIAw \&}Ϲ.0]]DMyS6bNϾ C)LGG$xc r.-ǎiI9>>?g՟ƕ?{Zl2Z\~Bӳqh4y;'&[˟;n">;/=>Znd?Xek&(c];n}Ad;1µknIlϙǷgh{y3Y^Uh6鬒@3Şt4AAgk?gz}?ib#k Ѷ`gknD5;]_;:T .7T8)H<,E4N'mFu\ykvb<ͩ)x ^]4f_=;$Vh ;wKI{M'XlWO!5hqCkEy/%&G@7i?ca?M&G5*k[ꬺx>?Igf;/B{8IG:Gl(}4{1 ĆvbcjNG~a@]jg)~ V;xe%_~&hۛ%>nkS{Gu,ƅ/IF m} .y1lM0o8]㘴4f掰9U?%K+K_Vy|sL[P1zu Z}j?)]q-s\}C}=^N<9NFiսNG)ql53j}֑Ubrp5hފoaەb&mp,>zphg5/sF$k-I/<̗pwuaL1?)1J~m`1t'Q:l.SK׀?cǮj#WY|oت ą7Dzv/xޠa ѽX3̶a燌c)m=˜/x,J~mϘVKt5𱪏%xeZ;A^ &nvbѤ5}:T” n(1{4XAfr䏶r#6-|}}l=jW"湨1<6ߢ-#{iN4$[n;{N.9T_7J}= _"6k1lgx sl~6[߃kEtӘpyoI~1VܯoYvqؓ9:+⚓3 `?d]kl/N컫=yG5A+h!N-^5::s|pCqƗv'^l:j]i?4m qs9|-iw_(%yb*z^MX/&x+Z6Zj4gScWa)6xvì;qetOZPhGOk/^[l龈qh6mzzq kSccGD)(>5D3㡵*xHwχuVE[EGoJsFMo}o_nCs~ ZuA]Cl7#TEUm\^MA-'[V|V@ˏb+*3'yI0.s]mz+k.kGIޝOlE3]wzhQlERp7Zxb Eˏb+*am^dV \("ڶEfUb Eˏb+*am^dV \("_%ݐb0KhQlERp7Ppk+@mW . X\^j66`mpym 8Ppk+@mW+@ @ WJ `ypy<X\^,.. IENDB`keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_alt.png0000664000000000000000000006674214600607066026046 0ustar PNG  IHDR}0usBITO IDATxytS?6[lɒl}^/쐀%3I9Ӵss:9s$L4&mB@Pv̎}xGޱ-&/Z~|y {{߯?rd{* %8G![qJ%1 @@4j-ˌG"_jfy0u8ϗ\O|.ާ[|}}X $%%y{{XlP*|=_J12_\'*_^w 0CE$Ns uPRtd uXɗ3\O|.-)u ;xAk6 _ū,_wLL00:JGR~cagddpN,睝FpkttYpDx9 /-_Z)JCBB!jr||ozzzryee%]``R$D"Vv8v.H!FQӱ}6\Ʒ|mkbVƷ|9Z6kNNNF ^勋xu2 Ƶsxxx``l6añ;;66f6=zv,L6F'>zl6 >6\Ʒ|mkϝeqCU_____Q0(pr!w܄"^{-,,?"888)))88h4755ݾ}lLPxyyIRH4>>ܜǓٝovhh(!ڵk/^d;я~4?Xp@UUO7f#322r֭ 0JReeeEGG 벓Fh4O...f1BJׯOLLT*IHH8ug}5kТ{}>Bزe/Jr9+!M,YdÆ WNNN^^^^^^񹹹.\`1<^d/#JRܹsic+WYF$E"RT*ϟc7<;INNRw)l֝W^rX,6\]IX$߿ӓW[[a0T*Uttt``T*ݼysOO75SSSXmmVX,*jΛ6mzQkk+KHHȊ+zVyyyzZ~izb+ viprrZj@ `,* 555 """"11yŊ}}}lGj/rZZ!dxxY %''dtt9ôk ‰fH[F6l}ôB\L&۶m[tt4!qٲeDbo&իٷnݺ~]z]qtXlٲz{{7oN9oܸyŋK$G]I-[xñ=kYTTn0 D;wT(%//\ka6n(!wa*(JKK ȑ#֪}Dnԝj:##_Zwݻ+==3д4|MMM }b޽dڵܫ;GGGRŋsrr؎ؙWyfZtVTT|>ˏ]?~ttFhvqӧO?IҥKh!^^^###we;d“]:噟i3rqqILL$tttܻwplD<)Y__IQT,Df-=0W\2@?~d2D"Zr@ll,Җ544B|||؉n ! .d;b999<ք h HRf#b`u'/$&&/NLL]B؎ /& ?XؔAlbcq6ř' oooBhxӦ&:֋k"j=iTWWBbbb؎)~^z˞xvy Sj+"ݻէ)Z| aBPPZ&TUU~"Xh"BH?Nz#RT!!!S>7o!3#3f*>h=::J蠝rHvޞBf =Қ' ˽K/BFGGoݺv8eL{Ic#B`3C-^V 쵵F®4:d2ܾ};**J,GoݱcD"r A muvv~.OOOcq:t*Ďh!NNNJ2000<<\,mX7NF_r7orK"榦&`L& Z[[o߾=\nHMM%ܾ}Xl7oV(oVMMMaaaxxEzc8PQsrr |̡`h=ݘ@:ݓ}>!D(N~";օX5)))BñիWO~Gq.DuhKD򤤤3gp||1116mʣ\.?+WC8)%%:?{+JJJz}vvy󢣣h?RXXx::d͚5_~OWZe]r#:8{G]w>}u⋺{/ N޻woTT֍5ZcX<::pV7l{ڵ:ñgg͛7K$f>L=ӟdɒ!N?::Rッ_}U^ύ6H$M6޸q:GvZNW^^vtRB'BbtUˀ)ZAAҥK}||"##WPP900@}qi@*ҾiX?ˉ...aN-3{+N>}lҥK.]"T*GDD?~m#;;[ cǎ nܸ1;wK.ūVF)H!RѣG_|]}=喖7|S(._u… }}} !Y[n]h@ wt)))aaa{---=~8g9rdݞϟVUUN iO}CX,`eGmB󪬬\|D"YpaAAN^S(h41rhhhhh}vXU]]́>Ĥ$={666V.rv8Z,Ǐ[Nꦦ0ooﹼ;ȋۘfN6vn޼v"$$dƍIIIlGj-[Vb`.)))((رc!bpc? '''D֏ .4w=-[lٲկ~Eo~NFyxxݻw޼yf… lGĨxL`GVAEEynFM.D"OOOzB;mGGGXXP(h4ܫ;\uҢoQSS.\0&&3 /^xLAňRTI63lF `CD"]~dddD"H$D]u'sT*޽{5l>{,fΒW;W\\4^\rʕjeύ ITV48L{c;[p!m?F{=BΧQ(tK<`T*:5J%!"''''':ĉt>@"y{{/Xs.+s5hZ~=ݔ{9iiř[,'U|P"C溺ȅ >|pJlVV,h/tsgN㰟N^|ymmŃb1_p 7o,Jf˗fBCC***&ߵBBBnweN޷obR__#GFF80(!!a݃FQ*Λ7/22.2>>~9#vڞ殮.uww (jkk4̙3oƍ###kjj<<sΈF~x~|`vBxgϖ2]555:ujƍΩtWl6߸qcH&̜SP(.jT*Fpwww]]ݝ;wٸ 減7oz:`H.;99 q^O{}!1^SS-Y$66VTtڛ7or`)233iuYY[FFFxooowwwz(--w1ڒ`twru kQQQ{{{FFFHHP(ܹÓ:h3DIwe; }6gح[ܚ?Cr3 pڵk׮Ξ={Y`N`; s~;BHkkӾq+Q&&&&&&&&&Pw:K]3|lrAW'3Y8G ߙPw'g@QL He޾Dgxu2勓yʗ;?</oxE$X,UWp̌#_Lhxu2勓yzѓ%銋$%$H,>l(+ׁzX,_ެnXf -_බ6`.^nc; %<׶7+w܄Lh42i0ǖbbb+++kjj؎l#88l6GGG 7o2NgZ=>>_Xll͚5;8@.o߾=88X$ |V@?;sTՄñ B|||RRR^Z~b@ jOf%ԝ)11(//g7KOO'tttB233ݻ===]]]| [۷_whTv,/*..n֭r,Xn:///aX,$ ñ౱z``@Ѥ;RSS׭[vvvsŎ;|||k^Aad{ٳgVw-˟Ν;۷oOIIٶmJb;۵kתU/i tFَ233Aeee__ݻw !|}[lf;xf .o 6l0|zxxof1+[D{h4j^T*ݳgOHHHppoQ´LFDnnnlGd_T*r9vg!,\bXَŖ"""f۷ !K,QT7n`;:DiiiK,#wZ[[ Ysss@@@llltttmm7hիl_ZBHTTo[oEDD4MvvPիW l֝_/`6Ϝ9vW_s?cG -ZD*c%OOXB477w b/_f/:{qvvHMMʽEEEoc;4ٽ{ fs΍ڀ̘ƛ7odim۶ѱ@9ld2m޼y޼y?|֭[M&өSZ3 allE'!$&&211QXXv,l2X66yKK,}6wqqLIIqww'ttt]CyyyeffŅj\=4N/[Ƕ~cBݩh&h.ɦ|L&s-[h4{O,SN-mݺuK޿믿w<`+Rt:vQtn\[_c IDATCCBmN.BN(OBbŊϳde˖-ZH&Y,{:u*''g6Grr`zww/]Ғ˱(@!h48qbhhݐX;?}My磏>t좴itͥK8VtW_}cooZLNN8lgffs__F6yΝK/BOZ=>>wݻwy{ꫯ,XZZv,LpvvV(]]]lb/ >>>dbb޲W\rܸqKKx $''vuudggm>;x☘h085l2B;322!sp.N|l//{N.: !UUUz ޽{kNmbqRRVm۷ݝ۳*++}||\\\Z6bbb4ͺu/_^]]ϥ"?bqJJJbbb@@]ZZz,Ȱfրuuu , BJKKtԝ`cwE#G&RQSSsС;w]v7`1N{~E tRե VX!H.\h4zx^iRLHH?y$ѽoBfscccAA,^D亳0++gΜa5B 6vʕ78qM8sׯs$߯(""vhmmX,SebbbF./^xŔEZ.6ñGYWT*lʕ+###,5ԝ`c555O磩O>. Sj SVVƥ6+..Ŵg ,, yyys|Cg6*^O7w2L.\`+/yXq4/++3Pw̬%&ߎ6}===Sww7۱BHOOOiiiRRP(;fkc9{˗e2!z-&&&&&&&Pw:K]3|lrAW'3Y8G ߙPw'g@QL He޾Dgxu2勓yʗ;?</oxE$X,UWp̌#_Lhxu2勓yzѓ%銋$%$H,>l(+ׁd6*_.%K@p>1±ru'pN`N`N`N`N`N`N`N`N`N`~lφugZZ… 5@ wسgOtt7utt3R??͛7>3LlG/wߕJ%%%Ge;JJJھ}7o߾}iVZtiVV`{{{~~~mm-xZw?? yW͛711qqyʕĦB#xNbXT*ʘׯ_x툀M<;ׯ_OΞv#[2L}nxBHaa!d.MLL]nَ^>n$zjBHEE-:/^|rBHII NGh苖v#S!;کS}||m_8qwQTg&&&D" ہ˓U*djS&Ν;l:>=b7 ۴iP(lii!ѯP(|vr9!l6wvv Q?}a}fe0><88(x \>l0r]d21ڑN#h4???c-[_^шbggg//E?|w233#"",Xofee999,x?o޼pZwvuuxyyرɩ~~~۶mH$:СCՆR)!dlllbbX WWWv#w߽jz׮]ӟZZZN8cǎy_~%W7nؾ}޽{:::U. `xxݻnnn ,P(!!!!!!FGG\~u\u\]]w%ƾ^Bod2m& !\+ GW[[{ܹ젠;v& PWphFvR :???ƍ/XrMv%'䮮.v,>֝3ۻƃt:D}vF3::z>'';vฬ9( XAX,\pݺu'OBRRR ϳ s\.```СCIoo/]+N(Xqtuuutu"$___BNJl6>|by!WL_t:Ȱ毾ฺ֣5M@@'\ll,]oJNNNeeؘj=uTYYY__hd76fl6"HjLGx!Nn[l=mhhٳfY%Z6n488x)cx!&̙3`;`O; !:رclgΜrʔ79+FyyL&T9>h4}}}rd6*_.%K@p>1±rug_]!qrvܽ\YH$Kq 'Kx/%8/.i-߹Cv OWJB.Nc}߅sgf<ѓ%wZ3%Kx'K=_\[l)..; !q AlJñ@RIDZpnV܆B?;<UD"a7Xs&m4؍fmY9(ԝlf^f;3͏=b;&twwFȓ|p6ܬ/,w!Q>XY fmY9(wPwty7nܻwK.Sެ_F8ԝAiiiYYY"T*B4# tww' ֲ{2D:\2>>><<п\Y~ݹsΰ 0AV_ lwAAAl/jҥ6lBP(1117o޼p=r|ƍ XVݻwuίrf;ݳg,?FGGoܸq){ם?я!QQQoݺvD`wIII lc/{uuu5 ...AAAgΜs?+" CAAACCd[xZ^|۷FX@vaEppm<==U*UDDDdd%KΟ?vvB)//g;~6o޼gSvj#NkiX}]BJOγ^eeeFbWׯwuuѣGGGG !YYY/RUUszE"_k;}CCCQQѻᆱhVZUZZʇ$..n۶m$??ܹsccc֏FGGkjj!iiiW޴iٳgً׾!ålbGWtBAhh(WNzoi陑vh`_ֽ+z{{ٍ~\\\f'hIuVkkT*e7jjjZzdggO>_R """N>]TTd}^KJJ Jlٲtuu1:<jCBB6o|Qh066( ٲe QÃ2McN#D"??F"c\.߾}{RRb1 RT nٲv~JHHX,׮]ek׮ݹs`0x{{'%%M3//oҥϟlbccU*![zN߽n6i'm۶SNАlf4Vp8Yz&$$l޼Y(B-Z$6md0h!e˖dBȣG :;;ŹszT*fŋz=ѽ?޽{L&{ɓ'dɒxBѣGip6$e2( IDAT!dpxxh4ܮ;8PX[[{G޽[TdԹ?_"tvvZbbbBCC !ׯ_z*}ܹsSlmmmzzz|||nn.1\p~QTӏH$@ qd:r}?55ߧݕǝߟ褦\L&[~P(ꫯeee?J嫯B9pu4wyyyvvvZZZXKEKK˟5k{zzNLL455޿l`ttz2h4>+@_p`VBA"bbb~_M0]Baee7|Clkk+,,\n!Y`ɩey>==۾!2522F\+V8H"֮_*?9#ugXXXff&jjj>裟 bӦM]w.^{o厎cǎ۷O.[.88X >|x³gΟ?_V]|ٱYgg8Z;8?1ams?OT* !3+r3@FF]ssbq iFǑSR &>//t>7**b2iNP^^h"s%;V&bʕd\p &NvZ&X,SOY9DX,&EöW[倅 BZw=ztӔ։DBX)% qdʶ6BX,ItO[8ի&^O:PNY53MO1>>NdiXkbowZ%On4W7YϏ@O9riccc}-:,YvՄ>lʺx\őN_"))Օ|򐐐Ǐr ]bttt8aYӵBjkk9p+N6Bp<- zzz, m t:]HH׌`8HfX&/IǏ'رG#gg"˿wGNB׭?Y{7D"=q"Md2 4CxABld2@E>ɴNjkk{|Ui9~byJ WJEsz+++ߟHY~v~543[e2ݑB'>]5peqExxxoNӽ֭[R_#(>k׮ wwwX_yȮ.n tZmMrCYGR{{; t^N >gL^n߾"H233h'%w2>>~… 6_'K.}555hbp%uf!"""***..wzz:!dbbΝ;hV",9ҥK[`{ȑpŋ/N9R"lݺ5!!axx"]o[uuuxx,)((v֝ÿَt:׮]+z˗/WTTLȵkOooo _lۍ7ryZZZFF!`09sunMZZhtss\9/H^{-88d2-]Nfb;RrrrBajjjII W͛7'%%;w޵.O-Zhҥ ȑ#ShZoo/ݱjkk93?q+W(TZcǎ^{l6[+}СCONNNNNŴ=xxxȑ#hR^^j*>ԝǏߴikZZX,%%%S+ݻwlB̤BpIэ/_NA"i4X<>>Ù;$$ne;aPwr[[[-[) j7nܘR 6$&&Ўxy>8zڵkb1gTTTtvvfdd⑑BTAAgFFe49~aQQQQQQRRRddT*5A666N.l6 ;9 @'[7N j`EWs^o>z.JJJJJJ؎!ǎ;vQSZZZzQn D֙d:Ł0{]G xNlX87KTdff ]zzz83\~lݜi* Pwxzz;wpc.A \uhh;=8.ԝ0\ݩb;fYL$̘1f R>PBHph\aN\nX?_殐89;?@ 89}}|%<˗t4PLrr2cڗ֫Ԟ_ PH\x~ƃ_CÍVwܙF噒%<ѓ%wZ/.&aFqq; !q AL>l(+ς|>kg:tġ;#w_ƆX;'ԝL@ L@ L@ L@ L@ L@ L@ Lx@ P* D3H>YB@  kHvjfy0hY-Ɂ˳HEɁd3V"__i>>>>nnn/J...CCCƍY&K De?*c#ARR P*3)(3̔SeSRwM]?WŖeY7``}) &$m! C3)%m'e&i;J P&fi5l」 .Kvzu?;I,b_9N[nEs$.@ Dtglٲ^RMMMRl6s8M6ݹsٳqt,IMM]`AVVX,f2$In٬h߿o@ Hw&"hΝzjٲe]]];rH{{+W>{3g:uܹsz :uƍlvp#jZR۽{w Ou֝?۷o߲eJڿ|-Jt /fN_fy<^zzz~~~QQQ]]]mD ąNo޼$Wv bqM{/X ??_.s8:zVVwޕ+W<OmD ҝq?W*󕔔L>ҥKΜ93իWos8%Kl'N1@TD"͛7[hl6[ssZj^z6$*RSS+Z2ZjH w^uu5`ͥYps83g[_uDD8m۶'N^'I\.L&h4s~p8N_NNG9Z222 œYfKJJzu~b@#21D=\EEE/IAl6 % ۶mSTqNlcǎ%TՄӝٯڱcZZZm3p޼yo/yyy;vغudb2ӧO?p@utt۷r?7nL^i2Zmzzitk.QaXJJL&p8e0fsL&>|"hrFI,kҤIZbD8:ܵDT*qg2@`ppP(z-0x[#b~3(:[[[:hBu֭]`TTTnF\_}U@ `2Nqo~'%ކĂuˣo~s…Nȑ#?OҞfZxq<}x:N> 3SLyw1g:olZMьFlf2999T=8BT*ln0 q\.i$IKj1 KOO%@0└ANgX\nAAo#@PDs#2P+E7odw}7\t<~a$6lgX?裏cNڵ Òpsd2'OԤjaKiiyfKK?_xd2 rؿωE޼y4-''go֢EmZ#˥Rdjjjljjr8 B(6B% lB0A4>Z"l6d6f5M[[VlnnYYY!qðGd"mBxsFN wZ*F&Ɩ+Vlݺ05sx3:Md[l)..|w=v2s_|f755}ThaΜ9֭qԩSmmm3i5k νS]]]T%z o޼ p88>,Yr@ pɓ'⊊ɓ';v, KjjZ@GGGIIBn2,--f{DR|>Fs\}}}pH$4.K NAqvCe22eT* &Z0@jvww؁dff +B`0T*pghyyy]]]BP(b600 Ϟ4ͩ8h\~ x<^NN .O<l6q< ǣU6|ma"v2eJ j(>"(==Zeۻ8nBd2?~\PPߡ$L2bP,8(fn<"mDfϞr=Ujԩ3/@v;cǎ\Zo߾ↆ^_QQ}v귋-zfwӦM۵kjhhzjuIww7"J)~HnW*T`D!/h" î]vܹ7o:t?| ++kƍ1Aa0pPz].WpbeddvN2225nSPPr Coo/ //O*e2Ynn.Wx"F!L&S(L&t:\js8E.gddP (ȸ\.\qcaaL&X,n[Reff3+:;;u:@ T]Ѹ@=NYYYO@ŵ Xz.;t ٲlr@5jH$|N3LbPTCӹ\.Fc2===vnH;d #289ԗ%`S}}=.|;W^f~m'm<;|^xW^Y`ׯ_o2yw}O> O ;/I0 ̟??ep}`0ʎ?_h4 ÔJe2~j5_G~0u|`, ð!x<G(%h`M d"IRV&hjj(v>|e6a8F vB l \V Vn=iiiL&y___qq1RSS\ngg'\\n4f r6=jRɅ6t9Dz00@NDoH:N"HR\`0ӝA r]~ ThDBDc?dTW"FA"IP3bn3L;9Ʉ2Q(2 @G~[l6+JDbh4@ liÍ.SLVðOEv¥nMwڵ+''`tz` xl6;RY=SvccaˢEVѣG>+VnC孷""IwOOc2&)"\ &,N: % cua%~xl vb1y0!|>fL.1zbB«$ITda ACUwՈQ ĈfFQ tvv2LRaP($INb]ox<.K$a&h4Zȃp#2~eeD]D}AO*?7>DD"yWE''?pSY®MwnܸQT?~w޽ [xJRqppp`` 4kx>P2k vIDATX>FJwLRPPd2:@zzb)nZ`\.7nܸ.X㉓4*<ICa~?Fpo2d;\d&$:cbp`6d0܌D dc)F\'q0 {|x ģ[, *9`|+WY&ކz<(Q 2<# .ZplHgESlȐdN֣ x< sLN4^@8N!*) BM~D@```~xh@ l^9 d2T*D܈ W^1cFJJ |l6(v%uuu6 I9DzHԒ8mݺ0,\-tԩ92qӝ\$5̓-[600_644x:n޽V}}}.\H'gΜ3gΦMݻd2 Xhl~qCC˻:::T*ʕ+9`gb2?~eee* ðcۺd2UL0$sssf3A83 PewwwQQQaah$Iq6zzz, NAW UTLr Œd2و z^.~8V|>>”D- b m65@ T@(F@ww7ϷZn &%~NSVUPjUՓ&MR)2N("322N'X,A|T"bZ]F\h8ӝ7nde˖E^ csl+WXP]] 'aZ[[۴Q7IDUUUpˑ#GHP&n rgo]0 Ν{饗ٓ*ZJ:|0f֬Yk֬aX+V@32 fO!K*.Cupݏ=eǦL& JR$Ir``Vnp _9E; xQff&VF@o@kk+#ɼ^V}v‚]$)#9JoQ mnnVTbM E p\ 09Nv@jaqf4< دRv{Ge\&!FӧgϞZYY'B7£Ϝ93bd4TE"BCVk~}>_}}p=UJ@B *9%8sWjzjV.;nWG;jDB`|Ĉ@PD! b / !t $ &޽{L&{ׇk,++[z5ݻ!q%=j%IvҸ?r }WrrrB(I CV EΓѵf8\D="M^^Jd]]]yye2G}D-ˬ]_dXv͛9Noϒ˗/<<DҥK555ׯ;w.bXӟX,ٳG.wvv,AkRe8ѵf2!q(G1)--}饗ۋNzUrښH$ڲe խo\Ntgp8=z⒒DžBs8zvonwvvT*r?i0oݺܜDj6\KpK2~DDtg"2dxb@L 1h@  D @;@ N@ D,Aw)#te/_&/F9u|I/1 {  Ä"qvn~$#W&zg/3Ybb2bq/mbF9"X LOn`@f'U9YRu|4_&2Z'ԍ2ٝ_#N3sy<Ә vvh5܍R_: h 72I쨈ʄ`"k6IENDB`keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_default.png0000664000000000000000000006455414600607066026711 0ustar PNG  IHDRw+sBITO IDATxw|Tu?ϙ$3I$Б&M)" punnއ޻nq]׺(RQ"$^!6I2eӁ3sry=3>dffNDU&pU&pU&pU&pU&pU&pU&pO1 FDD!שp:||'#_|"HܼcNq3 a2 OccI0Lk0FcCCÄg"_!dyX$o^;A'_hry{{8 _R&K`M&_$Kp nޑ$2ޜ;̄ _L.W$u1勋 I]+MF///w, |1LJp\NPA⍍6p\N[ɬ"tyE 7I-߻[V!|GZRϏ]PPw8.C|rJbǵpn^qTa%sfa nR˗͑M\4U*+n {[p8,KOOḜmoow8MMM|---6fI$ߦ&'Wp󊛤+=S:%RjJe6f3QO]]]]]Q n^q+n^>VeHҥKF#!*;;pPeBMMҥKU*մiӪxПUd9sfrrrnn'%J… jn驯|rii)q/00pQQQz^P WTT?\d2ۿ!d|GĥiӦm۶m?-9sfttFZwPٱcGRRdlnnx܆~8'%%yxxlϷBCC.\d2YOO۷ϟ?_YYwh.a2-Z-^wh.q#GlܸQѬ]vgjgΜ9mڴPLl ~wd2`0 III.]:rqnܹW:NVgdd߿_Pׯ%(zCŋ,YhwDXĔxPP֭[~8TGN>G͙3gݺuC{{{$$$=z< sYvi:.>>>>>>77O><"׮]]tibb3_c0TəqqqRXs֭~~~¶6TL6ӧO)7RSS׭['GIIIeeeww^OLLt=خ]xowŋӥۛ~bqoD.aÆ9s׍onoo7*n:uڵkh"BHnnr-Bׯ_okkJNNP6lhmmjqqq=pϿy&!$>>>%%EP[093,߲3gzzzwww=z0]ĉiii+W,))+~+VBNgCCbdOۻw/+Wjkk׬YCY`h˗ӻO>qӧlْh,X [V@@ҥK !b]QBN#Gxrŋȑ#yyy|G555㟰xbBHWWץK͚5MMMz?}̙3JP,Z>5LάZJ.;Ç_ryʕe˖ʤ_FGm^^^nnO?hfϞ}Y=S{Zr~j~^{sYY/aǴi!V;wCp\  $TUU -1) ss`n~zZ%C*jJ4oXK 6''G4%.\`KLȑ#4M_DDDB***x"-.CBBk􊭭\DeBJeff&?I?m?yn Qmllͺl/9 .BjkkGmnn-|bx}BN8!NsZex,WՄGr.$-\a gY#a]ŨW\III!ʼn93**uȣth",~LÑEinnvړ8f^3% :pcPnl2BHqqkD\ejZBHww7߁C||lH1YhL&Ν;.̝;W&-X 77whڵk#ֻ+fYVNG!EvABFn+ vM24o<___"9CDBBOIIc.\ BNB]dɒ^q]vK-ZHP8NQ^'NZ|h#^(7ߜ8qB4S!gΜv4!!p:5&7^ANkZ~a)%xyy͙3UdL_^ZV.4T[[[VVVxxxYYSN}B|7| ®nZ?#v7⊊;w4B۷{^^^QQQCۧd2YxxxPPPUUqq744tCGDDlڴea@Rm6:69++K 9 edd$$$>ov]]rcܹtȩS0Db:Ը?~4MTTlvxb . ۰jppҥK?0!$))IU… i7|w,h4;v u:׮]khhIKK?~hh?_#<0룢 EXX]pda+:#185m۶EFFB^_577޽?'h4%K7F#@'f3}db&::p8@t&Czz*mkĊF1c!5''pl2:ɓﯬZ 'Nm6u3٧Ov:r|ƌ6lXne2YVV)9l}arJA[mٲ%!!RPPpqϝ;Ϗ6u<==G^^]mE'bBL&튪utбFnwww `zpB,ȑeeeEEEiii!!!q:qDSSܹsM&J뫭=bE3ymk~]C`ATnaVZZG<<<޿GwFd=XZx+**O}!1욠cm@e\>k,BHwwhˋ/4 tLjPPhLBȍ7FnF7"E0ͫP(RGVխaILYj ֭[{eC9sV\I9{=?/=*nr }!~7v ˗/;T**g͛7} QSTYh'"}%n6XUهa"/^L#Լbm]l#r:Ov^^8Zo޼{n1it:}}}4ȵpL!OODooaYhqmtٳgBĴPmmm**00P.|C6:DzrJqvvhߺuna+RQ7Ca;̞={ժU ޽[M1!!aÎZ&Z1T7;oݺ%MDv;]s˖-CGgF>tQq̤-@SN^fͰC)))t^]]e0! SٳgRSSvFK/3YYY&)66瞻~zggg@@@FFwC7o!p!ꫯ"##=<<ϟQRRޮ’3gΈl@lldO===Ȧ'}4OѹʬY$TVEEšCD0iC_cؗ9qILd;rGEE B100ZZZz…^{ܼk׮O6- fuuuUUU={V|f_F\.kjj;:-XpAii髯`x???Je-KuuKD9hplΆ|1 &''f2˅|G' Sʼt(WʠĽX:w|ڿUvs0)nǏ?~8߁[own_i۷o>pV-M=`pU&pU&pU&pU&pU&pU&pU&pU&pU&pU&po*CqO1a:W& .I]DbbsBR3Aj*W<4*bFҷ㟉|g+@<I+d G^7BN'CZ:_|~l“Q .f"|q1OR =Y|:m*6}FDdV,:w$Gr+(9Wj+XW4ܼAw$I;L73a:W& .I]DbbsBR3A {2{2{d$8Fbttt paɤT*[[[{{{&Kj7B3<m6ḜVZ͓Y++Uj:**[PP000wD%???*wAAdI !jqXRIlmmm|\Jl= +Ąhݼl*HCjJʽTVb2{zz:;;b;X{{{hjj;Ry[ZZl6fHMMM s/؞)NZRkݼfl6ĽTVbk` e&%%ر~Bcǎ8;ﴶ 2_z{ӓX?Ot:A wiΝ/o[@jjB;e˖]v<|Ń*;Jck׮x;::WVVuVBB2o߾#G]:vرcw}x2(rG[ŋzRonn˻p˜a)K.MNN===YYYnmذaΜ9={ ["n7n$|C͚5kӦMSN8q^?~RR^۷o_pAQ>ldd~UV _8o;!!'0/2!d``׿5qqoƍg&\pѣÎfddlٲRZZ{6m4k,B|PXX8~@_\nΝ^xX\h4odoooBaZ/]wh\JIIپ};!ѣ%%%tt,//?ydww7a˫͛7k4F|vTT获wzzzll{W[[]ii)2Usbb*322.8 <򈗗^ǏCrO]8?33SGGG?c#M0LcccQQQwwh>}N|z-̉Ҿ>F>[JFGG;Df *qDDD<*n9ΰLJzꆆ[nKdTY__w8.nUu֐+BN'ߡqd2 =EqO܁M6) QTTT^^nZOcǎ7xn)Gii[<==zc=EdN52|A:>++ɓϟgL&SBBBrrrQQa+W}*399BWQQ188[|#׭[GKC]z=tܹoۑaaa˗/xvrrrw.^O{{{Ly?Dυcbb!CKLBHooN_ o߾=$Ѧ/\溘9D BȾI~CsOLLd wʩ@BHaa![bRo&DFF;vL%dggӦak(yyy<pfϞm4 !CKLBHҬYr9?!FQQ$&pVIIIlTIaFj\GtLОqʹ he7*--%d2{\RRwjB?;܅6`jb_|yrBN:OFMz< W#ݻw7v\ vhfxx8}H IDATMM5LʬZ<}hCPlf-D>-:/++76I#VXe555ɄQۆn755EGGT,_#D.2Ylu?e* 3 ӦM#655=Cj:--ԩS޴:T&=Ww$;;{ʕlk`y? $0M-mi[&!Dӡta mdtWll,g988HL>^& WqETFFz?-@{ ð JXvv6}||H׫bRSS6gGyQ!rJ{{;!$%%VR*6mzeggl6~Btab˗׹|%!+VMOO%hf!~ǹ+W`jkkS}}}}͛e2ن RRRʺt:]tttbbBM.ve˖2Tuuucc#(?fOXXs=oZ}||G> bÆ 7o޴ZiiitH9P({챴[nΘ1>2֎z(pȵUf}}}6oެhu@ҏ>ȥLzXi6nF"XÈuuBvZak677' #׮]KOOW(NSU&!uuuvc}QJHQ*..>pjuJJʰl555{YC&!?55uXf{{WT*RTT?yz^TZaUii.i)rիWoݺhѢ(P(z{{-KAAKЊ)~(D2nII S\\w,RXXo/Y$<<\l6RQQq̙M6ׯWWW j655_x\eK,"X,J"*b6>_L*3..NxJVqMF|MMDb3XyG%|2e z sS 2\$%OܼwwPL\b B**7EW2VoZ':/a PyQer 66VTBl6[[[V%Л=P(XWTF0|X@o^Thjjr8}}}z ‡@ E9`(޼2D",,, pHL;wB^xcq3f,_חjx8f͚ B8pUÁFFFB^|Şq *߱͛7d~kk֬;wn{{;w8pPeے%Kh{ܹ6VwPw#--MT&$$@0@Zd"~G*--u:7o;2`00 Cimm;{uǏpmt8F b"̸9s愄t:\tƍ+WKΛ7/44ӓaW/_M;ʲUvؑ399_&l_*- h4yyygϞk455;ƻq7`XlYLL7!ɓ"^ջvj\۶mSv|G U֭7oЩ))){1<έXbҥCtqqqqqq16΅>KOLLD#̙3gݺukr<444444..N۽d[paTT[o%BSqZt:?s R2WX`BHwwwNNN]] ={NKHHXjձc3ӧOihhp:aaa3fP*f2_5arClݺYJtSOBJKK9Bq:|ƱhĬ,//3iiiqqq|Gw&fߺukpp0888--MP.Yĉ|$00p!++… |GT#; gyFRʜ={6r\իWKJJm&f͚%*sٲeFR]]9_}^|ٖ<.֩+W%ŋi%M:ujQQQvO&u8G|2NII֭[ ! 2h40/^쳡z{{gx ^Mz%&!$//bBN{']999CAmVuG^Buww+(S( .`ijjڻw/g¶o>́_׼/T bӦMCsX~~L&[r/dɒB ;0>o$M 6m}UVVo< *s˖-iii쪪vڗ:lAHNN 1 &99999͛| %tlVI&X,^P(6lwuup^;BUfPP r7xc.!̜9?&&wt`],DVo$#F]6%%gӦM c>-^R(1jZflmm=skF{###3uuuE@@+KreI&Q}ft %K$QeT*bLRN/3fg?~bŊaVkuu5!aGt7̈́k 8tyJJ\.vo䛂 FE{zzhǎzo!сN(AOׯ_T*5### !&^OKKx"p@U&!͛oҥKu:0EEEN".ݾwLɤje2jmii)((ш/YbE||(//Zz5LvZss%KõZ`KKKnns^|EBwM <|mrUjjjjkk ^I$477۷ob]wn}С߿=jkk%0[MM?MNGZ|ŁIޤ}ٰm܇ڵkA c*../~`L$1mTZZ]]dA0LҒlڴ6[\)6{qk;N 1!JIIQ*f͊onnf&,,,==]Bn޼wpfΜH1ͨ2U&LiR(iii~~~K.v4??_n%bΜ9aaa?/_c0!T0?o={vXX`d׮];@W%00P&+W`~=h; p={fPePePePebg&EL{'drTbJ ;?A@p9B1sUKTy{ 0JlL$KD%W;6䋛wR˗/Lff&1kЖXj-/>?6BO q =;JH,_'K︄/nI-_^L*6}FDd4ݧXpz{{nݸ>,Atw,XN ߉:_ܼZ7uL8.U&pU&pU&pU&pU&pU&pU&pO0`pKGGG{{dd&666""!TuuuEEdBS]]]^^>ɓ%%;$n vOb&((HӹNVk4Oc&##d2'*1 >>>&|333`0 )|%x1K-_\D&qUFQ:NJP0 79qqqBYF.|JVO,XIHb&7PeJQz tH|k2H*_1%K yGBMC C sJF0dR*|r hlll|pOFb;ÇLA2Ga.((; !j{j:**[PP000wD+c0RI_(x$cTTFp؋aF1|X*`<Xܡfl6 "p8,KOO>` ]ZR{bfwp:lPaS2{hR=~oV HIIپ};!$;;{|pOPeORR֭[:Z\\{nw0/555 futt9sPeKxyym߾=<<}GRL6m<&*9~xvv6߱p#/////(&eZb{yy%''{yyGy31Vpp;eḮZgΜ9r䈫sW?ϟOILL|7Ο?wDG1oV{{;}ɓ;wIIIżB?z'kst:*g @K|$tuuaaat!^lٲ@gggEEɓ'3III;v dee:ujɒ%)))r2++K͛Gye2… <==v{[[[AAAVV=sܹ3fWMMM/_~:߫7nTVVBb/ĺs]$ק>qVCKW^yeppO~r:|%Zux\痖g]|\AP,\pժU6kr<$$$$$d2hۯ_^WWT*5kV~~8v=uVBBd2LC&&&BѪ`0F^cv4{l\XTTm4O<==|zٳ{zz T*UXXXbbL&~ӓڪjccc#""YhQAAaZ !|ñK={|g'NY\\n?S+4VeZbR)4GzjZb=zq… iY[[o[V+Wl"׬YSRRk\b{Ϟ=SN9aRSSQeB>}vBAG} Su,'O>> _}!$99Yv===( :li``࣏>_Iv'|eZCVH ho_ } T(C%ķ0qqqK,!߿x#śKIII!XVvmgʢ~ee%m۷oĜ;we˖B׿i)\H2~ddd-[/fw*++.5t:D96nHo8qBd)xfi3lbKNNܹse2ӳЮ =8yOOoooZ{Ĥpwp):@>$$$33-bwF*##>2544lUv9tLMMMffի988xMBrZi&QUAAVS%ills%$$Ɔ>s7nܠ;LFEEM6M.;?\47dDEEY}ty#[xqtttYYa2--nR__3O=V=}'M>L-'^4k3E|abcc#""\KUWWOd nP]]]QQ1]ErAwd2ypp8 t6jF=iL2YB0& Q`0 0LFF70 >>>)R|Q#;2UhԯR( sh~3I'OFJV D/F$?H%E)dȄ eJw of2g"| 2\$E)dcpU&pU&po╌HPQ6pGj>>>]]]\ Ƈ*)<<LJ"˫@xA`FC;1@9BOP*HJj5ޡ-ĩ~L455 MRѸp„ V+ɬVkKK˭[.\PYYy粲؞)4ܺL'l6@i@@͛͛RV6mںu =&&sppoֱbiӦ͛7wuukgΜk׮]v-..;κu낂~v7 CʜB-[vڐBޮVӷlrՃbH9٘!19Tf$4;k9ʸF444L:ٳ_5B?iuu~6^b"l6[oo>POd2GI$ݻUNt\K `I>/~LjH$b±|>?؂aRfAX,vuxVu:]ww7|T*-))^o?BYѨV\[hvZ}}b EG@ D"PBGGǴi,XZ{eނS#Y|| |֭[YΰqB!!6H$Rp۶m1c$Yy\x sAzZR4?tp812Á@ix:X,j@P]]- VBr'~R9ebDpHb 's\Dp8BЈ敕>Ν;.KR1K^8NMMX,% Je/(J500 Zmiii7zP__lˈ~X鸖@ ClVTeeeϐ@4Ycj}v| 2Y,`0vpIL@(r\h)((Fp4ryUUBl6;L/Z3́@`08ݻw C0 XbD0 <>=44ϔ[nB4Mm߾Y TTT> 0s9?K&ceee/-Μ9c2VX<sX O6 /ɴp܅ “Ӳ`y1-/ dXAh480#2tB"b1`0@Dl6Cp4lիWk٦MnwfbX:. [N:߼y3@b +A^8β2H F!vas^dc4\QQP(b2eJLćT* Gmɮk f3Cluu\. Bk @&v;<Q__顡!&$IX,I0,h&4@5 zT)4L$r1t:%%%R R)EQx7N7nPUYY o]r1?n06m4k֬۷Ö3gD!x„KG裏n޼$˗h Eԙ4!t1Bif Zf9r$3I>}Y`00}o e˖y˺loL&IЂ0&3XT*.F%eV,ZV*&R)$#2 ^T*e 9pKNS(CCCoN^/,,C.#q$I4_)#Htl sd8h*//ɮ?5nۥRD" Bk `-m c#`kkkB 5s......δuI/CBR-\$+W|Wŋ777W_}5!Y0&pr rxbYrhoYjUOO_en)eBN D"  - L& HJ),((NrGd:kAx<^8'K4=.KsjEcHv.@iۘx<N'vX,r DB4\ΒB@ J J,+8h#{_>|Ctر۷?zT*eizΜ9|w݊> ms}O.?!tΝ~zKYdRe.Y ?0Oр) Fe:&j.L!JJJ\.WC$ 4=b!>FSK Y\<ڗBD.SWrWC1b0ٌl&rBa s$ BDzz<6 P(p3L w\p. Am`Я &9q׮]嗝+Wܶm[opXf? VZUXXg b(R3BM'HXRZZc9WB.]r\kn޼|rF:"TCCMӗ.]&K`E Y wx5 ə| Ba@ քΠ<#OP&%LJt:RʌD")j+H$""974MlEs]PoVK$׮Vjuwww:6>O*b1F(l !X,Tw8ZV.CvfmD0y˗\2{Yf?wQ(-/SLY~}SSbٳg477{Xֲ2| -W*x" 6M$@ 5b h6zhTRl6 L0/LfKP!PA"™G(J\vKJJ` @=)\CiBB IDATBHT2qU*TP(vI_rTrzP僙z{ -녅v Ԯ7ͣlrB$ $;>ڈ`^y啧zd2 ڵkÆ yc٢(IH… zl6{۶mr5!9G$2Lp8P>SdꫯvܹtRLv/\.\04428|9s6l_sܦ&/^t:oݺյbŊ^V裏 պpSN566655uuu1M)JH,K|)S8NHp8LaHX[[[SSci&I&OMbwֺ\.6R(DBP|TT&ρ"\R3bT*FAǿK^/(("B0op87bidPRՠbD" ӷ\2"vAXf C f3 nZb̂h4:00N  s:L:nhh9!].N(*TI1"z׿믿{С/bŊrf|'N}ɷg±ZG~/AV˖-H͝;k֬`pv1z{{J%d=BYɑ@ `٘we:7n@lxb{qAQFh44M~8bg׫R`d&ρFQEݸq&n޼ TJe8%qPg1 MӌXf1j\k ׵ZL&|Go2E\ E"`0 k]ҝ;wRK=n1__zބS%`P*J`0S. رСC@}}}KK^?s̾}&MdDcccS.{z#2GgYdݻ oa4w؁zϝ;gVk׮sݻ?5k"ݻa=NjgB+VJ͛K/t+vvv0 1|>ʆgږqS[[K4}LNG#UdR^^ecO}-+!͛i&\wɓ'OƇlܹs.\8sh4z?pM*'N(#82Y|@ػw/EQ˖-{'ۛ/^_0}6nH#G,_%11% 9ZmsIb8]ײZ<`)//eP<8{lwwwssEx≍7l6ؤJ$|.]AN] :::hO~/\isRUfVۻaÆ_|7lܸ?|ٳg[,7$I޹sucEV`2wޕH$eee9tr8^oZSEײ"I2}:_ K 2>_͛xHsD0 6^˴ޞiC2LK,󵵵M>$IDD|>b9|,..oδ-! ^~=Ӵ6\rFLD0LvUf6ݝKXp8섄rkMn`:8&?4Mwvv&S`0 &GLL(j޽׮]˴- `&dEa`0L>U&`0 f*`0 3``0 x`0 L*Fө{IY.ȸ<~N $25f<Lڅe\>P7P7\wv\yd n IENDB`keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwerty_mobi_shift.png0000664000000000000000000007175314600607066026401 0ustar PNG  IHDRw,\sBITO IDATxwtSg8ز\$Kw0qcJ(&0 IHHv&ggٙsfvsΜ9soH& $!@6$1`ؘ{Ȗlٲ~9CoWW}+!B1Jv!BD!B*!B1LB!<2B!D!B*!B1LB!<Ѽ-( C4d6mrN{{{ccc|y,wn/w.0 ʏ)JMMc:6{垞֛9`iii\W.+y[b\|Ex1šu;O̓P(TTV`%HM0_ZHI;̗;C;ϼLwN3o:/w-$̗b/'ku1pB!bV!ByXe"B!ͿBهT*t  Za;߬D-QQQb ؖD" RY]]=55vD!4Y9Bhn$v@'KQBhzV1)::zΝ7of;N3LVhL&ZjlB{#Ĥ+Vh4 . tuuuuu6Md"aۮ]Ξ=;::v,47+2B!ǵqƜUK.MJJa ݹspp!(JR "̕Flݺu999fXwݎooW^yݝp졣#999==}]e\rǎPYYyIñgg甔___777X'&&4MkkkuuG؎&6lذaÆG%lݺuڵ--->1(,,lӦMaaaRo1<<|ڵ[n3RSSWZ#juuu F#qDHHȏcz;;;j /$''ݻgmFTDDDoѦ"Zvh+WWWglb'6m(իlü?'?޽{9vD6ܜ}O>xد2]L&W^Fh6zX,vvv!!!k֬oץ;ZLLKHHxg.ܵkL&իWo۶(Z ڵk=vh䔗w!v,zWWWOO#G G&>8cP{\juAAcbbV^}u# Rr]aʤK^V틊IP(aaaqqqK,[ZZ؎I>>>C=Nsvv޵k)1n޼ꚞ%֭[vON,PURRry}7n{{2/ `֭lbv"%f[[ݻwFcBBBBB> R_:dgg+Jt9c樨WTTt:# .(ʥKnڴÇlELqAV[TTti T*JT([nMJJz饗=FdrGGyU.@kk+1'55ZZZ`FOQԊ+AVVpT:11AJLoll쉉qe^VVVccc]]ہVPP? |ꪨя~Lyƍw%;LZdɕ+W f$Izz:ֶ]r%22mڵ/^d;{/ Xxܗ>hfiIR}gRR凈H499IW`lllppؘ@^̜wrFBppbD"i#3X,޾}@ (..SI*@cqd^"Yr฻B ;FRRի|ͷz+''G(l^rooo޼9$$0m"++\ϼ\3Sss3v,eU<ܰaCDDԧ~je逥SNuuu:<D#N`` ?' p=s~lfxxHg'w&Tj&#ݳeoof!뫯gٲmzbdvVy뮮ZM6U\;vzܲ')) gZ$#`;U\._jO+1WXA&Ꚛ"~…^{-%%|' 7;;v̮1 9z 2g*`:>>.JnJ$4LNwYcӧOIIIof;"[immrrrsww'N۶m#JdXIIIIII|||\\\ddP5::X]]ͧyR$0 ᇺlHHHMljU|1_jիW-KOO(`0F//u%&&:t}||bccI ZZZZVX+VQzx۶mk׮MII> >P(tf\bŊ;wZ_(*/////oԩSFGG޽)Jwyҥݻw@}}~v6QWWWWWk*nܸDtt4s̎͡N'HiNʴ !_QQaƍ322L&ӵk׮\299k.Ba9'**U|@^DY$J_ ?}}}lFɜ777x<Xׯ2]]]I7<);6o> q}||bbbfsyyٳgyONNNLLh|AJJJNNNkk+oVaDxi`` 88K(z^TQɛpOOOhYe]^J/p#KCt:N:@.'''5YjySbǏ%իZ[[ټM_&?66FzjX<44d9>m#+r{zz)\!K,גKX6T*աCJJJȯR$EGGٳ322؎ζv);R`qJG;UUU1N5ߣ w8"11q߾}E?EvC)XGn,=m&.я d<2.Le@=#@MMe2.h40c'ufz׮]Ȉ  "///<<ĉlh7n "}+VJ \\lT*ɳ-ҥK뾾>2w֭*jH뫪-[&{Qz3}s}o޼[XXH۷o'''744>,Dol*};qiU&BfsYGo9*Ap:V{ʕ+W_~ҥE5k 2VN΀Gփ-K999Eyy9̄;w BV{M6߿> ߆*J> %_~wo͛u2郝xW?2-{jm2IzAUOXq˿ۿ;[nݺu;w޽{75>{9vXWW=##UΝ;JJJ:::֭[?11qܹ۷)Zl-_MP,..r^" H//4m[^/ȯۡť#ʺETe/LLve*SZIJR9h!gfTRRtҠ WWp ١}}}d)[bb"o7nLLLVyMrLWHHȏc8teL[o.N"y?~|OB<*r+ӧO{xx߿ >z@Ss*F";`#?CxeU&VVT?ׯg򗿐w6mڔ{ lEEEEEE3spwݺuF1??|]Y"dygj7|sQyfz"D"Rs܄رc?BCCI~:=ҋ!d2Zf;!ga ]ɡ/QDPPRUo~/g9DFҹk4y4icDRVVL!TQ5G'~Ν;:778a` ״D'''?32)tݸq y,ɍqgDU&i5N#2}D"!Ė-[we=>>>~]ElGvҟiGp]CCy Hr4NWUVEFF |7<5KBl 6Q"grr[g2}&k4L&A\G̃<(J]ƏN=۪nٲE$mݺU LMM^:22Rxxx$%%۷O q\RdCbʏEN#'>x𠶶vxxXPĤ|ڞ}rrRVZY[[;44$W\ <>=EV{MmQQQTT[rrR$WX, LLL}>.GDSSdd>!}|8<<߿v,(*++~룣Fqxxʕ+Gmnn/{zzD"B***:z(3"$$5^Fv`OgNo>̳]3fˎ9rjjjJT #G~a=n---[TTѣqɤ뇇?ҥK{޽lNjI+&&X$)) v,a; -[0Z޿75,߹|2nܸq __]v9sơ& }lG_6okxf||| <#u֚5k\]]333y|-00tp}ߗKeeeB瞳wtUb"Eݾ}U+JJJ؎ű`i+gΜ>8v> 쏘Б#G8}ڪ*zH$ (9 '"8Aˡ|}v@P___ZZv8Lxw7nܸ|]vt:N' ]]]aَ!_xq˖-*s%Je_~v8L?{ד#""JL&3CCCmmmdr B!dg%%%bxÆ 9992SSS#""?>m!XePqqqqq1ہ B###r@wЂ,1قU&B!ܹv6j;v ט#B!aB!U&B!bV!ByTarBr|ˡ.fp|b~6\P3`h*sxd]&vr(Ѩ슢(L5cA=G   L 䟧Li6~~Ncm}xَ~؎TV|D!B2B!H$zW><88f06WZ"t:PSSgd{ncǬoV`` ]O ///## _>y8}۷g6ػwoZZ={͛6yq^{zzlM͕`teeecccYοo_v7|cxlmϞ=ѣVZ?%Ks)>o+j;3WM6@iiiAA _ EEED"N7<<\ZZh؎1oFPkkkiiZl /DGGyzz8pg;VUfXXX^^޴߱kHHHzz_][[k:Z[[I윗d&ˑ堠K.qkBTJ>酅wa;(&۷/11q``[n]t><99J<62### FQ&EEE?GmjjE,7B|L#s杝@Rq}^kkҊOӒurrR*111r}޽Z`8{7===׮] wޝSN/h47ouUeY())t믇hloo陚"Rtǎ...lˤsY/ryttK^^TUU2h###G9qD"ٿG}JHWRtݤĬz|zT IDATe۷^iΝӟF#1h||_TZ4>>^"2,$$òAtt4٘f; ;5YX /$$$7r43'U&/W\IIIQ(eeeY<:=cΝTT_}UKKO׭[i&PɧڣA -[|BFȑ#,XcP(ɓJL(,,oo˗3:;;@ Lygbbt{Ok@wp:Y꫉ vwwg;" Õ+W5kB˟UVl.**b!>,,,,%%?i%&\vŋ  [;{,YסP(2d2?~6E\\ \&KdUNq-- }}}=Gʕ+-n:\MMM $⢕+WRs-vYm`4_ֈ) WeepmmFh41כL&dzyy@{{;( tvvFFF1%;^K.fXj}KVVK.B @Fz̉jjjȋqD9~I?1񹌌7clll``W$ѳ=duuիbqBBl"$$x1)l6;As5r}+ ֮]K,NjzhhۛɃGu:=zB0!!W.x3)q|U[[{9+纱M6ѫ^Y=ƚ׬ȱ@|zΝsH_zĞ8L4iGGG#G8.rD͎3AGGG{zz"""IiΛIdZIb KL~vZjj*&#^vvv&O3m3LeeeV6A`ʤׯYGG722h4~i'jY|zje;~Н{[y_.טpA?~xדd d6ŘՓH$dl]fܑF2 #Y؈AwN[Tw q_ 2q2ÇpJ6 Rh&%%)JRɏCgRT*xzz^E@DD촾(z,&""bɒ%l<ȸT*%{+ΊܦWMD"9M`.C,V"?aN6l >Dz%r9Y<>X744ΛI^J^dggB# 33sR/h2 7nGXu5kHPWWNBLaʼz*5!!a۶m3> 0?&n"N>Fh(//'Ț5kȜrKnnn/"ynll5m^YY ...*}m͚57oxEBD<;}/f͚<==#""HǞN;s El6Q̺g%ԗnjjjwUqq񫯾JQڵkܹ)"n߾)ۗڪhbo\\)1 =|//POO_{rr-,,fsqq1vT#1_e@CCç~P(q꯾>LYی<A՜y_e755EGG+ʵk>h1u:ݪUD"QXXr̙6COerr?ܳgҥKAxxxxxeR"Dd*?LDb6u:]cc7dCnReZ94TO"##ʕ+o޼911vDosNVVVXXBprr2cccwŃ8M?~<---44M,tR1JKKc++x8qҘ/{V8iu14/ϒB!*!B1LB!<2B!D!B*!B1LB!<2B!D!B*!B1LB!ļyLg}Ⰿy|k!`P38Xx1?Yp04O9<2.;9ShTvEQ]圅' /9 /^V8TBCCCBBݝFx___MMMEEhd;! Xww;w5?v옕 ?>~_d2_X;V\ ?/׿5 g;G2/_N^޲P(~L;T"H$__ԫW^tl(RLNNnoo?s /B(޽;55U @ d2YLLLff'X rfMIP(SNMLL$bEnn+`bb?z8`)Hbbbk@qYvCbD"9x𠷷7=|_KҐ(P+.\v)//RoDDkhh???~~j08p 66FcsssGGX,񉋋suu xWj߾}@wwwOLL899Ź$%%I$?H]X"77(^v#BWe._4Gbb"\Rbvuu}ǣ?ٿD"Yvm}}}[[;Q2͛Hm۶ݻo6F2lܸ---?8p@PPBضm_|R tRjGVI(FEEegg_r0%''o۶M LgΜ5G9rh41mVDGGJLhhh())Peh||/}6xxxlݺqqq!sL&ɓ'hN8 !!ATHLL( n޼9jhhԩS8ݗ\bbb#f ***؎!8V uuudӲe؎a[[[gmp~a`xx= 2P__4kD v񹹹dvLˋ-$$'\~ڵklGk<##(\QQ199АP(T*1fbb]$tttlV=J&?<;UUUk׮ IIIs}E(,,/$^'/JӤ4L _JPYYy9#Baԗ) ѣG}H$`98F^3kښ {t7F\A_VzVjS=nsLNN14do2_dpI#ByTe&''{xx@MM yapp،i/___7|s޽l&zW.) 5TUUUWWK/tdPv\\\\8@i>z?g;"lFSRR@חoԬ[+>>7Z#Gv䔖622z^/% ۱0Ã7SOOv c9vضm233BalllllD{{{cc#=Y|.d$u/?ʰT "<<,]YF #G,Ydʕ@.lݺڵk>>8tڜD"!u"o{5MMMb2nnԩS9XiiiiisJJJFFF@@T*t3Y yT*'|299ϞAAA;w2cccw\͖,Y*622rҥ^{-((#''les⧙{ԣLպb˓6ݝ499y֭[nٳ'==]$mذMj'|B᯾W_˗/9EqZ]]/~ X,bߟޟHNjjBv 5QQQŬE,cbb؍2W3gΐy;dH$2L&9;;[i6sb.׵͗.]njh1}R|E ܸqc6Es}Djjjzz:^~}6---FQ(:"R+j2&2+ɒdo>k8<ă";;[T^|툞J[[ds5Drf3L zkBBu>}gϞ=}& /YL&}x>| ^_ܹC펌#gYd;v :<<<^|Eґ9::qх .T6lۛ>DgT*2¼W"(>>TWW-222m uww{IIIAAANNNFqllmd2MNNvvvVUU9q % 7>YX̹,*sxd]&vr(XEQb'gWwjxzK$ x“˗;7^+-_Piiil0gn=l6˓ Wzd6zZ|+Yp|,`Vq=_ZhbVtYJhXT*e;'1>>t·>n`r:Y||;/GoB!k1D!B\U&B!bV!ByXe"B!aB!U&B!bV!ByXeWB!bȞ1DEzQmlL(****44QN{{{SSB|9q*_$ v1^+(6 iQT _(AZuryB{EQ~~~v FrgoofoZZ gޖ^̎\!@"k*3:-)1 _(tVʬ" ?-a%HM,_$ v1Y) )1 HDQĄ= ̛5&f7̗C˧d}ޙd|gB!D!B*!B1Ϯ;!i IDAT9Eqñ9HDV A( wwwZ=22v,67+a5^^^dj;T2OZN{9$$Ba{{Ƈ" H@TVWWOMMm-Λ͊DXL^Dòq+VӋ/?LdB}1S%y_e.Λ͊p^&B֨TIv,000`0 xLj4ɤVZ-ެ"O<=1NǞΞ={Y[ö3ټy`qެloV}!ByXe"B!9۷/55u2kǬsի\\\FV~UU1GVZDjwޱWt {ףʕ+.\?Bcǎݿo3Mɤjugg;wYYwZʼ!!!?~!2?O+[lYny[z%K||| Hcck4 ۡ!*%Ko.wBgRRRSSɓ't;ʺuہЃHg[6&&%\ϲen߾}bL&۾}'BaVVVAA-.]jx_& >nC*sf 7P좲ѣGV._ZmSSⲡ;w]-juKKȈX,QQQ?>̧7nРRV޽3ϸuvvrٲeE>.]7 !!! ++KsB3 `Æ `4Ϟ=ˏxQٽ{ 88vv86D?uvv&˭ cF7t:(ovD6! +**̬yjR8[Vwttttt;%z̙!<`4G{.Ç?iq*sZI&з:t{n2|֭zaF`` yaL%;99fܸ4k fAe˖il۶Tuuu ZZZs۶mlcBdNRRҬiiid"DUU"Jdў^$yzg'3~]tü,4VeZb[hnٲ}><04_^]ΛeZߒ< ofMR@&%$$L)=ʿ R3˿˚5kvY2:|lCl 7oʔH$*ec*@d"SzSNw#Cccc&ɮL+%&ᘅfttU`jjd:?8;;cRԶ1QEEqs S0 777@Vܽ{޽{pݿo|ړr m۶>!U[H5@znnnD"}fSSϞ b7 ['NIo&'2훧$IId׮]W\\̳EӼtm͏yrhJBB|JcLL/--|c%%%m۶g1qUoT*nv8 #2ZM&,X6$o߾ W~2ѣG_|0l.?я,9ǿ{"xReAJ |%&G\.gǎJ^v8 ky^r09-[I{}?Z Xllď1gœ*( 2XnK~dGçHIIIIIV˧#h8Лe >}Çge;7L~AT]]]]]]Ef/j@bb"Ëgzzzð@ xg4HQjhh '&&ҏiiidWzLHD:vJL8yB,!ɩd&(lnpJ(G>ySSSI#>-t^7XvP(LLL$ H'Z/*))ٰa7'LLL֦ \VVvh6twtiP(ȰH$z׷mF6ǓLd)((t队Y755\9'N,Y¿5CCCdrxxxFFw߻wZQQ_[nfVXAtwwra}ǏirαH$k <2HW4O{P(#]n޼ɛc~rՑsi}||<MMM.JqsM7dZMo 333l6~Bٳg֒9RGGǣG`ٲedA |ڱx^_cǞl؁741aժx`~9-[mw\ǫMtww޽[$X"11yddD$y{{GDD{hhlksQQQlb{wT6ٓfO4ځBA6YfQP(:ǃ3W8:qtP8(*iHttKڤItvs?oɤ4MEo.7vϜ9xb@[jc{̒U|~ZZZQQz7uuuwAngfddzhh(B)))6lŃ/wO'fzb6njSN-X7d6663$$$ 'D}yyy&?S7,sd.˗/Ϛ5@T|3<iXnx𣶶ϫ . YIB  , A-Д$҄xY  & -_|̙6@A[&5A|3- 4---. Ěoo w)xm Y&>2@A L|2K!1n\?4% qÁxW U,x'Ch ebJiBuLe_"O>4\t%jL}4[, " %"4e`s "l'uY1,x lm?H9!bC \qw^r !DJ,_3]&,x=X׿EJ_ !d7|G4DM)-vh7 p)eY9ֶk ޱDu YQ,xw\QoKL`9>2@A L|e,d w d2T* Ai"b1LG&`BAeff"PZ-c ^@h˗/T8LD?vB92̔?/VBaP x<[lEQ^^R8RT.tq$bڴi/ RL&'PFȑ'˔qu0EȈ}b,B(???όc2~Lqub DWʘ vB=2ˌ_KG&XG RK Յ2|e,+X,enw'N2,''f4L222d2BdjpOHg͚BN=ʼncbwP'%(o'R.sM𿃶L >M,"D*gϞ]XXVA;vիέyyyCCCped6fsKQ,NIIIk֬p8NSx<@]RR|/۷:… .\zdtsνD"QkkÇ|9SQQ1w܊?8\E42#NEEEiiinnH$JHHp\MMM'Nѱ@,;׬YczÇ_s|pj+I!.*YfY`ߞlll&M:uԩk׮=uԾ}`8dɒkvuuk`ѢEyyyr`l6V?=zc=6sM6.~\9A,?7ndX.ʕ+[l!Iի۶ms\==='N6mږ-[prssn?Y1̇~_3ghkkklll?/rnZ__?k֬%K;mᗜ>)) #yꩧ<ϻK7777+W믿z{IMM}[r{Y,ֻk0>ظ{zĻkΜ9/֭[z뭿/k֬VkCgЖf'Tnr}zeeB555W.//6]pJ\.輪b0yyy*jJTX,^]&XXfcx"'I&IT\lth\\.ʕ+ot'O̼x"EQ!.c0F@ S>P^^h4++++++BG}7=xIgg'BH.!fѢEׯ'IL6ĉ.ј"= ;wѣG:N DcUCEE@ ¥wttYB̙3$I,fi4PD$Aox<%%%*;Q(\.t @ HMMMHH`0###:NGFd|>( T*> ,..%IKKSTmmmbtvvz< %LbJR&t:Fcoo/G*vttD"HDPgg'.-))oe2HhW~_wEp\TjټJts,>`b8??`0݊=Oss3SR)))TV'f;;;U*;|r~~>~"f3@J1Lx1 ACSBȻfɳfBm߾~ Uc_"vu)nO6n`Dtt | "HPL3\ IDAT`MLRx@.r9}B&fZ'cbx!;BAuww B| `0}lHp8ikٮ^j6J%=bB~|B l6wwwԌ wNOOGiZ^/ q,444s@B "BYYYC+O "p7ۆ+Wx7$z<^Nv=0x<>f񖄄ۍL&C~Dl6^?22hB]]]nv|w'|~j6|ރ!r+W9s&B͛7ӓBˉE[n糄-333駟W V{1Np†o3m4slfgϞ-fͪXOAZoCpA=zOQTzz:lll_0yt314~%d;1 8d>hOOnX,xޞftEEEtZ-nQ*Fnn*S*\.w nf6: U^/zzzG &T8]6h4] a(jpp%JId0R Atnu8b^n4tހ4L)))bx``!$IΏǪp2"Jdnn.~iŊx,5_QQyfHR30#z<N1ϝ;FAAw"b":EB8p@.)G?_x`ؿcƣ/uuudٲeҥK>K,z-XzgQQQ^^^$o[}|rAotrt:N[300T*lDVδ<hLMM> `bF?n[VXd2}x!tr|pp7&)===11_h>}t#n!:˔d.˻;Ud2\Nde`Xce$I^2:+GMo7bX$9@ʏM"p?x};t\"XV6LfqR(X,V__}m_92ɤVe2 ƪZ 8Ul.]2eJt-PTTTY>v;XXXY\3?pnL2[ZZ^xtT*gϞ-J/^x)ܹsW^mX^}U8cƅO/^Ν;bܹgѢE[/^|%zo[$GO _݋x<"g<nY=onK$.;|&$$xddd>ݎ[L&v'$$8_t:O;pfODk6VwС3gX_駟jkk-ZiӦ~WSSSSSlٲK~'ŋ'&&۷/L2}#y"Lo]w!tY=mj瑸%+UVVFQٳg񟹹j:07Ix„w,B|+7z&N|1= |>߻ߙVqɴl>iii ",rY[t  F ɼ9CƇ:O"l T3]RT@Fl6XxnƏ tpYi?55U&љ>9X5b޹s.^xM7UTTr|Μ9{駟=srrVZUYYۻm6<e_}UC Gmذ׿oӀW^ye1eN2eŊK.?<܅ Ϛ5رcE^ |<~o.++tMMMSLt#YaחIӖW*p8$ &)JqOp6`0njnRi0I$6wm{MxL$Y8s``@V+ |$b2x tI.BCWBHPЋ*Jτ?p8E*zax=ы\jū|]Ox ^oh4q.׮cA .khhH.XсU# ܹ^zu:]ww+v˗?SvKR==رcNzy'cBy1^]xd}y oݺUѼ=B?>ymRSS_y啓'On߾{Ylںu+,Bh…A ?x?WЭCa\./LXaa!EQǣEuh_#%' 6g,{7P7e2V=rȑ#GL3fϞ]ZZvݻwQqmC{~LDeƉ۷$y-{;w^zܹs>Ln:w,X`hhV @p9~Je4kT* $4ZST[#[VV6"1ǏoiiYz9su *@rI<{}b`L555EWr:Owq,3"ر}ڵgY&''W\ wY@p(V QZs3D&2#QKKK 2@A L|e,8YBrDq#H,\?% @bx!o'@b e,;!'ˤ%AT X({ *9D,CsHzQ!9$=,C4Vlst?` ȲOCDqA"9D=gCҳzI"9D Bgw[(G"s"^!c#5">6^DsgK25">6^!c#5HxMD>6-_~c_>fwzpaQaQaQaQaQaQaEXVe7|mTZ/ett=.3;/{N{s~N'j-=#2 ","2 ", 2*", 2 ","2 ","2 ", Š\*;w9Rtb?|ϹR;}G{}|ڿ/||ౖpaQaQaQaQaQaQaE.H=) >+9}J>+DZw;K((˨(((+r:z*#NJjP.`ח?Kw7", 2*", 2 ","2 ", 2*", 2*", 2 "ȕJ/vMy(kM=|ߥRKtψ˨((˨˨("W*ݣӂ %v3S9qw37.|-=#2 ","2 ", 2*", 2 ","2 ","2 ", Š-;3k{K˻b7{w:Gow'Y¥{FeDXFEeDXFAeTDXFAeDXFEeDXFEeDXFATbNxkJlp&%wp,?=3*}_O*.3", 2*", 2 ","2 ", 2*", 2*", 2 "&+*paQaQaQaQaQaQaE7]tψ˨((˨˨("כ.S\gDXFAeTDXFAeDXFEeDXFAeTDXFAeTDXFAeDXX¥{FeDXFEeDXFAeTDXFAeDXFEeDXFEeDXFA9ۏ%\gDXFAeTDXFAeDXFEeDXFAeTDXFAeTDXFAeDXXBtG]|9})ɀ((LO~M8/||&ylNeTDXFAeDXFEeDXFEeDXFA9ۏ%DJO+AeDXFEeDX'](L?{ 2=ϟ_ޞE2Ae0S}dEXFAeDXXBtgr6bLS~2<6M˴n|02=y&8ܚsd.28ӛw,LuL{Bu-GdZ{ , 2 "~,!Pʻ޾T_$4G]d3iۡl2ڍ2=y=PUй˴G-ݣUhz|}#p 2}GsoV2("gK$2=zҍ\݈) ڏ^ɭ2;^\)F 2HJ?d鮽Qt?)u}ҝqLvt,("g/R 2=zҽNsT?ah!,Ӳ vR =W\o(V˴c~3 G,yq>>FV[/",ӲX_wцLwfsP`~޸DXFAeDXX¥{Feztt_7F[ CiPPyzÊwiw^`e6ri'j6ͩt7,sJYtG'"aެ=rl(߈ 2{=VP9ۏ%\gDXGSebh$_||)نiI\(2wǛ9Njf>wyKsV 28.5ڒLfӵBt_̮'kΓtwcai]npaKwaǛ6X$d~QLϚwiFrޣ y:yJw"2툥{|^d8^Ο+ Y)߰DX}u2rMezre5;vfƃEXuQn{Ktʻ<9Iq?J b",ӌ.Sҝ=y<^?sw˴tFfr=* ",Ӳ#|f2 뺹 , 2m.3",ӥYt'Q.aDXU3Yy@XI5rwK7<hL̂<;[|옘|Ss*2M}agAMP!aM1", 2{=tۋ%\gDXK/ݼ$/3S(/ZoafP|^,zfpKRL39LK^WxGkhz<])2x]#b׍K{+eDXuPn{Kti{@V6n$mH",Ӷx. 2<śSfL;:o 'W;}K 2;rYnFk";^}o(?sau\eLt[KQJ"dFeZrxǯ00'2MtW)ek:FVwsav/ݣ̫G)Ϩx#,"2=n",ӭ'qx˴KEKtψLtMY+2-I.Fev|xagc#=XL!,ӎkJz9RXұ˨LWfSbAezueDXFA9ۏ%\gDXFAe+[3)~,n/(LOƲ~] ,"2 ", 2*",ӛQo̭1ۃT޴EXFAeDXX¥{FeDXwu+2=ҽ_eDXFAeTDX;7ۍL{_08("gK(LS}t8LOtaQanG8Џ&M\W-B/2 "~,=#2 ","2 ",ӓ.EXFAeDXFEetǪ,ʹtU9ۏ%\gDXFAeTDXFAezҥ{(˨LelSddz/ ", 2 "~,]<]!YD=,CsH*"/w5gWȚes`E?/>D=gCҳzQ!YD=gl>]Â` ~嗗g"szQ!9$=EsHzQ!+t}OSJ.#39D,CsHzQ!9$=,C4Vlst>YO"jw#=EszI"9$=_淗WS]p͑ {x%<EszI"9D=gEs!8Vl{$sgtd GsH9D:gCҳzQ!YD=g[~N8:?XPz.c1cåc1c.c1c̝p6c1cĦ_gK$ Ge_Q; !qYxI"9D=gCҳzIv\;~ } 4??QP,CsHzQ!9$=,n<եVc 76JG5 !4 !YD=,CsHzQ!YֹyJwxۜD{ |tqCBqCҳzQ!YD=,CҳlU;1+>w ]#!8 !YD=,CsHzQ!YV6ρ~Hxً`P5x xM$gq Kt7*AsHBHxMDd_Sa/9qQaQaQaQaQax`=oAWaQaQaQaQaQa[o;KntWU((˨((zKܩt_ #k{QUa˨((˨˨}J?;}/C+;n((˨((zK/Ma>?#~lWaQaQaQaQaQa[oLXޯKwxG;U((˨((zK/."EU1="2 ","2 ", 2*", 2 ","2 ","2.ݍU((˨((zKt7*^Ts*", 2*", 2 ","2 ", 2*", 2*",c-ݨ{QUa˨((˨˨Kw"EU1="2 ","2 ", 2*", 2 ","2 ","2.ݍU((˨((zKt7*^Ts*", 2*", 2 ","2 ", 2*", 2*",s|}G}ncSKt7*^Ts*", 2*", 2 ","2 ", 2*",ӫ|s)F3 a]\DXFw7yY=}kpnTwӷF7'3ӢY9G/Yy3yvD_",Ӧ׏'@X+,CDX+s9pnT;uw4]Qkӛlw_Zet_Bicd鬹h",Ӈ2Mo K'˴HWE\XC˴t;o . IoEzg[9˴Kw16p>l6K\eѥ{,ko642mZǪ#2=Ε..mX¥Q3xWef~A`; O.l|&''He4_kukPi7$2}]m@X]7~] ,\l ,Ӧ׏| sDX'Ӟl^a>1r,ݨ{Qw9:A;Q+sey_^f%>2m:Jw~#'X{a>V2i]\sҽ#e/Ri׏ a~ځL_zX¥Q𲂥Ik_0nL曢:[+\qa>\_&ri_NnK'<׺\#,ӦkX3DXWyLwn2.ݍuw)ݵu3:SfN'lnyqy eڴnL瞋Lf犊9!,c-ݨ{Q9>}-ҝ| BXM a,#[DXBsp̳M놽H鐙uLnc͋LtW+*愰Kw"Ek~L-ݓ@7 ׍AQ*[ et_@icdtXAepAX ,ӟ2vtq^$_CXMEX .EXG[¥Q6C|vۻ[.69gRxs*s;fbcL+(2mt7kݷFC9S;\AX?ׯe.{Ya2me5/2ݘ{Xes<pnT~lm 8ǟf~r{39}{}k",Ӧ.H6`=RٜSkk>mYL ?&LpaM ,Ӧ.fYyDX/=V,ݨ{Qoc.^#+[.69bv"q'r_@icS eХ;*6?>\9o",ӟ2m8}sϧ{etk^ezrˏ1Kw"Eϲ.(Um0",Ӧd3hy6˴cR@Xח\ePof䬕IezqiFse^z˴Kt׭Ae2;~jn",c-ݨ{Qoꪋ]~W.+?3^FXM]#'J2}՜Cu^ 2(S_]s/˴Kכ..mX¥Qřb=~grR:)t=Fp2AeХ;q(de{zKt7*^Ts*", 2*", 2 ","2 ", 2*",ӕEX'B 2.ݍU((˨(kEX/$;0ZKw"EU1="2 ","2 ", 2*", 2 ","2Y32-wzKt7?/OU2(sEszI"9D=g1)}9>%}|V6uNe}RzI"9D=gCҳzIⶲyTPY97Ed///x YxI"9D=gCҳzIⶲyT_}->y#k=8 !8 !YD=,CsHzQ!YV6ρݏ׿eS<噏JEszI"9D=gmgt E{Í0h4 !2 !YD=,CsHzQ!Y֥yK@xlً߫sHuCҳzQ!YD=,Cr,6m1c1Ƙ:\1c1Ƙ;m1c1 nc1c1NlEji3uۭGE/vAy-G,CsHzQ!9$">)v5t_96 ү? !:7 !2 !YD=,CsH]Iӥ.70%ɂDhPC4 !c#5x pWvJwxۜ}sۦckqd=$sH(sHzQ!9$=Y=Ւ>ξmSv%< ;qYv7RqAHxMD?p`'!9$|lD&^!c#5">6JvKAE|>6"^ x w%;Xtoha' Q1="2 ","2 ", 2*", 2 ","V.7Opw|9yY"섡 2*UDXFAeTDXFAeDXFEeDXFAeTD^jZbg}oϥ3~ɳ>?8 unWeTa˨((˨x7ϳĮ=,~OHvN ",b{\EeDXFEeDXFAeTDXFAeDXFEc?QyP-t_tN ",b{\EeDXFEeDXFAeTDXFAeDXFE]5-tGuE3f.Ngrû{-k(x<܏>>6-yEa' Q1="2 ","2 ", 2*", 2 ","5{a4}Y2C۸"%7YtcfOkMǥ;˨WaQaQaQaQa{ځRo6"{aGОef]{]ia;wҟ[,-WI8ss wa' Q1="2 ","2 ", 2*", 2 ","쎝b*N;JKZKJ0DXF((˨(ۋה]ށ֕ԋrSaog.rӅ\^L(ݷ{;= 3˨WaQaQaQaQa{˻κҽf_KᅦTaĹR8YϒoHW0DXF((˨(ۋ߽tWKc-t>;|=.ia~<|R׳>oR>ws} ;a(9qQaQaQaQaF[Q3=,tz)qY$c{R tͥM&ɟdߟ9;a(9qQaQaQaQap>;a(9qQaQaQaQahtۋ˨WaQaQaQaQa{qi ˨WaQaQaQaQa{qi ˨WaQaQaQaQa{qi ˨WaQaQaQaQa{qi ˨WaQaQaQaOߞ^>Qͻ׿}^N| D^jZ¥"х>oޑ̌˴o~!@/ 96{I˴k|2˴7ߐ{a",s{=ޝ [4EXM!,Ӟk#?'2 ",Ӆtn.a'l $2-;W*ХorM ",Ӯsҽv7O,sKkՠKT=>~\7,Ӷ.ݷa.1Wŭ%\*N],n4˴ꚍyPtb3LnϑJlqf2rq]K7LۺtRe0/ånKAE y-9}6}|GiRX}i.G,ݥ^xVni@iKr8X#u]+Z'a\~~k wau龥aZzX+ۋ[MKtT0ZAx=eBa]9:ouJw5\AavcDX%񵮽jt?]]9k˴K-EX2 7F+ V.a'Maә6#lQڒ96\_*FɊ?LfQ*QᵿPqIe{z=X?;es埰Xy@Xm]\{#a>8ʆYմKAE i섘mj7˴h~!UaRuLfUtnԼCRenz2Yx~y^3Ie֥{N=!pi[9K^p>;a4kQw-Ӧ4)ͻ{F{ ],ҺAX M$27qq}BqLۺtҽ]ŭ%\*N5(r&2:XԵ%<=ކK &2ҽ<̉u\toWt]{EXm]o)2*"l/n5-}Pvhl@fW\@iۼp+"96u.}\KeZ{/;šp龥˨մKAE I v,92oSoXҽcDX k^۹cls;wq/kiOXGëΧIe֥","V.a' ğ]fRq(2g2Ltå;Z?;eړ=?8.*~fEXm]o)2*"l/n5-}Pvhυ3Sz 96R*?'SZm6=>/T|j^^[z2Yz~Z](˴K-EXFEŭ%\*N͉TY_4,ӻo{ u av͞L^v_t-LJKw~v˴_W},2m}KQa{qi FkMܝ{ezWt$a ,ӮoU.Q}v|^DXm]o)2*"l/n5-}Pvh˵ɺ )2fQ)wmn=[Sil>J{.Gs#j>CaymΗe֥","V.a'\ALFa;(6+Xk 2Gtъ4s8뎏J;gz-Apkkƺ9i[9GRp;p>;adѷLiL{7u.osm幟, ",Ӯ|Jw iM[5 +˟6@X=+ܼZj˴-hXc=0Kvp>;a㖍Y ,Ӣܢu3abR{favX_]^:>-Jʊ7fLۺtҽ]ŭ%\*N͸|B?C/py-Sil>{pnl?6,s[+UWiukc> 2m=Kvp>;a(9qQaQaQaQap>;a(9qQaQaQaQap>;a(9qQaQaQaQap>;a(9qQaQaQaQap>;a(9qQaQaQaQap>;a(9qQaQaQaQap>r v8'XNA(5EszI"9D=$ۏ[=Yp>.Q_ 8 Qk"9$=EszI6 z.ol7+'v8~'Yx DsHxMD< 6PUW6 NGsH,<,6"^ x w%m:Xt ߌGl=N%cdN"G2\<,<,΀lypK9DsHuCҳzQ!YD=2 ֕lo5kcu6c1cL.c1c̝p6c1cK1c1s'Vg>{~;}a '~~H02t㈿xij=gCҳzɭp_pM.ݿxg C3#*?Vhfg4.wʨ;q*(˨((ۓ[hKܵt7cOOqzڿ=y?_]m`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEkT+>U"t!n_ėɿr`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEɃ+\W?O?̆>Fia3XUa'NQaQaQaQaQa{rhKl,phaA]_Fu^E؉SAeTDXFAeDXFEeDXFAeTDXFAeTD{rxK+s `ZėEzG')7UK2XUa'NQaQaQaQaQW-6s''.KwBE5P"ĩ 2*", 2 ","2 ", 2*", 2*"lObm]HmtE ĻHit]8DXFEeDXFAeTDXFAeDXFEeDXFEɃ+UuY‹F1QvTaQaQaQaQa'OX{p9tȥ;ʨ;q*(˨((ۓOu_ KoM?ҝ`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEɩ+i鎋w˨((˨˨=9}J"X/.!kO+*"ĩ 2*", 2 ","2 ", 2*", 2*"=}%}hF..[/sA-`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEW-q۟鶯2XUa'NQaQaQaQaQa{rkm ;`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEɭ}%\ QvTaiw>*߼#DXFAeTDXFAeDXFEeDXFEɭ}%\ QvTaiR(˨˨=Kd2"N ","2 ", 2*", 2 ","2 ",">.wʨ;q*(˨((ۓ[hKtA+*"ĩ 2*", 2 ","2 ", 2*", 2*"lOn-}˨((˨˨=Kd2"N-7drSio>yaӷ蟙av|wz{闤Ae1B<^˴q6\eQ^>et(Lf_=Kd2"N-=P]WiG2M1Kl~繱 2Y_u avT>6Ͻʷ޾Kw(LNn=Kd2"N-*]'XNYeڑ|+G-ݣ2;A?SD!,ӞkKيwpiGc= ,"2 ",Ӳ;T'іp龃 VFUD؉k"2FX ưP7&6Qe1Ǜ?ZtFkfqO]#K@X Jµlk'L߆9֝KiEeZ6`{rkm ;`eTE8ut8i\*޽Ƌd;˴c~7K_*P-xMd]w׾s2|l{CZoծ^-`a6\ֈL׎{ɭ}%\ Qv|\NyPK*6G.ݫ>be2Y_2zҭulsΝt_Kwf0Lfkcsa[!lOn-}g-m<ۼ,ԱxNl}=P?cϡ89ұ1}Fn8 sb^ioe=Kd2"Nݹݾ<۴!^. ,ӎk3n a-NkEX Kv_>g;l]DXmoS֕+ɭ}%\ Qvao/vS<2ȋq:|xkgDX=Y(Y.=f鎎z6a.XttۣX¥2XUa'Ζ7O[. <ۼDx4'eqDbT)ݣ0-",ӞkJR K",ӎsyt޾|#,Ӷٚ\QGn{.wʨ;q6i^@w\ iTmrPeڱns=գomEa\SM1L;*zTtt܌EX-~sf",">.wʨ;qgAAeڐlM(eڱvs~LM՟8L{I\L;*ϝXQa{rkm ;`eTE8P$j, eq9L;o)loiO\>FiGcå{y1;_ ,ӆƝ(D؞G[¥2XUa'T/ݯ%\lqfj,Tk!2tX5uN9بN[DX]-}gstgΔ?뎰L;\ Ȇztq eڳt2|lt?ZeDX]-}˨((˨˨=Kd2"N ","2 ", 2*", 2 ","2 ",">.wʨ;q*(˨((ۓ[hKtA+*"ĩ 2m;5$((˨˨=Kd2"N ",Ӷ.ݷaQaQaQa'іp龃 VFL NG<˵mJ1f_!9$=EsHY=KdBKwʤgCҳzQ!YD=$ۓ[hKTکW]6&OVJ_DNG/<EszI"9D=gl+ٖz`t۩aV_}' ^Llxȯ?9=EszI"9$,W-@UѲsw7jv.|ҝ<)jw=EszI"9$fbR.ݿ_zCeh 'ԣ.CԳzQ!YD=,Cri+=6bN!}>r~9ӣHys9$d' υ}Q,CsHzQ!9$=\; եc1c1utc1c1w¥c1c.c1c̝~q/꿼,͵k,2kqe`2u-z'^\ޫKw5~1^_'m\ZcZkn)G=oxƚ^]7cΰ9TOkd\=oxΥ^Umc7cn/[ccula֪>j]oz*ݾ r[}oek,<xXkjw[U}SO`EZkmaR_&쵲-$MqZk6ao 'il>vpXk"ZjkڄVv%,g_ӟǏIԫ^ Z*®unۋ} }}ɴ {muQbs?:2OVQL'rY[epXk"ZeoJHK{'&r7EK* ^ϙy3s>D,M'N_J*Y/1E؆ZkUaҸ)w%diZ]}Ht5$^לpXk"ZZWBopx.ǯ7{}M_yɴ {zZvK; '{hl>,~" wk{akVU]K#nM"XI{awk5 Lתn-t;3.r GO"la֪ktzwt/RqFNMkzoXWeD{$|8B/= Z*®tý.Jw{'&g5\s}u&XN^~h̭|d㋰ Z*®|^}JsNMkz?k^ƏLlnZ.zh,Dq RXsj"la֪kii:8t/2|oS]Bj5 Lת~q_wJvpXk"ZIQ˻gsFT&ڤ.O$|~ZkUEصt#[?ڻMkY%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk~c]K~MK4 6_m:ZE]iZ*7~SͿr x}^mpb)/6mYK1c1cp6c1cK1c1s'\1c1Ƙ;m1c1 nc1c1Ntc1c1w¥c1c.c1c̝Or&IENDB`keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey1.png0000664000000000000000000001764014600607066025315 0ustar PNG  IHDRU8sRGBgAMA a pHYs+5IDATx^ah$i~_ǐ 4J8f5Ȥ Ehɛ1GءY`$-4D RB^ļPWɂj"E N8'DHnֺ~w/ROSR%~n{[U~S}sg7ARD?Z-G+.peIniar)6B-GE }5,//ns  6 -bp  6 -bp  6n?mfgY{7myMI˫dQʫ/PN}y~o;]wpn^DJGV27}umGV2J4]j谄Ώf4igS9h;զR+:<4ӊRC 'ϥzq=&>Ѱv-G|ʴŎXnn E+ʰiuwrcwUq4\9{R 4eʚidڍbmcp2tx~SK;*;-I?qiz>1Ǯ%ZߥR3^mji]P{EKi@f1{smku%_jveC&ݮs?W=a ^>z.Л\[Am5SlCbF.oC=ӢjB=[ӹa!(Ts]!OO*A_] tܭov*=ֶܶVjI'tS^ARmΨJڥyݘ}.7@O麯}1t8|&)7sL^x\גڬfʽΰ mK:h̭pX M3a;K+0NcHKKCpjܭ]#=]]M88fl&\oQDZN sN ^xXBvIGCG-{V>PG2!y)*=Op=_oٺnNދ7sMۖa s׽UlWf1S3C[LrZfg&l~{晦tJ\އ:(<ܭ&jZe0 뷺OBRC3}^ʘZǰpUndFm qKVVGvqW3,i`˛cm_isRRv+ۿ\D-a~KhY_]_b[YoNz> M]^4L+贜֟VŷޟP/3,j"AwҰRaNK:]iͰ] 'Ş`)ژIz;ېk3NJ?tht14ֽ[cn@m*P^#|#11fxt s*%uM19>5ۣ ^+ x^BB?wA \oCg\>M>-iߛ~iarxVARD?Z-G+./,,hkkK)-X^^Ύ!ОvX˔_ι mgEw[S4?Z-G+/,,ѣGvImީN{Vp{5ۿi{cevmm>{gjJ$!GEroW1lι{>:V3nmmٹΎ\$FqGEѢhQ M߷K駟Rím$ hQ?Z-o*.?jrn<L%i6 1Ѫ6`. Z-1PVDVm5 ڶr5 -hF@lnn:W__^%; 2sM$0Ȫ]RR7S~I/?5VmsSzs;_‰%؆pYip.pG{fQ^+vK~[ſ+۹j@|.l֛ * 3)7g_@H3j-\v"Е fRD#iiBZ6ϝՑn5җ&ą\lFmgDnu8!u8jq'PjSg[~=frtA׺?A<ܮOV쌊qM&͔՛i1)jzN8jqX*YMٙVqJ*yl*W9H+ Wzl>ӵS.Ѷ3.:ڕy6݂^폇5n04ODdcAǜ`wΎ5]q+=ai;"޿#}^Tm4܎͸cRȼ^*̥tץ֫N խO9ު{1\{) um-}6M](Ygs*8wӭE=yRM؝P;]~@ E(wqX"` xc9y^49>-g[K'vh·k)ٶgg$p7rFͰu-ILu77澷Bؤ; !4,}sն" le?4qW;'7PqPOxX!4n h2O p"\ ]pm M0y-dop5[9 LqѰ~=;[i"8ep 1wNh-@ j- &Z}x?~p 'pM51j7 jg?+;^_}7\ jAdtտZ %ommM=s񶳳]YGEѢhXi-7~>ri[p{5qrZ{yUg\pkZnQ۽{35W% GEѢh\~g>jkٹvkk!099y4E$FqGEѢhť~n-_jڂ|VW~sr+[^^&FEѢhQRn1_gn>z{.SGᖻ%04&xynHPRo=-Ee]$L'7 U_V+;M[A@ln[8W__^%;ROD›Fjvuζ%FsEdᶭ?);fp z:mYHOyme:sorC$ܚ`;z{Cc٬f;[J;*;uӭEe,jnvj3f{r8g͔՛GpGK{B~^{v55_ʆ4]لjhyqNs]#%\c;d[di9 mCM={6sN->-k]]n<ohɤH}g3n-;L+xAfR+]MkDZqcpZ7+̫9=]Ev&(H.:oM;ѿɜѡTiO+U|ʜdkɶΔ{ukOAkT啧:dS<7Eom}] }S왇LZ]b[MEθ٩Dmmx '?kOןtQ;Ztl1#7pV\VXotXv2^J޸`Fʣ/'uѷj{_ClMi&h-gٛWμ>/e`P Z J{FgCйq6\Z.8MzFޔCC"u}VPf/f}/{3 ׻ƴ;VP=y)V,|P+swK~K9M:w| ,j%5!9hNS۸`,h"TfM?mAK~F&kF K؛cikkKvI02R>]p]^^Ύ5;;K 0ϟ߽{;&<ݷ4f-h/,,4_ yy.i [\ -zTp9>w~4f򬝫n]fpkZn޽{GEѢhQLn0ype599y4E%qGEѢhť~n㐇.{umMU믿u-B-G[Py/n[b;.[A@ln[A@ln/?џ|qm^cm[r~Ӵ455MYuebZO_9(חWpaՇۮ]AvʞkVz5*zHTwTln^{q %z??gS-.[㇇:<ƽ%xi-JWr[ֽ3t]s'&ԟU2٫Q\WgP~w:n5 Mw-~WڈF\|_Uf{ro`'w_FG"qaz>-_pB:e$۳'ti>_P\ИwƑ_N5oO_\Aኆ'jcNcwRQg0ܩpޞy`u׵Mh{JJC Wn?Uu]xWӚStX}zZ,[n3+0tYByC/S/'uw/^HMJH+ʸv[Q1=7w@[LTݺ;<&Qz m?꾫MϻT՝VM)pa'4YZ|Agi"~}ԡ.ModBZR1Mtk|w@s;RZ mxۿ?:'.6\nVC 毳$cښmiyyY;;;#_;^>~p.~_~ǚ=5!G׿::|K'լlVFPB,Py˳v[s:>Gv x'v5whACnG eHHE;1}g# 6 -bp  6 -b­fpy 6U_G96mm'EwsS4?Z-GԿ<w&yy׮]wf5-{Uz9ϻkD'q:yqN~>5֖C&''hGˮn `կz{ǯsj޶KPo}}_vp n9~FjZwK@ln[A@ln[A@lnnζ$E_ğQm[NSSSvʩ9w*uͺ4!_Gjp5+|ƲYe4w$߮6ݹ-m5.UpۥR!?=D{󚚷s L#(g˚gԟU2٫`Y{; }ن;8.ǯ "gnn(YЋ5֥쨷 y+;+$ &ϛfTL}zOBdj릴~{6sڻB{{/]mywʺ B.u9.(;P9y,/'uӷz{JΆvuZ,g5.}ҵμ֘.,we0ڛTfMő4v]Lʻ~ee|'>,靫}o=w4Bͮǯ g:,ao>lzt^؆n5s Y/ ҵsQ8~]9"qppphִmX^^ΎiԧUey}]` jvv'q:y1j}>qAp -bp  6 -bp  6 -b#qppphw!?z".ӭ/~ߣ86;;{ۓ8~<8'?7k#\E7V[We{ڮz{ǯq|jF\Ř[A@l0g2w'jVD"tATIWmdIENDB`keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey2.png0000664000000000000000000002016214600607066025307 0ustar PNG  IHDRF[>sRGBgAMA a pHYs+ IDATx^aL#i")QN2Dww^/ AL7+3k>@-QP r/ǫ(pH{CDv9 A>C h2+RO1n6m\~Ϩ]e7wʃs'|/944Y EpE~l155݋7LM=!؆EpQ?\AAٱϴW-cl [D@@$l [D@@$l [DBC&Jy8m@l3kH}G-e8iMY3Yb٩?;ֻXރs˽ lt.sC>_|ކ_ݵ}@(S2sհh8ңI;[JLJ ?p+=NċZ1Fg2}gd]숵 ?m=h:"u޴Ϻ;11^{k\ߜ=izŠS)4x-*od(ɱ:]{wޅ[̉=-~虝lrD\Kx!3^lii]P{ru)W4AMͭl[+^Fv+UҚ[ڔە:Y^>>w6 + ϥ5PCjwK[Am%;9Ť\*߄zEդzlWsCAPIuX{2,M|ѭUo>'ܪf&VvJ,i?\|W0X ǵ}BؖԌr>>2ϥAoy[?c\+qPSmqsֳL+=TvwOމQ_B\އ:t[=_Mb{KÒW5X~/ Ϭut8g U ̿{SJϗ'QPώKXjmJjqylqsylZ8)}o١hjR~ hAٰpE]_b[WoNr>HM]^4CL_YmOܗ'-ߨ/~">+$Fθ\_ӒpK9tRJ=y$a%\#iZ͟zv2wGx ^^I=Εu; ԞcwG}}jo^K۱C 0TutC3&vV؍̸6o_@Uad(Bɿ;v{S\OMɡ߸n_}}{yx7LM=?φ\444Y EpEmookgg>23 )eK/<ݕeZl[ԏs{ŭg! -"` H  -"` H  b/H~|`z6ߛ໪?.C˲v,^v>ߙv}}>{ghb"EB7*L;7noo۹蚚]0MwIu"Ep` Ύ]MQ?\.+? ϕ[H  -"` H  -"` H  /ض (PuV>v\1s3]|vorpM2W@%u*6ё&w'uվ:bfWl5N) +7)=o_@ -&ngZEJ⦺R+Dia?- [zNIׇZJ\lFmgTnF}0au8ݟjI8jWk[K?--`}'6A>7SPoܮi'# ҰSSlU#Ϛ~wO]keckbKu-=2I SGLȭδv%Nɮ@G#|f74DhcAǜ`o:Ό<}7&4 p/JVJE¦#6T.~]߳Mi&[n/'?36Ai΄J<9?wsJrSЄIIٰJ^]$J7gwΜС)w+5Ծܮ[tc~#Z?Y.ol͛/-Z)O-%N ΛN9,ji1I4A9[{-9J*p[l zilqɫQ"x]j|Mqn䰆wy|VY" 4~p?DA {/Aci_Jr?}heք\ۊ_'զd^ז)^e Z*7BimRdZu 3wO݄tE+usYM+c?amg cOqjOш`K }gPsX1Ъk .4 j[fJ37oZ\'N5-Vf{ ׵d[{g^b?#zi\l,/3=0:+cnOtǼbv5J..Sv ͺ/~Զ"A~hBwʹ;pjşҡ\NP7eCk-^RnTX't߆ //,Mf0.svǂo3>GYl@=8[)m1w(13Eb7*K hj+ 1k6Uz؆2+߷wW׏_yemg_ٿ]W{&sԩ5\'?/3N q` Є*`oɃ?O4:5E d Ut] [\6KM~#ۿ?:\-@f+S3ϞORSE\[+VMwU-AY.\h &6[%yy pcGC;m7{ %nQ?\.EwXsVL Y-9/%eڵkja[Iw"j Jִآ{ghb"EW!~]}oщ U[qTq肋LwIu"ErJ6;o,>}-Wnl`űcEp5{Z#?D?~G P)rWZrpL-kB-*kt%TP[F[-@רpK5"lj@p[o[s֢~jK*[m gճՖ` PZkZm @|VY+~b1o՚]stqZT9NF֞_N[;ZB mie2;5fp kz2ё&mYh_YR W!r`Wim#4<ؚP;v{S㩔Rf;$[uꦝjӭE%,jnvj=S:ůeg[ImVڷK?\W*hTKJۦ㘵QӅl'C\tw k.vx5/ ëf7bX 5}y9ؚdDG 1ߞDnOm`mlmxaSϋmM(; z^tŒ;Zэ0]fZc0kO4XiZ;UM>v%z5Mkϫѹ =Km~)Χf]~xgZ6WS3:cq߿_hquXWʶW./_*$+6Aw_󙒖`ؖXGv3nvoǶy!k"!ycpq ןξv]ou#ƗoጢoHjѶvUqHrp_ Z_?y}VJ@\ǔ4?'hj*=0+{ulͥoZ99=ߴXmp>]P `A@/͟mwt;/yE@/BVk3+x*sw~K9G[u\w|L.j51!9hBo)޶kg[DÇ"ϧ5SXpu}i.R:'?7_>K;7qL>󲬝+ ׮]PJA}ZXg[b\Ũ?D.e_XXsɃ?N|hލ~&l휻C\d[Q?\.WT7yN?IG ޅvgh,// }+>Cvl!pQ?\ ؾN*p*Ј _J-wE3*ngfv^gFk`o4w^Pl,6@-(Uf -@PXKЬe~v-` J2S.Sc!+ afulPiUg) Jk` H ^?Ͽ8 mۀٳ d).Y_M;Ywb_ըoJٕc9ȼ»^oA3R603@4)VF%ZW^" feܗ]9fQ.~앳Q*=}pgK5ёӄP[&k}PS+g;#+N^,xVЦd^yϧN͟{wGՊ{lFK[ iBj}6~7>f= mIcʺԗS⾈dlM&E=2b ϵ3VF<=HS6c_ +4S ?-עmDRic 417Skj)Χ3|T0oO>*\Ft׵Mi5+WSu]xOӚ X{ɑvZ,]- JA鳃¦/uP˃7} 7G+#.*o~WA=PLTg_NN߭#zfҔGw5xyWSuڳI8wF}Z+]Cg]'Ҫ7Ggh8 #-nD@mWJ遒SH>m?s Qu jT~KKseRW6iQOnZ΍d)gZ:13=^1;58YoW4__Rޱ&p3f6\Ƌ4w~P7C~<)- ÿp"tkboPsw 'Jsg[n$'F m-qE~HW-;<<(mEp"=/ڹ`{5h~g[b˹wީ[VZߗY?y7#@ }[SSl555JSx5Ze}_v\` ӕ^m9_#O5FϧbٱKP𣾾/~.Bl9~UFjJwE@$l [D@@$l [D@@$l lNζ$E_ȟQCm@ZLNi \]aWxY&v[nojBa$Q6.-͜n>sop[.ǯ¿xBY:(uӶcE?%wl+a_*;_ub91v W:•18Uq7Xo\94_#g5vCHɒ+2}!^;G{ W3w㬌]ӸV*v<8~]9+аi@d3]ח e7uxfVEce17 όn9Keck{{[;;;v ]y.Nˮl8~<>/` H  -"` H  -"` H  bG>seKUeE|M{'fgg뾿-|)|Nk׮GZ7V[Ѳ@eߖu>OU c H  L.D*\<&J [[IENDB`keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/chwertyftkey3.png0000664000000000000000000002020314600607066025304 0ustar PNG  IHDRsRGBgAMA a pHYs+ IDATx^ah#i~zqtDg8ѻ;Y/&s/x>MӐqgB^L { >;>vcg;YcǴ)̎ɻݝi_=Zmҿ 5*Uw?~TN$7k4\܁-}3h%6I.Ճ1\P;-s K˟ۗl-t1FdCWvmȣ -WㄬΛj<ݑAqA2ʾd[E~˘;Kk$[ɭ-ہ$N%~KЮrqh* 2+˪ՌٮLuCAŐ}6>uo>uFgVN[pa\ڭnal{&&D2II:[v}mu9vVW0,pN+pVd r"+c]ZטIqIP#>'nd.{_aPh L݉҅QL\T 8s]cj틻"fz[OLMRE3mp &%5| ۶`KeuvJbw@3YLR\p(K-n:[kdvw&feNaWxv.1/-zLޖMLO25%p)^zL5l}*PLZPN,M1YZc+~Va汵e]OegŝQ)oW;Mo?Lz]rOvϮ5ϴJIZvxazEYq*]1j)ilWc6FҴ:vw2OGUv̸Z3!sY[}^Wx({ߍ{Wkok/?,2S;me7i_ٵHȲa̾}Gyn+ g|q)_"1Tc$S'_?F<rB#lPބvA-k|F"(pCc `lZXeլ (sAhq$|kڹF[*'kZo\A3BAP2ܚإ?+hV5TchߟQ5@jZlj'j'r|||bAN%]>{]أv. ?@?X?X?X?Xa(xVߴsQ9c]>|(wܱkc_,k*k8-huM;~CCCVHǀ]t@c b؁a\`knӵ.N4Ӭ60?/ϝl^&Q`Q`Q`Q`Q`\vmj?T3OP0QXdS+#ʠz֤ @@(l [@@(l [BێaI.@Frv49F"1]G.3P(3),~KhpTZ԰ .6&%>zDN{ =:r}}®58R*)ɤ3MI>&SfޙRKv|zd9!v+С=I_+nǮ5˻Ŗޔh5- ^GaG>%1Y0!^ǭItII)S"W.+PY5cVGc&Zv+m[sK6}m>/Vs!}Y;8q- +Y5ebQnt%ob9Y[t~N,OwDF`#w`sbc3UwEWgZ$f$+) ydwܚ,ʜ|7q]2bsYSue({i=&cJ/0жy'i[eoK̮r7RadbKx$3L~u7;73EfNv/0M%&Hm1֕?zn+U\ݩCKK5xv_W0{ae9#zln̻-SΛ31'go죌-dPSZh+Ι b P%<3?;ޖ[Qw͋zޒ]rjeM}M Ndln̘t7 ơs1wE5^k,t.0+j[s238 K{f(B-QLU7$ ^6c{7=8zc"^W "k:8d{5&;4Igiy2友Lꦰ:rwߑ{gDk,&9iʿ8" ּ`TE@-}ƻ].WO%ivs[&9Q^b=å 49Ȼ"k%)8\{Q oqǰRNNUkzߟQfct!I]wHN20݀^dŮq+c@ei1C-%[kߑT|ANv~6Q{\ n+1$[vRJr۷inxCmy|⭴׌=/X`Q9ҟW=J~)Y7JWB6ӺLuHb2'Ɖalݾs)Y99pʿlBbϯd{֬7G ;Zwеӿ\щL3R*Mq_f}_[N̼y]Beٟoֺy{mU.z"Yo`#nK:e,}-ؖHOf*5ntK|϶9!k:_ܚ,:CNX 7;}ފ3\QE47L[RuHrp[dMSk9\>#0 Zm-' Y6e7;{v%>'sY}hr|&hޘ<3?;ޖ[Qw :>)qZ3ܩ59OnIލ?JOZeN7%(k鎲1UֿXؘh@-C*]'fNWhi{ ޠgG<¡s@67Dw$,y[}f3uI쮲fzLƺp?KPip}>zddKMLJ=YH?񉝗Mݕ=! UwohttT(@(/udG2ؠ1>kp|dYnvwgƛsJx-܇xhO e~5glXݙ;ۛS˅z8 3֜QZl [@@(l [@@(l 0onnʝ;wwo1]۔??X?X?X?X7o޴Kl&9Y.Uk׮9lMmX WxZE" ,,,,S%:j]׃C42-^׋F?X?X?X?Xa) aCa3ޞ]jY/ܟZDEEE Pyyly*BkG-B` P  -B` P  u8>+}`1,԰tt $N;SRzV5'%j220]峅0۞;%kTٶX=n^II&Ӳu7#(o~O?v8 D$R&5ȭ-K]n{m򂭩b+L󒍾qzl%ZC3DG}Awޓ/$[\XLIqv.ɵZW;s۲rluy7UqQ*DDry=5S\#0ݘ:ӤB> OvȫȀd4ejx,;!fbr\[6ll˶RѨeUD쭊1Y|~M+Vr2ek-MyoD[Z eB2 Zq0>mj%+ݳ=y*w&lN.2m*ֿ3dl\YҺO EY#"6 ]6_g[R2u/:oc֛@FrY_+ܾd#@uH<+CYWU^G&Mi=]?eK w-pafdBu#W:ER\ț2?uGee,.P q-'͗,Fiu =II .B8 ܛͯD>Ddҵ8"ZSmM.͝+LsOsn$K%Α8?U Of76ʭɢxp]+4-x/x{ߑuc:3"+c8SC^>ŮBbNsgYv;"'.Ĺ#? <櫊6_DOlnn5:{s_?_{5|/gk~ ߽fW__fttߘȣA9i5_yQ^>|<v^s]Ӡ1yȿg&Rޝ@~Q$4%?~ ~. _t(ԙXsKmP@@(l [@@(l ml7{b PyssSܹct3l|FwmS`P`Q`Q`Q`?|04y(Ls]׮]sevvV~_ӗ_~N_}UOɜԽr~HD^}UyWʦ?n`kZlQ=vz,W^s ;}6TT?/]z M.]o`v0m-/`zӕ~Jj#O5Gj۳kp/ㇽ뭟lq.B{Zy آ#O5G"@ &SŲQe3](u6r~>R~_969xl[8NSfɮqݛ\)QggjW_}B*4jpC?MeX-"+r嬿 P7-ԡ2z&* @ &VVY_6f-` u*fPu@slUbc/` 5!{"οnT%"@ &f^B!BQ_O}clpQN:}X?TJ}y :q/v K*5,v-Q@ݼ ΏҲ0- 3@8ߣێᔤi;dߚ u^K0+nl%b Wy/b \ 篋#g51ؚʾwk[IIij[X-lVu m.'jr+-ϫYn΋E l{~̒5r$%d WIgk˽bpޜ}-i^DDr[Wm%PʫJ](X;2AN~Zv< "gyl;ސh~[kۯGwʩ0 cj-*;h4*Gڼdco9[RfMUIzblwsX;[)u B |y%YEMc[Uśqx[7JWgמQ>*oxVC;BgۭCqA {ZlP Kf99g/\ cq{n{QVP b ^+7U\o19p8rVQZl5aI* ̹F{ ;qq֦.4%kUsW;W 񶕁֯xc W=Y E8\J|D6ӽԼ%mU2Yce17wsJwΙu /B/z "ţޞ]X]]}qҮ9vz,W^s;-x;ADUvn+kϝWbfFYnc_1DqԄ @5pJj#O5G'@NEv|}h̲ :۸/` u­? K4.Ae5̛aEKR`2` / iZtzl[?U[*4[9yv8-\(` S*C& (@l-/3/r||\}|;w.n~rU{% ~6TT?eڵkvn}ZW8OYb-B` P  D?(ʯ'4IENDB`keyman/common/test/keyboards/obolo_chwerty_6347/source/welcome/welcome.htm0000664000000000000000000000772514600607066024146 0ustar 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.

Key Combination

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

Keyboard Layout (default)

Keyboard Layout (shift)

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.

Keyboard Layout Mobile (default)

Keyboard Layout Mobile (shift)

Keyboard Layout Mobile (alt)

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:

ANSI Keyboard

ISO/JIS Keyboard

Backward-L Keyboard

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! keyman/common/test/keyboards/obolo_chwerty_6351/0000775000000000000000000000000014600607066017026 5ustar keyman/common/test/keyboards/obolo_chwerty_6351/HISTORY.md0000664000000000000000000000257114600607066020516 0ustar 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 keyman/common/test/keyboards/obolo_chwerty_6351/LICENSE.md0000664000000000000000000000207214600607066020433 0ustar 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. keyman/common/test/keyboards/obolo_chwerty_6351/README.md0000664000000000000000000000202414600607066020303 0ustar 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 keyman/common/test/keyboards/obolo_chwerty_6351/obolo_chwerty_6351.kpj0000664000000000000000000001512414600607066023074 0ustar $PROJECTPATH\build True True True keyboard id_e2041c991cdc20c570b342a5803447b0 obolo_chwerty_6351.kmn source\obolo_chwerty_6351.kmn 1.2.1 .kmn

Obolo Chwerty #6351 © 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_c2590fd2792d98557e2c2005ee77c7ad 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_425d4d61d84287d1991f48eb0158c78c obolo_chwerty_6351.ico source\obolo_chwerty_6351.ico .ico id_e2041c991cdc20c570b342a5803447b0 id_22ef002cab6c6662df596ae9b904a55b obolo_chwerty_6351.kvk source\..\build\obolo_chwerty_6351.kvk .kvk id_c2590fd2792d98557e2c2005ee77c7ad id_0579d0765b08c34563efd3d9ed90acd5 obolo_chwerty_6351.kmx source\..\build\obolo_chwerty_6351.kmx .kmx id_c2590fd2792d98557e2c2005ee77c7ad id_c87a8ab6b4f8526da91e8322bcc9fa38 obolo_chwerty_6351.js source\..\build\obolo_chwerty_6351.js .js id_c2590fd2792d98557e2c2005ee77c7ad id_f6212220adf6c5eb0ae25c33cb973c64 chwerty_default.png source\welcome\chwerty_default.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_cd62e578000692c9966c069950904d06 chwerty_keycombi.png source\welcome\chwerty_keycombi.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_2d29737f21e65a75ca98a9c3ab1f4a6f chwerty_mobi_alt.png source\welcome\chwerty_mobi_alt.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_2d856489cc6083c4b74a1b8c2b528785 chwerty_mobi_default.png source\welcome\chwerty_mobi_default.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_ee5bdb44f34cd08e1c6012f91790c302 chwerty_mobi_shift.png source\welcome\chwerty_mobi_shift.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_743e9cd02f1d4004a5320b9faa355587 chwerty_shift.png source\welcome\chwerty_shift.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_a81a3f903e8ce052259e09e4a6fbabb0 chwertyftkey1.png source\welcome\chwertyftkey1.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_cb8167846a4ac07edd78e5a39a7cc587 chwertyftkey2.png source\welcome\chwertyftkey2.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_7325a11eaf4f66357aa7185056091802 chwertyftkey3.png source\welcome\chwertyftkey3.png .png id_c2590fd2792d98557e2c2005ee77c7ad id_724e5b4c63f10bc0abf7077f7c3172fc welcome.htm source\welcome\welcome.htm .htm id_c2590fd2792d98557e2c2005ee77c7ad id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_c2590fd2792d98557e2c2005ee77c7ad keyman/common/test/keyboards/obolo_chwerty_6351/source/0000775000000000000000000000000014600607066020326 5ustar keyman/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.css0000664000000000000000000000071714600607066024402 0ustar /* 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;} keyman/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.ico0000664000000000000000000000217614600607066024365 0ustar  h(  333fff333333ffffffffffffffffff333333keyman/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.keyman-touch-layout0000664000000000000000000014270714600607066027537 0ustar { "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": "" } }keyman/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kmn0000664000000000000000000001605514600607066024401 0ustar 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(&newLayer = "") if(&layer = 'numeric') any(digit) > context if(&layer = 'caps') > context if(&newLayer = "") > 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) keyman/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kps0000664000000000000000000000712014600607066024402 0ustar 15.0.211.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 #6351 obolo_chwerty_6351 1.2.1 Obolo (Andoni) keyman/common/test/keyboards/obolo_chwerty_6351/source/obolo_chwerty_6351.kvks0000664000000000000000000000655014600607066024571 0ustar
10.0 obolo_chwerty_6351
` 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 v b n m , . / ' ¬ ! @ # $ % & * ( ) _ + CH W E R T Y U I O P { } " A S D F G SH J K L : Z V B N M < > ?
keyman/common/test/keyboards/obolo_chwerty_6351/source/readme.htm0000664000000000000000000000155714600607066022305 0ustar 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:

  • Files renamed
  • NCAPS mismatches have been resolved
  • Font and PHP help have been removed (reduce distribution size)
keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/0000775000000000000000000000000014600607066021761 5ustar keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_default.png0000664000000000000000000005142114600607066025663 0ustar PNG  IHDRH9UsRGBgAMA a pHYsodRIDATx^݊lu[obúO`Xue~۠zB1 $tDJdْm|;Gdh9fDf][>G!B!B0!Cn!B!2B!B!Cn!B!2B!Ba/xӟ=|w=-fO{#go/xgv~}վkt~>>HL?o?O`O3܎/rہ@D&{3"oH韾H R4`1l/@,avmpTofOk_#:ӿ? Vq,i)Cn{:+:[꽙%oH韲m>ICU%Osgܶpޛ)le׾FOsUIr*[?]=2+[YI2V|kO9W)窲3C. VnVnVBg8PY2*qV eUhzm|kqr[[;PY2*qV eU(BgvC?}[̐{=2+TwBuw+TwBuw+TwV eU(Bg8PY2*4Lk`7~ܭfȽr[[;PY2*qV eU(Bg.ri!X[[ eU(Bg8PY2*qVajj=OW|rs<~ OS>÷ϮO[~c߾wާ=2+TwBuw+TwBuw+TwV eU(Bg8PY2*4L톼:ޮ݇~vȴW{tpqw}iӀzlz_w{GbVnVn*qV eU(Bg8PY Y zgIgxXyR{Ͼ§.v: O|=#CnBuw+TwBuw+TwBug8PY2*qV eU(BPs4 |}gCnj};{=2+TwBuw+TwBuw+TwV eU(Bg8PY2*4L]=}"gtϾgɐ8> 'm,{ϲg3~!X[[ eU(Bg8PY2*qVal(aW| OXN1P,ׂ>|:fέP}Dћ}1BuXޛ eFKK*ډkyQRWʌ- eU(BT~=^74Upwno{B\NB M!ۃrr\'B1dW(3k eU(BTxxѻin{6lkȽ߰-*Tιus卞kr!wYS*޹C2upȭ^φ } eF~c{?ۇ7m.U(BgroB1z%w#CVC^c㺧T_훇7WެP}D3oTʬ2- |OA׮]~n( 8^i*qV SqL{d-V>r.5+T_W70ʢޛև sz/ ZpSho3z/v=a~=PY2*4L1!X*\xQ'+T_O52.WxT 0KT(:ON*m)w3 [%U(BTr ō?-7xN,d2.Wp>Z*Y_%׷LjB\8.)ew_R2*4L1!X*̐{r+CY,Y6+TE̶\r5@hꀏcAUYSܦB=M=ˠ߹+˥C;ʌo/BgȐ[P}f=Z.> &CB}BǷN{SܦBQ<ڽmPf,ː;۟됷t*y.סBTr O֧ 9 GwkCno;mY/8ʌeYNnPj)nS̸P\xS(3z?3fP}!7=2+T_rۡBuy6P}$O7vCns1Pf,.r;3(Yu/; ezzI~}!zz\!&0ǴGb0C"皿ZfЫP}$o}Uwn[*]TOXްȝ9ʬ²o5(3e^u/r2^!VȐ[P}n|ȽumVJ9 G2CB;A2ct2l'ʌ~lE̸pt>u/}wKC*qVa*i Wᆇܳgg҅CNBySfv]OkB)nSX.}cPfI_V(BgȐ[P}nt}۬P}^P}mf}tW(3s~Z8P(3?m*˥]x+=#DŽB\t*yߞ񮲿Vhc#CnBU!^}QP}mv%f]|Tp.ZnxT(3Kt[ esSr^=~Iʼo3FGbpcCK Go{ צx˟v)&{T(3}w1Pf<{/`,{PY2*4L1!X*АnB< q{۬P}mna=ߋl_J6el\k΋ܹ` eƳ~Le c= ecubjPY2*4L1!XWlg\9 G귯\Хh֛KfksKC׾Ѡ̰Co*?m*StvQ(3ĄvW}qV SqL{d-V>rk6vjk~_ux2<, evb?wq5(3bPY2*4L1!X[[ eU(Bg8PY2*qVa*i ݭP ݭP ՝U(Bg8PY2*qV SqL{d-VnVnVBg8PY2*qV eUhc#CnBuw+TwBuw+TwBug8PY2*qV eU(BTr[[;PY2*qV eU(BgȐO 82nA9WW(jO \iϿ&C^=)lO8\M_?+s*糇ܶp?wĖzo_I۽5?+ቆ8_4C/ G[-L鿒{kOYGW*%;evmlO}?{kOdOSmc_~Or嗻ۉz${o\u0^m+_ srhA&[Ku7zo57O?>* _um}X<B!B!7B! rC!B!pgr>o_yA4g;_ʖw齙fH7m?wCn Vn_Wzվr7OFO?휟mXگg{`v" dM?}SofOD?}cx!=Z,5:1M_r[꽙%oH韲rX.^˳Cn( f大tR8JhOYG-L鿒{kOYG|@/]4wvgq~:)\UެOg+[5J>{=2=SUeof%8[򵯑?\U2^o!X۲ *qV eP ݭP ݭPY2*qV qqW !uP|1,oKNg8PY2VnVnVBg8PY8oW}.S|GUdpV eU(lVnVn*qV eUhxݷ+7 TdpV eU(lVnVn*qV eUhx!i>?dBg8P ݭP ݭP ՝U(Bg8rC. Kܧ?B+WdpV eU(lVnVn*qV eUhx!?|{{7۾vᩦB' eU(Bg+TwBuw+TwBuw+TwV eU(BC\Nj~&~2䶷3 ;:U(Bg8[[[ eU(Bg=nr˩Bg8P ݭP ݭP ՝U(Bg8!w:U(Bg8[[[ eU(Bg=2B' eU(Bg+TwBuw+TwBuw+TwV eU(BC\GTdpV eU(lVnVn*qV eUhȐ; *qV eP ݭP ݭPY2*qV qqrPY2*qV[[;PY2*qV!.#C*t28PY2*qBuw+TwBuw+TwBug8PY2*4y{d@Ng8PY2VnVnVBg8PY-|=|#{d@NGoۏ~ eU(Bg+TwBuw+TwBuw+TwV eoC{|[9{S!yy=2B'pf}18P ݭP ݭP}~qoqfo*qV:̐{mM8w|cΫ=2B'pf}18P i[W+TwBuw+T_rPY2tf=Pf ~_]ڌ=2B'pf}18P c[P WiE*qV:̐{fN?=~FwtȐ; Ù!T(Bg+T_roBuw+TwBug8Pff=3C!w:3CPY2V3bVn*qV:̐{fܻ#C*t2Vo͒!'A2o|f_+޲N13BUHB.o>G+To=|aO!|ߓgq~3gV0s~w'+T_[*Nطu2䞛!nȐ; X=jBBfoR_xe}bG̸.phʬB/dE+TrO. Շ3Cn_ gݷc7(3䞙!nȐ; MK/·; Oʂgv~{6P .v eF7E~2m܃w-שq[pfkZᢿк>y_:̐{fܻ#C*t24@}![8]Yofq q9v?lqKCn}2˷EÙ!q^\xTp};[Y̼I:̐{fܻ#C*t2+Gˍn§P}:DM=靶ݍῸ`APf!wnm ׷ ՇsIorM_VXS(3 `O*Yr<^#3侶=2B'ztɅ~@{pvЗ]ʌ›ڂc@*\xǍ u!//j ^4P}839\ es᾵]ʬ wGTdxUoY/?W.vȔڱk/tʲo:u (YGV6NPpf5׸ljB\ \G3䞙!nȐ; -%߳*y^5[yRspiB,vSǀBUxyhq{C. gܾ_s;'Y2ùtdPffȽ=2B'ëz͍Ysʼou`=bpagtRprLPf޸M*T_r᳇/uP}83uk됷tdPffȽ=2B'ztɅ~@{Ka[cBm!ʬk G/*T }m_~~&u2Pf^k*Yrf ^>\qɅ~@\۪EPf޸~EнҭkB}U͐{fܻ#C*t28PY2*qBuw+T_׾UP ݭPY2T20Crf Bg8P ݭP}|ͅ۸ ݭP ՝U(3r gfȽ=2B' eU(Bg+TwB=.hS+TwBuw+TwVpf3䞙!nȐ; *qV eP ?8uBuw+TwBug g\AOezo*4y{d@Ng8PY2VnC[K ݭP ՝U(3r ThȐ; *qV eP ݭP ݭPY2*qV qqr߳ot2ɧ?w}r_?W(s58'~M!=!7:r)lO8\M_A.N! `4ŗW>~:)}]H韲j[꽙%oH韲rX.^r ٶҾF'?+[K7^?SQk; +!@{>?چ* pqڶm Sl{~;1tҬCOKrn7O?oz?ߏ%6X!7B!B !B!lȐB!B>fLip,C}>#]zo-7Z6ʺy /XND|?vl)_Kڿ{6jW@1m'B@'ۅ|{LBk_#v*Cn{,L?<j 'bBg8PY2*qBuw+TwBuw+TwBugZgǕCSރO}fg?~vso/gN8fNCOq|.*qV eU(Bg+TwBuw+TwBuw+TwVqo6h6zbvx"g'saٚqݐ<S_h}/w~(>;9P'o OXO8PY2*qV eP ݭP ݭPYs8g7'ߺU Csw +'uX[οu]G|vS eU(Bg8P ݭP ݭP ՝Uh}|4Tfѐ6=ė+ EC  <@<~}ī4=އ ] U(Bg8PY2VnVnVBޠIhF}0TO9 ɽ聆;be;P_s}]~<M2*qV eU(lVnVn*> _r&r4{hϾywѧu߃ ] U(Bg8PY2VnVnVB޼BaYgnhώ/o[i;tVwnS eU(Bg8P ݭP ݭP ՝Uh}!w*t1pV eU(Bg8[[[ =2\.*qV eU(Bg+TwBuw+TwBuw+TwVq{r˩Y2*qV eU(lVnVn*>Ȑr8PY2*qV eP ݭP ݭPYrWBg8PY2*qV[[;8#CUbBg8PY2*qBuw+TwBuw+TwBugZG{d] ] U(Bg8PY2VnVnVBo +W eU(J?>xW eV7?zx$8Pf8˾}1ԯBuw+T:*T_Wl ݭP}~7{ޛBo +W eU(J7<֛| eU(3rg1?7+T f]lxϐȐr8PY2tCnY}棇oPPY2Ù!w ˭P}f]lꫴ s_qGܕY2*YrOOq?|:U2* f]n4Cb+T_ Bo +W eU(J7: 68Pf83侘ki3.BUzi}!w*t1pV eV&o=|.C2 gBa͐;mVN?~xrcrWBQ=- "|: en~cC칰C>2CK7OET_mu~7+T wv,߬P}nt=Buz_ZG{d] ] &נؖwN_ʌ钾rtrp]ĿI! Gv*T_r3CطGܕ`H72~RY<](3u^ cm OaEN2#:Ϟb>/^k Wqmpȭ~5BU:m dTh}!w*t1X ot e4ͽ-o͆2Lۅ ]2q#Cnj A]?WVz\q r8#CUbN-ʌT(3'_s PThz%BJ79䞎nBU!+TwVqGܕ`|?Ӷ!wɂT(3 PTXc~% Wf4Cb+TwVqGܕ`Xӊ9}\yRws?Pf(&C!p_}/Y/\WJ76V^VJ ݭPYrWB\N=S(3S'͆ PTP%`vP}nxEBUhVBo +WxַMԷ3䞜z۶2r^ GWKT*ؐgr^#P ՝Uh}!w*t1NSfC6P(3k\na9dp_*ؐ{ؿg*͐ ՝Uh}!w*t1E7 KB\8eȅ erk ntmo. PYrWB,71rv[/N eFbz$T(0օ._ː nxȭ/X?cY{BugZG{d] ] Ƴ,/n;cFYo~!EƐ[[% W馇ܵY*]x7+T_u/\v*>Ȑr ٍ|q!wΥe WFz_PYrWBg8PY2*YAg5qBU!P cyo ՝Uh}!w*t1pV eU(B5z|Y)qB5z ݭP Wuj*>Ȑr8PY2*qVxߖ=U eP}uַ}/xU[Z<~w:X =2\.*qV eU(3Y|yBg+Tߩca+TwBuw+T_s`5Z =2\.*qV eU(3SygqB!7I\lV]VBo +W eU(Bg8P ݭP ݭP ՝Uh}!w/eNO>پs5r)lO84)rWl \M_82nAk1տzN. OOYGlfOk_#HrE)ޛ?Wv}5Z'G_8PfF^__{-^?}?[轙?{kd^َs3P;/w?~l'r/SZv!Oڿ{6jW@{=nn?J@|^x@˶. C.kRjn7O-KJqwqX<B!B!7B! rC!B!ذx?{6__õ|.>q#ڿK6FOgn/-3Xwo~Tlm9\lůڿ{6뽑nktktٺ.tp]ȧr[轙?{kOd?sC|m`!={lAG+[K7^?Sx/uyvͫ1ν>@G-ޛ?Wv})h?sCKCS. *[k7+?Sʖ})窲ik#C3"ޛ)le׾FOsUzNCwbmN93SY2VnVnVBg8PY2*N!=nrp`5Rﯙ}et1pV[[;PY2*qV 37ײǕC@?yځV棷so eP ݭP ݭPY2*qV eU.ə!~w5z,CU(lVnVn*qV eU(rN_W>ӇDlwޚ Ӂu搛R䑜.*qBuw+TwBuw+TwBug8PY2*qV\'gng?{:Spw >kWq}Ȕ8OrׯBg+TwBuw+TwBuw+TwV eU(BgZ'gneԣZ:kNt1pV[[;PY2*qV wfn`ۆ܃ǃtn`.*qBuw+TwBuw+TwBug8PY2*qVu yCns>Tu 8P ݭP ݭP ՝U(Bg8PYn|n/g t 8P ݭP ݭP ՝U(Bg8PYfȍ/d\߶jzہ|mD eP ݭP ݭPY2*qV eU.ə+'k~tzz1SY2VnVnVBg8PY2*N_Ɲ.*qBuw+TwBuw+TwBug8PY2*qVure t 8P ݭP ݭP ՝U(Bg8PY1=2>)bBg+TwBuw+TwBuw+TwV eU(BgZ'ZȐL eP ݭP ݭPY2*qV eUhk#C3.*qBuw+TwBuw+TwBug8PY2*qVure t 8P ݭP ݭP ՝U(Bg8PY1=2>)bBg+TwBuw+TwBuw+TwV eU(BgZ'ZȐL eP ݭP ݭPY2*qV eUhk#C3.*qBuw+TwBuw+To~>xP ՝U(Bg8Pf~uGºB_rt1pV[~v?OVnÙ!T(Bg8PfoM_O_rt1pV[f})+T /Bg8PY2o>zUhk#C3.*qBuw+TwBuw+T /Bg8PY2kVB_rt1pV[[pf}18PY2*Y*7Z'ZȐL eP ݭP Շ3CPY2*qV*=Uq1=2>)bBq]qC[Kz%+TNro:, dzo?o|=ެP}8a<8ZpP^sEG8PfB_rt1pV̸nuȅ߅/>uVeN#zjaBO}`ǿBv]WU(By:'<Z'ZȐL eiY/ Tō>՘`YOboA`j!s<mP_nСpP^wBS{}1cuPY2*Y"B_rt1pV==ZE^?ͪP}8"x i9; x_Чp.=nV>/x+|ߪ eU(6~Thk#C3.*YeȻ-;T˲^ed'!E}->u_] 8PY2t c|-{d}SY2rSfc|xiՇs" ԬP}XKE~B\osBwk*qV̪<*7Z'ZȐL e'8+Tʅ7<͠p.Wl ui{ѥ6w) ~ /Bgʬ {woThk#C3.*Y ߦWP}(. EfCisB\o3vBwϐ2*qVz<{A1=2>)bBUX6K`P}(.vfh;U>~7|'CsF e=C˨PY2p/UZ'ZȐL eƷus`c"Y*7+T΅toOy[g}8Pf5^[VB_rt1pVB\W/oV>gO,{rB\osv[g}8Pf-ΉoUn*N!NAg mY\s?Xh.菃OT>/oV>HB\oo_W(swrj+Ycy7Bux[ c|-{d}SY2͔ggSKIfkѼ|gٷs{[gȝ5ooPfmnr=\\)N!NAg k]vZW>.?Շ.*T<{=q3O2Onq=0Thk#C3.*{' v Շ hP}8iקͭ<~P.3N{:/v)Yr; Z'ZȐL eP ݭP ݭPY2*Y׽إPY2{|AUB_rt1pV[[;PY2r eU(3'WU:9ײGg:] U(lk>٬P ݭP ՝U(BUyAgʌoUn*N!NAg8[̐{[;PY2kpXt2*gU:9ײGg:] U(lk0CVnVBgʬS2*qVure t 8P ݭP ݭP ՝U(Bg8PY1=2>)b'l ʹS+qvk ʹӿB9WZ'ZȐL ПOgP-7(jO \ikcv;ɿoKOG}'zo_I۽5 ^`fܟ>mL/WeofOk_#:/ v`vmUv+[xEwdok_#'tkdkt_7FVm'p.=~嗻 ] l[߽fOH?o 5]:5CXxm۰K+- Фƚl=Trn7O?!`B!Bat2B!B!Cn!B!LnbZ[>r-c}Vs?1ӗ}fyf ̬GAerzȭ;~M֡mrx\|]1ZU^xX4XsyF} 2'ݱ01=C.4&Gw6c'kFWB1ƸV/, zZ5Ƞk0o>zgrw޹:MvX"gOWB cq*t/ܭ [/7dIk[ V}qо c=rp!";Vut{A節ұAVThc1U/y2xʂ|rqwƀ 7'ǚz8k:Mm*@1תBk=9x>pn0o5t!:Mm*@1תBklL_s7k1!wmx -b1Ƶн(ր c@~LȐ{mx -b1Ƶн0f7z{dȽ[IM1ZU^o3x=2C$ަB cq*t/ƀMr֡moSB1ƸV c@&^o wp6!c\ m1}G;uhThc1U6о#C:Mm*@1תBxa h!n&6Z ckU{a0oȐ{mx -b1Ƶн0f7z{dȽ[IM1ZU^o3x=2C$ަB cq*t/ƀMr֡moSB1ƸV c@&^o wp6!c\ m1}G;uhThc1U6о#C:Mm*@1תBxa h!n&6Z ckU{a0oȐ{mx -b1Ƶн0f7z{dȽ[IM1ZU^o3x=2C$ަB cq*t/ƀMr֡moSB1ƸV c@&^o wp6!c\ m1}G;uhThc1U6о#C:Mm*@1תBxa h!n&6Z ckU{a0oȐ{mx -b1Ƶн0f7z{dȽ[IM1ZU^o3x=2C$ަB cq*t/ƀMr֡moSB1ƸV c@&^o wp6!c\ m1}G;uhThc1U6о#C:Mm*@1תBxa h!n&6Z ckU{a0oȐ{mx -b15ɧ?Nн0f7z{dȽ[IM 1͐1}7wCrz5K B1Ƹ6D/c֣c.9gܟ>.murt,/pc1vOSxw<;6jU9ܱ1>.yf=:9owr~#qvmqtc_~[Т!cbmM5f=:&9o;h3LhKm^LmRb$c| }ޢKrL˫ﱦe3˿|ߺ|ewkS&')^zy;#grY Ϲ=_0mvO{?C kT(D߾?K/k׏x,/>|qr|/.z@ d5?ӥ1~adt.Nwo^ vz͗Q;?cl @ [RJ.Zqj.IK.]Ktmkno_!Zcuo\@%&=B۾vtI+/1k /φ4_^ ^TS?rm_^@_zLuƟv~/U@ _B9&5^Fӟ m L6[o^%y@ kU=_^/N'li ̶.@ &HrLߜoZ7O%䠋/YG@ dWς -kK:4.'uױ/1/l˗|L_8?V, R^L_u@ U W@_ۤBy?ɗY@^Cpy@  .-B W@\^!q>W@^Spy@  .-B W@֖×W@ @+p'Ppk+@mW . X\^j66`mpym\ry Y2 iYwƚx)ݐb0KhQl&ի]p`RCPsjM&Up`RCPsjM&Up`RCPsjM&Up`RCPsjM&Up`RCPsjM&Up`RCPsjM&{kO?_GEQ=W!<5(Zg\8-?֤zUoW>mh6\,אc̷kڶ*6Qsl(ZUI~|Y=W!ए__qo|L">~>,3 jyx]նU1|ѹcΫxew-?֤zU]!tJHn𗔃vB65.u!'a\^coyIk;pm\Xx]^S>vZ-?mA6ӮG9E EӍ_&ν:j:# -ξ^5Y׭9.G5g-UGˏb-$wx5eף ͓|_t;jožWڬNh><V[sLo\b$I9x"̴ޫ-%?zA`z\I4Φ{Wm\JxHqi:%ɚkL "~#Xq.Wͳk{--55*GlV3?^=}lp7~x|MK);MND_c8?lCσc̩!)גJm2ǮǙ6Nw%l?okur"jPnR7ouV>E {cuvNeSYሯ7 b_fzxs}zrñPZoPGՖT7.dopܘvғTH$ D?ʼnڝY;GiCBi핏ɆVynkYUAԅy Of{koW`Aˏb5W|`>&]ߐԅy OVWdek,+Z~[I(w|K A]b Eˏb5W|K A]b Eˏb5W|K A]b Eˏb5W|K A]b Eˏb5Wi,4,;cs+G՚TWMe> ܥyxe(Z~U,X5o;VkR]5ӍQݿ>ϟq]/cTfGu9hQl&ի|>ݘ1C|q/r+ ŏKuogX9f!ݨpZ~[I$<ۮP܍E31Ho.K68S5~X>p8!O^k*/ζ+3@϶+.~NPsԂGkیz5J~p6Z~[I$|,C(:3߅?IU} n6zq ?οtFCk[5ZWP š>4r1;8PWf˧3.3th=]>+8'b>ʝ|G՚MCBs$aa310xY)֝~A6Zshd<گeS6oN0{3_ulmmn}^]WI4+u=KE;E^Τ)gsjH<|/8ݮ1E:Wy#en<3G:\MlK{0#WIVsZ]Ӌyudoсq9wRf<-Gk~m aMڼz/V[R~2QC@Lfγjl, >NV-">a VM)'nsDVD$uEѯƿDˈ}Ko9591n ?^ǴZ)v1\$PƻZ䟯`C|Pb gVgв6y|=aDGcLp,FM'$>E9O~lNnS}Ht]%/~ӺKqQyz'̩,Yڤ "~\^̿5 {4qĮ#̜gHkވ9?]G!K!滠oKkܑSߏy$7K٘T#~cG|`}O1t8|y#|z PN`14ǮǙ9ϒ Nmӡ/OIK^w0_Y&,#gMUj*u֭틦?wL۾"f3kidCA>sjE {ٸ\{2jԴ7|d_ 5*Sa1mWƋ7_kϗS}9g~Pl&{MĦy <ka+Զ`cQ\af359.ڤ\H%;:\Z_)|srUjks?bly07v'CG̹}g>V_C{|=ӯ1>dӡX!_sU1#HcILfc}al=ClxV;asyچ&ݨUkpY`Q(ZUI.vY`]OZs{͟Ȗ?|@=K 9b.cp(Z~U,2!~0LK\c}'MH~jYR7%c}Kdynksq+7.b,/<^^gׯ9YW~-Gˏb5y 5j̜ǤƤC? yDŽèvU1xzBU׉X-~VW;.!NhQl%UCQ]_RDӻuf׃ ͓6mH? (F+ .ǖ|4Gv}q\|/!Il$u,{)&Y\s5WWw+6N1v[9ǻ'Mڻ儕>>0ww<^Vl5loX۟܎6MIOzI_{GG1s}tͅaJEFh;Gnc:[6W3ch*\m8::zb61i}us3.ijkC8?MUHجu]3s%ct'i:ɘn?9ؙ~zdkOyLHϬ{x\k&jzmbKaT:s"V7'|cURiksi]ur=Ik'nw bK_Cygd Vv\^N]盒^qTOSݚֽ؇6wm}q( :I[4%Z 61t\ɨ؏[cԾ+?c*{Yp58nwg,ޭM^ϠFˏb-O?6VX25b ̜g؆$%)A1 *pZ 16R"(K,n!6~'onǖjTG%#Qxl&>k?*{a"~PSjHXkۑrdWg5ʗB-yZ}eTޓt~ vlvE(msu~qЇݰ?^8VgݾԷYH[U}WThQl,K+l2uCݡ$"%ʐc:C RL4Jdaq zq-!6TںdY7-\Wr>eu Hqi:%I_aiYsͅkZ-7h CsX4WٜSkM:\]b_%z܆ihYǎj}RֱݷnWc*E9zڤ*.Ǵت O ~O*2s5c+$

; XV:l^$J#JjTGnG(tJ$zaR6D<ҙmzk5c ] ۡrǼ s1+Z7!]ɟnR7ouIho^BC%U?ӊekp=ųnbubߐ)νo3>H[U}WThQl%qA v83Y5$&n/9Y'҇ 2>D2{v\u`G ds\3wۡ~y4ߕS{o]vRl5l_VϛXO!zƜB:'a/ucW GyeV];GsvA7%ɯݭ=,o0Eރe{[RE"b_%o+nqq[ǖ4SGb4:Ż^@Fˏb5 *k1ˮG9Ϩc7) 9)/±| 93'%m^'y  a.hĦet\(?뉶XOc~ɫK<8\؃W_k W\pxfܓg!am6 G7?S^{Ÿܻ91';6|ޜ``_%y.VRgG:::ԜGY;EXOa=x>s}ޝC>u*? K{cClqLf+]hSzt_[#%POaGg(`k3&|Xu8>b5l Gˏb5^b;^OAi0 ^^u#ܥ+G՚TWMe> ܥyxe(Z~U,X5o;VkR]5[;>|}O3?ϧTZCx3k#.3FjMW%v w{Aҙ1~|:F5g1 BM05lE(29tҌ>lZ\Ͽt=ߧ)G.U~`s_Ka}\3+ԏcgl]bQ#Y^\"*[Q =dmٵqcFb~(Zh߉|̲Qfγjl݄n X#83 a>V Ƅ8M[hΪ!ֶn1ߌEyvxY05oeQvSΰbwvxܟmbhQl5QcQ3qmlyfm=t l/=Rh{O+Fmb'bڗrİ3ww<.3Z'mAIWn'v֛5-Y]Ri~jst J.zn4}h L:}a^mvu}y(p:>:Ni|ƢD&Ʊ+/sq)6#s@U6# St;.m+E)Lį's5}kٔ.&;a>T0\UPTVנD_ϛ|"sj6Ks6i6Go0ÆzAhjc&=Vmg բJG9Ϛ?ga,iϔEKD.vmo-#TWr{;l4K;&UP%RL/]OaNfX "~<4k^3{OFGW#vNah]J>#\1\o^1pr]!۔rjX¯O޶lC$7/*NE,JӨ?8ZԡxTjFZ &m_k12`-?:?lhiR0sUc磉ӿ sd,%xoݒ5]rQm{:s*Wno SuP<ܩ},}):h6 r1Y} YfՐ_kOѸ<8U󯵿'Gt+"|u8>E7j.XYzG^[MjMW%e>?]-4^qrĮ/6fL%W \^5^[=jM&UpZ~buXUyv٘9| .:-hQl&Uk. wV.5v͛>+G՚TWMe> ܥyxe(Z~U,X5o;VkR]5ٯj;+psjMUbA?Kf!5KXϑ3ł4~XϒYHs5Z~[T 6`mpym 8Ppk+@m˫XϒYHs3 ܥ.G՚T~>\__?ӫ?_U7N7gN}xf.jxSkHsAg]+նUw-G՚To[ŔwVC[{]pyqI 5W*10VkRm.BZz] ?Ӿ{e*kCI63&{\1՘k*x+s]j۪\uܘR:u]87ܯvc H4gV쾵ts{ř{Clq?Hnៅ? m ~1]wؕ` xX`ys֥ڂI7iaI9;ah:8doL(>*b0/Øc1k<ԶU1|[ׅsj1[ſf^[!UF==fw(Z/s5+/)UU:N˓-b\I2dW3}Bf~!Š7S~x !)<7ߊ8z)vgJ>؎'ѳ[_/jWON z3X{l0=_luo퇸#u{'H(f?ְ>'=N+r[}Զ13K\>QUXɞjd`ĜWx]ףU_?OlGG€t~$e_|C+TӨݭu;O͛|mx=VmG7&I Oa׶8F!eaLwçG6d-1yME(;c$eB [Hpq1bwpm>YǺ^;Zmhz]{IK`{U|qz^tnKO\Ҟr Ω! |]8ǮzM9qkuim 1{ۡӈПtvra771ck{w}=tsIm6}T|ީuo"11N[{qu}e7X, E|N|E[k|3FIJl&v(Z;6ȩp>ƠO`za3V,IC8,n.)^.Ea%'za96w:vإ||ꝪGSs'myU}]cJ>mtT6J$=.WV`\}X@A {B׌{̂]Ŷ)v*mU|g5Q %9{r%hMy|XZ)Q_op| b_Lhzl)v+B0wn/JYֵmx{ ;!58oq߰"" +MQ3;tu!?S|q S=6Ҏ}nG{.UT=z9hXߢ:Z!<MymzuAa#}$wݥ{}kde5b@{cy8Ž3pc~p]{؆ت S K,ktQZ]t f}_2Q WB_ 099\w؟3k'z4m>Y_NգSsG軡 vy7>5|n;?!bV9kJ-Ρh}I_3vÚ< 4.6JvWe5bQܼPxLNK>emϭ1b[G՚Ti\p@kq!.4j1 B/.-@]"ooҜn, qyɴ/9d}x]=?wQ|N9v׻X|緬6qk~7~.Wvα+#{!sgF^!0jDolmOƶoɮs̺9UWuj'vC}Jw|/y/흣hQl&V~=rP+8ˮi&+mb{X0)o,'Z=Vk>ͬ--oaQ_V" Otӳ;nel9$}==3?yDt=m`& Y<%|ﱵ{׏? cyNSoF~cOs;{6 <}βK ~~ܶDŽyg*JXc[cM,9}$):Vߞoj׈bΩɺu縳:Zzzkn6$9Ax[1<7ci~HvtC7=l!j8B>@forW*'oh#hQa5 фbΛ`ǚq]RV\p1^Aˏb5v Kkq+%pS:<WpOOsqk 뙼t]8c> f뙼+|3hQl&US_9ݮ9cqyw%]8>jưCyח1qy3\5(ZpP2DׂQfnRL!/py}U5Eˏb5^b;+p0VkR]5ٯj;+p0VkR]5ٯj;+p0VkR Y2 iYwƚx)ݐb0KhQlERp7Ppk+@mW . XK.UbA?Kf!5KXϑ3ł4~R f -?֤zU]]j<[x.Z~[Iud]]j<[x.Z~[Iud]]j<[x.Z~[Iud]]j<[x.Z~[Iud]]j<[x.Z~[Iud]]j<[x.Z~[Iudoχwz5L-}>~~7?>~C> XV?אUb Eˏb5.U~|?]Pjqc.cj#jskHӍ[zmͽW(Z?\ ~a߲,+@~<wrA^:ax-yP^\Յu@l=yWϗVkR]5ٯje}h$?7phˆGȘk{:GxDzɳ9s^ҬpݘRJuxHN=;fO7s\w7?똍ogq[A0O\Qf3ئkߣns<#gM| 1C$Cpyb.!\Xsg9zƇD]+qVpvVo89w[~W:shQl&1׷,݈zyx  v\pZCP¡$^~LQ]/-E|?>={zk}Gk4A|\l*^Ԡ(ъݞ񱭷^.ڼ~R ze6H,cZ}#tsڞ[Әe׾f=*|Ng?3bycS>.1|QҪXɞ52bzIK_u_Vcжc|ʺt}W kXHܷ3j0!F\0)vQB D׬#{ރr*󎖷g/ֱ=o:^G>*>ԺC7etCf\8ƾZMO9ɳRcZ_ʷ>~ u%6oiEˏb5k1ˮG9Ϫåmp#&9!I'ρGt&:J~m㔑u=:DZ 6jGWK/m`{gCvt|m}-yPnqHYvV  $ ߍ%kJ``Z#Ma󎠻U]lG~f5}3>9xLjXmt7w+=dOX}!j8cUppx]24_d׏ E͐nձ-snpQQa  ~h>\1?9yH7Vn@3Ayzudfs,W^l?mŁTmx#kњ[HJa]!<.*>0Fklϝ~V/ H{Uj9fxK[u|t{?Gk $]Y wr3fuab63?TΈóz[e ,# В>=˜x,J~m VKtȉލcUKKv\MUqݐĢIkCyu8YvP(!ĨI,C{9$Ϯ?9'絮Igh`U5Ҕ|t{ƅ}ʹlq<RL2w )ciFD b϶kjMcUpb@Feף̜gȡ eOusO6O*jiLwڠl@ DKrt|MOz?g_m|iw$ۨsث5CoA׌0Gג|sI > gš{}rW>zҜ|V1$wZE}O+ե\b sX^sϒ;Qw)Q;i qRc80wC- r!f$7/!~}^ }KGˏb5S,esz]eTzӣM@|ۘ/g_q6E2Y75]`G~f5}7Y L# ]w|qn:>sza6b63Bj[s /<&~ sI 7<eCpz1(u5Z~[I$|, iHuԐ.u뙼{ݭ_-?֤j_. w"̝,ÚE\^_.u7{Iˏb5Z.vYSkH \(Z~U,Xԅy \(Z~U,Xԅy \(Z~U,Xԅy \(ZXϒYHs3B__?Û_?_;F؊ nXkx?_Ԭ0>Odkծ;0؆KlǯOע(oRh)|')>?wgٶU1Em}W9ׯ_Zۮ3 5}y!|~|q]lmG"ߟ.wrA^:ߟGu,ɚ~,Y?&}pf-ͫ}>/<՗\mߜifFX m}<=Vc]jێQj؟r%V]dļpnF \\(82zY{:Gx+ߓg1K/:TR?Bvy{mDi^#QΈj:s+}/J>={zk}e6dZchΊFls9l;ǯzRG+6v{ZǶ^{hInm> 5ek}َ%RឯsUIAw \&}Ϲ.0]]DMyS6bNϾ C)LGG$xc r.-ǎiI9>>?g՟ƕ?{Zl2Z\~Bӳqh4y;'&[˟;n">;/=>Znd?Xek&(c];n}Ad;1µknIlϙǷgh{y3Y^Uh6鬒@3Şt4AAgk?gz}?ib#k Ѷ`gknD5;]_;:T .7T8)H<,E4N'mFu\ykvb<ͩ)x ^]4f_=;$Vh ;wKI{M'XlWO!5hqCkEy/%&G@7i?ca?M&G5*k[ꬺx>?Igf;/B{8IG:Gl(}4{1 ĆvbcjNG~a@]jg)~ V;xe%_~&hۛ%>nkS{Gu,ƅ/IF m} .y1lM0o8]㘴4f掰9U?%K+K_Vy|sL[P1zu Z}j?)]q-s\}C}=^N<9NFiսNG)ql53j}֑Ubrp5hފoaەb&mp,>zphg5/sF$k-I/<̗pwuaL1?)1J~m`1t'Q:l.SK׀?cǮj#WY|oت ą7Dzv/xޠa ѽX3̶a燌c)m=˜/x,J~mϘVKt5𱪏%xeZ;A^ &nvbѤ5}:T” n(1{4XAfr䏶r#6-|}}l=jW"湨1<6ߢ-#{iN4$[n;{N.9T_7J}= _"6k1lgx sl~6[߃kEtӘpyoI~1VܯoYvqؓ9:+⚓3 `?d]kl/N컫=yG5A+h!N-^5::s|pCqƗv'^l:j]i?4m qs9|-iw_(%yb*z^MX/&x+Z6Zj4gScWa)6xvì;qetOZPhGOk/^[l龈qh6mzzq kSccGD)(>5D3㡵*xHwχuVE[EGoJsFMo}o_nCs~ ZuA]Cl7#TEUm\^MA-'[V|V@ˏb+*3'yI0.s]mz+k.kGIޝOlE3]wzhQlERp7Zxb Eˏb+*am^dV \("ڶEfUb Eˏb+*am^dV \("_%ݐb0KhQlERp7Ppk+@mW . X\^j66`mpym 8Ppk+@mW+@ @ WJ `ypy<X\^,.. IENDB`keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_alt.png0000664000000000000000000006674214600607066026041 0ustar PNG  IHDR}0usBITO IDATxytS?6[lɒl}^/쐀%3I9Ӵss:9s$L4&mB@Pv̎}xGޱ-&/Z~|y {{߯?rd{* %8G![qJ%1 @@4j-ˌG"_jfy0u8ϗ\O|.ާ[|}}X $%%y{{XlP*|=_J12_\'*_^w 0CE$Ns uPRtd uXɗ3\O|.-)u ;xAk6 _ū,_wLL00:JGR~cagddpN,睝FpkttYpDx9 /-_Z)JCBB!jr||ozzzryee%]``R$D"Vv8v.H!FQӱ}6\Ʒ|mkbVƷ|9Z6kNNNF ^勋xu2 Ƶsxxx``l6añ;;66f6=zv,L6F'>zl6 >6\Ʒ|mkϝeqCU_____Q0(pr!w܄"^{-,,?"888)))88h4755ݾ}lLPxyyIRH4>>ܜǓٝovhh(!ڵk/^d;я~4?Xp@UUO7f#322r֭ 0JReeeEGG 벓Fh4O...f1BJׯOLLT*IHH8ug}5kТ{}>Bزe/Jr9+!M,YdÆ WNNN^^^^^^񹹹.\`1<^d/#JRܹsic+WYF$E"RT*ϟc7<;INNRw)l֝W^rX,6\]IX$߿ӓW[[a0T*Uttt``T*ݼysOO75SSSXmmVX,*jΛ6mzQkk+KHHȊ+zVyyyzZ~izb+ viprrZj@ `,* 555 """"11yŊ}}}lGj/rZZ!dxxY %''dtt9ôk ‰fH[F6l}ôB\L&۶m[tt4!qٲeDbo&իٷnݺ~]z]qtXlٲz{{7oN9oܸyŋK$G]I-[xñ=kYTTn0 D;wT(%//\ka6n(!wa*(JKK ȑ#֪}Dnԝj:##_Zwݻ+==3д4|MMM }b޽dڵܫ;GGGRŋsrr؎ؙWyfZtVTT|>ˏ]?~ttFhvqӧO?IҥKh!^^^###we;d“]:噟i3rqqILL$tttܻwplD<)Y__IQT,Df-=0W\2@?~d2D"Zr@ll,Җ544B|||؉n ! .d;b999<ք h HRf#b`u'/$&&/NLL]B؎ /& ?XؔAlbcq6ř' oooBhxӦ&:֋k"j=iTWWBbbb؎)~^z˞xvy Sj+"ݻէ)Z| aBPPZ&TUU~"Xh"BH?Nz#RT!!!S>7o!3#3f*>h=::J蠝rHvޞBf =Қ' ˽K/BFGGoݺv8eL{Ic#B`3C-^V 쵵F®4:d2ܾ};**J,GoݱcD"r A muvv~.OOOcq:t*Ďh!NNNJ2000<<\,mX7NF_r7orK"榦&`L& Z[[o߾=\nHMM%ܾ}Xl7oV(oVMMMaaaxxEzc8PQsrr |̡`h=ݘ@:ݓ}>!D(N~";օX5)))BñիWO~Gq.DuhKD򤤤3gp||1116mʣ\.?+WC8)%%:?{+JJJz}vvy󢣣h?RXXx::d͚5_~OWZe]r#:8{G]w>}u⋺{/ N޻woTT֍5ZcX<::pV7l{ڵ:ñgg͛7K$f>L=ӟdɒ!N?::Rッ_}U^ύ6H$M6޸q:GvZNW^^vtRB'BbtUˀ)ZAAҥK}||"##WPP900@}qi@*ҾiX?ˉ...aN-3{+N>}lҥK.]"T*GDD?~m#;;[ cǎ nܸ1;wK.ūVF)H!RѣG_|]}=喖7|S(._u… }}} !Y[n]h@ wt)))aaa{---=~8g9rdݞϟVUUN iO}CX,`eGmB󪬬\|D"YpaAAN^S(h41rhhhhh}vXU]]́>Ĥ$={666V.rv8Z,Ǐ[Nꦦ0ooﹼ;ȋۘfN6vn޼v"$$dƍIIIlGj-[Vb`.)))((رc!bpc? '''D֏ .4w=-[lٲկ~Eo~NFyxxݻw޼yf… lGĨxL`GVAEEynFM.D"OOOzB;mGGGXXP(h4ܫ;\uҢoQSS.\0&&3 /^xLAňRTI63lF `CD"]~dddD"H$D]u'sT*޽{5l>{,fΒW;W\\4^\rʕjeύ ITV48L{c;[p!m?F{=BΧQ(tK<`T*:5J%!"''''':ĉt>@"y{{/Xs.+s5hZ~=ݔ{9iiř[,'U|P"C溺ȅ >|pJlVV,h/tsgN㰟N^|ymmŃb1_p 7o,Jf˗fBCC***&ߵBBBnweN޷obR__#GFF80(!!a݃FQ*Λ7/22.2>>~9#vڞ殮.uww (jkk4̙3oƍ###kjj<<sΈF~x~|`vBxgϖ2]555:ujƍΩtWl6߸qcH&̜SP(.jT*Fpwww]]ݝ;wٸ 減7oz:`H.;99 q^O{}!1^SS-Y$66VTtڛ7or`)233iuYY[FFFxooowwwz(--w1ڒ`twru kQQQ{{{FFFHHP(ܹÓ:h3DIwe; }6gح[ܚ?Cr3 pڵk׮Ξ={Y`N`; s~;BHkkӾq+Q&&&&&&&&&Pw:K]3|lrAW'3Y8G ߙPw'g@QL He޾Dgxu2勓yʗ;?</oxE$X,UWp̌#_Lhxu2勓yzѓ%銋$%$H,>l(+ׁzX,_ެnXf -_බ6`.^nc; %<׶7+w܄Lh42i0ǖbbb+++kjj؎l#88l6GGG 7o2NgZ=>>_Xll͚5;8@.o߾=88X$ |V@?;sTՄñ B|||RRR^Z~b@ jOf%ԝ)11(//g7KOO'tttB233ݻ===]]]| [۷_whTv,/*..n֭r,Xn:///aX,$ ñ౱z``@Ѥ;RSS׭[vvvsŎ;|||k^Aad{ٳgVw-˟Ν;۷oOIIٶmJb;۵kתU/i tFَ233Aeee__ݻw !|}[lf;xf .o 6l0|zxxof1+[D{h4j^T*ݳgOHHHppoQ´LFDnnnlGd_T*r9vg!,\bXَŖ"""f۷ !K,QT7n`;:DiiiK,#wZ[[ Ysss@@@llltttmm7hիl_ZBHTTo[oEDD4MvvPիW l֝_/`6Ϝ9vW_s?cG -ZD*c%OOXB477w b/_f/:{qvvHMMʽEEEoc;4ٽ{ fs΍ڀ̘ƛ7odim۶ѱ@9ld2m޼y޼y?|֭[M&өSZ3 allE'!$&&211QXXv,l2X66yKK,}6wqqLIIqww'ttt]CyyyeffŅj\=4N/[Ƕ~cBݩh&h.ɦ|L&s-[h4{O,SN-mݺuK޿믿w<`+Rt:vQtn\[_c IDATCCBmN.BN(OBbŊϳde˖-ZH&Y,{:u*''g6Grr`zww/]Ғ˱(@!h48qbhhݐX;?}My磏>t좴itͥK8VtW_}cooZLNN8lgffs__F6yΝK/BOZ=>>wݻwy{ꫯ,XZZv,LpvvV(]]]lb/ >>>dbb޲W\rܸqKKx $''vuudggm>;x☘h085l2B;322!sp.N|l//{N.: !UUUz ޽{kNmbqRRVm۷ݝ۳*++}||\\\Z6bbb4ͺu/_^]]ϥ"?bqJJJbbb@@]ZZz,Ȱfրuuu , BJKKtԝ`cwE#G&RQSSsС;w]v7`1N{~E tRե VX!H.\h4zx^iRLHH?y$ѽoBfscccAA,^D亳0++gΜa5B 6vʕ78qM8sׯs$߯(""vhmmX,SebbbF./^xŔEZ.6ñGYWT*lʕ+###,5ԝ`c555O磩O>. Sj SVVƥ6+..Ŵg ,, yyys|Cg6*^O7w2L.\`+/yXq4/++3Pw̬%&ߎ6}===Sww7۱BHOOOiiiRRP(;fkc9{˗e2!z-&&&&&&&Pw:K]3|lrAW'3Y8G ߙPw'g@QL He޾Dgxu2勓yʗ;?</oxE$X,UWp̌#_Lhxu2勓yzѓ%銋$%$H,>l(+ׁd6*_.%K@p>1±ru'pN`N`N`N`N`N`N`N`N`N`~lφugZZ… 5@ wسgOtt7utt3R??͛7>3LlG/wߕJ%%%Ge;JJJھ}7o߾}iVZtiVV`{{{~~~mm-xZw?? yW͛711qqyʕĦB#xNbXT*ʘׯ_x툀M<;ׯ_OΞv#[2L}nxBHaa!d.MLL]nَ^>n$zjBHEE-:/^|rBHII NGh苖v#S!;کS}||m_8qwQTg&&&D" ہ˓U*djS&Ν;l:>=b7 ۴iP(lii!ѯP(|vr9!l6wvv Q?}a}fe0><88(x \>l0r]d21ڑN#h4???c-[_^шbggg//E?|w233#"",Xofee999,x?o޼pZwvuuxyyرɩ~~~۶mH$:СCՆR)!dlllbbX WWWv#w߽jz׮]ӟZZZN8cǎy_~%W7nؾ}޽{:::U. `xxݻnnn ,P(!!!!!!FGG\~u\u\]]w%ƾ^Bod2m& !\+ GW[[{ܹ젠;v& PWphFvR :???ƍ/XrMv%'䮮.v,>֝3ۻƃt:D}vF3::z>'';vฬ9( XAX,\pݺu'OBRRR ϳ s\.```СCIoo/]+N(Xqtuuutu"$___BNJl6>|by!WL_t:Ȱ毾ฺ֣5M@@'\ll,]oJNNNeeؘj=uTYYY__hd76fl6"HjLGx!Nn[l=mhhٳfY%Z6n488x)cx!&̙3`;`O; !:رclgΜrʔ79+FyyL&T9>h4}}}rd6*_.%K@p>1±rug_]!qrvܽ\YH$Kq 'Kx/%8/.i-߹Cv OWJB.Nc}߅sgf<ѓ%wZ3%Kx'K=_\[l)..; !q AlJñ@RIDZpnV܆B?;<UD"a7Xs&m4؍fmY9(ԝlf^f;3͏=b;&twwFȓ|p6ܬ/,w!Q>XY fmY9(wPwty7nܻwK.Sެ_F8ԝAiiiYYY"T*B4# tww' ֲ{2D:\2>>><<п\Y~ݹsΰ 0AV_ lwAAAl/jҥ6lBP(1117o޼p=r|ƍ XVݻwuίrf;ݳg,?FGGoܸq){ם?я!QQQoݺvD`wIII lc/{uuu5 ...AAAgΜs?+" CAAACCd[xZ^|۷FX@vaEppm<==U*UDDDdd%KΟ?vvB)//g;~6o޼gSvj#NkiX}]BJOγ^eeeFbWׯwuuѣGGGG !YYY/RUUszE"_k;}CCCQQѻᆱhVZUZZʇ$..n۶m$??ܹsccc֏FGGkjj!iiiW޴iٳgً׾!ålbGWtBAhh(WNzoi陑vh`_ֽ+z{{ٍ~\\\f'hIuVkkT*e7jjjZzdggO>_R """N>]TTd}^KJJ Jlٲtuu1:<jCBB6o|Qh066( ٲe QÃ2McN#D"??F"c\.߾}{RRb1 RT nٲv~JHHX,׮]ek׮ݹs`0x{{'%%M3//oҥϟlbccU*![zN߽n6i'm۶SNАlf4Vp8Yz&$$l޼Y(B-Z$6md0h!e˖dBȣG :;;ŹszT*fŋz=ѽ?޽{L&{ɓ'dɒxBѣGip6$e2( IDAT!dpxxh4ܮ;8PX[[{G޽[TdԹ?_"tvvZbbbBCC !ׯ_z*}ܹsSlmmmzzz|||nn.1\p~QTӏH$@ qd:r}?55ߧݕǝߟ褦\L&[~P(ꫯeee?J嫯B9pu4wyyyvvvZZZXKEKK˟5k{zzNLL455޿l`ttz2h4>+@_p`VBA"bbb~_M0]Baee7|Clkk+,,\n!Y`ɩey>==۾!2522F\+V8H"֮_*?9#ugXXXff&jjj>裟 bӦM]w.^{o厎cǎ۷O.[.88X >|x³gΟ?_V]|ٱYgg8Z;8?1ams?OT* !3+r3@FF]ssbq iFǑSR &>//t>7**b2iNP^^h"s%;V&bʕd\p &NvZ&X,SOY9DX,&EöW[倅 BZw=ztӔ։DBX)% qdʶ6BX,ItO[8ի&^O:PNY53MO1>>NdiXkbowZ%On4W7YϏ@O9riccc}-:,YvՄ>lʺx\őN_"))Օ|򐐐Ǐr ]bttt8aYӵBjkk9p+N6Bp<- zzz, m t:]HH׌`8HfX&/IǏ'رG#gg"˿wGNB׭?Y{7D"=q"Md2 4CxABld2@E>ɴNjkk{|Ui9~byJ WJEsz+++ߟHY~v~543[e2ݑB'>]5peqExxxoNӽ֭[R_#(>k׮ wwwX_yȮ.n tZmMrCYGR{{; t^N >gL^n߾"H233h'%w2>>~… 6_'K.}555hbp%uf!"""***..wzz:!dbbΝ;hV",9ҥK[`{ȑpŋ/N9R"lݺ5!!axx"]o[uuuxx,)((v֝ÿَt:׮]+z˗/WTTLȵkOooo _lۍ7ryZZZFF!`09sunMZZhtss\9/H^{-88d2-]Nfb;RrrrBajjjII W͛7'%%;w޵.O-Zhҥ ȑ#ShZoo/ݱjkk93?q+W(TZcǎ^{l6[+}СCONNNNNŴ=xxxȑ#hR^^j*>ԝǏߴikZZX,%%%S+ݻwlB̤BpIэ/_NA"i4X<>>Ù;$$ne;aPwr[[[-[) j7nܘR 6$&&Ўxy>8zڵkb1gTTTtvvfdd⑑BTAAgFFe49~aQQQQQQRRRddT*5A666N.l6 ;9 @'[7N j`EWs^o>z.JJJJJJ؎!ǎ;vQSZZZzQn D֙d:Ł0{]G xNlX87KTdff ]zzz83\~lݜi* Pwxzz;wpc.A \uhh;=8.ԝ0\ݩb;fYL$̘1f R>PBHph\aN\nX?_殐89;?@ 89}}|%<˗t4PLrr2cڗ֫Ԟ_ PH\x~ƃ_CÍVwܙF噒%<ѓ%wZ/.&aFqq; !q AL>l(+ς|>kg:tġ;#w_ƆX;'ԝL@ L@ L@ L@ L@ L@ L@ Lx@ P* D3H>YB@  kHvjfy0hY-Ɂ˳HEɁd3V"__i>>>>nnn/J...CCCƍY&K De?*c#ARR P*3)(3̔SeSRwM]?WŖeY7``}) &$m! C3)%m'e&i;J P&fi5l」 .Kvzu?;I,b_9N[nEs$.@ Dtglٲ^RMMMRl6s8M6ݹsٳqt,IMM]`AVVX,f2$In٬h߿o@ Hw&"hΝzjٲe]]];rH{{+W>{3g:uܹsz :uƍlvp#jZR۽{w Ou֝?۷o߲eJڿ|-Jt /fN_fy<^zzz~~~QQQ]]]mD ąNo޼$Wv bqM{/X ??_.s8:zVVwޕ+W<OmD ҝq?W*󕔔L>ҥKΜ93իWos8%Kl'N1@TD"͛7[hl6[ssZj^z6$*RSS+Z2ZjH w^uu5`ͥYps83g[_uDD8m۶'N^'I\.L&h4s~p8N_NNG9Z222 œYfKJJzu~b@#21D=\EEE/IAl6 % ۶mSTqNlcǎ%TՄӝٯڱcZZZm3p޼yo/yyy;vغudb2ӧO?p@utt۷r?7nL^i2Zmzzitk.QaXJJL&p8e0fsL&>|"hrFI,kҤIZbD8:ܵDT*qg2@`ppP(z-0x[#b~3(:[[[:hBu֭]`TTTnF\_}U@ `2Nqo~'%ކĂuˣo~s…Nȑ#?OҞfZxq<}x:N> 3SLyw1g:olZMьFlf2999T=8BT*ln0 q\.i$IKj1 KOO%@0└ANgX\nAAo#@PDs#2P+E7odw}7\t<~a$6lgX?裏cNڵ Òpsd2'OԤjaKiiyfKK?_xd2 rؿωE޼y4-''go֢EmZ#˥Rdjjjljjr8 B(6B% lB0A4>Z"l6d6f5M[[VlnnYYY!qðGd"mBxsFN wZ*F&Ɩ+Vlݺ05sx3:Md[l)..|w=v2s_|f755}ThaΜ9֭qԩSmmm3i5k νS]]]T%z o޼ p88>,Yr@ pɓ'⊊ɓ';v, KjjZ@GGGIIBn2,--f{DR|>Fs\}}}pH$4.K NAqvCe22eT* &Z0@jvww؁dff +B`0T*pghyyy]]]BP(b600 Ϟ4ͩ8h\~ x<^NN .O<l6q< ǣU6|ma"v2eJ j(>"(==Zeۻ8nBd2?~\PPߡ$L2bP,8(fn<"mDfϞr=Ujԩ3/@v;cǎ\Zo߾ↆ^_QQ}v귋-zfwӦM۵kjhhzjuIww7"J)~HnW*T`D!/h" î]vܹ7o:t?| ++kƍ1Aa0pPz].WpbeddvN2225nSPPr Coo/ //O*e2Ynn.Wx"F!L&S(L&t:\js8E.gddP (ȸ\.\qcaaL&X,n[Reff3+:;;u:@ T]Ѹ@=NYYYO@ŵ Xz.;t ٲlr@5jH$|N3LbPTCӹ\.Fc2===vnH;d #289ԗ%`S}}=.|;W^f~m'm<;|^xW^Y`ׯ_o2yw}O> O ;/I0 ̟??ep}`0ʎ?_h4 ÔJe2~j5_G~0u|`, ð!x<G(%h`M d"IRV&hjj(v>|e6a8F vB l \V Vn=iiiL&y___qq1RSS\ngg'\\n4f r6=jRɅ6t9Dz00@NDoH:N"HR\`0ӝA r]~ ThDBDc?dTW"FA"IP3bn3L;9Ʉ2Q(2 @G~[l6+JDbh4@ liÍ.SLVðOEv¥nMwڵ+''`tz` xl6;RY=SvccaˢEVѣG>+VnC孷""IwOOc2&)"\ &,N: % cua%~xl vb1y0!|>fL.1zbB«$ITda ACUwՈQ ĈfFQ tvv2LRaP($INb]ox<.K$a&h4Zȃp#2~eeD]D}AO*?7>DD"yWE''?pSY®MwnܸQT?~w޽ [xJRqppp`` 4kx>P2k vIDATX>FJwLRPPd2:@zzb)nZ`\.7nܸ.X㉓4*<ICa~?Fpo2d;\d&$:cbp`6d0܌D dc)F\'q0 {|x ģ[, *9`|+WY&ކz<(Q 2<# .ZplHgESlȐdN֣ x< sLN4^@8N!*) BM~D@```~xh@ l^9 d2T*D܈ W^1cFJJ |l6(v%uuu6 I9DzHԒ8mݺ0,\-tԩ92qӝ\$5̓-[600_644x:n޽V}}}.\H'gΜ3gΦMݻd2 Xhl~qCC˻:::T*ʕ+9`gb2?~eee* ðcۺd2UL0$sssf3A83 PewwwQQQaah$Iq6zzz, NAW UTLr Œd2و z^.~8V|>>”D- b m65@ T@(F@ww7ϷZn &%~NSVUPjUՓ&MR)2N("322N'X,A|T"bZ]F\h8ӝ7nde˖E^ csl+WXP]] 'aZ[[۴Q7IDUUUpˑ#GHP&n rgo]0 Ν{饗ٓ*ZJ:|0f֬Yk֬aX+V@32 fO!K*.Cupݏ=eǦL& JR$Ir``Vnp _9E; xQff&VF@o@kk+#ɼ^V}v‚]$)#9JoQ mnnVTbM E p\ 09Nv@jaqf4< دRv{Ge\&!FӧgϞZYY'B7£Ϝ93bd4TE"BCVk~}>_}}p=UJ@B *9%8sWjzjV.;nWG;jDB`|Ĉ@PD! b / !t $ &޽{L&{ׇk,++[z5ݻ!q%=j%IvҸ?r }WrrrB(I CV EΓѵf8\D="M^^Jd]]]yye2G}D-ˬ]_dXv͛9Noϒ˗/<<DҥK555ׯ;w.bXӟX,ٳG.wvv,AkRe8ѵf2!q(G1)--}饗ۋNzUrښH$ڲe խo\Ntgp8=z⒒DžBs8zvonwvvT*r?i0oݺܜDj6\KpK2~DDtg"2dxb@L 1h@  D @;@ N@ D,Aw)#te/_&/F9u|I/1 {  Ä"qvn~$#W&zg/3Ybb2bq/mbF9"X LOn`@f'U9YRu|4_&2Z'ԍ2ٝ_#N3sy<Ә vvh5܍R_: h 72I쨈ʄ`"k6IENDB`keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_default.png0000664000000000000000000006455414600607066026704 0ustar PNG  IHDRw+sBITO IDATxw|Tu?ϙ$3I$Б&M)" punnއ޻nq]׺(RQ"$^!6I2eӁ3sry=3>dffNDU&pU&pU&pU&pU&pU&pU&pO1 FDD!שp:||'#_|"HܼcNq3 a2 OccI0Lk0FcCCÄg"_!dyX$o^;A'_hry{{8 _R&K`M&_$Kp nޑ$2ޜ;̄ _L.W$u1勋 I]+MF///w, |1LJp\NPA⍍6p\N[ɬ"tyE 7I-߻[V!|GZRϏ]PPw8.C|rJbǵpn^qTa%sfa nR˗͑M\4U*+n {[p8,KOOḜmoow8MMM|---6fI$ߦ&'Wp󊛤+=S:%RjJe6f3QO]]]]]Q n^q+n^>VeHҥKF#!*;;pPeBMMҥKU*մiӪxПUd9sfrrrnn'%J… jn驯|rii)q/00pQQQz^P WTT?\d2ۿ!d|GĥiӦm۶m?-9sfttFZwPٱcGRRdlnnx܆~8'%%yxxlϷBCC.\d2YOO۷ϟ?_YYwh.a2-Z-^wh.q#GlܸQѬ]vgjgΜ9mڴPLl ~wd2`0 III.]:rqnܹW:NVgdd߿_Pׯ%(zCŋ,YhwDXĔxPP֭[~8TGN>G͙3gݺuC{{{$$$=z< sYvi:.>>>>>>77O><"׮]]tibb3_c0TəqqqRXs֭~~~¶6TL6ӧO)7RSS׭['GIIIeeeww^OLLt=خ]xowŋӥۛ~bqoD.aÆ9s׍onoo7*n:uڵkh"BHnnr-Bׯ_okkJNNP6lhmmjqqq=pϿy&!$>>>%%EP[093,߲3gzzzwww=z0]ĉiii+W,))+~+VBNgCCbdOۻw/+Wjkk׬YCY`h˗ӻO>qӧlْh,X [V@@ҥK !b]QBN#Gxrŋȑ#yyy|G555㟰xbBHWWץK͚5MMMz?}̙3JP,Z>5LάZJ.;Ç_ryʕe˖ʤ_FGm^^^nnO?hfϞ}Y=S{Zr~j~^{sYY/aǴi!V;wCp\  $TUU -1) ss`n~zZ%C*jJ4oXK 6''G4%.\`KLȑ#4M_DDDB***x"-.CBBk􊭭\DeBJeff&?I?m?yn Qmllͺl/9 .BjkkGmnn-|bx}BN8!NsZex,WՄGr.$-\a gY#a]ŨW\III!ʼn93**uȣth",~LÑEinnvړ8f^3% :pcPnl2BHqqkD\ejZBHww7߁C||lH1YhL&Ν;.̝;W&-X 77whڵk#ֻ+fYVNG!EvABFn+ vM24o<___"9CDBBOIIc.\ BNB]dɒ^q]vK-ZHP8NQ^'NZ|h#^(7ߜ8qB4S!gΜv4!!p:5&7^ANkZ~a)%xyy͙3UdL_^ZV.4T[[[VVVxxxYYSN}B|7| ®nZ?#v7⊊;w4B۷{^^^QQQCۧd2YxxxPPPUUqq744tCGDDlڴea@Rm6:69++K 9 edd$$$>ov]]rcܹtȩS0Db:Ը?~4MTTlvxb . ۰jppҥK?0!$))IU… i7|w,h4;v u:׮]khhIKK?~hh?_#<0룢 EXX]pda+:#185m۶EFFB^_577޽?'h4%K7F#@'f3}db&::p8@t&Czz*mkĊF1c!5''pl2:ɓﯬZ 'Nm6u3٧Ov:r|ƌ6lXne2YVV)9l}arJA[mٲ%!!RPPpqϝ;Ϗ6u<==G^^]mE'bBL&튪utбFnwww `zpB,ȑeeeEEEiii!!!q:qDSSܹsM&J뫭=bE3ymk~]C`ATnaVZZG<<<޿GwFd=XZx+**O}!1욠cm@e\>k,BHwwhˋ/4 tLjPPhLBȍ7FnF7"E0ͫP(RGVխaILYj ֭[{eC9sV\I9{=?/=*nr }!~7v ˗/;T**g͛7} QSTYh'"}%n6XUهa"/^L#Լbm]l#r:Ov^^8Zo޼{n1it:}}}4ȵpL!OODooaYhqmtٳgBĴPmmm**00P.|C6:DzrJqvvhߺuna+RQ7Ca;̞={ժU ޽[M1!!aÎZ&Z1T7;oݺ%MDv;]s˖-CGgF>tQq̤-@SN^fͰC)))t^]]e0! SٳgRSSvFK/3YYY&)66瞻~zggg@@@FFwC7o!p!ꫯ"##=<<ϟQRRޮ’3gΈl@lldO===Ȧ'}4OѹʬY$TVEEšCD0iC_cؗ9qILd;rGEE B100ZZZz…^{ܼk׮O6- fuuuUUU={V|f_F\.kjj;:-XpAii髯`x???Je-KuuKD9hplΆ|1 &''f2˅|G' Sʼt(WʠĽX:w|ڿUvs0)nǏ?~8߁[own_i۷o>pV-M=`pU&pU&pU&pU&pU&pU&pU&pU&pU&pU&po*CqO1a:W& .I]DbbsBR3Aj*W<4*bFҷ㟉|g+@<I+d G^7BN'CZ:_|~l“Q .f"|q1OR =Y|:m*6}FDdV,:w$Gr+(9Wj+XW4ܼAw$I;L73a:W& .I]DbbsBR3A {2{2{d$8Fbttt paɤT*[[[{{{&Kj7B3<m6ḜVZ͓Y++Uj:**[PP000wD%???*wAAdI !jqXRIlmmm|\Jl= +Ąhݼl*HCjJʽTVb2{zz:;;b;X{{{hjj;Ry[ZZl6fHMMM s/؞)NZRkݼfl6ĽTVbk` e&%%ر~Bcǎ8;ﴶ 2_z{ӓX?Ot:A wiΝ/o[@jjB;e˖]v<|Ń*;Jck׮x;::WVVuVBB2o߾#G]:vرcw}x2(rG[ŋzRonn˻p˜a)K.MNN===YYYnmذaΜ9={ ["n7n$|C͚5kӦMSN8q^?~RR^۷o_pAQ>ldd~UV _8o;!!'0/2!d``׿5qqoƍg&\pѣÎfddlٲRZZ{6m4k,B|PXX8~@_\nΝ^xX\h4odoooBaZ/]wh\JIIپ};!ѣ%%%tt,//?ydww7a˫͛7k4F|vTT获wzzzll{W[[]ii)2Usbb*322.8 <򈗗^ǏCrO]8?33SGGG?c#M0LcccQQQwwh>}N|z-̉Ҿ>F>[JFGG;Df *qDDD<*n9ΰLJzꆆ[nKdTY__w8.nUu֐+BN'ߡqd2 =EqO܁M6) QTTT^^nZOcǎ7xn)Gii[<==zc=EdN52|A:>++ɓϟgL&SBBBrrrQQa+W}*399BWQQ188[|#׭[GKC]z=tܹoۑaaa˗/xvrrrw.^O{{{Ly?Dυcbb!CKLBHooN_ o߾=$Ѧ/\溘9D BȾI~CsOLLd wʩ@BHaa![bRo&DFF;vL%dggӦak(yyy<pfϞm4 !CKLBHҬYr9?!FQQ$&pVIIIlTIaFj\GtLОqʹ he7*--%d2{\RRwjB?;܅6`jb_|yrBN:OFMz< W#ݻw7v\ vhfxx8}H IDATMM5LʬZ<}hCPlf-D>-:/++76I#VXe555ɄQۆn755EGGT,_#D.2Ylu?e* 3 ӦM#655=Cj:--ԩS޴:T&=Ww$;;{ʕlk`y? $0M-mi[&!Dӡta mdtWll,g988HL>^& WqETFFz?-@{ ð JXvv6}||H׫bRSS6gGyQ!rJ{{;!$%%VR*6mzeggl6~Btab˗׹|%!+VMOO%hf!~ǹ+W`jkkS}}}}͛e2ن RRRʺt:]tttbbBM.ve˖2Tuuucc#(?fOXXs=oZ}||G> bÆ 7o޴ZiiitH9P({챴[nΘ1>2֎z(pȵUf}}}6oެhu@ҏ>ȥLzXi6nF"XÈuuBvZak677' #׮]KOOW(NSU&!uuuvc}QJHQ*..>pjuJJʰl555{YC&!?55uXf{{WT*RTT?yz^TZaUii.i)rիWoݺhѢ(P(z{{-KAAKЊ)~(D2nII S\\w,RXXo/Y$<<\l6RQQq̙M6ׯWWW j655_x\eK,"X,J"*b6>_L*3..NxJVqMF|MMDb3XyG%|2e z sS 2\$%OܼwwPL\b B**7EW2VoZ':/a PyQer 66VTBl6[[[V%Л=P(XWTF0|X@o^Thjjr8}}}z ‡@ E9`(޼2D",,, pHL;wB^xcq3f,_חjx8f͚ B8pUÁFFFB^|Şq *߱͛7d~kk֬;wn{{;w8pPeے%Kh{ܹ6VwPw#--MT&$$@0@Zd"~G*--u:7o;2`00 Cimm;{uǏpmt8F b"̸9s愄t:\tƍ+WKΛ7/44ӓaW/_M;ʲUvؑ399_&l_*- h4yyygϞk455;ƻq7`XlYLL7!ɓ"^ջvj\۶mSv|G U֭7oЩ))){1<έXbҥCtqqqqqq16΅>KOLLD#̙3gݺukr<444444..N۽d[paTT[o%BSqZt:?s R2WX`BHwwwNNN]] ={NKHHXjձc3ӧOihhp:aaa3fP*f2_5arClݺYJtSOBJKK9Bq:|ƱhĬ,//3iiiqqq|Gw&fߺukpp0888--MP.Yĉ|$00p!++… |GT#; gyFRʜ={6r\իWKJJm&f͚%*sٲeFR]]9_}^|ٖ<.֩+W%ŋi%M:ujQQQvO&u8G|2NII֭[ ! 2h40/^쳡z{{gx ^Mz%&!$//bBN{']999CAmVuG^Buww+(S( .`ijjڻw/g¶o>́_׼/T bӦMCsX~~L&[r/dɒB ;0>o$M 6m}UVVo< *s˖-iii쪪vڗ:lAHNN 1 &99999͛| %tlVI&X,^P(6lwuup^;BUfPP r7xc.!̜9?&&wt`],DVo$#F]6%%gӦM c>-^R(1jZflmm=skF{###3uuuE@@+KreI&Q}ft %K$QeT*bLRN/3fg?~bŊaVkuu5!aGt7̈́k 8tyJJ\.vo䛂 FE{zzhǎzo!сN(AOׯ_T*5### !&^OKKx"p@U&!͛oҥKu:0EEEN".ݾwLɤje2jmii)((ш/YbE||(//Zz5LvZss%KõZ`KKKnns^|EBwM <|mrUjjjjkk ^I$477۷ob]wn}С߿=jkk%0[MM?MNGZ|ŁIޤ}ٰm܇ڵkA c*../~`L$1mTZZ]]dA0LҒlڴ6[\)6{qk;N 1!JIIQ*f͊onnf&,,,==]Bn޼wpfΜH1ͨ2U&LiR(iii~~~K.v4??_n%bΜ9aaa?/_c0!T0?o={vXX`d׮];@W%00P&+W`~=h; p={fPePePePebg&EL{'drTbJ ;?A@p9B1sUKTy{ 0JlL$KD%W;6䋛wR˗/Lff&1kЖXj-/>?6BO q =;JH,_'K︄/nI-_^L*6}FDd4ݧXpz{{nݸ>,Atw,XN ߉:_ܼZ7uL8.U&pU&pU&pU&pU&pU&pU&pO0`pKGGG{{dd&666""!TuuuEEdBS]]]^^>ɓ%%;$n vOb&((HӹNVk4Oc&##d2'*1 >>>&|333`0 )|%x1K-_\D&qUFQ:NJP0 79qqqBYF.|JVO,XIHb&7PeJQz tH|k2H*_1%K yGBMC C sJF0dR*|r hlll|pOFb;ÇLA2Ga.((; !j{j:**[PP000wD+c0RI_(x$cTTFp؋aF1|X*`<Xܡfl6 "p8,KOO>` ]ZR{bfwp:lPaS2{hR=~oV HIIپ};!$;;{|pOPeORR֭[:Z\\{nw0/555 futt9sPeKxyym߾=<<}GRL6m<&*9~xvv6߱p#/////(&eZb{yy%''{yyGy31Vpp;eḮZgΜ9r䈫sW?ϟOILL|7Ο?wDG1oV{{;}ɓ;wIIIżB?z'kst:*g @K|$tuuaaat!^lٲ@gggEEɓ'3III;v dee:ujɒ%)))r2++K͛Gye2… <==v{[[[AAAVV=sܹ3fWMMM/_~:߫7nTVVBb/ĺs]$ק>qVCKW^yeppO~r:|%Zux\痖g]|\AP,\pժU6kr<$$$$$d2hۯ_^WWT*5kV~~8v=uVBBd2LC&&&BѪ`0F^cv4{l\XTTm4O<==|zٳ{zz T*UXXXbbL&~ӓڪjccc#""YhQAAaZ !|ñK={|g'NY\\n?S+4VeZbR)4GzjZb=zq… iY[[o[V+Wl"׬YSRRk\b{Ϟ=SN9aRSSQeB>}vBAG} Su,'O>> _}!$99Yv===( :li``࣏>_Iv'|eZCVH ho_ } T(C%ķ0qqqK,!߿x#śKIII!XVvmgʢ~ee%m۷oĜ;we˖B׿i)\H2~ddd-[/fw*++.5t:D96nHo8qBd)xfi3lbKNNܹse2ӳЮ =8yOOoooZ{Ĥpwp):@>$$$33-bwF*##>2544lUv9tLMMMffի988xMBrZi&QUAAVS%ills%$$Ɔ>s7nܠ;LFEEM6M.;?\47dDEEY}ty#[xqtttYYa2--nR__3O=V=}'M>L-'^4k3E|abcc#""\KUWWOd nP]]]QQ1]ErAwd2ypp8 t6jF=iL2YB0& Q`0 0LFF70 >>>)R|Q#;2UhԯR( sh~3I'OFJV D/F$?H%E)dȄ eJw of2g"| 2\$E)dcpU&pU&po╌HPQ6pGj>>>]]]\ Ƈ*)<<LJ"˫@xA`FC;1@9BOP*HJj5ޡ-ĩ~L455 MRѸp„ V+ɬVkKK˭[.\PYYy粲؞)4ܺL'l6@i@@͛͛RV6mںu =&&sppoֱbiӦ͛7wuukgΜk׮]v-..;κu낂~v7 CʜB-[vڐBޮVӷlrՃbH9٘!19Tf$4;k9ʸF444L:ٳ_5B?iuu~6^b"l6[oo>POd2GI$ݻUNt\K `I>/~LjH$b±|>?؂aRfAX,vuxVu:]ww7|T*-))^o?BYѨV\[hvZ}}b EG@ D"PBGGǴi,XZ{eނS#Y|| |֭[YΰqB!!6H$Rp۶m1c$Yy\x sAzZR4?tp812Á@ix:X,j@P]]- VBr'~R9ebDpHb 's\Dp8BЈ敕>Ν;.KR1K^8NMMX,% Je/(J500 Zmiii7zP__lˈ~X鸖@ ClVTeeeϐ@4Ycj}v| 2Y,`0vpIL@(r\h)((Fp4ryUUBl6;L/Z3́@`08ݻw C0 XbD0 <>=44ϔ[nB4Mm߾Y TTT> 0s9?K&ceee/-Μ9c2VX<sX O6 /ɴp܅ “Ӳ`y1-/ dXAh480#2tB"b1`0@Dl6Cp4lիWk٦MnwfbX:. [N:߼y3@b +A^8β2H F!vas^dc4\QQP(b2eJLćT* Gmɮk f3Cluu\. Bk @&v;<Q__顡!&$IX,I0,h&4@5 zT)4L$r1t:%%%R R)EQx7N7nPUYY o]r1?n06m4k֬۷Ö3gD!x„KG裏n޼$˗h Eԙ4!t1Bif Zf9r$3I>}Y`00}o e˖y˺loL&IЂ0&3XT*.F%eV,ZV*&R)$#2 ^T*e 9pKNS(CCCoN^/,,C.#q$I4_)#Htl sd8h*//ɮ?5nۥRD" Bk `-m c#`kkkB 5s......δuI/CBR-\$+W|Wŋ777W_}5!Y0&pr rxbYrhoYjUOO_en)eBN D"  - L& HJ),((NrGd:kAx<^8'K4=.KsjEcHv.@iۘx<N'vX,r DB4\ΒB@ J J,+8h#{_>|Ctر۷?zT*eizΜ9|w݊> ms}O.?!tΝ~zKYdRe.Y ?0Oр) Fe:&j.L!JJJ\.WC$ 4=b!>FSK Y\<ڗBD.SWrWC1b0ٌl&rBa s$ BDzz<6 P(p3L w\p. Am`Я &9q׮]嗝+Wܶm[opXf? VZUXXg b(R3BM'HXRZZc9WB.]r\kn޼|rF:"TCCMӗ.]&K`E Y wx5 ə| Ba@ քΠ<#OP&%LJt:RʌD")j+H$""974MlEs]PoVK$׮Vjuwww:6>O*b1F(l !X,Tw8ZV.CvfmD0y˗\2{Yf?wQ(-/SLY~}SSbٳg477{Xֲ2| -W*x" 6M$@ 5b h6zhTRl6 L0/LfKP!PA"™G(J\vKJJ` @=)\CiBB IDATBHT2qU*TP(vI_rTrzP僙z{ -녅v Ԯ7ͣlrB$ $;>ڈ`^y啧zd2 ڵkÆ yc٢(IH… zl6{۶mr5!9G$2Lp8P>SdꫯvܹtRLv/\.\04428|9s6l_sܦ&/^t:oݺյbŊ^V裏 պpSN566655uuu1M)JH,K|)S8NHp8LaHX[[[SSci&I&OMbwֺ\.6R(DBP|TT&ρ"\R3bT*FAǿK^/(("B0op87bidPRՠbD" ӷ\2"vAXf C f3 nZb̂h4:00N  s:L:nhh9!].N(*TI1"z׿믿{С/bŊrf|'N}ɷg±ZG~/AV˖-H͝;k֬`pv1z{{J%d=BYɑ@ `٘we:7n@lxb{qAQFh44M~8bg׫R`d&ρFQEݸq&n޼ TJe8%qPg1 MӌXf1j\k ׵ZL&|Go2E\ E"`0 k]ҝ;wRK=n1__zބS%`P*J`0S. رСC@}}}KK^?s̾}&MdDcccS.{z#2GgYdݻ oa4w؁zϝ;gVk׮sݻ?5k"ݻa=NjgB+VJ͛K/t+vvv0 1|>ʆgږqS[[K4}LNG#UdR^^ecO}-+!͛i&\wɓ'OƇlܹs.\8sh4z?pM*'N(#82Y|@ػw/EQ˖-{'ۛ/^_0}6nH#G,_%11% 9ZmsIb8]ײZ<`)//eP<8{lwwwssEx≍7l6ؤJ$|.]AN] :::hO~/\isRUfVۻaÆ_|7lܸ?|ٳg[,7$I޹sucEV`2wޕH$eee9tr8^oZSEײ"I2}:_ K 2>_͛xHsD0 6^˴ޞiC2LK,󵵵M>$IDD|>b9|,..oδ-! ^~=Ӵ6\rFLD0LvUf6ݝKXp8섄rkMn`:8&?4Mwvv&S`0 &GLL(j޽׮]˴- `&dEa`0L>U&`0 f*`0 3``0 x`0 L*Fө{IY.ȸ<~N $25f<Lڅe\>P7P7\wv\yd n IENDB`keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwerty_mobi_shift.png0000664000000000000000000007175314600607066026374 0ustar PNG  IHDRw,\sBITO IDATxwtSg8ز\$Kw0qcJ(&0 IHHv&ggٙsfvsΜ9soH& $!@6$1`ؘ{Ȗlٲ~9CoWW}+!B1Jv!BD!B*!B1LB!<2B!D!B*!B1LB!<Ѽ-( C4d6mrN{{{ccc|y,wn/w.0 ʏ)JMMc:6{垞֛9`iii\W.+y[b\|Ex1šu;O̓P(TTV`%HM0_ZHI;̗;C;ϼLwN3o:/w-$̗b/'ku1pB!bV!ByXe"B!ͿBهT*t  Za;߬D-QQQb ؖD" RY]]=55vD!4Y9Bhn$v@'KQBhzV1)::zΝ7of;N3LVhL&ZjlB{#Ĥ+Vh4 . tuuuuu6Md"aۮ]Ξ=;::v,47+2B!ǵqƜUK.MJJa ݹspp!(JR "̕Flݺu999fXwݎooW^yݝp졣#999==}]e\rǎPYYyIñgg甔___777X'&&4MkkkuuG؎&6lذaÆG%lݺuڵ--->1(,,lӦMaaaRo1<<|ڵ[n3RSSWZ#juuu F#qDHHȏcz;;;j /$''ݻgmFTDDDoѦ"Zvh+WWWglb'6m(իlü?'?޽{9vD6ܜ}O>xد2]L&W^Fh6zX,vvv!!!k֬oץ;ZLLKHHxg.ܵkL&իWo۶(Z ڵk=vh䔗w!v,zWWWOO#G G&>8cP{\juAAcbbV^}u# Rr]aʤK^V틊IP(aaaqqqK,[ZZ؎I>>>C=Nsvv޵k)1n޼ꚞ%֭[vON,PURRry}7n{{2/ `֭lbv"%f[[ݻwFcBBBBB> R_:dgg+Jt9c樨WTTt:# .(ʥKnڴÇlELqAV[TTti T*JT([nMJJz饗=FdrGGyU.@kk+1'55ZZZ`FOQԊ+AVVpT:11AJLoll쉉qe^VVVccc]]ہVPP? |ꪨя~Lyƍw%;LZdɕ+W f$Izz:ֶ]r%22mڵ/^d;{/ Xxܗ>hfiIR}gRR凈H499IW`lllppؘ@^̜wrFBppbD"i#3X,޾}@ (..SI*@cqd^"Yr฻B ;FRRի|ͷz+''G(l^rooo޼9$$0m"++\ϼ\3Sss3v,eU<ܰaCDDԧ~je逥SNuuu:<D#N`` ?' p=s~lfxxHg'w&Tj&#ݳeoof!뫯gٲmzbdvVy뮮ZM6U\;vzܲ')) gZ$#`;U\._jO+1WXA&Ꚛ"~…^{-%%|' 7;;v̮1 9z 2g*`:>>.JnJ$4LNwYcӧOIIIof;"[immrrrsww'N۶m#JdXIIIIII|||\\\ddP5::X]]ͧyR$0 ᇺlHHHMljU|1_jիW-KOO(`0F//u%&&:t}||bccI ZZZZVX+VQzx۶mk׮MII> >P(tf\bŊ;wZ_(*/////oԩSFGG޽)Jwyҥݻw@}}~v6QWWWWWk*nܸDtt4s̎͡N'HiNʴ !_QQaƍ322L&ӵk׮\299k.Ba9'**U|@^DY$J_ ?}}}lFɜ777x<Xׯ2]]]I7<);6o> q}||bbbfsyyٳgyONNNLLh|AJJJNNNkk+oVaDxi`` 88K(z^TQɛpOOOhYe]^J/p#KCt:N:@.'''5YjySbǏ%իZ[[ټM_&?66FzjX<44d9>m#+r{zz)\!K,גKX6T*աCJJJȯR$EGGٳ322؎ζv);R`qJG;UUU1N5ߣ w8"11q߾}E?EvC)XGn,=m&.я d<2.Le@=#@MMe2.h40c'ufz׮]Ȉ  "///<<ĉlh7n "}+VJ \\lT*ɳ-ҥK뾾>2w֭*jH뫪-[&{Qz3}s}o޼[XXH۷o'''744>,Dol*};qiU&BfsYGo9*Ap:V{ʕ+W_~ҥE5k 2VN΀Gփ-K999Eyy9̄;w BV{M6߿> ߆*J> %_~wo͛u2郝xW?2-{jm2IzAUOXq˿ۿ;[nݺu;w޽{75>{9vXWW=##UΝ;JJJ:::֭[?11qܹ۷)Zl-_MP,..r^" H//4m[^/ȯۡť#ʺETe/LLve*SZIJR9h!gfTRRtҠ WWp ١}}}d)[bb"o7nLLLVyMrLWHHȏc8teL[o.N"y?~|OB<*r+ӧO{xx߿ >z@Ss*F";`#?CxeU&VVT?ׯg򗿐w6mڔ{ lEEEEEE3spwݺuF1??|]Y"dygj7|sQyfz"D"Rs܄رc?BCCI~:=ҋ!d2Zf;!ga ]ɡ/QDPPRUo~/g9DFҹk4y4icDRVVL!TQ5G'~Ν;:778a` ״D'''?32)tݸq y,ɍqgDU&i5N#2}D"!Ė-[we=>>>~]ElGvҟiGp]CCy Hr4NWUVEFF |7<5KBl 6Q"grr[g2}&k4L&A\G̃<(J]ƏN=۪nٲE$mݺU LMM^:22Rxxx$%%۷O q\RdCbʏEN#'>x𠶶vxxXPĤ|ڞ}rrRVZY[[;44$W\ <>=EV{MmQQQTT[rrR$WX, LLL}>.GDSSdd>!}|8<<߿v,(*++~룣Fqxxʕ+Gmnn/{zzD"B***:z(3"$$5^Fv`OgNo>̳]3fˎ9rjjjJT #G~a=n---[TTѣqɤ뇇?ҥK{޽lNjI+&&X$)) v,a; -[0Z޿75,߹|2nܸq __]v9sơ& }lG_6okxf||| <#u֚5k\]]333y|-00tp}ߗKeeeB瞳wtUb"Eݾ}U+JJJ؎ű`i+gΜ>8v> 쏘Б#G8}ڪ*zH$ (9 '"8Aˡ|}v@P___ZZv8Lxw7nܸ|]vt:N' ]]]aَ!_xq˖-*s%Je_~v8L?{ד#""JL&3CCCmmmdr B!dg%%%bxÆ 9992SSS#""?>m!XePqqqqq1ہ B###r@wЂ,1قU&B!ܹv6j;v ט#B!aB!U&B!bV!ByTarBr|ˡ.fp|b~6\P3`h*sxd]&vr(Ѩ슢(L5cA=G   L 䟧Li6~~Ncm}xَ~؎TV|D!B2B!H$zW><88f06WZ"t:PSSgd{ncǬoV`` ]O ///## _>y8}۷g6ػwoZZ={͛6yq^{zzlM͕`teeecccYοo_v7|cxlmϞ=ѣVZ?%Ks)>o+j;3WM6@iiiAA _ EEED"N7<<\ZZh؎1oFPkkkiiZl /DGGyzz8pg;VUfXXX^^޴߱kHHHzz_][[k:Z[[I윗d&ˑ堠K.qkBTJ>酅wa;(&۷/11q``[n]t><99J<62### FQ&EEE?GmjjE,7B|L#s杝@Rq}^kkҊOӒurrR*111r}޽Z`8{7===׮] wޝSN/h47ouUeY())t믇hloo陚"Rtǎ...lˤsY/ryttK^^TUU2h###G9qD"ٿG}JHWRtݤĬz|zT IDATe۷^iΝӟF#1h||_TZ4>>^"2,$$òAtt4٘f; ;5YX /$$$7r43'U&/W\IIIQ(eeeY<:=cΝTT_}UKKO׭[i&PɧڣA -[|BFȑ#,XcP(ɓJL(,,oo˗3:;;@ Lygbbt{Ok@wp:Y꫉ vwwg;" Õ+W5kB˟UVl.**b!>,,,,%%?i%&\vŋ  [;{,YסP(2d2?~6E\\ \&KdUNq-- }}}=Gʕ+-n:\MMM $⢕+WRs-vYm`4_ֈ) WeepmmFh41כL&dzyy@{{;( tvvFFF1%;^K.fXj}KVVK.B @Fz̉jjjȋqD9~I?1񹌌7clll``W$ѳ=duuիbqBBl"$$x1)l6;As5r}+ ֮]K,NjzhhۛɃGu:=zB0!!W.x3)q|U[[{9+纱M6ѫ^Y=ƚ׬ȱ@|zΝsH_zĞ8L4iGGG#G8.rD͎3AGGG{zz"""IiΛIdZIb KL~vZjj*&#^vvv&O3m3LeeeV6A`ʤׯYGG722h4~i'jY|zje;~Н{[y_.טpA?~xדd d6ŘՓH$dl]fܑF2 #Y؈AwN[Tw q_ 2q2ÇpJ6 Rh&%%)JRɏCgRT*xzz^E@DD촾(z,&""bɒ%l<ȸT*%{+ΊܦWMD"9M`.C,V"?aN6l >Dz%r9Y<>X744ΛI^J^dggB# 33sR/h2 7nGXu5kHPWWNBLaʼz*5!!a۶m3> 0?&n"N>Fh(//'Ț5kȜrKnnn/"ynll5m^YY ...*}m͚57oxEBD<;}/f͚<==#""HǞN;s El6Q̺g%ԗnjjjwUqq񫯾JQڵkܹ)"n߾)ۗڪhbo\\)1 =|//POO_{rr-,,fsqq1vT#1_e@CCç~P(q꯾>LYی<A՜y_e755EGG+ʵk>h1u:ݪUD"QXXr̙6COerr?ܳgҥKAxxxxxeR"Dd*?LDb6u:]cc7dCnReZ94TO"##ʕ+o޼911vDosNVVVXXBprr2cccwŃ8M?~<---44M,tR1JKKc++x8qҘ/{V8iu14/ϒB!*!B1LB!<2B!D!B*!B1LB!<2B!D!B*!B1LB!ļyLg}Ⰿy|k!`P38Xx1?Yp04O9<2.;9ShTvEQ]圅' /9 /^V8TBCCCBBݝFx___MMMEEhd;! Xww;w5?v옕 ?>~_d2_X;V\ ?/׿5 g;G2/_N^޲P(~L;T"H$__ԫW^tl(RLNNnoo?s /B(޽;55U @ d2YLLLff'X rfMIP(SNMLL$bEnn+`bb?z8`)Hbbbk@qYvCbD"9x𠷷7=|_KҐ(P+.\v)//RoDDkhh???~~j08p 66FcsssGGX,񉋋suu xWj߾}@wwwOLL899Ź$%%I$?H]X"77(^v#BWe._4Gbb"\Rbvuu}ǣ?ٿD"Yvm}}}[[;Q2͛Hm۶ݻo6F2lܸ---?8p@PPBضm_|R tRjGVI(FEEegg_r0%''o۶M LgΜ5G9rh41mVDGGJLhhh())Peh||/}6xxxlݺqqq!sL&ɓ'hN8 !!ATHLL( n޼9jhhԩS8ݗ\bbb#f ***؎!8V uuudӲe؎a[[[gmp~a`xx= 2P__4kD v񹹹dvLˋ-$$'\~ڵklGk<##(\QQ199АP(T*1fbb]$tttlV=J&?<;UUUk׮ IIIs}E(,,/$^'/JӤ4L _JPYYy9#Baԗ) ѣG}H$`98F^3kښ {t7F\A_VzVjS=nsLNN14do2_dpI#ByTe&''{xx@MM yapp،i/___7|s޽l&zW.) 5TUUUWWK/tdPv\\\\8@i>z?g;"lFSRR@חoԬ[+>>7Z#Gv䔖622z^/% ۱0Ã7SOOv c9vضm233BalllllD{{{cc#=Y|.d$u/?ʰT "<<,]YF #G,Ydʕ@.lݺڵk>>8tڜD"!u"o{5MMMb2nnԩS9XiiiiisJJJFFF@@T*t3Y yT*'|299ϞAAA;w2cccw\͖,Y*622rҥ^{-((#''les⧙{ԣLպb˓6ݝ499y֭[nٳ'==]$mذMj'|B᯾W_˗/9EqZ]]/~ X,bߟޟHNjjBv 5QQQŬE,cbb؍2W3gΐy;dH$2L&9;;[i6sb.׵͗.]njh1}R|E ܸqc6Es}Djjjzz:^~}6---FQ(:"R+j2&2+ɒdo>k8<ă";;[T^|툞J[[ds5Drf3L zkBBu>}gϞ=}& /YL&}x>| ^_ܹC펌#gYd;v :<<<^|Eґ9::qх .T6lۛ>DgT*2¼W"(>>TWW-222m uww{IIIAAANNNFqllmd2MNNvvvVUU9q % 7>YX̹,*sxd]&vr(XEQb'gWwjxzK$ x“˗;7^+-_Piiil0gn=l6˓ Wzd6zZ|+Yp|,`Vq=_ZhbVtYJhXT*e;'1>>t·>n`r:Y||;/GoB!k1D!B\U&B!bV!ByXe"B!aB!U&B!bV!ByXeWB!bȞ1DEzQmlL(****44QN{{{SSB|9q*_$ v1^+(6 iQT _(AZuryB{EQ~~~v FrgoofoZZ gޖ^̎\!@"k*3:-)1 _(tVʬ" ?-a%HM,_$ v1Y) )1 HDQĄ= ̛5&f7̗C˧d}ޙd|gB!D!B*!B1Ϯ;!i IDAT9Eqñ9HDV A( wwwZ=22v,67+a5^^^dj;T2OZN{9$$Ba{{Ƈ" H@TVWWOMMm-Λ͊DXL^Dòq+VӋ/?LdB}1S%y_e.Λ͊p^&B֨TIv,000`0 xLj4ɤVZ-ެ"O<=1NǞΞ={Y[ö3ټy`qެloV}!ByXe"B!9۷/55u2kǬsի\\\FV~UU1GVZDjwޱWt {ףʕ+.\?Bcǎݿo3Mɤjugg;wYYwZʼ!!!?~!2?O+[lYny[z%K||| Hcck4 ۡ!*%Ko.wBgRRRSSɓ't;ʺuہЃHg[6&&%\ϲen߾}bL&۾}'BaVVVAA-.]jx_& >nC*sf 7P좲ѣGV._ZmSSⲡ;w]-juKKȈX,QQQ?>̧7nРRV޽3ϸuvvrٲeE>.]7 !!! ++KsB3 `Æ `4Ϟ=ˏxQٽ{ 88vv86D?uvv&˭ cF7t:(ovD6! +**̬yjR8[Vwttttt;%z̙!<`4G{.Ç?iq*sZI&з:t{n2|֭zaF`` yaL%;99fܸ4k fAe˖il۶Tuuu ZZZs۶mlcBdNRRҬiiid"DUU"Jdў^$yzg'3~]tü,4VeZb[hnٲ}><04_^]ΛeZߒ< ofMR@&%$$L)=ʿ R3˿˚5kvY2:|lCl 7oʔH$*ec*@d"SzSNw#Cccc&ɮL+%&ᘅfttU`jjd:?8;;cRԶ1QEEqs S0 777@Vܽ{޽{pݿo|ړr m۶>!U[H5@znnnD"}fSSϞ b7 ['NIo&'2훧$IId׮]W\\̳EӼtm͏yrhJBB|JcLL/--|c%%%m۶g1qUoT*nv8 #2ZM&,X6$o߾ W~2ѣG_|0l.?я,9ǿ{"xReAJ |%&G\.gǎJ^v8 ky^r09-[I{}?Z Xllď1gœ*( 2XnK~dGçHIIIIIV˧#h8Лe >}Çge;7L~AT]]]]]]Ef/j@bb"Ëgzzzð@ xg4HQjhh '&&ҏiiidWzLHD:vJL8yB,!ɩd&(lnpJ(G>ySSSI#>-t^7XvP(LLL$ H'Z/*))ٰa7'LLL֦ \VVvh6twtiP(ȰH$z׷mF6ǓLd)((t队Y755\9'N,Y¿5CCCdrxxxFFw߻wZQQ_[nfVXAtwwra}ǏirαH$k <2HW4O{P(#]n޼ɛc~rՑsi}||<MMM.JqsM7dZMo 333l6~Bٳg֒9RGGǣG`ٲedA |ڱx^_cǞl؁741aժx`~9-[mw\ǫMtww޽[$X"11yddD$y{{GDD{hhlksQQQlb{wT6ٓfO4ځBA6YfQP(:ǃ3W8:qtP8(*iHttKڤItvs?oɤ4MEo.7vϜ9xb@[jc{̒U|~ZZZQQz7uuuwAngfddzhh(B)))6lŃ/wO'fzb6njSN-X7d6663$$$ 'D}yyy&?S7,sd.˗/Ϛ5@T|3<iXnx𣶶ϫ . YIB  , A-Д$҄xY  & -_|̙6@A[&5A|3- 4---. Ěoo w)xm Y&>2@A L|2K!1n\?4% qÁxW U,x'Ch ebJiBuLe_"O>4\t%jL}4[, " %"4e`s "l'uY1,x lm?H9!bC \qw^r !DJ,_3]&,x=X׿EJ_ !d7|G4DM)-vh7 p)eY9ֶk ޱDu YQ,xw\QoKL`9>2@A L|e,d w d2T* Ai"b1LG&`BAeff"PZ-c ^@h˗/T8LD?vB92̔?/VBaP x<[lEQ^^R8RT.tq$bڴi/ RL&'PFȑ'˔qu0EȈ}b,B(???όc2~Lqub DWʘ vB=2ˌ_KG&XG RK Յ2|e,+X,enw'N2,''f4L222d2BdjpOHg͚BN=ʼncbwP'%(o'R.sM𿃶L >M,"D*gϞ]XXVA;vիέyyyCCCped6fsKQ,NIIIk֬p8NSx<@]RR|/۷:… .\zdtsνD"QkkÇ|9SQQ1w܊?8\E42#NEEEiiinnH$JHHp\MMM'Nѱ@,;׬YczÇ_s|pj+I!.*YfY`ߞlll&M:uԩk׮=uԾ}`8dɒkvuuk`ѢEyyyr`l6V?=zc=6sM6.~\9A,?7ndX.ʕ+[l!Iի۶ms\==='N6mږ-[prssn?Y1̇~_3ghkkklll?/rnZ__?k֬%K;mᗜ>)) #yꩧ<ϻK7777+W믿z{IMM}[r{Y,ֻk0>ظ{zĻkΜ9/֭[z뭿/k֬VkCgЖf'Tnr}zeeB555W.//6]pJ\.輪b0yyy*jJTX,^]&XXfcx"'I&IT\lth\\.ʕ+ot'O̼x"EQ!.c0F@ S>P^^h4++++++BG}7=xIgg'BH.!fѢEׯ'IL6ĉ.ј"= ;wѣG:N DcUCEE@ ¥wttYB̙3$I,fi4PD$Aox<%%%*;Q(\.t @ HMMMHH`0###:NGFd|>( T*> ,..%IKKSTmmmbtvvz< %LbJR&t:Fcoo/G*vttD"HDPgg'.-))oe2HhW~_wEp\TjټJts,>`b8??`0݊=Oss3SR)))TV'f;;;U*;|r~~>~"f3@J1Lx1 ACSBȻfɳfBm߾~ Uc_"vu)nO6n`Dtt | "HPL3\ IDAT`MLRx@.r9}B&fZ'cbx!;BAuww B| `0}lHp8ikٮ^j6J%=bB~|B l6wwwԌ wNOOGiZ^/ q,444s@B "BYYYC+O "p7ۆ+Wx7$z<^Nv=0x<>f񖄄ۍL&C~Dl6^?22hB]]]nv|w'|~j6|ރ!r+W9s&B͛7ӓBˉE[n糄-333駟W V{1Np†o3m4slfgϞ-fͪXOAZoCpA=zOQTzz:lll_0yt314~%d;1 8d>hOOnX,xޞftEEEtZ-nQ*Fnn*S*\.w nf6: U^/zzzG &T8]6h4] a(jpp%JId0R Atnu8b^n4tހ4L)))bx``!$IΏǪp2"Jdnn.~iŊx,5_QQyfHR30#z<N1ϝ;FAAw"b":EB8p@.)G?_x`ؿcƣ/uuudٲeҥK>K,z-XzgQQQ^^^$o[}|rAotrt:N[300T*lDVδ<hLMM> `bF?n[VXd2}x!tr|pp7&)===11_h>}t#n!:˔d.˻;Ud2\Nde`Xce$I^2:+GMo7bX$9@ʏM"p?x};t\"XV6LfqR(X,V__}m_92ɤVe2 ƪZ 8Ul.]2eJt-PTTTY>v;XXXY\3?pnL2[ZZ^xtT*gϞ-J/^x)ܹsW^mX^}U8cƅO/^Ν;bܹgѢE[/^|%zo[$GO _݋x<"g<nY=onK$.;|&$$xddd>ݎ[L&v'$$8_t:O;pfODk6VwС3gX_駟jkk-ZiӦ~WSSSSSlٲK~'ŋ'&&۷/L2}#y"Lo]w!tY=mj瑸%+UVVFQٳg񟹹j:07Ix„w,B|+7z&N|1= |>߻ߙVqɴl>iii ",rY[t  F ɼ9CƇ:O"l T3]RT@Fl6XxnƏ tpYi?55U&љ>9X5b޹s.^xM7UTTr|Μ9{駟=srrVZUYYۻm6<e_}UC Gmذ׿oӀW^ye1eN2eŊK.?<܅ Ϛ5رcE^ |<~o.++tMMMSLt#YaחIӖW*p8$ &)JqOp6`0njnRi0I$6wm{MxL$Y8s``@V+ |$b2x tI.BCWBHPЋ*Jτ?p8E*zax=ы\jū|]Ox ^oh4q.׮cA .khhH.XсU# ܹ^zu:]ww+v˗?SvKR==رcNzy'cBy1^]xd}y oݺUѼ=B?>ymRSS_y啓'On߾{Ylںu+,Bh…A ?x?WЭCa\./LXaa!EQǣEuh_#%' 6g,{7P7e2V=rȑ#GL3fϞ]ZZvݻwQqmC{~LDeƉ۷$y-{;w^zܹs>Ln:w,X`hhV @p9~Je4kT* $4ZST[#[VV6"1ǏoiiYz9su *@rI<{}b`L555EWr:Owq,3"ر}ڵgY&''W\ wY@p(V QZs3D&2#QKKK 2@A L|e,8YBrDq#H,\?% @bx!o'@b e,;!'ˤ%AT X({ *9D,CsHzQ!9$=,C4Vlst?` ȲOCDqA"9D=gCҳzI"9D Bgw[(G"s"^!c#5">6^DsgK25">6^!c#5HxMD>6-_~c_>fwzpaQaQaQaQaQaQaEXVe7|mTZ/ett=.3;/{N{s~N'j-=#2 ","2 ", 2*", 2 ","2 ","2 ", Š\*;w9Rtb?|ϹR;}G{}|ڿ/||ౖpaQaQaQaQaQaQaE.H=) >+9}J>+DZw;K((˨(((+r:z*#NJjP.`ח?Kw7", 2*", 2 ","2 ", 2*", 2*", 2 "ȕJ/vMy(kM=|ߥRKtψ˨((˨˨("W*ݣӂ %v3S9qw37.|-=#2 ","2 ", 2*", 2 ","2 ","2 ", Š-;3k{K˻b7{w:Gow'Y¥{FeDXFEeDXFAeTDXFAeDXFEeDXFEeDXFATbNxkJlp&%wp,?=3*}_O*.3", 2*", 2 ","2 ", 2*", 2*", 2 "&+*paQaQaQaQaQaQaE7]tψ˨((˨˨("כ.S\gDXFAeTDXFAeDXFEeDXFAeTDXFAeTDXFAeDXX¥{FeDXFEeDXFAeTDXFAeDXFEeDXFEeDXFA9ۏ%\gDXFAeTDXFAeDXFEeDXFAeTDXFAeTDXFAeDXXBtG]|9})ɀ((LO~M8/||&ylNeTDXFAeDXFEeDXFEeDXFA9ۏ%DJO+AeDXFEeDX'](L?{ 2=ϟ_ޞE2Ae0S}dEXFAeDXXBtgr6bLS~2<6M˴n|02=y&8ܚsd.28ӛw,LuL{Bu-GdZ{ , 2 "~,!Pʻ޾T_$4G]d3iۡl2ڍ2=y=PUй˴G-ݣUhz|}#p 2}GsoV2("gK$2=zҍ\݈) ڏ^ɭ2;^\)F 2HJ?d鮽Qt?)u}ҝqLvt,("g/R 2=zҽNsT?ah!,Ӳ vR =W\o(V˴c~3 G,yq>>FV[/",ӲX_wцLwfsP`~޸DXFAeDXX¥{Feztt_7F[ CiPPyzÊwiw^`e6ri'j6ͩt7,sJYtG'"aެ=rl(߈ 2{=VP9ۏ%\gDXGSebh$_||)نiI\(2wǛ9Njf>wyKsV 28.5ڒLfӵBt_̮'kΓtwcai]npaKwaǛ6X$d~QLϚwiFrޣ y:yJw"2툥{|^d8^Ο+ Y)߰DX}u2rMezre5;vfƃEXuQn{Ktʻ<9Iq?J b",ӌ.Sҝ=y<^?sw˴tFfr=* ",Ӳ#|f2 뺹 , 2m.3",ӥYt'Q.aDXU3Yy@XI5rwK7<hL̂<;[|옘|Ss*2M}agAMP!aM1", 2{=tۋ%\gDXK/ݼ$/3S(/ZoafP|^,zfpKRL39LK^WxGkhz<])2x]#b׍K{+eDXuPn{Kti{@V6n$mH",Ӷx. 2<śSfL;:o 'W;}K 2;rYnFk";^}o(?sau\eLt[KQJ"dFeZrxǯ00'2MtW)ek:FVwsav/ݣ̫G)Ϩx#,"2=n",ӭ'qx˴KEKtψLtMY+2-I.Fev|xagc#=XL!,ӎkJz9RXұ˨LWfSbAezueDXFA9ۏ%\gDXFAe+[3)~,n/(LOƲ~] ,"2 ", 2*",ӛQo̭1ۃT޴EXFAeDXX¥{FeDXwu+2=ҽ_eDXFAeTDX;7ۍL{_08("gK(LS}t8LOtaQanG8Џ&M\W-B/2 "~,=#2 ","2 ",ӓ.EXFAeDXFEetǪ,ʹtU9ۏ%\gDXFAeTDXFAezҥ{(˨LelSddz/ ", 2 "~,]<]!YD=,CsH*"/w5gWȚes`E?/>D=gCҳzQ!YD=gl>]Â` ~嗗g"szQ!9$=EsHzQ!+t}OSJ.#39D,CsHzQ!9$=,C4Vlst>YO"jw#=EszI"9$=_淗WS]p͑ {x%<EszI"9D=gEs!8Vl{$sgtd GsH9D:gCҳzQ!YD=g[~N8:?XPz.c1cåc1c.c1c̝p6c1cĦ_gK$ Ge_Q; !qYxI"9D=gCҳzIv\;~ } 4??QP,CsHzQ!9$=,n<եVc 76JG5 !4 !YD=,CsHzQ!YֹyJwxۜD{ |tqCBqCҳzQ!YD=,CҳlU;1+>w ]#!8 !YD=,CsHzQ!YV6ρ~Hxً`P5x xM$gq Kt7*AsHBHxMDd_Sa/9qQaQaQaQaQax`=oAWaQaQaQaQaQa[o;KntWU((˨((zKܩt_ #k{QUa˨((˨˨}J?;}/C+;n((˨((zK/Ma>?#~lWaQaQaQaQaQa[oLXޯKwxG;U((˨((zK/."EU1="2 ","2 ", 2*", 2 ","2 ","2.ݍU((˨((zKt7*^Ts*", 2*", 2 ","2 ", 2*", 2*",c-ݨ{QUa˨((˨˨Kw"EU1="2 ","2 ", 2*", 2 ","2 ","2.ݍU((˨((zKt7*^Ts*", 2*", 2 ","2 ", 2*", 2*",s|}G}ncSKt7*^Ts*", 2*", 2 ","2 ", 2*",ӫ|s)F3 a]\DXFw7yY=}kpnTwӷF7'3ӢY9G/Yy3yvD_",Ӧ׏'@X+,CDX+s9pnT;uw4]Qkӛlw_Zet_Bicd鬹h",Ӈ2Mo K'˴HWE\XC˴t;o . IoEzg[9˴Kw16p>l6K\eѥ{,ko642mZǪ#2=Ε..mX¥Q3xWef~A`; O.l|&''He4_kukPi7$2}]m@X]7~] ,\l ,Ӧ׏| sDX'Ӟl^a>1r,ݨ{Qw9:A;Q+sey_^f%>2m:Jw~#'X{a>V2i]\sҽ#e/Ri׏ a~ځL_zX¥Q𲂥Ik_0nL曢:[+\qa>\_&ri_NnK'<׺\#,ӦkX3DXWyLwn2.ݍuw)ݵu3:SfN'lnyqy eڴnL瞋Lf犊9!,c-ݨ{Q9>}-ҝ| BXM a,#[DXBsp̳M놽H鐙uLnc͋LtW+*愰Kw"Ek~L-ݓ@7 ׍AQ*[ et_@icdtXAepAX ,ӟ2vtq^$_CXMEX .EXG[¥Q6C|vۻ[.69gRxs*s;fbcL+(2mt7kݷFC9S;\AX?ׯe.{Ya2me5/2ݘ{Xes<pnT~lm 8ǟf~r{39}{}k",Ӧ.H6`=RٜSkk>mYL ?&LpaM ,Ӧ.fYyDX/=V,ݨ{Qoc.^#+[.69bv"q'r_@icS eХ;*6?>\9o",ӟ2m8}sϧ{etk^ezrˏ1Kw"Eϲ.(Um0",Ӧd3hy6˴cR@Xח\ePof䬕IezqiFse^z˴Kt׭Ae2;~jn",c-ݨ{Qoꪋ]~W.+?3^FXM]#'J2}՜Cu^ 2(S_]s/˴Kכ..mX¥Qřb=~grR:)t=Fp2AeХ;q(de{zKt7*^Ts*", 2*", 2 ","2 ", 2*",ӕEX'B 2.ݍU((˨(kEX/$;0ZKw"EU1="2 ","2 ", 2*", 2 ","2Y32-wzKt7?/OU2(sEszI"9D=g1)}9>%}|V6uNe}RzI"9D=gCҳzIⶲyTPY97Ed///x YxI"9D=gCҳzIⶲyT_}->y#k=8 !8 !YD=,CsHzQ!YV6ρݏ׿eS<噏JEszI"9D=gmgt E{Í0h4 !2 !YD=,CsHzQ!Y֥yK@xlً߫sHuCҳzQ!YD=,Cr,6m1c1Ƙ:\1c1Ƙ;m1c1 nc1c1NlEji3uۭGE/vAy-G,CsHzQ!9$">)v5t_96 ү? !:7 !2 !YD=,CsH]Iӥ.70%ɂDhPC4 !c#5x pWvJwxۜ}sۦckqd=$sH(sHzQ!9$=Y=Ւ>ξmSv%< ;qYv7RqAHxMD?p`'!9$|lD&^!c#5">6JvKAE|>6"^ x w%;Xtoha' Q1="2 ","2 ", 2*", 2 ","V.7Opw|9yY"섡 2*UDXFAeTDXFAeDXFEeDXFAeTD^jZbg}oϥ3~ɳ>?8 unWeTa˨((˨x7ϳĮ=,~OHvN ",b{\EeDXFEeDXFAeTDXFAeDXFEc?QyP-t_tN ",b{\EeDXFEeDXFAeTDXFAeDXFE]5-tGuE3f.Ngrû{-k(x<܏>>6-yEa' Q1="2 ","2 ", 2*", 2 ","5{a4}Y2C۸"%7YtcfOkMǥ;˨WaQaQaQaQa{ځRo6"{aGОef]{]ia;wҟ[,-WI8ss wa' Q1="2 ","2 ", 2*", 2 ","쎝b*N;JKZKJ0DXF((˨(ۋה]ށ֕ԋrSaog.rӅ\^L(ݷ{;= 3˨WaQaQaQaQa{˻κҽf_KᅦTaĹR8YϒoHW0DXF((˨(ۋ߽tWKc-t>;|=.ia~<|R׳>oR>ws} ;a(9qQaQaQaQaF[Q3=,tz)qY$c{R tͥM&ɟdߟ9;a(9qQaQaQaQap>;a(9qQaQaQaQahtۋ˨WaQaQaQaQa{qi ˨WaQaQaQaQa{qi ˨WaQaQaQaQa{qi ˨WaQaQaQaQa{qi ˨WaQaQaQaOߞ^>Qͻ׿}^N| D^jZ¥"х>oޑ̌˴o~!@/ 96{I˴k|2˴7ߐ{a",s{=ޝ [4EXM!,Ӟk#?'2 ",Ӆtn.a'l $2-;W*ХorM ",Ӯsҽv7O,sKkՠKT=>~\7,Ӷ.ݷa.1Wŭ%\*N],n4˴ꚍyPtb3LnϑJlqf2rq]K7LۺtRe0/ånKAE y-9}6}|GiRX}i.G,ݥ^xVni@iKr8X#u]+Z'a\~~k wau龥aZzX+ۋ[MKtT0ZAx=eBa]9:ouJw5\AavcDX%񵮽jt?]]9k˴K-EX2 7F+ V.a'Maә6#lQڒ96\_*FɊ?LfQ*QᵿPqIe{z=X?;es埰Xy@Xm]\{#a>8ʆYմKAE i섘mj7˴h~!UaRuLfUtnԼCRenz2Yx~y^3Ie֥{N=!pi[9K^p>;a4kQw-Ӧ4)ͻ{F{ ],ҺAX M$27qq}BqLۺtҽ]ŭ%\*N5(r&2:XԵ%<=ކK &2ҽ<̉u\toWt]{EXm]o)2*"l/n5-}Pvhl@fW\@iۼp+"96u.}\KeZ{/;šp龥˨մKAE I v,92oSoXҽcDX k^۹cls;wq/kiOXGëΧIe֥","V.a' ğ]fRq(2g2Ltå;Z?;eړ=?8.*~fEXm]o)2*"l/n5-}Pvhυ3Sz 96R*?'SZm6=>/T|j^^[z2Yz~Z](˴K-EXFEŭ%\*N͉TY_4,ӻo{ u av͞L^v_t-LJKw~v˴_W},2m}KQa{qi FkMܝ{ezWt$a ,ӮoU.Q}v|^DXm]o)2*"l/n5-}Pvh˵ɺ )2fQ)wmn=[Sil>J{.Gs#j>CaymΗe֥","V.a'\ALFa;(6+Xk 2Gtъ4s8뎏J;gz-Apkkƺ9i[9GRp;p>;adѷLiL{7u.osm幟, ",Ӯ|Jw iM[5 +˟6@X=+ܼZj˴-hXc=0Kvp>;a㖍Y ,Ӣܢu3abR{favX_]^:>-Jʊ7fLۺtҽ]ŭ%\*N͸|B?C/py-Sil>{pnl?6,s[+UWiukc> 2m=Kvp>;a(9qQaQaQaQap>;a(9qQaQaQaQap>;a(9qQaQaQaQap>;a(9qQaQaQaQap>;a(9qQaQaQaQap>;a(9qQaQaQaQap>r v8'XNA(5EszI"9D=$ۏ[=Yp>.Q_ 8 Qk"9$=EszI6 z.ol7+'v8~'Yx DsHxMD< 6PUW6 NGsH,<,6"^ x w%m:Xt ߌGl=N%cdN"G2\<,<,΀lypK9DsHuCҳzQ!YD=2 ֕lo5kcu6c1cL.c1c̝p6c1cK1c1s'Vg>{~;}a '~~H02t㈿xij=gCҳzɭp_pM.ݿxg C3#*?Vhfg4.wʨ;q*(˨((ۓ[hKܵt7cOOqzڿ=y?_]m`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEkT+>U"t!n_ėɿr`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEɃ+\W?O?̆>Fia3XUa'NQaQaQaQaQa{rhKl,phaA]_Fu^E؉SAeTDXFAeDXFEeDXFAeTDXFAeTD{rxK+s `ZėEzG')7UK2XUa'NQaQaQaQaQW-6s''.KwBE5P"ĩ 2*", 2 ","2 ", 2*", 2*"lObm]HmtE ĻHit]8DXFEeDXFAeTDXFAeDXFEeDXFEɃ+UuY‹F1QvTaQaQaQaQa'OX{p9tȥ;ʨ;q*(˨((ۓOu_ KoM?ҝ`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEɩ+i鎋w˨((˨˨=9}J"X/.!kO+*"ĩ 2*", 2 ","2 ", 2*", 2*"=}%}hF..[/sA-`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEW-q۟鶯2XUa'NQaQaQaQaQa{rkm ;`eTE8DXFEeDXFAeTDXFAeDXFEeDXFEɭ}%\ QvTaiw>*߼#DXFAeTDXFAeDXFEeDXFEɭ}%\ QvTaiR(˨˨=Kd2"N ","2 ", 2*", 2 ","2 ",">.wʨ;q*(˨((ۓ[hKtA+*"ĩ 2*", 2 ","2 ", 2*", 2*"lOn-}˨((˨˨=Kd2"N-7drSio>yaӷ蟙av|wz{闤Ae1B<^˴q6\eQ^>et(Lf_=Kd2"N-=P]WiG2M1Kl~繱 2Y_u avT>6Ͻʷ޾Kw(LNn=Kd2"N-*]'XNYeڑ|+G-ݣ2;A?SD!,ӞkKيwpiGc= ,"2 ",Ӳ;T'іp龃 VFUD؉k"2FX ưP7&6Qe1Ǜ?ZtFkfqO]#K@X Jµlk'L߆9֝KiEeZ6`{rkm ;`eTE8ut8i\*޽Ƌd;˴c~7K_*P-xMd]w׾s2|l{CZoծ^-`a6\ֈL׎{ɭ}%\ Qv|\NyPK*6G.ݫ>be2Y_2zҭulsΝt_Kwf0Lfkcsa[!lOn-}g-m<ۼ,ԱxNl}=P?cϡ89ұ1}Fn8 sb^ioe=Kd2"Nݹݾ<۴!^. ,ӎk3n a-NkEX Kv_>g;l]DXmoS֕+ɭ}%\ Qvao/vS<2ȋq:|xkgDX=Y(Y.=f鎎z6a.XttۣX¥2XUa'Ζ7O[. <ۼDx4'eqDbT)ݣ0-",ӞkJR K",ӎsyt޾|#,Ӷٚ\QGn{.wʨ;q6i^@w\ iTmrPeڱns=գomEa\SM1L;*zTtt܌EX-~sf",">.wʨ;qgAAeڐlM(eڱvs~LM՟8L{I\L;*ϝXQa{rkm ;`eTE8P$j, eq9L;o)loiO\>FiGcå{y1;_ ,ӆƝ(D؞G[¥2XUa'T/ݯ%\lqfj,Tk!2tX5uN9بN[DX]-}gstgΔ?뎰L;\ Ȇztq eڳt2|lt?ZeDX]-}˨((˨˨=Kd2"N ","2 ", 2*", 2 ","2 ",">.wʨ;q*(˨((ۓ[hKtA+*"ĩ 2m;5$((˨˨=Kd2"N ",Ӷ.ݷaQaQaQa'іp龃 VFL NG<˵mJ1f_!9$=EsHY=KdBKwʤgCҳzQ!YD=$ۓ[hKTکW]6&OVJ_DNG/<EszI"9D=gl+ٖz`t۩aV_}' ^Llxȯ?9=EszI"9$,W-@UѲsw7jv.|ҝ<)jw=EszI"9$fbR.ݿ_zCeh 'ԣ.CԳzQ!YD=,Cri+=6bN!}>r~9ӣHys9$d' υ}Q,CsHzQ!9$=\; եc1c1utc1c1w¥c1c.c1c̝~q/꿼,͵k,2kqe`2u-z'^\ޫKw5~1^_'m\ZcZkn)G=oxƚ^]7cΰ9TOkd\=oxΥ^Umc7cn/[ccula֪>j]oz*ݾ r[}oek,<xXkjw[U}SO`EZkmaR_&쵲-$MqZk6ao 'il>vpXk"ZjkڄVv%,g_ӟǏIԫ^ Z*®unۋ} }}ɴ {muQbs?:2OVQL'rY[epXk"ZeoJHK{'&r7EK* ^ϙy3s>D,M'N_J*Y/1E؆ZkUaҸ)w%diZ]}Ht5$^לpXk"ZZWBopx.ǯ7{}M_yɴ {zZvK; '{hl>,~" wk{akVU]K#nM"XI{awk5 Lתn-t;3.r GO"la֪ktzwt/RqFNMkzoXWeD{$|8B/= Z*®tý.Jw{'&g5\s}u&XN^~h̭|d㋰ Z*®|^}JsNMkz?k^ƏLlnZ.zh,Dq RXsj"la֪kii:8t/2|oS]Bj5 Lת~q_wJvpXk"ZIQ˻gsFT&ڤ.O$|~ZkUEصt#[?ڻMkY%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk"ZjkڄVv%\I"la֪kݯiZp~&c Z*®vMke[¥I/6Zk6ao 'il>vpXk~c]K~MK4 6_m:ZE]iZ*7~SͿr x}^mpb)/6mYK1c1cp6c1cK1c1s'\1c1Ƙ;m1c1 nc1c1Ntc1c1w¥c1c.c1c̝Or&IENDB`keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey1.png0000664000000000000000000001764014600607066025310 0ustar PNG  IHDRU8sRGBgAMA a pHYs+5IDATx^ah$i~_ǐ 4J8f5Ȥ Ehɛ1GءY`$-4D RB^ļPWɂj"E N8'DHnֺ~w/ROSR%~n{[U~S}sg7ARD?Z-G+.peIniar)6B-GE }5,//ns  6 -bp  6 -bp  6n?mfgY{7myMI˫dQʫ/PN}y~o;]wpn^DJGV27}umGV2J4]j谄Ώf4igS9h;զR+:<4ӊRC 'ϥzq=&>Ѱv-G|ʴŎXnn E+ʰiuwrcwUq4\9{R 4eʚidڍbmcp2tx~SK;*;-I?qiz>1Ǯ%ZߥR3^mji]P{EKi@f1{smku%_jveC&ݮs?W=a ^>z.Л\[Am5SlCbF.oC=ӢjB=[ӹa!(Ts]!OO*A_] tܭov*=ֶܶVjI'tS^ARmΨJڥyݘ}.7@O麯}1t8|&)7sL^x\גڬfʽΰ mK:h̭pX M3a;K+0NcHKKCpjܭ]#=]]M88fl&\oQDZN sN ^xXBvIGCG-{V>PG2!y)*=Op=_oٺnNދ7sMۖa s׽UlWf1S3C[LrZfg&l~{晦tJ\އ:(<ܭ&jZe0 뷺OBRC3}^ʘZǰpUndFm qKVVGvqW3,i`˛cm_isRRv+ۿ\D-a~KhY_]_b[YoNz> M]^4L+贜֟VŷޟP/3,j"AwҰRaNK:]iͰ] 'Ş`)ژIz;ېk3NJ?tht14ֽ[cn@m*P^#|#11fxt s*%uM19>5ۣ ^+ x^BB?wA \oCg\>M>-iߛ~iarxVARD?Z-G+./,,hkkK)-X^^Ύ!ОvX˔_ι mgEw[S4?Z-G+/,,ѣGvImީN{Vp{5ۿi{cevmm>{gjJ$!GEroW1lι{>:V3nmmٹΎ\$FqGEѢhQ M߷K駟Rím$ hQ?Z-o*.?jrn<L%i6 1Ѫ6`. Z-1PVDVm5 ڶr5 -hF@lnn:W__^%; 2sM$0Ȫ]RR7S~I/?5VmsSzs;_‰%؆pYip.pG{fQ^+vK~[ſ+۹j@|.l֛ * 3)7g_@H3j-\v"Е fRD#iiBZ6ϝՑn5җ&ą\lFmgDnu8!u8jq'PjSg[~=frtA׺?A<ܮOV쌊qM&͔՛i1)jzN8jqX*YMٙVqJ*yl*W9H+ Wzl>ӵS.Ѷ3.:ڕy6݂^폇5n04ODdcAǜ`wΎ5]q+=ai;"޿#}^Tm4܎͸cRȼ^*̥tץ֫N խO9ު{1\{) um-}6M](Ygs*8wӭE=yRM؝P;]~@ E(wqX"` xc9y^49>-g[K'vh·k)ٶgg$p7rFͰu-ILu77澷Bؤ; !4,}sն" le?4qW;'7PqPOxX!4n h2O p"\ ]pm M0y-dop5[9 LqѰ~=;[i"8ep 1wNh-@ j- &Z}x?~p 'pM51j7 jg?+;^_}7\ jAdtտZ %ommM=s񶳳]YGEѢhXi-7~>ri[p{5qrZ{yUg\pkZnQ۽{35W% GEѢh\~g>jkٹvkk!099y4E$FqGEѢhť~n-_jڂ|VW~sr+[^^&FEѢhQRn1_gn>z{.SGᖻ%04&xynHPRo=-Ee]$L'7 U_V+;M[A@ln[8W__^%;ROD›Fjvuζ%FsEdᶭ?);fp z:mYHOyme:sorC$ܚ`;z{Cc٬f;[J;*;uӭEe,jnvj3f{r8g͔՛GpGK{B~^{v55_ʆ4]لjhyqNs]#%\c;d[di9 mCM={6sN->-k]]n<ohɤH}g3n-;L+xAfR+]MkDZqcpZ7+̫9=]Ev&(H.:oM;ѿɜѡTiO+U|ʜdkɶΔ{ukOAkT啧:dS<7Eom}] }S왇LZ]b[MEθ٩Dmmx '?kOןtQ;Ztl1#7pV\VXotXv2^J޸`Fʣ/'uѷj{_ClMi&h-gٛWμ>/e`P Z J{FgCйq6\Z.8MzFޔCC"u}VPf/f}/{3 ׻ƴ;VP=y)V,|P+swK~K9M:w| ,j%5!9hNS۸`,h"TfM?mAK~F&kF K؛cikkKvI02R>]p]^^Ύ5;;K 0ϟ߽{;&<ݷ4f-h/,,4_ yy.i [\ -zTp9>w~4f򬝫n]fpkZn޽{GEѢhQLn0ype599y4E%qGEѢhť~n㐇.{umMU믿u-B-G[Py/n[b;.[A@ln[A@ln/?џ|qm^cm[r~Ӵ455MYuebZO_9(חWpaՇۮ]AvʞkVz5*zHTwTln^{q %z??gS-.[㇇:<ƽ%xi-JWr[ֽ3t]s'&ԟU2٫Q\WgP~w:n5 Mw-~WڈF\|_Uf{ro`'w_FG"qaz>-_pB:e$۳'ti>_P\ИwƑ_N5oO_\Aኆ'jcNcwRQg0ܩpޞy`u׵Mh{JJC Wn?Uu]xWӚStX}zZ,[n3+0tYByC/S/'uw/^HMJH+ʸv[Q1=7w@[LTݺ;<&Qz m?꾫MϻT՝VM)pa'4YZ|Agi"~}ԡ.ModBZR1Mtk|w@s;RZ mxۿ?:'.6\nVC 毳$cښmiyyY;;;#_;^>~p.~_~ǚ=5!G׿::|K'լlVFPB,Py˳v[s:>Gv x'v5whACnG eHHE;1}g# 6 -bp  6 -b­fpy 6U_G96mm'EwsS4?Z-GԿ<w&yy׮]wf5-{Uz9ϻkD'q:yqN~>5֖C&''hGˮn `կz{ǯsj޶KPo}}_vp n9~FjZwK@ln[A@ln[A@lnnζ$E_ğQm[NSSSvʩ9w*uͺ4!_Gjp5+|ƲYe4w$߮6ݹ-m5.UpۥR!?=D{󚚷s L#(g˚gԟU2٫`Y{; }ن;8.ǯ "gnn(YЋ5֥쨷 y+;+$ &ϛfTL}zOBdj릴~{6sڻB{{/]mywʺ B.u9.(;P9y,/'uӷz{JΆvuZ,g5.}ҵμ֘.,we0ڛTfMő4v]Lʻ~ee|'>,靫}o=w4Bͮǯ g:,ao>lzt^؆n5s Y/ ҵsQ8~]9"qppphִmX^^ΎiԧUey}]` jvv'q:y1j}>qAp -bp  6 -bp  6 -b#qppphw!?z".ӭ/~ߣ86;;{ۓ8~<8'?7k#\E7V[We{ڮz{ǯq|jF\Ř[A@l0g2w'jVD"tATIWmdIENDB`keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey2.png0000664000000000000000000002016214600607066025302 0ustar PNG  IHDRF[>sRGBgAMA a pHYs+ IDATx^aL#i")QN2Dww^/ AL7+3k>@-QP r/ǫ(pH{CDv9 A>C h2+RO1n6m\~Ϩ]e7wʃs'|/944Y EpE~l155݋7LM=!؆EpQ?\AAٱϴW-cl [D@@$l [D@@$l [DBC&Jy8m@l3kH}G-e8iMY3Yb٩?;ֻXރs˽ lt.sC>_|ކ_ݵ}@(S2sհh8ңI;[JLJ ?p+=NċZ1Fg2}gd]숵 ?m=h:"u޴Ϻ;11^{k\ߜ=izŠS)4x-*od(ɱ:]{wޅ[̉=-~虝lrD\Kx!3^lii]P{ru)W4AMͭl[+^Fv+UҚ[ڔە:Y^>>w6 + ϥ5PCjwK[Am%;9Ť\*߄zEդzlWsCAPIuX{2,M|ѭUo>'ܪf&VvJ,i?\|W0X ǵ}BؖԌr>>2ϥAoy[?c\+qPSmqsֳL+=TvwOމQ_B\އ:t[=_Mb{KÒW5X~/ Ϭut8g U ̿{SJϗ'QPώKXjmJjqylqsylZ8)}o١hjR~ hAٰpE]_b[WoNr>HM]^4CL_YmOܗ'-ߨ/~">+$Fθ\_ӒpK9tRJ=y$a%\#iZ͟zv2wGx ^^I=Εu; ԞcwG}}jo^K۱C 0TutC3&vV؍̸6o_@Uad(Bɿ;v{S\OMɡ߸n_}}{yx7LM=?φ\444Y EpEmookgg>23 )eK/<ݕeZl[ԏs{ŭg! -"` H  -"` H  b/H~|`z6ߛ໪?.C˲v,^v>ߙv}}>{ghb"EB7*L;7noo۹蚚]0MwIu"Ep` Ύ]MQ?\.+? ϕ[H  -"` H  -"` H  /ض (PuV>v\1s3]|vorpM2W@%u*6ё&w'uվ:bfWl5N) +7)=o_@ -&ngZEJ⦺R+Dia?- [zNIׇZJ\lFmgTnF}0au8ݟjI8jWk[K?--`}'6A>7SPoܮi'# ҰSSlU#Ϛ~wO]keckbKu-=2I SGLȭδv%Nɮ@G#|f74DhcAǜ`o:Ό<}7&4 p/JVJE¦#6T.~]߳Mi&[n/'?36Ai΄J<9?wsJrSЄIIٰJ^]$J7gwΜС)w+5Ծܮ[tc~#Z?Y.ol͛/-Z)O-%N ΛN9,ji1I4A9[{-9J*p[l zilqɫQ"x]j|Mqn䰆wy|VY" 4~p?DA {/Aci_Jr?}heք\ۊ_'զd^ז)^e Z*7BimRdZu 3wO݄tE+usYM+c?amg cOqjOш`K }gPsX1Ъk .4 j[fJ37oZ\'N5-Vf{ ׵d[{g^b?#zi\l,/3=0:+cnOtǼbv5J..Sv ͺ/~Զ"A~hBwʹ;pjşҡ\NP7eCk-^RnTX't߆ //,Mf0.svǂo3>GYl@=8[)m1w(13Eb7*K hj+ 1k6Uz؆2+߷wW׏_yemg_ٿ]W{&sԩ5\'?/3N q` Є*`oɃ?O4:5E d Ut] [\6KM~#ۿ?:\-@f+S3ϞORSE\[+VMwU-AY.\h &6[%yy pcGC;m7{ %nQ?\.EwXsVL Y-9/%eڵkja[Iw"j Jִآ{ghb"EW!~]}oщ U[qTq肋LwIu"ErJ6;o,>}-Wnl`űcEp5{Z#?D?~G P)rWZrpL-kB-*kt%TP[F[-@רpK5"lj@p[o[s֢~jK*[m gճՖ` PZkZm @|VY+~b1o՚]stqZT9NF֞_N[;ZB mie2;5fp kz2ё&mYh_YR W!r`Wim#4<ؚP;v{S㩔Rf;$[uꦝjӭE%,jnvj=S:ůeg[ImVڷK?\W*hTKJۦ㘵QӅl'C\tw k.vx5/ ëf7bX 5}y9ؚdDG 1ߞDnOm`mlmxaSϋmM(; z^tŒ;Zэ0]fZc0kO4XiZ;UM>v%z5Mkϫѹ =Km~)Χf]~xgZ6WS3:cq߿_hquXWʶW./_*$+6Aw_󙒖`ؖXGv3nvoǶy!k"!ycpq ןξv]ou#ƗoጢoHjѶvUqHrp_ Z_?y}VJ@\ǔ4?'hj*=0+{ulͥoZ99=ߴXmp>]P `A@/͟mwt;/yE@/BVk3+x*sw~K9G[u\w|L.j51!9hBo)޶kg[DÇ"ϧ5SXpu}i.R:'?7_>K;7qL>󲬝+ ׮]PJA}ZXg[b\Ũ?D.e_XXsɃ?N|hލ~&l휻C\d[Q?\.WT7yN?IG ޅvgh,// }+>Cvl!pQ?\ ؾN*p*Ј _J-wE3*ngfv^gFk`o4w^Pl,6@-(Uf -@PXKЬe~v-` J2S.Sc!+ afulPiUg) Jk` H ^?Ͽ8 mۀٳ d).Y_M;Ywb_ըoJٕc9ȼ»^oA3R603@4)VF%ZW^" feܗ]9fQ.~앳Q*=}pgK5ёӄP[&k}PS+g;#+N^,xVЦd^yϧN͟{wGՊ{lFK[ iBj}6~7>f= mIcʺԗS⾈dlM&E=2b ϵ3VF<=HS6c_ +4S ?-עmDRic 417Skj)Χ3|T0oO>*\Ft׵Mi5+WSu]xOӚ X{ɑvZ,]- JA鳃¦/uP˃7} 7G+#.*o~WA=PLTg_NN߭#zfҔGw5xyWSuڳI8wF}Z+]Cg]'Ҫ7Ggh8 #-nD@mWJ遒SH>m?s Qu jT~KKseRW6iQOnZ΍d)gZ:13=^1;58YoW4__Rޱ&p3f6\Ƌ4w~P7C~<)- ÿp"tkboPsw 'Jsg[n$'F m-qE~HW-;<<(mEp"=/ڹ`{5h~g[b˹wީ[VZߗY?y7#@ }[SSl555JSx5Ze}_v\` ӕ^m9_#O5FϧbٱKP𣾾/~.Bl9~UFjJwE@$l [D@@$l [D@@$l lNζ$E_ȟQCm@ZLNi \]aWxY&v[nojBa$Q6.-͜n>sop[.ǯ¿xBY:(uӶcE?%wl+a_*;_ub91v W:•18Uq7Xo\94_#g5vCHɒ+2}!^;G{ W3w㬌]ӸV*v<8~]9+аi@d3]ח e7uxfVEce17 όn9Keck{{[;;;v ]y.Nˮl8~<>/` H  -"` H  -"` H  bG>seKUeE|M{'fgg뾿-|)|Nk׮GZ7V[Ѳ@eߖu>OU c H  L.D*\<&J [[IENDB`keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/chwertyftkey3.png0000664000000000000000000002020314600607066025277 0ustar PNG  IHDRsRGBgAMA a pHYs+ IDATx^ah#i~zqtDg8ѻ;Y/&s/x>MӐqgB^L { >;>vcg;YcǴ)̎ɻݝi_=Zmҿ 5*Uw?~TN$7k4\܁-}3h%6I.Ճ1\P;-s K˟ۗl-t1FdCWvmȣ -WㄬΛj<ݑAqA2ʾd[E~˘;Kk$[ɭ-ہ$N%~KЮrqh* 2+˪ՌٮLuCAŐ}6>uo>uFgVN[pa\ڭnal{&&D2II:[v}mu9vVW0,pN+pVd r"+c]ZטIqIP#>'nd.{_aPh L݉҅QL\T 8s]cj틻"fz[OLMRE3mp &%5| ۶`KeuvJbw@3YLR\p(K-n:[kdvw&feNaWxv.1/-zLޖMLO25%p)^zL5l}*PLZPN,M1YZc+~Va汵e]OegŝQ)oW;Mo?Lz]rOvϮ5ϴJIZvxazEYq*]1j)ilWc6FҴ:vw2OGUv̸Z3!sY[}^Wx({ߍ{Wkok/?,2S;me7i_ٵHȲa̾}Gyn+ g|q)_"1Tc$S'_?F<rB#lPބvA-k|F"(pCc `lZXeլ (sAhq$|kڹF[*'kZo\A3BAP2ܚإ?+hV5TchߟQ5@jZlj'j'r|||bAN%]>{]أv. ?@?X?X?X?Xa(xVߴsQ9c]>|(wܱkc_,k*k8-huM;~CCCVHǀ]t@c b؁a\`knӵ.N4Ӭ60?/ϝl^&Q`Q`Q`Q`Q`\vmj?T3OP0QXdS+#ʠz֤ @@(l [@@(l [BێaI.@Frv49F"1]G.3P(3),~KhpTZ԰ .6&%>zDN{ =:r}}®58R*)ɤ3MI>&SfޙRKv|zd9!v+С=I_+nǮ5˻Ŗޔh5- ^GaG>%1Y0!^ǭItII)S"W.+PY5cVGc&Zv+m[sK6}m>/Vs!}Y;8q- +Y5ebQnt%ob9Y[t~N,OwDF`#w`sbc3UwEWgZ$f$+) ydwܚ,ʜ|7q]2bsYSue({i=&cJ/0жy'i[eoK̮r7RadbKx$3L~u7;73EfNv/0M%&Hm1֕?zn+U\ݩCKK5xv_W0{ae9#zln̻-SΛ31'go죌-dPSZh+Ι b P%<3?;ޖ[Qw͋zޒ]rjeM}M Ndln̘t7 ơs1wE5^k,t.0+j[s238 K{f(B-QLU7$ ^6c{7=8zc"^W "k:8d{5&;4Igiy2友Lꦰ:rwߑ{gDk,&9iʿ8" ּ`TE@-}ƻ].WO%ivs[&9Q^b=å 49Ȼ"k%)8\{Q oqǰRNNUkzߟQfct!I]wHN20݀^dŮq+c@ei1C-%[kߑT|ANv~6Q{\ n+1$[vRJr۷inxCmy|⭴׌=/X`Q9ҟW=J~)Y7JWB6ӺLuHb2'Ɖalݾs)Y99pʿlBbϯd{֬7G ;Zwеӿ\щL3R*Mq_f}_[N̼y]Beٟoֺy{mU.z"Yo`#nK:e,}-ؖHOf*5ntK|϶9!k:_ܚ,:CNX 7;}ފ3\QE47L[RuHrp[dMSk9\>#0 Zm-' Y6e7;{v%>'sY}hr|&hޘ<3?;ޖ[Qw :>)qZ3ܩ59OnIލ?JOZeN7%(k鎲1UֿXؘh@-C*]'fNWhi{ ޠgG<¡s@67Dw$,y[}f3uI쮲fzLƺp?KPip}>zddKMLJ=YH?񉝗Mݕ=! UwohttT(@(/udG2ؠ1>kp|dYnvwgƛsJx-܇xhO e~5glXݙ;ۛS˅z8 3֜QZl [@@(l [@@(l 0onnʝ;wwo1]۔??X?X?X?X7o޴Kl&9Y.Uk׮9lMmX WxZE" ,,,,S%:j]׃C42-^׋F?X?X?X?Xa) aCa3ޞ]jY/ܟZDEEE Pyyly*BkG-B` P  -B` P  u8>+}`1,԰tt $N;SRzV5'%j220]峅0۞;%kTٶX=n^II&Ӳu7#(o~O?v8 D$R&5ȭ-K]n{m򂭩b+L󒍾qzl%ZC3DG}Awޓ/$[\XLIqv.ɵZW;s۲rluy7UqQ*DDry=5S\#0ݘ:ӤB> OvȫȀd4ejx,;!fbr\[6ll˶RѨeUD쭊1Y|~M+Vr2ek-MyoD[Z eB2 Zq0>mj%+ݳ=y*w&lN.2m*ֿ3dl\YҺO EY#"6 ]6_g[R2u/:oc֛@FrY_+ܾd#@uH<+CYWU^G&Mi=]?eK w-pafdBu#W:ER\ț2?uGee,.P q-'͗,Fiu =II .B8 ܛͯD>Ddҵ8"ZSmM.͝+LsOsn$K%Α8?U Of76ʭɢxp]+4-x/x{ߑuc:3"+c8SC^>ŮBbNsgYv;"'.Ĺ#? <櫊6_DOlnn5:{s_?_{5|/gk~ ߽fW__fttߘȣA9i5_yQ^>|<v^s]Ӡ1yȿg&Rޝ@~Q$4%?~ ~. _t(ԙXsKmP@@(l [@@(l ml7{b PyssSܹct3l|FwmS`P`Q`Q`Q`?|04y(Ls]׮]sevvV~_ӗ_~N_}UOɜԽr~HD^}UyWʦ?n`kZlQ=vz,W^s ;}6TT?/]z M.]o`v0m-/`zӕ~Jj#O5Gj۳kp/ㇽ뭟lq.B{Zy آ#O5G"@ &SŲQe3](u6r~>R~_969xl[8NSfɮqݛ\)QggjW_}B*4jpC?MeX-"+r嬿 P7-ԡ2z&* @ &VVY_6f-` u*fPu@slUbc/` 5!{"οnT%"@ &f^B!BQ_O}clpQN:}X?TJ}y :q/v K*5,v-Q@ݼ ΏҲ0- 3@8ߣێᔤi;dߚ u^K0+nl%b Wy/b \ 篋#g51ؚʾwk[IIij[X-lVu m.'jr+-ϫYn΋E l{~̒5r$%d WIgk˽bpޜ}-i^DDr[Wm%PʫJ](X;2AN~Zv< "gyl;ސh~[kۯGwʩ0 cj-*;h4*Gڼdco9[RfMUIzblwsX;[)u B |y%YEMc[Uśqx[7JWgמQ>*oxVC;BgۭCqA {ZlP Kf99g/\ cq{n{QVP b ^+7U\o19p8rVQZl5aI* ̹F{ ;qq֦.4%kUsW;W 񶕁֯xc W=Y E8\J|D6ӽԼ%mU2Yce17wsJwΙu /B/z "ţޞ]X]]}qҮ9vz,W^s;-x;ADUvn+kϝWbfFYnc_1DqԄ @5pJj#O5G'@NEv|}h̲ :۸/` u­? K4.Ae5̛aEKR`2` / iZtzl[?U[*4[9yv8-\(` S*C& (@l-/3/r||\}|;w.n~rU{% ~6TT?eڵkvn}ZW8OYb-B` P  D?(ʯ'4IENDB`keyman/common/test/keyboards/obolo_chwerty_6351/source/welcome/welcome.htm0000664000000000000000000000772514600607066024141 0ustar 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.

Key Combination

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

Keyboard Layout (default)

Keyboard Layout (shift)

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.

Keyboard Layout Mobile (default)

Keyboard Layout Mobile (shift)

Keyboard Layout Mobile (alt)

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:

ANSI Keyboard

ISO/JIS Keyboard

Backward-L Keyboard

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! keyman/common/test/keyboards/start_of_sentence_3621/0000775000000000000000000000000014600607066017651 5ustar keyman/common/test/keyboards/start_of_sentence_3621/HISTORY.md0000664000000000000000000000015414600607066021334 0ustar start_of_sentence_3621 Change History ==================== 1.0 (2021-11-22) ---------------- * Created by keyman/common/test/keyboards/start_of_sentence_3621/LICENSE.md0000664000000000000000000000203714600607066021257 0ustar The MIT License (MIT) © 2021 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. keyman/common/test/keyboards/start_of_sentence_3621/README.md0000664000000000000000000000057514600607066021137 0ustar start_of_sentence_3621 keyboard ============== Version 1.0 Description ----------- start_of_sentence_3621 generated from template Links ----- Copyright --------- See [LICENSE.md](LICENSE.md) Supported Platforms ------------------- * Windows * macOS * Linux * Web * iPhone * iPad * Android phone * Android tablet * Mobile devices * Desktop devices * Tablet devices keyman/common/test/keyboards/start_of_sentence_3621/source/0000775000000000000000000000000014600607066021151 5ustar keyman/common/test/keyboards/start_of_sentence_3621/source/readme.htm0000664000000000000000000000077114600607066023125 0ustar start_of_sentence_3621

start_of_sentence_3621

start_of_sentence_3621 1.0 generated from template.

©

././@LongLink0000644000000000000000000000014600000000000007774 Lustar keyman/common/test/keyboards/start_of_sentence_3621/source/start_of_sentence_3621.keyman-touch-layoutkeyman/common/test/keyboards/start_of_sentence_3621/source/start_of_sentence_3621.keyman-touch-layou0000664000000000000000000007501414600607066031015 0ustar { "tablet": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "a", "pad": 70 }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "sp": "10", "width": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": 70 }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "sp": "10", "width": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "text": "$", "layer": "shift", "pad": 70 }, { "id": "K_2", "text": "@", "layer": "shift" }, { "id": "K_3", "text": "#", "layer": "shift" }, { "id": "K_5", "text": "%", "layer": "shift" }, { "id": "K_7", "text": "&", "layer": "shift" }, { "id": "K_HYPHEN", "text": "_", "layer": "shift" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "text": "|", "layer": "shift" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1" }, { "id": "K_LBRKT", "text": "[", "sk": [ { "id": "U_00AB", "text": "\u00AB" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "text": "(", "layer": "shift" }, { "id": "K_0", "text": ")", "layer": "shift" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "\u00BB" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "text": "+", "layer": "shift" }, { "id": "K_HYPHEN", "text": "-", "layer": "default" }, { "id": "K_8", "text": "*", "layer": "shift" }, { "id": "K_SLASH", "text": "/", "layer": "default" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "140", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] } ] }, "phone": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "a", "pad": "50" }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "100", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "150", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": "50" }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "150", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "layer": "shift", "text": "$", "pad": "50" }, { "id": "K_2", "layer": "shift", "text": "@" }, { "id": "K_3", "layer": "shift", "text": "#" }, { "id": "K_5", "layer": "shift", "text": "%" }, { "id": "K_7", "layer": "shift", "text": "&" }, { "id": "K_HYPHEN", "layer": "shift", "text": "_" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "layer": "shift", "text": "|" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_LBRKT", "text": "[", "pad": "110", "sk": [ { "id": "U_00AB", "text": "\u00AB" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "layer": "shift", "text": "(" }, { "id": "K_0", "layer": "shift", "text": ")" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "\u00BB" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "layer": "shift", "text": "+" }, { "id": "K_HYPHEN", "text": "-" }, { "id": "K_8", "layer": "shift", "text": "*" }, { "id": "K_SLASH", "text": "/" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "100", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "150", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] } ] } } keyman/common/test/keyboards/start_of_sentence_3621/source/start_of_sentence_3621.kmn0000664000000000000000000000336214600607066026044 0ustar c This keyboard provides a reasonably complete example of c start-of-sentence detection, for use in testing #3621. store(&VERSION) '10.0' store(&NAME) 'start_of_sentence_3621' store(©RIGHT) '©' store(&KEYBOARDVERSION) '1.0' store(&TARGETS) 'any' store(&VISUALKEYBOARD) 'start_of_sentence_3621.kvks' store(&LAYOUTFILE) 'start_of_sentence_3621.keyman-touch-layout' begin Unicode > use(main) begin NewContext > use(NewContext) begin PostKeystroke > use(PostKeystroke) group(NewContext) readonly c Any time we get a new context, by mouse click, tap, c cursor movement, new document, etc, we'll try and c determine the best layer to use nomatch > use(nextLayer) group(PostKeystroke) readonly store(caps) 'A'..'Z' store(digit) '0'..'9' c this is a heuristic that we can use until we support a CAPS layer (#3620): c if we find two+ characters in capitals, leave us in shift layer, c assuming the user hasn't just switched layer themselves. Once we have a c proper CAPS layer, we'll get rid of this. if(&newLayer = "") any(caps) any(caps) > context c stay on the numeric layer if we are there already if(&newLayer = "") if(&layer = 'numeric') any(digit) > context c no other changes, so detect sentence or layer change, as long c as the user hasn't attempted to change layer themselves if(&newLayer = "") > use(nextLayer) group(nextLayer) readonly store(sentencePunctuation) '.?!' nul > layer('shift') c note that 'readonly' layers do not need to use 'context' unless there is c no other content on output of rule (empty output is illegal) any(sentencePunctuation) ' ' > layer('shift') any(sentencePunctuation) ' ' > layer('shift') nomatch > layer('default') group(main) using keys keyman/common/test/keyboards/start_of_sentence_3621/source/start_of_sentence_3621.kps0000664000000000000000000000331614600607066026053 0ustar 15.0.114.0 7.0 readme.htm start_of_sentence_3621 © ..\build\start_of_sentence_3621.kmx 0 .kmx ..\build\start_of_sentence_3621.js 0 .js ..\build\start_of_sentence_3621.kvk 0 .kvk welcome.htm 0 .htm readme.htm 0 .htm start_of_sentence_3621 start_of_sentence_3621 1.0 English keyman/common/test/keyboards/start_of_sentence_3621/source/start_of_sentence_3621.kvks0000664000000000000000000000027014600607066026230 0ustar
10.0 start_of_sentence_3621
keyman/common/test/keyboards/start_of_sentence_3621/source/welcome.htm0000664000000000000000000000112414600607066023314 0ustar Start Using start_of_sentence_3621

Start Using start_of_sentence_3621

start_of_sentence_3621 1.0 generated from template.

Keyboard Layout

keyman/common/test/keyboards/start_of_sentence_3621/start_of_sentence_3621.kpj0000664000000000000000000000644614600607066024551 0ustar $PROJECTPATH\build True True True keyboard id_51d2ccbdcbeeb798d532100b86252a19 start_of_sentence_3621.kmn source\start_of_sentence_3621.kmn 1.0 .kmn
start_of_sentence_3621 ©
id_feb278f5f21f5a2c56418aef3d610100 start_of_sentence_3621.kps source\start_of_sentence_3621.kps .kps
start_of_sentence_3621 ©
id_ede98e4633e239f933cbfd1f4e1b766c HISTORY.md HISTORY.md .md id_53e892b8b41cc4caece1cfd5ef21d6e7 LICENSE.md LICENSE.md .md id_0730bb7c2e8f9ea2438b52e419dd86c9 README.md README.md .md id_8b42366ff2333c0b6d85e2d23cf930d7 start_of_sentence_3621.kmx source\..\build\start_of_sentence_3621.kmx .kmx id_feb278f5f21f5a2c56418aef3d610100 id_b0e85ab76446356d09d86b4187efbdad start_of_sentence_3621.js source\..\build\start_of_sentence_3621.js .js id_feb278f5f21f5a2c56418aef3d610100 id_3659e166ed1a8f97952e727f3a571a88 start_of_sentence_3621.kvk source\..\build\start_of_sentence_3621.kvk .kvk id_feb278f5f21f5a2c56418aef3d610100 id_356e5d149c1e539356d72698c1e401a6 welcome.htm source\welcome.htm .htm id_feb278f5f21f5a2c56418aef3d610100 id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_feb278f5f21f5a2c56418aef3d610100
keyman/common/test/keyboards/text_selection_tests_keyboard_9073/0000775000000000000000000000000014600607066022306 5ustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/HISTORY.md0000664000000000000000000000017614600607066023775 0ustar Text Selection Tests Keyboard Change History ==================== 1.0 (2023-11-14) ---------------- * Created by Keyman Team keyman/common/test/keyboards/text_selection_tests_keyboard_9073/LICENSE.md0000664000000000000000000000205314600607066023712 0ustar The MIT License (MIT) © 2023 Keyman Team 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. keyman/common/test/keyboards/text_selection_tests_keyboard_9073/README.md0000664000000000000000000000067314600607066023573 0ustar Text Selection Tests Keyboard keyboard ============== Version 1.0 Description ----------- Text Selection Tests Keyboard generated from template Links ----- https://github.com/keymanapp/keyman/issues/9073 Copyright --------- See [LICENSE.md](LICENSE.md) Supported Platforms ------------------- * Windows * macOS * Linux * Web * iPhone * iPad * Android phone * Android tablet * Mobile devices * Desktop devices * Tablet devices keyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/0000775000000000000000000000000014600607066023606 5ustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/readme.htm0000664000000000000000000000103214600607066025551 0ustar Text Selection Tests Keyboard

Text Selection Tests Keyboard

Text Selection Tests Keyboard 1.0 generated from template.

© Keyman Team

././@LongLink0000644000000000000000000000015600000000000007775 Lustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.icokeyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard0000664000000000000000000000217614600607066031672 0ustar  h(  AAr@AC@AC@AC@AC[XArnXACXArXArAYXACXArXArnnoCXArXArXArXYXArAAr@AC@AC@AC@ACrXArnoCXArXArXArXoXArXArXAro[XArXArXArXY[XArAAr@AC@AC@AC@AC[AArYC±XAr././@LongLink0000644000000000000000000000017600000000000007777 Lustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.keyman-touch-layoutkeyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard0000664000000000000000000002707614600607066031700 0ustar { "tablet": { "displayUnderlying": false, "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1", "nextlayer": "shift" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" }, { "id": "K_HYPHEN", "text": "-" }, { "id": "K_EQUAL", "text": "=" }, { "id": "K_BKSP", "text": "*BkSp*", "width": 100, "sp": 1 } ] }, { "id": 2, "key": [ { "id": "K_Q", "text": "q", "pad": 75 }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" }, { "id": "K_LBRKT", "text": "[" }, { "id": "K_RBRKT", "text": "]" }, { "id": "T_new_136", "width": 10, "sp": 10 } ] }, { "id": 3, "key": [ { "id": "K_BKQUOTE", "text": "dk(1)" }, { "id": "K_A", "text": "a" }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "id": "K_COLON", "text": ";" }, { "id": "K_QUOTE", "text": "'" }, { "id": "K_BKSLASH", "text": "\\" } ] }, { "id": 4, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": 160, "sp": 1, "nextlayer": "shift" }, { "id": "K_oE2", "text": "\\" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_COMMA", "text": "," }, { "id": "K_PERIOD", "text": "." }, { "id": "K_SLASH", "text": "/" }, { "id": "T_new_162", "width": 10, "sp": 10 } ] }, { "id": 5, "key": [ { "id": "K_LOPT", "text": "*Menu*", "width": 140, "sp": 1 }, { "id": "K_SPACE", "width": 930 }, { "id": "K_ENTER", "text": "*Enter*", "width": 145, "sp": 1 } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "!" }, { "id": "K_2", "text": "@" }, { "id": "K_3", "text": "#" }, { "id": "K_4", "text": "$" }, { "id": "K_5", "text": "%" }, { "id": "K_6", "text": "^" }, { "id": "K_7", "text": "&" }, { "id": "K_8", "text": "*" }, { "id": "K_9", "text": "(" }, { "id": "K_0", "text": ")" }, { "id": "K_HYPHEN", "text": "_" }, { "id": "K_EQUAL", "text": "+" }, { "id": "K_BKSP", "text": "*BkSp*", "width": 100, "sp": 1 } ] }, { "id": 2, "key": [ { "id": "K_Q", "text": "Q", "pad": 75 }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" }, { "id": "K_LBRKT", "text": "{" }, { "id": "K_RBRKT", "text": "}" }, { "id": "T_new_246", "width": 10, "sp": 10 } ] }, { "id": 3, "key": [ { "id": "K_BKQUOTE", "text": "~" }, { "id": "K_A", "text": "A" }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "id": "K_COLON", "text": ":" }, { "id": "K_QUOTE", "text": "\"" }, { "id": "K_BKSLASH", "text": "|" } ] }, { "id": 4, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": 160, "sp": 1, "nextlayer": "default" }, { "id": "K_oE2", "text": "|" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_COMMA", "text": "<" }, { "id": "K_PERIOD", "text": ">" }, { "id": "K_SLASH", "text": "?" }, { "id": "T_new_272", "width": 10, "sp": 10 } ] }, { "id": 5, "key": [ { "id": "K_LOPT", "text": "*Menu*", "width": 140, "sp": 1 }, { "id": "K_SPACE", "width": 930 }, { "id": "K_ENTER", "text": "*Enter*", "width": 145, "sp": 1 } ] } ] } ] } }././@LongLink0000644000000000000000000000015600000000000007775 Lustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kmnkeyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard0000664000000000000000000000136214600607066031666 0ustar c text_selection_tests_keyboard_9073 generated from template at 2023-11-14 15:23:49 c with name "Text Selection Tests Keyboard" store(&VERSION) '10.0' store(&NAME) 'Text Selection Tests Keyboard' store(©RIGHT) '© Keyman Team' store(&KEYBOARDVERSION) '1.0' store(&TARGETS) 'any' store(&BITMAP) 'text_selection_tests_keyboard_9073.ico' store(&VISUALKEYBOARD) 'text_selection_tests_keyboard_9073.kvks' store(&LAYOUTFILE) 'text_selection_tests_keyboard_9073.keyman-touch-layout' begin Unicode > use(main) group(main) using keys '^' + [K_A] > 'â' '^' + [SHIFT K_A] > 'Â' '^' + [K_BKSP] > 'foo' + '`' > dk(1) + [K_T] > U+0009 c TAB 'a' dk(1) 'b' + [K_BKSP] > 'ok1' 'a' 'b' + [K_BKSP] > 'fail1' 'a' dk(1) + [K_BKSP] > 'fail2' dk(1) + 'o' > 'ok3' ././@LongLink0000644000000000000000000000015600000000000007775 Lustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kpskeyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard0000664000000000000000000000344314600607066031670 0ustar 16.0.142.0 7.0 readme.htm Text Selection Tests Keyboard © Keyman Team Keyman Team ..\build\text_selection_tests_keyboard_9073.kmx 0 .kmx ..\build\text_selection_tests_keyboard_9073.js 0 .js ..\build\text_selection_tests_keyboard_9073.kvk 0 .kvk welcome.htm 0 .htm readme.htm 0 .htm Text Selection Tests Keyboard text_selection_tests_keyboard_9073 1.0 English ././@LongLink0000644000000000000000000000015700000000000007776 Lustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kvkskeyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard0000664000000000000000000000641114600607066031666 0ustar
10.0 text_selection_tests_keyboard_9073
dk(1) 1 2 3 4 5 6 7 8 9 0 - = q w e r t y u i o p [ ] \ a s d f g h j k l ; ' \ z x c v b n m , . / ~ ! @ # $ % ^ & * ( ) _ + Q W E R T Y U I O P { } | A S D F G H J K L : " | Z X C V B N M < > ?
keyman/common/test/keyboards/text_selection_tests_keyboard_9073/source/welcome.htm0000664000000000000000000000115114600607066025751 0ustar Start Using Text Selection Tests Keyboard

Start Using Text Selection Tests Keyboard

Text Selection Tests Keyboard 1.0 generated from template.

Keyboard Layout

././@LongLink0000644000000000000000000000016100000000000007771 Lustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.keyboard_infokeyman/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.k0000664000000000000000000000021314600607066031273 0ustar { "license": "mit", "languages": [ "en" ], "description": "Text Selection Tests Keyboard generated from template" } ././@LongLink0000644000000000000000000000014700000000000007775 Lustar keyman/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.kpjkeyman/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.k0000664000000000000000000001012014600607066031271 0ustar $PROJECTPATH\build True True True keyboard id_dda967022de452e1fe199096e795f0ab text_selection_tests_keyboard_9073.kmn source\text_selection_tests_keyboard_9073.kmn 1.0 .kmn
Text Selection Tests Keyboard © Keyman Team
id_ba932837e6a67a86abc409a393242255 text_selection_tests_keyboard_9073.kps source\text_selection_tests_keyboard_9073.kps .kps
Text Selection Tests Keyboard © Keyman Team
id_ede98e4633e239f933cbfd1f4e1b766c HISTORY.md HISTORY.md .md id_53e892b8b41cc4caece1cfd5ef21d6e7 LICENSE.md LICENSE.md .md id_0730bb7c2e8f9ea2438b52e419dd86c9 README.md README.md .md id_4b87bd35cc2e16f1ff8680a6f2caed52 text_selection_tests_keyboard_9073.keyboard_info text_selection_tests_keyboard_9073.keyboard_info .keyboard_info id_bbf31cea8a9cfe0cb838f67055690bf8 text_selection_tests_keyboard_9073.ico source\text_selection_tests_keyboard_9073.ico .ico id_dda967022de452e1fe199096e795f0ab id_b8f7a473cac52dd0436273de657cdf46 text_selection_tests_keyboard_9073.kmx source\..\build\text_selection_tests_keyboard_9073.kmx .kmx id_ba932837e6a67a86abc409a393242255 id_73d0cd87e78d9b8d7f514809dbb36a47 text_selection_tests_keyboard_9073.js source\..\build\text_selection_tests_keyboard_9073.js .js id_ba932837e6a67a86abc409a393242255 id_71aafc060dc3251e4bb611ea539dc8e0 text_selection_tests_keyboard_9073.kvk source\..\build\text_selection_tests_keyboard_9073.kvk .kvk id_ba932837e6a67a86abc409a393242255 id_356e5d149c1e539356d72698c1e401a6 welcome.htm source\welcome.htm .htm id_ba932837e6a67a86abc409a393242255 id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_ba932837e6a67a86abc409a393242255
keyman/common/test/keyboards/u_xxxx_yyyy_2858/0000775000000000000000000000000014600607066016625 5ustar keyman/common/test/keyboards/u_xxxx_yyyy_2858/HISTORY.md0000664000000000000000000000014614600607066020311 0ustar U_xxxx_yyyy_2858 Change History ==================== 1.0 (2021-11-11) ---------------- * Created by keyman/common/test/keyboards/u_xxxx_yyyy_2858/LICENSE.md0000664000000000000000000000203714600607066020233 0ustar The MIT License (MIT) © 2021 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. keyman/common/test/keyboards/u_xxxx_yyyy_2858/README.md0000664000000000000000000000064114600607066020105 0ustar U_xxxx_yyyy_2858 keyboard ============== Version 1.0 Description ----------- U_xxxx_yyyy_2858 generated from template Links ----- https://github.com/keymanapp/keyman/issues/2858 Copyright --------- See [LICENSE.md](LICENSE.md) Supported Platforms ------------------- * Windows * macOS * Linux * Web * iPhone * iPad * Android phone * Android tablet * Mobile devices * Desktop devices * Tablet devices keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/0000775000000000000000000000000014600607066020125 5ustar keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/NotoSansOldItalic-Regular.ttf0000664000000000000000000001660014600607066025577 0ustar  PGDEFAGPOS  GSUB =OS/2h``cmapg\glyfPYheadn6hheat$hmtxloca{XmaxpG> name%6postPH^3!%!!^563du&&'#7%&&'Z3P1`dG4+,tJ50TWc}j'2N+u-#'7>54&&'6654&&'85n_jaQ_)T`#QH.Ck54.'35h/iXp@3Wr? 91Sbg7.cWEICu%#7%%Z%_/ G  LgJtu  3#7%%Z$c%:$ OtOx/!#5'75'753''SZZHL?FL>FL?FL<u( 7!!5!!5!u6!xx(ze$G "*1%".54>327&&#"6654&'7'27'HyY15\yC@w^7VbH)+FWS<J 2YyFNyS++SyN^WR12SQ21P}(u33uZ6u[ 3#3ZZR:B!BA;u'3%)Z) ~P:8 '33#XZSSdI QG: '3#YU}VM \MFu( 7!35#35#35#35#ur⻻(zd F#%".54>32'26654&&#"Cy]55^yC@w^77_w@Dm@@mCCoBBn/YzKIxX0/VzKKzX/Q@qJJp@@pJJq@uF3#!#5!ZZn 377#'n//Y :H=$5.54>3226654&&#"4?qG0Si:6hT2FrA,6\88\76\78\2 FvP?fH&$FgBPvG 3^?@Y00Y@?^3u 3#75>54&'Z5³=[h+r|FB0__2T'E>,h5J'6654.54667q ' #IM\ !#'7537gZZ>OE?PH '%7"UU'l ` 7'7iKPKR(3( ((A!5.5466326654&'LFeASUfD=uUVMbcJbbJ23M[-RxCKzHAvO dSRg gRSb   !573:EZBM9{ 8KB,<"&&5467.54663226654&&#"26654&&#"HIsAGD*9?mDMj8B??OApI(A&$B-,A$(D',I,-K.(G,+I 2X89\6@6[8:Z00\UC7Z4 7#9%%9!8! <*#6 !;'#9 u3 3#75>54&&'Z5J>fm*-nb$MK#!LN%R2*,3u3 '3>54&&'τD#Wv5Zfm*-nb#IG"9==2*,3-w!##533wZZ7#%tY+4Gd`1P3oJt,j}cWT0Aj5+N2F#.54667&&54667ƂT)_Qaj_n5Z;lC.HQ#_k+AD;D',K(%MDEu(*$(%*B-?&'>54.'7L&pH$N}Y(}Y8gK-to%IRP M)=/kj]7/ .54667'i/hʑ5Z?rW3@2gbS19 DWCIEWc)'%5'%5'%#5P'G /_%Z ItJgL 9/ !'%5'%i$:%c$'xOtO 7/35'75'75377ǫZʮʌLF?LH0 !'%73B:RZmABH6%%73)Z P~f=(& #'33}IdSSZ BNbQR( #73EuMV}U @STN!!#!Z\?T4 !5&&5467'4Z[h+rD?YA@&F>+iK.54>54&&'7u?&;83.15MHM% =:73/Y)\ !'753' ZHP?EO>n* .54>7#D#Wv5Zfn)-oa#IH!9=>@x3),34 3.54667Z5J>fn)-oa@%LK#!LN%R3),3u333#uZO;77?~~6]%M3GM  3#'3Z-EZB9Y8J(0%&&5467&&54667&&546555XccXoZNw36Z%\Sfn &=G G=&S\%p;><85EN Gd $& ӧ& &&%52]6~%JrMRG  #'&BZE-8 Y9Mu (0%'74&'>4.'>6654&&'CoZ63xNZoXccnfS\% &=G G=&eo%\SG N58<>;5&$ & &A=:t/HYq$Aw4Ek?` *CUu,D &_<q 8X^usu ;u?u8uI/ u'GDuu7u`::\u'Fun=SuJs ~A K]u]u- ~(^ ~\sF &7?)8/I/07%`((NS4Ks]*g4uO; VJ:& Vu-` 8AkXKX^2B  GOOG@--% $\$ \8  d X  #-/> ^ (^  H 8  2. D` * ( B >8 <v  4HCopyright 2017 Google Inc. All Rights Reserved.Noto Sans Old ItalicRegular2.002;GOOG;NotoSansOldItalic-RegularNoto Sans Old Italic RegularVersion 2.002NotoSansOldItalic-RegularNoto is a trademark of Google Inc.Monotype Imaging Inc.Monotype Design TeamDesigned by Monotype design team.http://www.google.com/get/noto/http://www.monotype.com/studioThis Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.http://scripts.sil.org/OFL2A      !"#$%&'()*+,-./0123456789:;<=>?@NULLCRuni00A0u10300u10301u10302u10303u10304u10305u10306u10307u10308u10309u1030Au1030Bu1030Cu1030Du1030Eu1030Fu10310u10311u10312u10313u10314u10315u10316u10317u10318u10319u1031Au1031Bu1031Cu1031Du1031Eu1031Fu10320u10321u10322u10323u10300_ru10301_ru10302_ru10303_ru10304_ru10305_ru10306_ru1030A_ru1030B_ru1030C_ru1030D_ru10310_ru10313_ru10314_ru10315_ru1031B_ru1031C_ru1031D_ru1032D_ru1032E_ru1032F_ru1032Du1032Eu1032F @  ,italrtlm0)*+,-./0123456789:;<=   ">@keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/OFL.txt0000664000000000000000000001037714600607066021316 0ustar Copyright 2012 Google Inc. All Rights Reserved. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/readme.htm0000664000000000000000000000074714600607066022104 0ustar U_xxxx_yyyy_2858

U_xxxx_yyyy_2858

U_xxxx_yyyy_2858 1.0 generated from template.

©

keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/u_xxxx_yyyy_2858.keyman-touch-layout0000664000000000000000000003747614600607066027143 0ustar { "tablet": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "U_1234_1340", "text": "ሴፀ", "pad": 70 }, { "id": "U_10300_10301_10302", "text": "𐌀𐌁𐌂", "sk": [ { "text": "", "id": "U_10302_10303_10304" } ] }, { "id": "U_1235_1341", "text": "", "sk": [ { "text": "", "id": "U_1342_1343" } ] }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "id": "T_new_54", "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": 70 }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "sp": "10", "width": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "text": "$", "layer": "shift", "pad": 70 }, { "id": "K_2", "text": "@", "layer": "shift" }, { "id": "K_3", "text": "#", "layer": "shift" }, { "id": "K_5", "text": "%", "layer": "shift" }, { "id": "K_7", "text": "&", "layer": "shift" }, { "id": "K_HYPHEN", "text": "_", "layer": "shift" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "text": "|", "layer": "shift" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1" }, { "id": "K_LBRKT", "text": "[", "sk": [ { "id": "U_00AB", "text": "«" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "text": "(", "layer": "shift" }, { "id": "K_0", "text": ")", "layer": "shift" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "»" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "text": "+", "layer": "shift" }, { "id": "K_HYPHEN", "text": "-", "layer": "default" }, { "id": "K_8", "text": "*", "layer": "shift" }, { "id": "K_SLASH", "text": "/", "layer": "default" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "140", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] } ], "displayUnderlying": false } }keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/u_xxxx_yyyy_2858.kmn0000664000000000000000000000060214600607066023766 0ustar c u_xxxx_yyyy_2858 generated from template at 2021-11-11 12:27:04 c with name "U_xxxx_yyyy_2858" store(&VERSION) '15.0' store(&NAME) 'U_xxxx_yyyy_2858' store(©RIGHT) '©' store(&KEYBOARDVERSION) '1.0' store(&TARGETS) 'any' store(&VISUALKEYBOARD) 'u_xxxx_yyyy_2858.kvks' store(&LAYOUTFILE) 'u_xxxx_yyyy_2858.keyman-touch-layout' begin Unicode > use(main) group(main) using keys keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/u_xxxx_yyyy_2858.kps0000664000000000000000000000422514600607066024003 0ustar 15.0.146.0 7.0 readme.htm U_xxxx_yyyy_2858 © ..\build\u_xxxx_yyyy_2858.kmx 0 .kmx ..\build\u_xxxx_yyyy_2858.js 0 .js ..\build\u_xxxx_yyyy_2858.kvk 0 .kvk welcome.htm 0 .htm readme.htm 0 .htm NotoSansOldItalic-Regular.ttf Font Noto Sans Old Italic Regular 0 .ttf OFL.txt File OFL.txt 0 .txt U_xxxx_yyyy_2858 u_xxxx_yyyy_2858 1.0 NotoSansOldItalic-Regular.ttf NotoSansOldItalic-Regular.ttf English keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/u_xxxx_yyyy_2858.kvks0000664000000000000000000000026214600607066024161 0ustar
10.0 u_xxxx_yyyy_2858
keyman/common/test/keyboards/u_xxxx_yyyy_2858/source/welcome.htm0000664000000000000000000000110214600607066022264 0ustar Start Using U_xxxx_yyyy_2858

Start Using U_xxxx_yyyy_2858

U_xxxx_yyyy_2858 1.0 generated from template.

Keyboard Layout

keyman/common/test/keyboards/u_xxxx_yyyy_2858/u_xxxx_yyyy_2858.kpj0000664000000000000000000000633614600607066022477 0ustar $PROJECTPATH\build True True True keyboard id_7e810b4833243057b00c8d803899b99f u_xxxx_yyyy_2858.kmn source\u_xxxx_yyyy_2858.kmn 1.0 .kmn
U_xxxx_yyyy_2858 ©
id_e45c659d6b3f6aa669e8d9488bf2602d u_xxxx_yyyy_2858.kps source\u_xxxx_yyyy_2858.kps .kps
U_xxxx_yyyy_2858 ©
id_ede98e4633e239f933cbfd1f4e1b766c HISTORY.md HISTORY.md .md id_53e892b8b41cc4caece1cfd5ef21d6e7 LICENSE.md LICENSE.md .md id_0730bb7c2e8f9ea2438b52e419dd86c9 README.md README.md .md id_a1200478ad69b7f058fdce369fb1d960 u_xxxx_yyyy_2858.kmx source\..\build\u_xxxx_yyyy_2858.kmx .kmx id_e45c659d6b3f6aa669e8d9488bf2602d id_e3aacd883345f12f694ac409407de6da u_xxxx_yyyy_2858.js source\..\build\u_xxxx_yyyy_2858.js .js id_e45c659d6b3f6aa669e8d9488bf2602d id_6c1c142b76341666d0679b0979b76793 u_xxxx_yyyy_2858.kvk source\..\build\u_xxxx_yyyy_2858.kvk .kvk id_e45c659d6b3f6aa669e8d9488bf2602d id_356e5d149c1e539356d72698c1e401a6 welcome.htm source\welcome.htm .htm id_e45c659d6b3f6aa669e8d9488bf2602d id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_e45c659d6b3f6aa669e8d9488bf2602d
keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/0000775000000000000000000000000014600607066024442 5ustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/HISTORY.md0000664000000000000000000000016714600607066026131 0ustar Issue 6005 Test Keyboard Change History ==================== 1.0 (2022-04-11) ---------------- * Created by SIL Int'l keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/LICENSE.md0000664000000000000000000000205114600607066026044 0ustar The MIT License (MIT) © 2022 SIL Int'l 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. keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/README.md0000664000000000000000000000061714600607066025725 0ustar Issue 6005 test keyboard - model interactions with unmatched final group ============== Version 1.0 Description ----------- Generated from template Links ----- Copyright --------- See [LICENSE.md](LICENSE.md) Supported Platforms ------------------- * Windows * macOS * Linux * Web * iPhone * iPad * Android phone * Android tablet * Mobile devices * Desktop devices * Tablet devices keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/0000775000000000000000000000000014600607066025742 5ustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/readme.htm0000664000000000000000000000147514600607066027720 0ustar Issue 6005 Test Keyboard

Issue 6005 Test Keyboard

Issue 6005 Test Keyboard 1.0 generated from template.

Designed as a test keyboard for specialized cases where an early rule matches but a later-applied keyboard rule on the same keypress does not. Only tolerates two continguous vowels at most; will not emit a third vowel in a row. Does not interfere with consonants or the semi-vowel 'y'.

©2022 SIL Int'l

././@LongLink0000644000000000000000000000022400000000000007771 Lustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/unmatched_final_group_model_interactions_6005.keyman-touch-layoutkeyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/unmatched_final_gr0000664000000000000000000007501414600607066031505 0ustar { "tablet": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "a", "pad": 70 }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "sp": "10", "width": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": 70 }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "sp": "10", "width": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "text": "$", "layer": "shift", "pad": 70 }, { "id": "K_2", "text": "@", "layer": "shift" }, { "id": "K_3", "text": "#", "layer": "shift" }, { "id": "K_5", "text": "%", "layer": "shift" }, { "id": "K_7", "text": "&", "layer": "shift" }, { "id": "K_HYPHEN", "text": "_", "layer": "shift" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "text": "|", "layer": "shift" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1" }, { "id": "K_LBRKT", "text": "[", "sk": [ { "id": "U_00AB", "text": "\u00AB" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "text": "(", "layer": "shift" }, { "id": "K_0", "text": ")", "layer": "shift" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "\u00BB" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "text": "+", "layer": "shift" }, { "id": "K_HYPHEN", "text": "-", "layer": "default" }, { "id": "K_8", "text": "*", "layer": "shift" }, { "id": "K_SLASH", "text": "/", "layer": "default" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "140", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] } ] }, "phone": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "a", "pad": "50" }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "100", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "150", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": "50" }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "150", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "layer": "shift", "text": "$", "pad": "50" }, { "id": "K_2", "layer": "shift", "text": "@" }, { "id": "K_3", "layer": "shift", "text": "#" }, { "id": "K_5", "layer": "shift", "text": "%" }, { "id": "K_7", "layer": "shift", "text": "&" }, { "id": "K_HYPHEN", "layer": "shift", "text": "_" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "layer": "shift", "text": "|" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_LBRKT", "text": "[", "pad": "110", "sk": [ { "id": "U_00AB", "text": "\u00AB" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "layer": "shift", "text": "(" }, { "id": "K_0", "layer": "shift", "text": ")" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "\u00BB" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "layer": "shift", "text": "+" }, { "id": "K_HYPHEN", "text": "-" }, { "id": "K_8", "layer": "shift", "text": "*" }, { "id": "K_SLASH", "text": "/" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "100", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "150", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] } ] } } ././@LongLink0000644000000000000000000000020400000000000007767 Lustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/unmatched_final_group_model_interactions_6005.kmnkeyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/unmatched_final_gr0000664000000000000000000000421614600607066031501 0ustar c unmatched_final_group_model_interactions_6005 generated from template at 2022-04-11 11:51:48 c with name "Vowel Hater" c c This test-oriented keyboard "hates" words with more than two consecutive vowels. c In order to test within-word applications of non-final rule matching with final rule non-matching, c Vowels are NOT emitted by keyboard rule; only by 'default' behavior. c c For test coverage, also really likes duplicating 'y' and 'Y'. store(&VERSION) '10.0' store(&NAME) 'Issue 6005 - "Vowel Hater"' store(©RIGHT) '© SIL Int' U+0027 'l' store(&KEYBOARDVERSION) '1.0' store(&TARGETS) 'any' store(&VISUALKEYBOARD) 'unmatched_final_group_model_interactions_6005.kvks' store(&LAYOUTFILE) 'unmatched_final_group_model_interactions_6005.keyman-touch-layout' store(vowels) 'aeiouAEIOU' c Doesn't hate 'y' or 'Y'. store(vowel_keys) [K_A] [K_E] [K_I] [K_O] [K_U] \ [SHIFT K_A] [SHIFT K_E] [SHIFT K_I] [SHIFT K_O] [SHIFT K_U] store(cons) 'bcdfghjklmn' \ 'pqrstvwxz' \ 'BCDFGHJKLMN' \ 'PQRSTVWXZ' store(cons_keys) [K_B] [K_C] [K_D] [K_F] [K_G] [K_H] \ [K_J] [K_K] [K_L] [K_M] [K_N] \ [K_P] [K_Q] [K_R] [K_S] [K_T] [K_V] \ [K_W] [K_X] [K_Z] \ [SHIFT K_B] [SHIFT K_C] [SHIFT K_D] [SHIFT K_F] [SHIFT K_G] [SHIFT K_H] \ [SHIFT K_J] [SHIFT K_K] [SHIFT K_L] [SHIFT K_M] [SHIFT K_N] \ [SHIFT K_P] [SHIFT K_Q] [SHIFT K_R] [SHIFT K_S] [SHIFT K_T] [SHIFT K_V] \ [SHIFT K_W] [SHIFT K_X] [SHIFT K_Z] begin Unicode > use(main) group(main) using keys + any(cons_keys) > index(cons, 1) c Vowel-hating pass 1 + any(vowel_keys) > use(vowel_tolerance) c Semi-vowel love (to test context manip early-match with no-match on later group) + [K_Y] > 'y' use(vowel_tolerance) + [SHIFT K_Y] > 'Y' use(vowel_tolerance) c Vowel-hating pass 2 group(vowel_tolerance) using keys c By matching a contiguous vowel pair, further contiguous vowels will be blocked. c Note that 'tolerated' vowels are only emitted due to default behavior. any(vowels) any(vowels) + any(vowel_keys) > context ././@LongLink0000644000000000000000000000020400000000000007767 Lustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/unmatched_final_group_model_interactions_6005.kpskeyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/unmatched_final_gr0000664000000000000000000000350514600607066031501 0ustar 15.0.231.0 7.0 readme.htm Issue 6005 - "Vowel Hater" © SIL Int'l SIL Int'l ..\build\unmatched_final_group_model_interactions_6005.kmx 0 .kmx ..\build\unmatched_final_group_model_interactions_6005.js 0 .js ..\build\unmatched_final_group_model_interactions_6005.kvk 0 .kvk welcome.htm 0 .htm readme.htm 0 .htm Issue 6005 - "Vowel Hater" unmatched_final_group_model_interactions_6005 1.0 English ././@LongLink0000644000000000000000000000020500000000000007770 Lustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/unmatched_final_group_model_interactions_6005.kvkskeyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/unmatched_final_gr0000664000000000000000000000642014600607066031500 0ustar
10.0 unmatched_final_group_model_interactions_6005
` 1 2 3 4 5 6 7 8 9 0 - = q w e r t y u i o p [ ] \ a s d f g h j k l ; ' \ z x c v b n m , . / ~ ! @ # $ % ^ & * ( ) _ + Q W E R T Y U I O P { } | A S D F G H J K L : " | Z X C V B N M < > ?
keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/source/welcome.htm0000664000000000000000000000164114600607066030111 0ustar Start Using This (Issue 6005) Test Keyboard

Start Using This (Issue 6005) Test Keyboard

This keyboard will automatically prevent production of vowels immediately following two consecutive vowels by use of rule groupings designed to test issue 6005 for output keys.

It will also automatically duplicate any typed 'y' keys, providing behavior useful to test another angle of the same issue.

Keyboard Layout

Follows the standard US QWERTY layout.

././@LongLink0000644000000000000000000000017500000000000007776 Lustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/unmatched-final-group-model-interactions-6005.kpjkeyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/unmatched-final-group-mod0000664000000000000000000000705014600607066031335 0ustar $PROJECTPATH\build True True True keyboard id_4f5496a37662e0a9f4c58a8fa7f278fe unmatched_final_group_model_interactions_6005.kmn source\unmatched_final_group_model_interactions_6005.kmn 1.0 .kmn
Issue 6005 - "Vowel Hater" © SIL Int'l
id_662849508b9a7885735a354908c0a3bb unmatched_final_group_model_interactions_6005.kps source\unmatched_final_group_model_interactions_6005.kps .kps
Issue 6005 - "Vowel Hater" © SIL Int'l
id_ede98e4633e239f933cbfd1f4e1b766c HISTORY.md HISTORY.md .md id_53e892b8b41cc4caece1cfd5ef21d6e7 LICENSE.md LICENSE.md .md id_0730bb7c2e8f9ea2438b52e419dd86c9 README.md README.md .md id_d84c8aa5318b9595b931fb2cd35a7527 unmatched_final_group_model_interactions_6005.kmx source\..\build\unmatched_final_group_model_interactions_6005.kmx .kmx id_662849508b9a7885735a354908c0a3bb id_48f335f84e3dab5d9e453b8239624b48 unmatched_final_group_model_interactions_6005.js source\..\build\unmatched_final_group_model_interactions_6005.js .js id_662849508b9a7885735a354908c0a3bb id_880465e1da554f209ca7c05243823415 unmatched_final_group_model_interactions_6005.kvk source\..\build\unmatched_final_group_model_interactions_6005.kvk .kvk id_662849508b9a7885735a354908c0a3bb id_356e5d149c1e539356d72698c1e401a6 welcome.htm source\welcome.htm .htm id_662849508b9a7885735a354908c0a3bb id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_662849508b9a7885735a354908c0a3bb
././@LongLink0000644000000000000000000000017500000000000007776 Lustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/unmatched_final_group_model_interactions_6005.kpjkeyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/unmatched_final_group_mod0000664000000000000000000000705014600607066031563 0ustar $PROJECTPATH\build True True True keyboard id_4f5496a37662e0a9f4c58a8fa7f278fe unmatched_final_group_model_interactions_6005.kmn source\unmatched_final_group_model_interactions_6005.kmn 1.0 .kmn
Issue 6005 - "Vowel Hater" © SIL Int'l
id_662849508b9a7885735a354908c0a3bb unmatched_final_group_model_interactions_6005.kps source\unmatched_final_group_model_interactions_6005.kps .kps
Issue 6005 - "Vowel Hater" © SIL Int'l
id_ede98e4633e239f933cbfd1f4e1b766c HISTORY.md HISTORY.md .md id_53e892b8b41cc4caece1cfd5ef21d6e7 LICENSE.md LICENSE.md .md id_0730bb7c2e8f9ea2438b52e419dd86c9 README.md README.md .md id_e85e92b4c5fbf57dc8ae85f00ce5a068 unmatched_final_group_model_interactions_6005.kmx source\..\build\unmatched_final_group_model_interactions_6005.kmx .kmx id_662849508b9a7885735a354908c0a3bb id_80197977032e3d5266b571033e0f0ff4 unmatched_final_group_model_interactions_6005.js source\..\build\unmatched_final_group_model_interactions_6005.js .js id_662849508b9a7885735a354908c0a3bb id_4e56168448a8471df8611394620e7775 unmatched_final_group_model_interactions_6005.kvk source\..\build\unmatched_final_group_model_interactions_6005.kvk .kvk id_662849508b9a7885735a354908c0a3bb id_356e5d149c1e539356d72698c1e401a6 welcome.htm source\welcome.htm .htm id_662849508b9a7885735a354908c0a3bb id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_662849508b9a7885735a354908c0a3bb
././@LongLink0000644000000000000000000000017600000000000007777 Lustar keyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/unmatched_final_group_model_interactions_6005.userkeyman/common/test/keyboards/unmatched_final_group_model_interactions_6005/unmatched_final_group_mod0000664000000000000000000000666414600607066031575 0ustar 1 1 C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\unmatched_final_group_model_interactions_6005.kpj id_4f5496a37662e0a9f4c58a8fa7f278fe C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\source\unmatched_final_group_model_interactions_6005.kmn 0 1 Consolas|-9| |0 Consolas|-9| |0 Consolas|-9| |0 False id_662849508b9a7885735a354908c0a3bb C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\source\unmatched_final_group_model_interactions_6005.kps id_ede98e4633e239f933cbfd1f4e1b766c C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\HISTORY.md id_53e892b8b41cc4caece1cfd5ef21d6e7 C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\LICENSE.md id_0730bb7c2e8f9ea2438b52e419dd86c9 C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\README.md id_e85e92b4c5fbf57dc8ae85f00ce5a068 C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\source\..\build\unmatched_final_group_model_interactions_6005.kmx id_80197977032e3d5266b571033e0f0ff4 C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\source\..\build\unmatched_final_group_model_interactions_6005.js id_4e56168448a8471df8611394620e7775 C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\source\..\build\unmatched_final_group_model_interactions_6005.kvk id_356e5d149c1e539356d72698c1e401a6 C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\source\welcome.htm id_8da344c4cea6f467013357fe099006f5 C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\source\readme.htm id_MRU0 unmatched_final_group_model_interactions_6005.kmn .kmn C:\keymanapp\keyman\common\test\keyboards\unmatched_final_group_model_interactions_6005\source\unmatched_final_group_model_interactions_6005.kmn keyman/common/test/keyboards/web_context_tests/0000775000000000000000000000000014600607066017234 5ustar keyman/common/test/keyboards/web_context_tests/HISTORY.md0000664000000000000000000000016214600607066020716 0ustar web_context_tests Change History ==================== 1.0 (2022-02-10) ---------------- * Created by Marc Durdin keyman/common/test/keyboards/web_context_tests/README.md0000664000000000000000000000103714600607066020514 0ustar web_context_tests keyboard ============== Version 1.0 Description ----------- web_context_tests is used for testing selection rules. It has a single rule: ``` 'abc' + 'd' > '!' ``` This rule is intended to be used to verify that having a selection does not mess up the tracking of the context or output. Links ----- Copyright --------- MIT License. Supported Platforms ------------------- * Windows * macOS * Linux * Web * iPhone * iPad * Android phone * Android tablet * Mobile devices * Desktop devices * Tablet devices keyman/common/test/keyboards/web_context_tests/assets/0000775000000000000000000000000014600607066020536 5ustar keyman/common/test/keyboards/web_context_tests/assets/NotoSansOldItalic-Regular.ttf0000664000000000000000000001660014600607066026210 0ustar  PGDEFAGPOS GSUB =`OS/2h`|`cmapgglyfPY dheadnD6hheat $hmtxloca{XmaxpG> nameF,6postP  @A=-` 8A_<q 8kXKX^2B  GOOG@--% :t/HYq$Aw4Ek?` *CUu,D  ,italrtlm0)*+,-./0123456789:;<=   ">@|$| $ X  #-/>8  dX^usu ;u?u8uI/ u'GDuu7u`::\u'Fun=SuJs ~A K]u]u- ~(^ ~\sF &7?)8/I/07%`((NS4Ks]*g4uO; VJ:& Vu2A      !"#$%&'()*+,-./0123456789:;<=>?@NULLCRuni00A0u10300u10301u10302u10303u10304u10305u10306u10307u10308u10309u1030Au1030Bu1030Cu1030Du1030Eu1030Fu10310u10311u10312u10313u10314u10315u10316u10317u10318u10319u1031Au1031Bu1031Cu1031Du1031Eu1031Fu10320u10321u10322u10323u10300_ru10301_ru10302_ru10303_ru10304_ru10305_ru10306_ru1030A_ru1030B_ru1030C_ru1030D_ru10310_ru10313_ru10314_ru10315_ru1031B_ru1031C_ru1031D_ru1032D_ru1032E_ru1032F_ru1032Du1032Eu1032F ^ (  H 8h N 2 D * ( BD > < 4 4http://scripts.sil.org/OFLThis Font Software is licensed under the SIL Open Font License, Version 1.1. This Font Software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the SIL Open Font License for the specific language, permissions and limitations governing your use of this Font Software.http://www.monotype.com/studiohttp://www.google.com/get/noto/Designed by Monotype design team.Monotype Design TeamMonotype Imaging Inc.Noto is a trademark of Google Inc.NotoSansOldItalic-RegularVersion 2.002Noto Sans Old Italic Regular2.002;GOOG;NotoSansOldItalic-RegularRegularNoto Sans Old ItalicCopyright 2017 Google Inc. All Rights Reserved.^3!%!!^563du&&'#7%&&'Z3P1`dG4+,tJ50TWc}j'2N+u-#'7>54&&'6654&&'85n_jaQ_)T`#QH.Ck54.'35h/iXp@3Wr? 91Sbg7.cWEICu%#7%%Z%_/ G  LgJtu  3#7%%Z$c%:$ OtOx/!#5'75'753''SZZHL?FL>FL?FL<u( 7!!5!!5!u6!xx(ze$G "*1%".54>327&&#"6654&'7'27'HyY15\yC@w^7VbH)+FWS<J 2YyFNyS++SyN^WR12SQ21P}(u33uZ6u[ 3#3ZZR:B!BA;u'3%)Z) ~P:8 '33#XZSSdI QG: '3#YU}VM \MFu( 7!35#35#35#35#ur⻻(zd F#%".54>32'26654&&#"Cy]55^yC@w^77_w@Dm@@mCCoBBn/YzKIxX0/VzKKzX/Q@qJJp@@pJJq@uF3#!#5!ZZn 377#'n//Y :H=$5.54>3226654&&#"4?qG0Si:6hT2FrA,6\88\76\78\2 FvP?fH&$FgBPvG 3^?@Y00Y@?^3u 3#75>54&'Z5³=[h+r|FB0__2T'E>,h5J'6654.54667q ' #IM\ !#'7537gZZ>OE?PH '%7"UU'l ` 7'7iKPKR(3( ((A!5.5466326654&'LFeASUfD=uUVMbcJbbJ23M[-RxCKzHAvO dSRg gRSb   !573:EZBM9{ 8KB,<"&&5467.54663226654&&#"26654&&#"HIsAGD*9?mDMj8B??OApI(A&$B-,A$(D',I,-K.(G,+I 2X89\6@6[8:Z00\UC7Z4 7#9%%9!8! <*#6 !;'#9 u3 3#75>54&&'Z5J>fm*-nb$MK#!LN%R2*,3u3 '3>54&&'τD#Wv5Zfm*-nb#IG"9==2*,3-w!##533wZZ7#%tY+4Gd`1P3oJt,j}cWT0Aj5+N2F#.54667&&54667ƂT)_Qaj_n5Z;lC.HQ#_k+AD;D',K(%MDEu(*$(%*B-?&'>54.'7L&pH$N}Y(}Y8gK-to%IRP M)=/kj]7/ .54667'i/hʑ5Z?rW3@2gbS19 DWCIEWc)'%5'%5'%#5P'G /_%Z ItJgL 9/ !'%5'%i$:%c$'xOtO 7/35'75'75377ǫZʮʌLF?LH0 !'%73B:RZmABH6%%73)Z P~f=(& #'33}IdSSZ BNbQR( #73EuMV}U @STN!!#!Z\?T4 !5&&5467'4Z[h+rD?YA@&F>+iK.54>54&&'7u?&;83.15MHM% =:73/Y)\ !'753' ZHP?EO>n* .54>7#D#Wv5Zfn)-oa#IH!9=>@x3),34 3.54667Z5J>fn)-oa@%LK#!LN%R3),3u333#uZO;77?~~6]%M3GM  3#'3Z-EZB9Y8J(0%&&5467&&54667&&546555XccXoZNw36Z%\Sfn &=G G=&S\%p;><85EN Gd $& ӧ& &&%52]6~%JrMRG  #'&BZE-8 Y9Mu (0%'74&'>4.'>6654&&'CoZ63xNZoXccnfS\% &=G G=&eo%\SG N58<>;5&$ & &keyman/common/test/keyboards/web_context_tests/assets/OFL.txt0000664000000000000000000001037714600607066021727 0ustar Copyright 2012 Google Inc. All Rights Reserved. This Font Software is licensed under the SIL Open Font License, Version 1.1. This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. keyman/common/test/keyboards/web_context_tests/source/0000775000000000000000000000000014600607066020534 5ustar keyman/common/test/keyboards/web_context_tests/source/readme.htm0000664000000000000000000000077014600607066022507 0ustar web_context_tests

web_context_tests

web_context_tests generated from template.

© SIL International

keyman/common/test/keyboards/web_context_tests/source/web_context_tests.keyman-touch-layout0000664000000000000000000007501414600607066030147 0ustar { "tablet": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "a", "pad": 70 }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "sp": "10", "width": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": 70 }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "sp": "10", "width": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "140", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "text": "$", "layer": "shift", "pad": 70 }, { "id": "K_2", "text": "@", "layer": "shift" }, { "id": "K_3", "text": "#", "layer": "shift" }, { "id": "K_5", "text": "%", "layer": "shift" }, { "id": "K_7", "text": "&", "layer": "shift" }, { "id": "K_HYPHEN", "text": "_", "layer": "shift" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "text": "|", "layer": "shift" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "width": "110", "sp": "1" }, { "id": "K_LBRKT", "text": "[", "sk": [ { "id": "U_00AB", "text": "\u00AB" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "text": "(", "layer": "shift" }, { "id": "K_0", "text": ")", "layer": "shift" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "\u00BB" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "text": "+", "layer": "shift" }, { "id": "K_HYPHEN", "text": "-", "layer": "default" }, { "id": "K_8", "text": "*", "layer": "shift" }, { "id": "K_SLASH", "text": "/", "layer": "default" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "90", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "140", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "630", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "140", "sp": "1" } ] } ] } ] }, "phone": { "font": "Tahoma", "layer": [ { "id": "default", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "q" }, { "id": "K_W", "text": "w" }, { "id": "K_E", "text": "e" }, { "id": "K_R", "text": "r" }, { "id": "K_T", "text": "t" }, { "id": "K_Y", "text": "y" }, { "id": "K_U", "text": "u" }, { "id": "K_I", "text": "i" }, { "id": "K_O", "text": "o" }, { "id": "K_P", "text": "p" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "a", "pad": "50" }, { "id": "K_S", "text": "s" }, { "id": "K_D", "text": "d" }, { "id": "K_F", "text": "f" }, { "id": "K_G", "text": "g" }, { "id": "K_H", "text": "h" }, { "id": "K_J", "text": "j" }, { "id": "K_K", "text": "k" }, { "id": "K_L", "text": "l" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "sp": "1", "nextlayer": "shift" }, { "id": "K_Z", "text": "z" }, { "id": "K_X", "text": "x" }, { "id": "K_C", "text": "c" }, { "id": "K_V", "text": "v" }, { "id": "K_B", "text": "b" }, { "id": "K_N", "text": "n" }, { "id": "K_M", "text": "m" }, { "id": "K_PERIOD", "text": ".", "sk": [ { "text": ",", "id": "K_COMMA" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "width": "100", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "150", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] }, { "id": "shift", "row": [ { "id": 1, "key": [ { "id": "K_Q", "text": "Q" }, { "id": "K_W", "text": "W" }, { "id": "K_E", "text": "E" }, { "id": "K_R", "text": "R" }, { "id": "K_T", "text": "T" }, { "id": "K_Y", "text": "Y" }, { "id": "K_U", "text": "U" }, { "id": "K_I", "text": "I" }, { "id": "K_O", "text": "O" }, { "id": "K_P", "text": "P" } ] }, { "id": 2, "key": [ { "id": "K_A", "text": "A", "pad": "50" }, { "id": "K_S", "text": "S" }, { "id": "K_D", "text": "D" }, { "id": "K_F", "text": "F" }, { "id": "K_G", "text": "G" }, { "id": "K_H", "text": "H" }, { "id": "K_J", "text": "J" }, { "id": "K_K", "text": "K" }, { "id": "K_L", "text": "L" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_SHIFT", "text": "*Shift*", "sp": "2", "nextlayer": "default" }, { "id": "K_Z", "text": "Z" }, { "id": "K_X", "text": "X" }, { "id": "K_C", "text": "C" }, { "id": "K_V", "text": "V" }, { "id": "K_B", "text": "B" }, { "id": "K_N", "text": "N" }, { "id": "K_M", "text": "M" }, { "id": "K_PERIOD", "text": ".", "layer": "default", "sk": [ { "text": ",", "id": "K_COMMA", "layer": "default" }, { "text": "!", "id": "K_1", "layer": "shift" }, { "text": "?", "id": "K_SLASH", "layer": "shift" }, { "text": "'", "id": "K_QUOTE", "layer": "default" }, { "text": "\"", "id": "K_QUOTE", "layer": "shift" }, { "text": "\\", "id": "K_BKSLASH", "layer": "default" }, { "text": ":", "id": "K_COLON", "layer": "shift" }, { "text": ";", "id": "K_COLON", "layer": "default" } ] }, { "id": "K_BKSP", "text": "*BkSp*", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_NUMLOCK", "text": "*123*", "width": "150", "sp": "1", "nextlayer": "numeric" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] }, { "id": "numeric", "row": [ { "id": 1, "key": [ { "id": "K_1", "text": "1" }, { "id": "K_2", "text": "2" }, { "id": "K_3", "text": "3" }, { "id": "K_4", "text": "4" }, { "id": "K_5", "text": "5" }, { "id": "K_6", "text": "6" }, { "id": "K_7", "text": "7" }, { "id": "K_8", "text": "8" }, { "id": "K_9", "text": "9" }, { "id": "K_0", "text": "0" } ] }, { "id": 2, "key": [ { "id": "K_4", "layer": "shift", "text": "$", "pad": "50" }, { "id": "K_2", "layer": "shift", "text": "@" }, { "id": "K_3", "layer": "shift", "text": "#" }, { "id": "K_5", "layer": "shift", "text": "%" }, { "id": "K_7", "layer": "shift", "text": "&" }, { "id": "K_HYPHEN", "layer": "shift", "text": "_" }, { "id": "K_EQUAL", "text": "=", "layer": "default" }, { "id": "K_BKSLASH", "layer": "shift", "text": "|" }, { "id": "K_BKSLASH", "text": "\\", "layer": "default" }, { "text": "", "width": "10", "sp": "10" } ] }, { "id": 3, "key": [ { "id": "K_LBRKT", "text": "[", "pad": "110", "sk": [ { "id": "U_00AB", "text": "\u00AB" }, { "id": "K_COMMA", "text": "<", "layer": "shift" }, { "id": "K_LBRKT", "text": "{", "layer": "shift" } ] }, { "id": "K_9", "layer": "shift", "text": "(" }, { "id": "K_0", "layer": "shift", "text": ")" }, { "id": "K_RBRKT", "text": "]", "sk": [ { "id": "U_00BB", "text": "\u00BB" }, { "id": "K_PERIOD", "text": ">", "layer": "shift" }, { "id": "K_RBRKT", "text": "}", "layer": "shift" } ] }, { "id": "K_EQUAL", "layer": "shift", "text": "+" }, { "id": "K_HYPHEN", "text": "-" }, { "id": "K_8", "layer": "shift", "text": "*" }, { "id": "K_SLASH", "text": "/" }, { "id": "K_BKSP", "text": "*BkSp*", "width": "100", "sp": "1" } ] }, { "id": 4, "key": [ { "id": "K_LOWER", "text": "*abc*", "width": "150", "sp": "1", "nextlayer": "default" }, { "id": "K_LOPT", "text": "*Menu*", "width": "120", "sp": "1" }, { "id": "K_SPACE", "text": "", "width": "610", "sp": "0" }, { "id": "K_ENTER", "text": "*Enter*", "width": "150", "sp": "1" } ] } ] } ] } } keyman/common/test/keyboards/web_context_tests/source/web_context_tests.kmn0000664000000000000000000000161114600607066025005 0ustar c web_context_tests generated from template at 2022-02-10 13:12:25 c with name "web_context_tests" store(&VERSION) '10.0' store(&NAME) 'web_context_tests' store(©RIGHT) '© SIL International' store(&KEYBOARDVERSION) '1.1' store(&TARGETS) 'any' store(&VISUALKEYBOARD) 'web_context_tests.kvks' store(&LAYOUTFILE) 'web_context_tests.keyman-touch-layout' begin Unicode > use(main) group(main) using keys 'abc' + 'd' > '!' c 'e' is not transformed c SMP tests + 'f' > '𐌀' + 'g' > '𐌁' + 'h' > '𐌂' '𐌀𐌁𐌂' + 'i' > '𐌙' + 'j' > '𐌈' c Mixed SMP + BMP tests + 'k' > '𐌰' + 'l' > 'B' + 'm' > '𐌲' '𐌰B𐌲' + 'n' > '𐌽' + 'o' > '𐍈' c 'p' always generates single char + 'p' > 'q' c 'q' is always untouched c other combos, mixing bmp and smp + 'r' > 'tuv' + 's' > '𐍈x' + 't' > '𐍈x𐌈' + 'u' > '𐍈𐌈𐌰' + 'v' > '𐍈𐌈x𐌰' c 'x' is always untouched keyman/common/test/keyboards/web_context_tests/source/web_context_tests.kps0000664000000000000000000000434014600607066025017 0ustar 15.0.227.0 7.0 readme.htm web_context_tests © SIL International Marc Durdin ..\build\web_context_tests.kmx 0 .kmx ..\build\web_context_tests.js 0 .js ..\build\web_context_tests.kvk 0 .kvk welcome.htm 0 .htm readme.htm 0 .htm ..\assets\NotoSansOldItalic-Regular.ttf Font Noto Sans Old Italic Regular 0 .ttf ..\assets\OFL.txt File OFL.txt 0 .txt web_context_tests web_context_tests 1.1 ..\assets\NotoSansOldItalic-Regular.ttf ..\assets\NotoSansOldItalic-Regular.ttf English keyman/common/test/keyboards/web_context_tests/source/web_context_tests.kvks0000664000000000000000000000026314600607066025200 0ustar
10.0 web_context_tests
keyman/common/test/keyboards/web_context_tests/source/welcome.htm0000664000000000000000000000110214600607066022673 0ustar Start Using web_context_tests

Start Using web_context_tests

web_context_tests generated from template.

Keyboard Layout

keyman/common/test/keyboards/web_context_tests/web_context_tests.kpj0000664000000000000000000000761614600607066023517 0ustar $PROJECTPATH\build True True True keyboard id_83bd7f5f7597798cfb2e5721191fb995 web_context_tests.kmn source\web_context_tests.kmn 1.1 .kmn
web_context_tests © SIL International
id_da027d4a221ffc8f298eba6a0b8936fc web_context_tests.kps source\web_context_tests.kps .kps
web_context_tests © SIL International
id_ede98e4633e239f933cbfd1f4e1b766c HISTORY.md HISTORY.md .md id_53e892b8b41cc4caece1cfd5ef21d6e7 LICENSE.md LICENSE.md .md id_0730bb7c2e8f9ea2438b52e419dd86c9 README.md README.md .md id_fa6acb8dd8884fe0c6c6262bb4477d27 web_context_tests.kmx source\..\build\web_context_tests.kmx .kmx id_da027d4a221ffc8f298eba6a0b8936fc id_3544e7baa082880a6cd9d4dc34ef5d2e web_context_tests.js source\..\build\web_context_tests.js .js id_da027d4a221ffc8f298eba6a0b8936fc id_ce3ce6d7552feb3edfd23b2b12532645 web_context_tests.kvk source\..\build\web_context_tests.kvk .kvk id_da027d4a221ffc8f298eba6a0b8936fc id_356e5d149c1e539356d72698c1e401a6 welcome.htm source\welcome.htm .htm id_da027d4a221ffc8f298eba6a0b8936fc id_8da344c4cea6f467013357fe099006f5 readme.htm source\readme.htm .htm id_da027d4a221ffc8f298eba6a0b8936fc id_ef0d4e6917e0b21ca6b8e1cd5152e161 NotoSansOldItalic-Regular.ttf source\..\assets\NotoSansOldItalic-Regular.ttf .ttf id_da027d4a221ffc8f298eba6a0b8936fc id_687b874531c874a9737a529d404e579f OFL.txt source\..\assets\OFL.txt .txt id_da027d4a221ffc8f298eba6a0b8936fc
keyman/common/tools/0000775000000000000000000000000014600607066011667 5ustar keyman/common/tools/hextobin/0000775000000000000000000000000014600607066013507 5ustar keyman/common/tools/hextobin/build.sh0000775000000000000000000000140014600607066015140 0ustar #!/usr/bin/env bash ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" # This script runs from its own folder cd "$THIS_SCRIPT_PATH" ################################ Main script ################################ builder_describe "Build hextobin" clean configure build builder_describe_outputs \ configure /node_modules \ build /common/tools/hextobin/build/index.js builder_parse "$@" builder_run_action clean rm -rf build/ node_modules/ builder_run_action configure verify_npm_setup builder_run_action build tsc --build keyman/common/tools/hextobin/hextobin.ts0000664000000000000000000000400514600607066015676 0ustar #!/usr/bin/env node import { Command } from 'commander'; import hextobin from './index.js'; let inputFilename: string = ""; let outputFilename: string = ""; const program = new Command(); program .description( `Will convert the input file which is a hex dump to the output file. Hex dump can contain blank lines, offsets, commands and comments. File writing will start at zero, padding is not currently supported. Format: # This is a comment block(name) # each part of file must be defined as a block 11 22 33 44 55 aa bb # inserts hex bytes offset(block) # inserts 4 byte offset of block from BOF sizeof(block[,divisor]) # inserts 4 byte size of block, optionally divided by divisor diff(block1,block2[,divisor]) # inserts 4 byte offset diff between start of block1 and block2, ÷divisor (default: ÷1) index(block1,block2[,divisor]) # inserts 4 byte index diff between block1 and block2, # optionally divided by divisor # block names are required, but if not referenced can be reused (e.g. block(x)) # Spaces after commas aren't allowed: 'sizeof(block,3)' not 'sizeof(block, 3)' ` ) .arguments('') .arguments('') .action((infile:any, outfile:any) => { inputFilename = infile; outputFilename = outfile; }); program.parse(process.argv); if(!inputFilename || !outputFilename) { exitDueToUsageError('Must provide an input and output filename.'); } function exitDueToUsageError(message: string): never { console.error(`${program._name}: ${message}`); console.error(); program.outputHelp(); return process.exit(64); // SysExits.EX_USAGE } hextobin(inputFilename, outputFilename, { silent: false }) .then((buffer) => { if (buffer) { process.exit(0); // OK } else { console.error(`${program._name}: Failed.`); process.exit(1); // no buffer - some err. } }, (err) => { console.error(err); console.error(`${program._name}: Failed.`); process.exit(1); }); keyman/common/tools/hextobin/index.ts0000664000000000000000000001642314600607066015174 0ustar import * as fs from 'fs'; import * as rd from 'readline'; export default async function hextobin(inputFilename: string, outputFilename?: string, options?: {silent?: boolean}): Promise { options = {...options}; options.silent = !!options.silent; let reader = rd.createInterface(fs.createReadStream(inputFilename)); type HexBlockRefType = 'sizeof' | // gets the size of a block, optionally divided by divisor: sizeof(block,divisor) 'offset' | // gets the offset of a block in bytes from start of file: offset(block) 'diff' | // gets the offset of a block in bytes from start of a base block: offset(baseBlock,block) 'index'; // gets the index of a block from a base block, optionally divided by divisor: index(baseBlock,block,divisor) interface HexBlockRef { type: HexBlockRefType; blockName: string; blockName2?: string; // used only by diff, index divisor?: number; // used only by sizeof, index offset: number; // actual byte offset in hex data (i.e. offset in string is * 2) }; interface HexBlock { name: string; offset: number; // calculated during reconciliation phase hex: string; refs: HexBlockRef[]; }; let blocks: HexBlock[] = []; let currentLine = ''; let currentLineNumber = 0; if(!await load()) { return null; } if(!reconciliation()) { return null; } return save(); function reportError(message: string) { if(!options.silent) { console.error(`Invalid input file: ${message} on line #${currentLineNumber}: "${currentLine}"`); } } function currentBlock(): HexBlock { return blocks.length ? blocks[blocks.length-1] : null; } function parseToken(token: string): { command: string, parameters: string[] } { let m = /^([a-z]+)\((.+)\)$/.exec(token); if(!m) { if(!token.match(/^[a-fA-F0-9]{2}$/)) { return null; } // hex byte return { command: 'data', parameters: [token] }; } // processing command return { command: m[1], parameters: m[2].split(',') }; } function token(token: string) { const t = parseToken(token); if(!t) { reportError(`expected command or hex at token "${token}"`); return false; } if(t.command == 'block') { blocks.push({name: t.parameters[0], offset: 0, hex: '', refs: []}); return true; } const b = currentBlock(); if(!b) { reportError(`expected block() before data`); return false; } switch(t.command) { case 'offset': b.refs.push({type: 'offset', blockName: t.parameters[0], offset: b.hex.length / 2}); b.hex += "_".repeat(8); // always 4 bytes, placeholder will be filled in during reconciliation phase break; case 'sizeof': // sizeof can take a second parameter, divisor { let divisor = t.parameters.length > 1 ? parseInt(t.parameters[1],10) : 1; b.refs.push({type: 'sizeof', blockName: t.parameters[0], divisor: divisor, offset: b.hex.length / 2}); b.hex += "_".repeat(8); // always 4 bytes, placeholder will be filled in during reconciliation phase } break; case 'diff': // diff can also take a divisor, defaults to 1 { const divisor = t.parameters.length > 2 ? parseInt(t.parameters[2],10) : 1; b.refs.push({type: 'diff', blockName: t.parameters[0], blockName2: t.parameters[1], divisor: divisor, offset: b.hex.length / 2}); b.hex += "_".repeat(8); // always 4 bytes, placeholder will be filled in during reconciliation phase } break; case 'index': // index can take a third parameter, divisor { let divisor = t.parameters.length > 2 ? parseInt(t.parameters[2],10) : 1; b.refs.push({type: 'index', blockName: t.parameters[0], blockName2: t.parameters[1], divisor: divisor, offset: b.hex.length / 2}); b.hex += "_".repeat(8); // always 4 bytes, placeholder will be filled in during reconciliation phase } break; case 'data': b.hex += t.parameters[0]; break; default: reportError(`unknown command ${t.command}`); return false; } return true; } async function load() { for await (const l of reader) { // Error reporting variables currentLine = l; currentLineNumber++; const tokens = l.split(/[ \t]+/); for(let t of tokens) { if(t.startsWith('#')) { // comment, ignore all subsequent tokens to EOL break; } if(t == '') { continue; } if(!token(t)) { return false; } } } return true; } function dwordLeToHex(v: number): string { // hacky but who cares let h = v.toString(16); h = "0".repeat(8-h.length) + h; return h.substring(6,8) + h.substring(4, 6) + h.substring(2, 4) + h.substring(0, 2); } function fillBlockPlaceholder(block: HexBlock, offset: number, value: number): void { const hexvalue = dwordLeToHex(value); block.hex = block.hex.substring(0, offset * 2) + hexvalue + block.hex.substring(offset * 2 + 8); } function reconciliation(): boolean { let offset = 0; // calculate block sizes for(let b of blocks) { b.offset = offset; offset += b.hex.length / 2; } // reconcile block offsets and sizes for(let b of blocks) { for(let r of b.refs) { const v = blocks.find(q => q.name == r.blockName); if(!v) { reportError(`Could not find block ${r.blockName} when reconciling ${b.name}`); return false; } switch(r.type) { case 'diff': { const v2 = blocks.find(q => q.name == r.blockName2); if(!v2) { reportError(`Could not find block ${r.blockName2} when reconciling ${b.name}`); return false; } fillBlockPlaceholder(b, r.offset, (v2.offset - v.offset) / r.divisor); } break; case 'offset': fillBlockPlaceholder(b, r.offset, v.offset); break; case 'sizeof': fillBlockPlaceholder(b, r.offset, v.hex.length / 2 / r.divisor); break; case 'index': { const v2 = blocks.find(q => q.name == r.blockName2); if(!v2) { reportError(`Could not find block ${r.blockName2} when reconciling ${b.name}`); return false; } fillBlockPlaceholder(b, r.offset, (blocks.indexOf(v2) - blocks.indexOf(v)) / r.divisor); } break; default: reportError(`Invalid ref ${r.type}`); return false; } } } return true; } function save(): Uint8Array { let total = blocks.reduce((total: number, item: HexBlock) => Math.max(item.offset + item.hex.length/2, total), 0); if(!options.silent) { console.log(`${currentLineNumber} lines read; ${blocks.length} sections to write. Total file size = ${total} bytes.` ); } let buffer = new Uint8Array(total); blocks.forEach(item => { let buf = Buffer.from(item.hex, 'hex'); buffer.set(buf, item.offset); }); if(outputFilename) { fs.writeFileSync(outputFilename, buffer); } return buffer; } } keyman/common/tools/hextobin/package.json0000664000000000000000000000060414600607066015775 0ustar { "name": "@keymanapp/hextobin", "description": "hextobin conversion tool", "type": "module", "private": true, "keywords": [ "keyman", "hex", "binary" ], "license": "MIT", "dependencies": { "commander": "^5.1.0" }, "main": "build/index.js", "bin": { "hextobin": "build/hextobin.js" }, "devDependencies": { "@types/node": "^18.7.18" } } keyman/common/tools/hextobin/tsconfig.json0000664000000000000000000000027514600607066016222 0ustar { "extends": "../../../tsconfig.base.json", "compilerOptions": { "rootDir": ".", "outDir": "build/" }, "exclude": ["node_modules"], "files": ["index.ts", "hextobin.ts"] } keyman/common/tools/sourcemap-path-remapper/0000775000000000000000000000000014600607066016430 5ustar keyman/common/tools/sourcemap-path-remapper/build.sh0000775000000000000000000000233114600607066020065 0ustar #!/usr/bin/env bash # # Compiles the JS sourcemap remapper tool used by some of our TS projects when complications # arise with sourcemap handling. # # Exit on command failure and when using unset variables: set -eu ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" # This script runs from its own folder cd "$THIS_SCRIPT_PATH" ################################ Main script ################################ builder_describe "Builds a sourcemap manipulation ES module for use in Web-related builds" \ "clean" \ "configure" \ "build" builder_describe_outputs \ configure /node_modules \ build build/index.js builder_parse "$@" ### CLEAN ACTIONS if builder_start_action clean; then rm -rf build/ builder_finish_action success clean fi ### CONFIGURE ACTIONS if builder_start_action configure; then verify_npm_setup builder_finish_action success configure fi ### BUILD ACTIONS if builder_start_action build; then npm run tsc builder_finish_action success build fikeyman/common/tools/sourcemap-path-remapper/package.json0000664000000000000000000000146114600607066020720 0ustar { "name": "@keymanapp/sourcemap-path-remapper", "description": "Sourcemap-path remapper utility", "main": "build/index.js", "type": "module", "scripts": { "tsc": "tsc" }, "repository": { "type": "git", "url": "git+https://github.com/keymanapp/keyman.git" }, "author": "Joshua A. Horton ", "license": "MIT", "bugs": { "url": "https://github.com/keymanapp/keyman/issues" }, "homepage": "https://github.com/keymanapp/keyman#readme", "devDependencies": { "@keymanapp/resources-gosh": "*", "@types/node": "^10.17.21", "chai": "^4.3.4", "mocha": "^10.0.0", "mocha-teamcity-reporter": "^4.0.0", "sinon": "^7.1.1", "ts-node": "^10.9.1", "typescript": "^4.9.5" }, "dependencies": { "convert-source-map": "^2.0.0" } } keyman/common/tools/sourcemap-path-remapper/src/0000775000000000000000000000000014600607066017217 5ustar keyman/common/tools/sourcemap-path-remapper/src/convert-source-map.d.ts0000664000000000000000000000004414600607066023540 0ustar declare module 'convert-source-map';keyman/common/tools/sourcemap-path-remapper/src/index.ts0000664000000000000000000001151514600607066020701 0ustar import * as fs from 'fs'; import path from 'path'; import convertSourceMap from 'convert-source-map'; // Transforms sourcemaps among various common formats. // Base64, stringified-JSON, end-of-file comment... // Because we're compiling the main project based on its TS build outputs, and our cross-module references // also link to build outputs, we need to clean up the sourcemap-paths. Also, the individual module sourcemaps. export interface Mapping { readonly from: RegExp | string; readonly to: string; } /** * An intermediate state for sourcemap source path remapping operations + functions to * mutate it. */ class RemappingState { constructor(srcmap: Object) { this.sourceMap = srcmap; this.resetChangedSourcepathTracking(); } public readonly sourceMap: any; private _unchangedSourcePaths: string[] = []; public get unchangedSourcepaths() { return this._unchangedSourcePaths; } public resetChangedSourcepathTracking() { this._unchangedSourcePaths = [...this.sourceMap.sources]; } /** * The sourcemap's `sourceRoot` property. */ public get sourceRoot() { return this.sourceMap.sourceRoot; } /** * The sourcemap's `sourceRoot` property. */ public set sourceRoot(path: string) { this.sourceMap.sourceRoot = path; } /** * Searches for source-file paths that match specified path-remapping rules and remaps them * accordingly. * @param transforms Path-remapping rules to apply. For each remappable path, only the first * matching rule in the specified set will be applied. * @returns `this` - the original instance - in order to facilitate function-call chaining. */ remapPaths(transforms: Mapping | Mapping[], logger?: (from: string, to: string) => void) { if(!(transforms instanceof Array)) { transforms = [transforms]; } const unusedTransforms = [...transforms]; const sourcePaths = this.sourceMap.sources; for(let i = 0; i < sourcePaths.length; i++) { for(const transform of transforms) { if(sourcePaths[i].match(transform.from)) { // Note that this source path has been remapped (if it wasn't previously) if(this.unchangedSourcepaths.includes(sourcePaths[i])) { this.unchangedSourcepaths.splice(this.unchangedSourcepaths.indexOf(sourcePaths[i]), 1); } // Note that this transform has been used. if(unusedTransforms.includes(transform)) { unusedTransforms.splice(unusedTransforms.indexOf(transform), 1); } let startPath = sourcePaths[i]; sourcePaths[i] = sourcePaths[i].replace(transform.from, transform.to); if(logger) { logger(startPath, sourcePaths[i]); } break; } } } if(unusedTransforms.length > 0) { console.warn(); console.warn("Unused sourcemath mappings:"); for(const transform of unusedTransforms) { let isRegex = transform.from instanceof RegExp; let delim = isRegex ? '' : '"'; console.warn(`* ${delim}${transform.from.toString()}${delim} => "${transform.to}"`); } } return this; } /** * Prepends all `sources` paths with the current sourceRoot (or just the part after a * specified index). * @param index */ public normalizeWithSourceRoot(index?: number) { const sources = this.sourceMap.sources; const originalSrcRoot = this.sourceRoot; index = index || 0; const prefix = originalSrcRoot.substring(index); this.sourceRoot = originalSrcRoot.substring(0, index); for(let i=0; i < sources.length; i++) { // Normalizes, then swaps Windows '\\' entries with '/' if they exist; // path.normalize respects Windows too much for our taste here. sources[i] = path.normalize(`${prefix}/${sources[i]}`).replace(/\\/g, '/'); } } /** * Writes the current state of the remapped sourcemap out to the specified file. * @param file */ public toFile(file: fs.PathLike) { fs.writeFileSync(file, convertSourceMap.fromObject(this.sourceMap).toJSON(2)); // 2 = space count } } export default class SourcemapRemapper { private constructor() {} /** * Starts sourcemap source path remapping from a pre-loaded JSON sourcemap instance. * @param obj * @returns */ public static fromObject(obj: Object) { return new RemappingState(obj); } /** * Starts sourcemap source path remapping from the specified .js.map file. * @param file * @returns */ public static fromFile(file: fs.PathLike) { return this.fromBuffer(fs.readFileSync(file)); } /** * Starts sourcemap source path remapping from a loaded but unparsed file. * @param buffer * @returns */ public static fromBuffer(buffer: Buffer) { return this.fromObject(convertSourceMap.fromJSON(buffer).toObject()); } }keyman/common/tools/sourcemap-path-remapper/tsconfig.json0000664000000000000000000000107314600607066021140 0ustar { "extends": "../../../tsconfig.base.json", "compilerOptions": { "allowJs": false, "allowSyntheticDefaultImports": true, "declaration": true, "sourceMap": false, "inlineSourceMap": true, "inlineSources": true, "sourceRoot": "/common/tools/sourcemap-path-remapper/src", "lib": ["dom", "es6"], "target": "es5", "types": ["node"], "downlevelIteration": true, "baseUrl": "./", "outDir": "build/", "tsBuildInfoFile": "build/tsconfig.tsbuildinfo", "rootDir": "./src/" }, "include": [ "src/**/*.ts" ] } keyman/configure-repo.sh0000775000000000000000000000402414600607066012522 0ustar #!/usr/bin/env bash # # Setup git hooks in this or all repositories. # # Run this script once to configure your system to work with our Git workflow. # if [[ -n "$WINDIR" ]]; then # https://stackoverflow.com/a/39160850/1836776 SCRIPT_DIR=$(cmd //C cd) else SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" fi case $1 in --global) # Requires Git 2.9 or later. coreHooksPath=`git config --global core.hooksPath` if [[ -z "$coreHooksPath" ]]; then coreHooksPath="(not set)"; fi echo "Current Git core.hooksPath is: $coreHooksPath" git config --global core.hooksPath $SCRIPT_DIR/resources/git-hooks echo "Git is now configured to use $SCRIPT_DIR/resources/git-hooks for all repositories" ;; --local) if [[ -n "$WINDIR" ]]; then # https://stackoverflow.com/a/39160850/1836776 WinPWD=$(cmd //C cd) cmd //C "mklink $WinPWD\\.git\\hooks\\commit-msg $WinPWD\\resources\\git-hooks\\commit-msg" cmd //C "mklink $WinPWD\\.git\\hooks\\prepare-commit-msg $WinPWD\\resources\\git-hooks\\prepare-commit-msg" cmd //C "mklink $WinPWD\\.git\\hooks\\pre-commit $WinPWD\\resources\\git-hooks\\pre-commit" else HOOKSDIR=$(git rev-parse --git-path hooks) ln -sf "$SCRIPT_DIR/resources/git-hooks/commit-msg" "$HOOKSDIR/commit-msg" ln -sf "$SCRIPT_DIR/resources/git-hooks/prepare-commit-msg" "$HOOKSDIR/prepare-commit-msg" ln -sf "$SCRIPT_DIR/resources/git-hooks/pre-commit" "$HOOKSDIR/pre-commit" fi ;; *) echo "" echo "Usage: configure-repo.sh --global|--local" echo "" echo " --local sets up sym links to resources/git-hooks/ for this repo" echo " On Windows, this requires an elevated shell (Run as Administrator)" echo " --global configures Git 2.9+ to check resources/git-hooks for all repos on your system (Beware!)" echo "" echo "The scripts check that their upstream or origin repos are in fact from keymanapp," echo "and explicitly exclude keyboards and lexical-models at this time." echo "" esac keyman/core/0000775000000000000000000000000014600607117010164 5ustar keyman/core/.build-builder0000664000000000000000000000041614600607066012714 0ustar The presence of this file tells CI to use the new builder_ style parameters for build.sh. Once all branches for 16.0+ are updated to merge the chore/core/7247-use-builder-for-build-sh branch, then we can remove this file and the corresponding bash test branches in CI. keyman/core/CORE_API_VERSION.md0000664000000000000000000000000614600607066013133 0ustar 1.0.0 keyman/core/README.md0000664000000000000000000000010714600607066011444 0ustar # Keyman Core Version 1.0.0 of libkeymancore released with Keyman 17.0keyman/core/build.bat0000664000000000000000000000660314600607066011763 0ustar @echo off rem **************************************************************** rem Run build.sh, not this file directly, to build on Windows. rem **************************************************************** setlocal enabledelayedexpansion if "%1"=="" goto help if "%1"=="all" goto all if "%1"=="x86" goto build if "%1"=="x64" goto build echo "Invalid parameter." goto help rem ---------------------------------- :help echo Usage: %0 x86^|x64^|all debug^|release [configure] [build] [test] [additional params for meson/ninja] echo or echo Usage: %0 x86^|x64 -c echo -c will leave your environment configured for Visual Studio for selected platform. echo. echo Otherwise, %0 is intended to be used by build.sh, not directly. echo At least one of 'configure', 'build', or 'test' is required. goto :eof rem ---------------------------------- :all setlocal cd %KEYMAN_ROOT%\core cmd /c build.bat x86 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! cd %KEYMAN_ROOT%\core cmd /c build.bat x64 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! goto :eof rem ---------------------------------- :build set ARCH=%1 shift if "%1"=="-c" goto :setup echo === Locating Visual Studio === rem From https://github.com/microsoft/vswhere for /f "usebackq delims=#" %%a in (`"%programfiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -property installationPath`) do ( set VsDevCmd_Path=%%a\Common7\Tools\VsDevCmd.bat ) if errorlevel 1 ( echo vswhere failed [!errorlevel!] exit /b !errorlevel! ) if not exist "!VsDevCmd_Path!" ( echo Could not find vsdevcmd.bat [!VsDevCmd_Path!] exit /b 1 ) echo === Configuring VC++ === set VSCMD_SKIP_SENDTELEMETRY=1 call "!VsDevCmd_Path!" -arch=!ARCH! -no_logo -startdir=none || exit !errorlevel! cd %KEYMAN_ROOT%\core set BUILDTYPE=%1 shift set STATIC_LIBRARY=--default-library both set COMMAND=%1 shift if "!COMMAND!" == "configure" ( echo === Configuring Keyman Core for Windows !ARCH! !BUILDTYPE! === if exist build\!ARCH!\!BUILDTYPE! rd /s/q build\!ARCH!\!BUILDTYPE! if "%1" == "--no-tests" ( meson setup build\!ARCH!\!BUILDTYPE! !STATIC_LIBRARY! --buildtype !BUILDTYPE! -Dkeyman_core_tests=false --werror %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! ) else ( meson setup build\!ARCH!\!BUILDTYPE! !STATIC_LIBRARY! --buildtype !BUILDTYPE! --werror %1 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! ) shift ) if "!COMMAND!" == "build" ( echo === Building Keyman Core for Windows !ARCH! !BUILDTYPE! === cd build\!ARCH!\!BUILDTYPE! || exit !errorlevel! ninja %1 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! cd ..\..\.. shift ) if "!COMMAND!" == "test" ( echo === Testing Keyman Core for Windows !ARCH! !BUILDTYPE! === cd build\!ARCH!\!BUILDTYPE! || exit !errorlevel! meson test --print-errorlogs %1 %2 %3 %4 %5 %6 %7 %8 %9 || exit !errorlevel! cd ..\..\.. shift ) goto :eof rem ---------------------------------- :setup rem Standalone build, so we'll make the environment available to the caller rem Also setup rem Note: Visual Studio 2022 doesn't provide vcvarsall.bat, so we'll have to find a different solution endlocal for /f "usebackq delims=#" %%a in (`"%programfiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -property installationPath`) do ( set VsDevCmd_Path=%%a\Common7\Tools\VsDevCmd.bat ) set VSCMD_SKIP_SENDTELEMETRY=1 "!VsDevCmd_Path!" -arch=!ARCH! -no_logo -startdir=none goto :eof rem ---------------------------------- keyman/core/build.sh0000775000000000000000000001433114600607066011627 0ustar #!/usr/bin/env bash set -e set -u ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" . "$THIS_SCRIPT_PATH/commands.inc.sh" cd "$THIS_SCRIPT_PATH" ################################ Main script ################################ cleanup_visual_studio_path MESON_LOW_VERSION=false if [[ `meson --version` < 0.54 ]]; then MESON_LOW_VERSION=true fi # # Restrict available targets to those that can be built on the current system # archtargets=(":wasm WASM build") case $BUILDER_OS in win) archtargets+=( ":x86 32-bit Windows (x86) build" ":x64 64-bit Windows (x64) build" ) ;; mac) archtargets+=( ":mac Mac all architectures fat library build" ":mac-x86_64 Mac Intel build" ":mac-arm64 Mac arm64 (M1) build" ) ;; linux) archtargets+=( ":arch Linux build -- current architecture" ) ;; esac # TODO: consider using "linux" instead of "arch"? # ":linux Build for current Linux architecture" builder_describe \ "Build Keyman Core Libraries will be built in 'build///src'. * : 'debug' or 'release' (see --debug flag) * All parameters after '--' are passed to meson or ninja \ " \ "@/common/tools/hextobin" \ "@/common/web/keyman-version" \ "@/developer/src/kmc" \ "clean" \ "configure" \ "build" \ "test" \ "install install libraries to current system" \ "uninstall uninstall libraries from current system" \ "${archtargets[@]}" \ "--no-tests do not configure tests (used by other projects)" \ "--test,-t=opt_tests test[s] to run (space separated)" builder_parse "$@" # # meson forces us to configure tests, including building compilers, even # if we don't plan to run them, for example when doing a dependency build # in CI # MESON_OPTION_keyman_core_tests= BUILD_BAT_keyman_core_tests= if builder_is_dep_build || builder_has_option --no-tests; then MESON_OPTION_keyman_core_tests="-Dkeyman_core_tests=false" BUILD_BAT_keyman_core_tests=--no-tests builder_remove_dep /common/tools/hextobin builder_remove_dep /common/web/keyman-version builder_remove_dep /developer/src/kmc fi # 'mac' target builds both x86_64 and arm architectures and # generates a 'fat' library from them. builder_describe_internal_dependency \ build:mac build:mac-x86_64 \ build:mac build:mac-arm64 builder_describe_outputs \ configure:x86 /core/build/x86/$BUILDER_CONFIGURATION/build.ninja \ configure:x64 /core/build/x64/$BUILDER_CONFIGURATION/build.ninja \ configure:mac /core/build/mac/$BUILDER_CONFIGURATION/ \ configure:mac-x86_64 /core/build/mac-x86_64/$BUILDER_CONFIGURATION/build.ninja \ configure:mac-arm64 /core/build/mac-arm64/$BUILDER_CONFIGURATION/build.ninja \ configure:arch /core/build/arch/$BUILDER_CONFIGURATION/build.ninja \ configure:wasm /core/build/wasm/$BUILDER_CONFIGURATION/build.ninja \ build:x86 /core/build/x86/$BUILDER_CONFIGURATION/src/libkeymancore.a \ build:x64 /core/build/x64/$BUILDER_CONFIGURATION/src/libkeymancore.a \ build:mac /core/build/mac/$BUILDER_CONFIGURATION/libkeymancore.a \ build:mac-x86_64 /core/build/mac-x86_64/$BUILDER_CONFIGURATION/src/libkeymancore.a \ build:mac-arm64 /core/build/mac-arm64/$BUILDER_CONFIGURATION/src/libkeymancore.a \ build:arch /core/build/arch/$BUILDER_CONFIGURATION/src/libkeymancore.a \ build:wasm /core/build/wasm/$BUILDER_CONFIGURATION/src/libkeymancore.a # Import our standard compiler defines; this is copied from # /resources/build/meson/standard.meson.build by build.sh, because meson doesn't # allow us to reference a file outside its root if builder_has_action configure; then mkdir -p "$THIS_SCRIPT_PATH/resources" cp "$KEYMAN_ROOT/resources/build/meson/standard.meson.build" "$THIS_SCRIPT_PATH/resources/meson.build" fi # Iterate through all possible targets; note that targets that cannot be built # on the current platform have already been excluded through the archtargets # settings above targets=(wasm x86 x64 mac-x86_64 mac-arm64 arch) do_action() { local action_function=do_$1 for target in "${targets[@]}"; do MESON_PATH="$KEYMAN_ROOT/core/build/$target/$BUILDER_CONFIGURATION" $action_function $target done } # ------------------------------------------------------------------------------- do_action clean # ------------------------------------------------------------------------------- do_action configure # After we have built the necessary internal dependencies, then we can go # ahead and build a fat library for external consumption if builder_start_action configure:mac; then mkdir -p "$KEYMAN_ROOT/core/build/mac/$BUILDER_CONFIGURATION" builder_finish_action success configure:mac fi # ------------------------------------------------------------------------------- do_action build if builder_start_action build:mac; then lipo -create \ "$KEYMAN_ROOT/core/build/mac-x86_64/$BUILDER_CONFIGURATION/src/libkeymancore.a" \ "$KEYMAN_ROOT/core/build/mac-arm64/$BUILDER_CONFIGURATION/src/libkeymancore.a" \ -output "$KEYMAN_ROOT/core/build/mac/$BUILDER_CONFIGURATION/libkeymancore.a" builder_finish_action success build:mac fi # ------------------------------------------------------------------------------- testparams="${builder_extra_params[@]} --print-errorlogs" if builder_has_option --test; then testparams="$opt_tests $testparams" fi do_action test if builder_start_action test:mac; then # We can only run the tests for the current architecture; we can # assume that build:mac has run so both architectures will be # available target=mac-`uname -m` MESON_PATH="$KEYMAN_ROOT/core/build/$target/$BUILDER_CONFIGURATION" meson test -C "$MESON_PATH" $testparams builder_finish_action success test:mac fi # ------------------------------------------------------------------------------- do_action install do_action uninstall keyman/core/commands.inc.sh0000664000000000000000000001214114600607066013073 0ustar # shellcheck shell=bash # no hashbang for .inc.sh . "$KEYMAN_ROOT/resources/locate_emscripten.inc.sh" # ---------------------------------------------------------------------------- # clean # ---------------------------------------------------------------------------- do_clean() { # clean: note build/ will be left, but build// should be gone local target=$1 builder_start_action clean:$target || return 0 rm -rf "$MESON_PATH" # Removes ICU cached components so it will be re-downloaded and built. Note: # we could use `git clean`, but this clarifies exactly what is deleted, and # but we try not to use git commands in build scripts, to maintain clear # responsibility rm -rf \ "$THIS_SCRIPT_PATH/subprojects/icu" \ "$THIS_SCRIPT_PATH/subprojects/*.tgz" \ "$THIS_SCRIPT_PATH/subprojects/*.zip" builder_finish_action success clean:$target } # ---------------------------------------------------------------------------- # configure # ---------------------------------------------------------------------------- do_configure() { local target=$1 builder_start_action configure:$target || return 0 local STANDARD_MESON_ARGS="$MESON_OPTION_keyman_core_tests --default-library both" local MESON_CROSS_FILE= if [[ -f "$THIS_SCRIPT_PATH/cross-$target.build" ]]; then MESON_CROSS_FILE="--cross-file cross-$target.build" fi builder_heading "======= Configuring $target =======" if [[ $target == wasm ]]; then # do_configure_wasm locate_emscripten build_meson_cross_file_for_wasm STANDARD_MESON_ARGS="$STANDARD_MESON_ARGS --cross-file wasm.defs.build --cross-file wasm.build --default-library static" fi if [[ $target =~ ^(x86|x64)$ ]]; then cmd //C build.bat $target $BUILDER_CONFIGURATION configure $BUILD_BAT_keyman_core_tests "${builder_extra_params[@]}" else pushd "$THIS_SCRIPT_PATH" > /dev/null # Additional arguments are used by Linux build, e.g. -Dprefix=${INSTALLDIR} meson setup "$MESON_PATH" $MESON_CROSS_FILE --werror --buildtype $BUILDER_CONFIGURATION $STANDARD_MESON_ARGS "${builder_extra_params[@]}" popd > /dev/null fi builder_finish_action success configure:$target } # ---------------------------------------------------------------------------- # build # ---------------------------------------------------------------------------- do_build() { local target=$1 builder_start_action build:$target || return 0 if [[ $target =~ ^(x86|x64)$ ]]; then cmd //C build.bat $target $BUILDER_CONFIGURATION build "${builder_extra_params[@]}" elif $MESON_LOW_VERSION; then pushd "$MESON_PATH" > /dev/null ninja popd else meson compile -C "$MESON_PATH" fi builder_finish_action success build:$target } # ---------------------------------------------------------------------------- # test # ---------------------------------------------------------------------------- do_test() { local target=$1 builder_start_action test:$target || return 0 if [[ $target =~ ^(x86|x64)$ ]]; then cmd //C build.bat $target $BUILDER_CONFIGURATION test $testparams else meson test -C "$MESON_PATH" $testparams fi builder_finish_action success test:$target } # ---------------------------------------------------------------------------- # install and uninstall # ---------------------------------------------------------------------------- do_install() { local target=$1 builder_start_action install:$target || return 0 if $MESON_LOW_VERSION; then pushd "$MESON_PATH" > /dev/null ninja install popd > /dev/null else meson install -C "$MESON_PATH" fi builder_finish_action success install:$target } do_uninstall() { local target=$1 builder_start_action uninstall:$target || return 0 pushd "$MESON_PATH" > /dev/null # Note: there is no meson uninstall command, which means # this probably won't work on Windows ninja uninstall popd > /dev/null builder_finish_action success uninstall:$target } # ---------------------------------------------------------------------------- # utility functions # ---------------------------------------------------------------------------- build_meson_cross_file_for_wasm() { if [ $BUILDER_OS == win ]; then local R=$(cygpath -w $(echo $EMSCRIPTEN_BASE) | sed 's_\\_\\\\_g') else local R=$(echo $EMSCRIPTEN_BASE | sed 's_/_\\/_g') fi sed -e "s/\$EMSCRIPTEN_BASE/$R/g" wasm.build.$BUILDER_OS.in > wasm.build } # # Remove Visual Studio from the path so that meson goes looking for it rather than # assuming that it's all available. If we don't do this, we get an error with link.exe: # # meson.build:8:0: ERROR: Found GNU link.exe instead of MSVC link.exe in C:\Program Files\Git\usr\bin\link.EXE. # This link.exe is not a linker. # You may need to reorder entries to your %PATH% variable to resolve this. # # TODO: is this still required with meson 1.0? # cleanup_visual_studio_path() { local _split_path _new_path="" IFS=':' read -ra _split_path <<<"$PATH" for p in "${_split_path[@]}"; do if ! [[ $p =~ Visual\ Studio ]]; then _new_path="$_new_path:$p" fi done PATH="${_new_path:1}" unset VSINSTALLDIR } keyman/core/cross-mac-arm64.build0000664000000000000000000000045014600607066014025 0ustar [host_machine] system = 'darwin' cpu_family = 'aarch64' cpu = 'arm64' endian = 'little' [binaries] c = ['clang', '-arch', 'arm64'] objc = ['clang', '-arch', 'arm64'] cpp = ['clang++', '-arch', 'arm64'] ar = 'ar' ld = 'ld' strip = 'strip' lipo = 'lipo' ranlib = 'ranlib' pkgconfig = 'pkg-config' keyman/core/cross-mac-x86_64.build0000664000000000000000000000045314600607066014035 0ustar [host_machine] system = 'darwin' cpu_family = 'x86_64' cpu = 'x86_64' endian = 'little' [binaries] c = ['clang', '-arch', 'x86_64'] objc = ['clang', '-arch', 'x86_64'] cpp = ['clang++', '-arch', 'x86_64'] ar = 'ar' ld = 'ld' strip = 'strip' lipo = 'lipo' ranlib = 'ranlib' pkgconfig = 'pkg-config' keyman/core/doc/0000775000000000000000000000000014600607066010734 5ustar keyman/core/doc/BUILDING.md0000664000000000000000000000040114600607066012446 0ustar # How to build the keyboard processor ## Prerequisites See [build configuration](../../docs/build/index.md) for details on how to configure your build environment. ## Building On all platforms, use `build.sh`. * See `./build.sh --help` for more details keyman/core/doc/hotdoc.json0000664000000000000000000000067714600607066013121 0ustar { "project_name": "@project_name@", "project_version": "@project_version@", "sitemap": "@doc_dir@/sitemap.txt", "index": "@doc_dir@/markdown_files/index.md", "c_sources": [ "@include_dir@/keyman/keyman_core_api.h" ], "c_include_directories": [ "@include_dir@", "@doc_dir@/../../common/include" ], "c_smart_index" : true, "output": ".", "extra_assets": [ "../../assets" ] } keyman/core/doc/introspection.schema0000664000000000000000000000343514600607066015023 0ustar {"$schema": "http://json-schema.org/draft-06/schema#", "$id": "@replace_me_with_introspection_schema_uri@", "$comment": "© 2018 SIL International. MIT Licensed", "title": "Keyboard Processor State object introspection", "description": "Internal data from a Keyboard Processor State object, sufficient for debugging and diagnostics", "type": "object", "definitions": { "options": { "type": "object", "properties": { "scope": { "enum": ["unknown", "environment", "keyboard"] }, "options": { "type": "object", "default": {} } }, "required": ["scope", "options"] }, "rule": { "type": "object" }, "keyboard" : { "type": "object", "properties": { "id": { "type": "string" }, "version": { "type": "string" }, "folder": { "type": "string"}, "options": { "$ref": "#definitions/options" }, "rules": { "type":"array", "items": { "$ref": "#/definitions/rule" } } }, "required": ["id", "version", "folder", "options", "rules"] }, "context": { "type":"array", "items": {"$ref": "#/definitions/context_item"}, "default": [] }, "context_item": { "oneOf": [ {"type": "string", "minLength": 1, "maxLength": 4}, {"type": "number"} ] } }, "properties": { "$schema": { "const": "keyman/core/doc/introspection.schema" }, "keyboard": { "$ref": "#/definitions/keyboard" }, "options": { "type": "object", "properties": { "enviroment": { "$ref": "#/definitions/options" }, "dynamic": { "$ref": "#/definitions/options" } }, "required": [ "enviroment","dynamic"] }, "context": { "$ref": "#/definitions/context" } } } keyman/core/doc/markdown_files/0000775000000000000000000000000014600607066013740 5ustar keyman/core/doc/markdown_files/index.md0000664000000000000000000000554514600607066015402 0ustar # Keyman Keyboard Processor API ## Requirements 1. Cross platform. 2. Cross language. 3. Facilitate stateless operation of the Engine. 4. Keyboard format agnostic -- support both KMN and future LDML based keyboards. 5. Support querying Engine attributes. 6. Support querying Keyboard attributes. 7. Idempotent ## Design decisions in support of requirements: - Use C or C99 types and calling convention for the interface, it has the broadest language FFI support. [1,2] - Have client (platform glue) code load keyboards, manage & pass state. [3,4,7] - Provide query calls to return static attributes data for keyboards and engine [5,6] - Provide get/set calls for client accessible keyboard state information [3,4] ## Glossary - __Platform layer:__ the code that consumes the Keyman Keyboard Processor API, and provides the operating system-specific handling of keystroke events and integration with applications. - __Client Application:__ the application that has the focus and receives text events from the Platform layer. - __Context:__ Text preceding the insertion point - __Marker:__ Positional state that can be placed in the Context. - __Keyboard:__ A set of rules for execution by an Engine - __Option:__ A variable in a dynamic or static key value store. - __Processor:__ The component that implements this API and can parse and execute a particular keyboard. - __State:__ An object that holds internal state of the Processor for a given insertion point - __Action:__ A directive output by the processor detailing how the Platform layer should transform the Client Application's text buffer. There may be several items produced by a single keyboard event. - __Keyboard Event:__ A virtual key board event and modifier map recevied from the Platform layer to be processed with the state object for this Client application. - __Virtual Key:__ A code based on the US English layout, with values matching the Windows virtual key codes. See `keyman_core_api_vkeys.h` for definitions. - __Modifier Key:__ The set of Control, Shift, Alt, Caps Lock keys. On some platforms these may have other names (e.g. Alt is called Option on macOS); other platform-specific modifiers such as Windows key are excluded from this set. Some modifiers are transient, such as Control, and others have long-lasting state, such as Caps Lock. ## API ### Namespace All calls, types and enums are prefixed with the namespace identifier `km_core_` ### Changes from 16.0 * The namespace identifier has changed from `km_kbp_` to `km_core_`. * Most context APIs are now private, and `km_core_context_set_if_needed` is the primary context function. Private APIs are available in `keyman_core_api_context.h`. * The action queue APIs are now private and deprecated. Instead, use `km_core_state_get_actions`. Private APIs are available in `keyman_core_api_actions.h`. * Debug APIs are available in `keyman_core_api_debug.h`. keyman/core/doc/meson.build0000664000000000000000000000217114600607066013077 0ustar # Copyright: © 2018 SIL International. # Description: Cross platform build script to extract and generate # documentation for the API. This is speculative ATM. # Create Date: 5 Oct 2018 # Authors: Tim Eves (TSE) # hotdoc = find_program('hotdoc', required: false) installdir = join_paths(get_option('datadir'), 'doc', meson.project_name()) if hotdoc.found() cfg = configuration_data() cfg.set('project_name', meson.project_name()) cfg.set('project_version', meson.project_version()) cfg.set('doc_dir', meson.current_source_dir()) cfg.set('include_dir', meson.current_source_dir() / '../include') configure_file(input: 'hotdoc.json', output: 'hotdoc.json', configuration: cfg) deps = files( '../include/keyman/keyman_core_api.h', '../src/jsonpp.hpp', '../src/utfcodec.hpp' ) docs = custom_target('docs', output: ['html'], input: ['sitemap.txt', 'markdown_files/index.md', deps], command: [hotdoc, '--verbose', '--conf-file=doc/hotdoc.json', '--output=doc', 'run'], depend_files: deps, install: true, install_dir: installdir) endif keyman/core/doc/sitemap.txt0000664000000000000000000000002214600607066013131 0ustar index.md c-index keyman/core/getversion.bat0000664000000000000000000000011014600607066013034 0ustar @echo off REM Get the version number from VERSION.md more ..\VERSION.md keyman/core/getversion.sh0000775000000000000000000000011714600607066012712 0ustar #!/usr/bin/env bash # Get the version number from VERSION.md cat ../VERSION.md keyman/core/include/0000775000000000000000000000000014600607066011612 5ustar keyman/core/include/keyman/0000775000000000000000000000000014600607066013076 5ustar keyman/core/include/keyman/keyman_core_api.h0000664000000000000000000012546414600607066016410 0ustar /* Copyright: © 2018 SIL International. Description: Cross platform API C/C++ declarations for libkeymancore Create Date: 2 Oct 2018 Authors: Tim Eves (TSE) */ #pragma once #include #include #include #include #include #if defined(__cplusplus) extern "C" { #endif /* --- filename: index.md title: Keyman Core API --- ## Overview Keyman Core is the component of Keyman Engine that implements keyboarding rules. It is platform independent and allows support for different keyboard formats to be implemented within Keyman Engine. Eventually, Keyman Core will be used in Keyman on all platforms. As of writing, Keyman for Linux, Keyman for Windows, Keyman for macOS, and Keyman Developer use Keyman Core. This is an internal API intended for use only within Keyman Engine. ## Reference * [Background](background) * [Changes from earlier versions](changes) * [Keyboards](keyboards) * [Options](options) * [Processor](processor) * [State and Actions](state) * [JSON introspection Schema](json-schema) * [Building Keyman Core](building) ## Requirements 1. Cross platform. 2. Cross language. 3. Facilitate stateless operation of the Engine. 4. Keyboard format agnostic -- support both KMN and future LDML based keyboards. 5. Support querying Engine attributes. 6. Support querying Keyboard attributes. 7. Idempotent ## Design decisions in support of requirements - Use C or C99 types and calling convention for the interface, it has the broadest language FFI support. [1,2] - Have client (Platform layer) code load keyboards, manage & pass state. [3,4,7] - Provide query calls to return static attributes data for keyboards and engine [5,6] - Provide get/set calls for client accessible keyboard state information [3,4] ## Glossary - __Platform layer:__ The code that consumes the Keyman Core API, and provides the operating system-specific handling of keystroke events and integration with applications. - __Client Application:__ The application that has the focus and receives text events from the Platform layer. - __Context:__ Text preceding the insertion point - __Marker:__ Positional state that can be placed in the Context. - __Keyboard:__ A set of rules for execution by an Engine - __Option:__ A variable in a dynamic or static key value store. - __Processor:__ The component that implements this API and can parse and execute a particular keyboard. - __State:__ An object that holds internal state of the Processor for a given insertion point - __Action:__ A directive output by the processor detailing how the Platform layer should transform the Client Application's text buffer. There may be several items produced by a single keyboard event. - __Keyboard Event:__ A virtual key event and modifier map received from the Platform layer to be processed with the state object for this Client application. - __Virtual Key:__ A code based on the US English layout, with values matching the Windows virtual key codes. See `keyman_core_api_vkeys.h` for definitions. - __Modifier Key:__ The set of Control, Shift, Alt, Caps Lock keys. On some platforms these may have other names (e.g. Alt is called Option on macOS); other platform-specific modifiers such as Windows key are excluded from this set. Some modifiers are transient, such as Control, and others have long-lasting state, such as Caps Lock. --- filename: changes.md title: Changes - Keyman Core API --- ## Changes between 16.0 and 17.0 * The namespace identifier has changed from `km_kbp_` to `km_core_`. * Most context APIs are now private, and [km_core_state_context_set_if_needed] is the primary context function. Private APIs are available in `keyman_core_api_context.h`. * The action queue APIs are now private and deprecated. Instead, use [km_core_state_get_actions]. Private APIs are available in `keyman_core_api_actions.h`. * Debug APIs are available in `keyman_core_api_debug.h`. ------------------------------------------------------------------------------- --- filename: background.md title: Background - Keyman Core API --- ## Namespace All calls, types and enums are prefixed with the namespace identifier `km_core_` ## API idioms ### Error Handling Error handling and success failure notification are communicated through a general mechanism similar to COM’s `HRESULT` scheme (unlike COM, any non-zero value is an error). Any functions that can fail will always return a status value and all results are returned via outparams passed to the function. ### Passing variable length data out Almost all calls marshalling variable length aggregate data in or out of an API object take the form: ```c km_core_status fn_name(object_ref, buffer_ptr, size_ptr) ``` where the `buffer_ptr` is nullable and all other arguments are required (will result in an [`KM_CORE_STATUS_INVALID_ARGUMENT`](#km_core_status_codes) status being returned if nulled). When `buffer_ptr` is `nullptr` or `0` the function will place the size of the required buffer in the variable pointed to by `size_ptr`. ### Resource management Calls which result in the allocation of resources, regardless of resulting ownership, are of the form: ```c km_core_status fn_name(object_ref, handle_out_ptr) ``` where `handle_out_ptr` is a valid pointer to a caller allocated variable to hold the resulting resource handle. This is often a reference to a created object. Unless stated all arguments are required (will result in an [`KM_CORE_STATUS_INVALID_ARGUMENT`](#km_core_status_codes) status being returned if nulled). All dispose calls are designed to accept `nullptr` or `0` as a valid value and will do nothing in that event. ### Fixed size attribute access For accessors to fixed size attributes of an object these will take the form: ```c attr_value fn_name(object_ref) ``` `object_ref` is required to be valid and will result in a nonsense value being returned if `nullptr` or `0`. ### Versioning scheme This follows the libtool interface versioning scheme of `current.age.revision`: `current` The most recent interface number that the engine implements. `age` How many interface numbers back from current the library implements. E.g. 5.2.0 would mean the library provides interface versions 3-5 and 5.0.0 would mean just interface version 5 and nothing older. `revision` The implementation version of the current interface. This represents improvements to the code that don't change the intended behaviour of the interface such as bug fixes and optimisations. For Linux and other OS which support this scheme the dynamic linker will automatically choose the most updated version if more than one implementation is available. For Windows or dynamic loaded shared objects on Linux you can use the [km_core_get_engine_attrs] call and [Library version macros](#lib-version-macros) to check the loaded DLL supplies the correct interface. ------------------------------------------------------------------------------- # Common functions, types, and macros ## Basic types Fundamental types for representing data passed across the API. ### km_core_cp type `uint16_t/char16_t` Represents a UTF16 codepoint, most strings are passed as UTF16. ### km_core_usv type `uint32_t/char32_t` An integral type capable of holding a single Unicode Scalar Value, a decoded UTF codepoint. ### km_core_virtual_key type `uint16_t` An integral type capable of holding a platform specific virtual key code. ### km_core_status type `uint32_t` An integral 32 bit wide type capable of holding any valid status code as defined by the `enum` [km_core_status_codes]. ### km_core_modifier_state type `uint16_t` An integral type bitmask representing the state of each modifier key. ## Resource types Opaque types for representing resources provided or created by the keyboard processor implementation. ### km_core_keyboard struct Represents a keyboard loaded from disk, that can be executed by the keyboard processor to consume events, update state associated with an insertion point and produce action items. A keyboard object may be referenced by any number of state objects but must be disposed of after all state objects referencing it have first been disposed of. ### km_core_state struct Represents all state associated with an insertion point using a keyboard. This tracks context, and current action items resulting from a processed keyboard event. There can be many state objects using the same keyboard. A state object may not live longer than the keyboard it manages state for. ### km_core_options struct Represents a set of option items for environmental state and keyboard state. ------------------------------------------------------------------------------- # km_core_status_codes enum ## Description An error code mechanism similar to COM’s `HRESULT` scheme (unlike COM, any non-zero value is an error). ## Specification ```c */ enum km_core_status_codes { KM_CORE_STATUS_OK = 0, KM_CORE_STATUS_NO_MEM = 1, KM_CORE_STATUS_IO_ERROR = 2, KM_CORE_STATUS_INVALID_ARGUMENT = 3, KM_CORE_STATUS_KEY_ERROR = 4, KM_CORE_STATUS_INSUFFICENT_BUFFER = 5, KM_CORE_STATUS_INVALID_UTF = 6, KM_CORE_STATUS_INVALID_KEYBOARD = 7, KM_CORE_STATUS_NOT_IMPLEMENTED = 8, KM_CORE_STATUS_OS_ERROR = 0x80000000 }; /* ``` ## Values `KM_CORE_STATUS_OK` : Success code. Call completed as documented. `KM_CORE_STATUS_NO_MEM` : The call failed to allocate memory during its execution, causing it to fail. `KM_CORE_STATUS_IO_ERROR` : The call performed an I/O operation which failed, causing it to fail. `KM_CORE_STATUS_INVALID_ARGUMENT` : The call detected one of its parameters was invalid or unsafe. `KM_CORE_STATUS_KEY_ERROR` : The provided key or index into a collection object was not present. `KM_CORE_STATUS_INSUFFICENT_BUFFER` : The provided buffer did not contain enough space to fully encode or copy the result of this call. `KM_CORE_STATUS_INVALID_UTF` : A malformed or partial UTF sequence prevented complete decoding of a unicode string. `KM_CORE_STATUS_INVALID_KEYBOARD` : An attempt to decode a keyboard file failed. `KM_CORE_STATUS_OS_ERROR` : This allows encapsulating a platform error code: the remaining 31 low bits are the error code returned by the OS for cases where the failure mode is platform specific. For HRESULT codes this only permits failure codes to be passed and not success codes. ------------------------------------------------------------------------------- # km_core_attr struct ## Description A structure describing information about Keyman Core implementing this API. ## Specification ```c */ typedef struct { size_t max_context; uint16_t current; uint16_t revision; uint16_t age; uint16_t technology; char const *vendor; } km_core_attr; /* ``` ## Members `max_context` : Maximum context size supported by processor. `current` : Current API number supported. `revision` : Implementation number of current API. `age` : current - age == Oldest API number supported. `technology` : A bit field of [km_core_tech_value] values, specifiying which Keyboard technologies the engine supports. `vendor` : A UTF-8 encoded string identifying the implementer of the processor. ------------------------------------------------------------------------------- # km_core_tech_value enum ## Description Values for a bit field indicating which keyboarding technologies a keyboard processor supports. ## Specification ```c */ enum km_core_tech_value { KM_CORE_TECH_UNSPECIFIED = 0, KM_CORE_TECH_MOCK = 1 << 0, KM_CORE_TECH_KMX = 1 << 1, KM_CORE_TECH_LDML = 1 << 2 }; /* ``` ## Values `KM_CORE_TECH_UNSPECIFIED` : The keyboard processor implementation does not disclose which technologies it implements. `KM_CORE_TECH_MOCK` : The keyboard processor implements a simple en-US keyboard for the purposes of testing the API. `KM_CORE_TECH_UNSPECIFIED` : The keyboard processor implements a Keyman KMX compatible engine. `KM_CORE_TECH_UNSPECIFIED` : The keyboard processor implements a LDML capable processing engine. ------------------------------------------------------------------------------- # km_core_get_engine_attrs() ## Description Get access processors attributes describing version and technology implemented. ## Specification ```c */ KMN_API km_core_attr const * km_core_get_engine_attrs(km_core_state const *state); /* ``` ## Parameters `state` : An opaque pointer to a [km_core_state]. ## Returns A pointer to a [km_core_attr] structure. Do not modify the contents of this structure. ------------------------------------------------------------------------------- # km_core_bool enum ## Description Defines a boolean state. ## Specification ```c */ typedef enum { KM_CORE_FALSE = 0, KM_CORE_TRUE = 1 } km_core_bool; /* ``` ------------------------------------------------------------------------------- --- filename: state.md title: State and Actions - Keyman Core API --- A State object maintains all per keyboard related state including context and dynamic options ("option stores" in kmn format). When a keystroke is processed by Keyman Core, Core provides back a set of actions for the Platform layer to emit to the Client application. These actions are owned by the state object. ------------------------------------------------------------------------------- # km_core_caps_state enum ## Description Describes a change to the hardware caps lock indicator state requested by Keyman Core to the Platform layer. ## Specification ```c */ typedef enum { KM_CORE_CAPS_UNCHANGED = -1, KM_CORE_CAPS_OFF = 0, KM_CORE_CAPS_ON = 1 } km_core_caps_state; /* ``` ## Values `KM_CORE_CAPS_UNCHANGED` : Caps lock state has not changed in this event. `KM_CORE_CAPS_OFF` : As a result of processing this event, the Platform layer should switch off Caps Lock on the hardware keyboard. `KM_CORE_CAPS_ON` : As a result of processing this event, the Platform layer should switch on Caps Lock on the hardware keyboard. ------------------------------------------------------------------------------- # km_core_actions struct ## Description This structure provides the results of processing a key event to the Platform layer and should be processed by the Platform layer to issue commands to the os text services framework to transform the text store in the Client Application, among other actions. This API replaces the Action items APIs, which are now deprecated and will be removed in the future. ## Specification ```c */ typedef struct { unsigned int code_points_to_delete; const km_core_usv* output; km_core_option_item * persist_options; km_core_bool do_alert; km_core_bool emit_keystroke; km_core_caps_state new_caps_lock_state; const km_core_usv* deleted_context; } km_core_actions; /* ``` ## Members `code_points_to_delete` : Number of codepoints (not codeunits!) to delete from app context. `output` : Null-term string of characters to insert into document. `persist_options` : List of options to persist, terminated with `KM_CORE_OPTIONS_END`. `do_alert` : Issue a beep, 0 = no, 1 = yes. `emit_keystroke` : Emit the (unmodified) input keystroke to the application, 0 = no, 1 = yes. `new_caps_lock_state` : -1=unchanged, 0=off, 1=on `deleted_context` : Reference copy of actual UTF32 codepoints deleted from end of context (closest to caret) exactly code_points_to_delete in length (plus null terminator). Used to determine encoding conversion differences when deleting; only set when using [km_core_state_get_actions], otherwise nullptr. ------------------------------------------------------------------------------- # km_core_state_get_actions() ## Description Returns a pointer to an actions object which details all the actions that the Platform layer must take after a keystroke. The `code_points_to_delete` action must be performed before the `output` action, but the other actions may be performed in any order. ## Specification ```c */ KMN_API km_core_actions const * km_core_state_get_actions( km_core_state const *state ); /* ``` ## Parameters `state` : An opaque pointer to a state object. ## Returns A pointer to a [km_core_actions] object. This data becomes invalid when the state object is destroyed, or after a call to [km_core_process_event]. Do not modify the contents of this data. ------------------------------------------------------------------------------- # km_core_context_status enum ## Description Return values for [km_core_state_context_set_if_needed]. ## Specification ```c */ typedef enum { KM_CORE_CONTEXT_STATUS_UNCHANGED = 0, KM_CORE_CONTEXT_STATUS_UPDATED = 1, KM_CORE_CONTEXT_STATUS_CLEARED = 2, KM_CORE_CONTEXT_STATUS_ERROR = 3, KM_CORE_CONTEXT_STATUS_INVALID_ARGUMENT = 4, } km_core_context_status; /* ``` ## Values `KM_CORE_CONTEXT_STATUS_UNCHANGED` : Cached context change was not needed. `KM_CORE_CONTEXT_STATUS_UPDATED` : Cached context was set to application context. `KM_CORE_CONTEXT_STATUS_CLEARED` : Application context was invalid, perhaps had unpaired surrogates, and so cached context was cleared instead. `KM_CORE_CONTEXT_STATUS_ERROR` : Internal error. `KM_CORE_CONTEXT_STATUS_INVALID_ARGUMENT` : One or more parameters was null. ------------------------------------------------------------------------------- # km_core_state_context_set_if_needed() ## Description Sets the internal cached context for the state object, to the passed-in application context string, if it differs from the codepoints in the cached context. For the purposes of comparison, (1) cached markers are ignored, (2) if the cached context is shorter than the application context, it is considered identical, but (3) if the cached context is longer, then it is considered different. If a difference is found, then the cached context will be set to the application context, and thus any cached markers will be cleared. [km_core_state_context_set_if_needed] and [km_core_state_context_clear] will replace most uses of the existing Core context APIs. ## Specification ```c */ KMN_API km_core_context_status km_core_state_context_set_if_needed( km_core_state *state, km_core_cp const *application_context ); /* ``` ## Parameters `state` : An opaque pointer to a state object. `application_context` : A pointer to an null-terminated array of utf16 encoded data representing the current context from the application. ## Returns A value from the [km_core_context_status] enum. ------------------------------------------------------------------------------- # km_core_state_context_clear() ## Description Clears the internal cached context for the state. This is the same as `km_core_context_clear(km_core_state_context(&state))`. [km_core_state_context_set_if_needed] and [km_core_state_context_clear] will replace most uses of the existing Core context APIs. ## Specification ```c */ KMN_API km_core_status km_core_state_context_clear( km_core_state *state ); /* ``` ## Parameters `state`: An opaque pointer to a state object. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If any parameters are null. ------------------------------------------------------------------------------- --- filename: options.md title: Options - Keyman Core API --- A state’s default options are set from the keyboard at creation time and the environment. The Platform layer is then is expected to apply any persisted options it is maintaining. Options are passed into and out of API functions as simple C arrays of [km_core_option_item] terminated with a `KM_CORE_OPTIONS_END` sentinel value. A state's options are exposed and manipulatable via the [km_core_options] API. All option values are of type C string. During processing when the Platform layer finds a PERSIST action type it should store the updated option in the appropriate place, based on its scope. For RESET the processor will apply the pristine value from the original scope, the Platform layer should update that only if it manages a previously persisted value. ------------------------------------------------------------------------------- # km_core_option_scope enum ## Description ## Specification ```c */ enum km_core_option_scope { KM_CORE_OPT_UNKNOWN = 0, KM_CORE_OPT_KEYBOARD = 1, KM_CORE_OPT_ENVIRONMENT = 2, KM_CORE_OPT_MAX_SCOPES }; /* ``` ## Values `KM_CORE_OPT_UNKNOWN` : An unknown option type. Reserved. `KM_CORE_OPT_KEYBOARD` : An option that is defined for the currently active keyboard; not all processors support this type of option. These options are specific to the active keyboard. `KM_CORE_OPT_ENVIRONMENT` : Properties of the current environment, often but not necessarily always read-only. ------------------------------------------------------------------------------- # km_core_option_item struct ## Description Defines a single option to be passed into the Keyman Core from the Platform layer. ## Specification ```c */ struct km_core_option_item { km_core_cp const * key; km_core_cp const * value; uint8_t scope; }; #define KM_CORE_OPTIONS_END { 0, 0, 0 } /* ``` ## Members `key` : Null-terminated string key for the option `value` : Null-terminated string value for the option `scope` : Scope which an option belongs to, from [km_core_option_scope]. ------------------------------------------------------------------------------- # km_core_options_list_size() ## Description Return the length of a terminated [km_core_option_item] array (options list). ## Specification ```c */ KMN_API size_t km_core_options_list_size(km_core_option_item const *opts); /* ``` ## Parameters `opts` : A pointer to a `KM_CORE_OPTIONS_END` terminated array of [km_core_option_item] values. ## Returns The number of items in the list, not including terminating item, or 0 if `opts` is null. ------------------------------------------------------------------------------- # km_core_state_option_lookup ## Description Lookup an option based on its key, in an options list. ## Specification ```c */ KMN_API km_core_status km_core_state_option_lookup(km_core_state const *state, uint8_t scope, km_core_cp const *key, km_core_cp const **value); /* ``` ## Parameters `state` : An opaque pointer to a state object. `scope` : Which key-value store to interrogate. `key` : A UTF-16 string that matches the key in the target [km_core_option_item]. `value` : A pointer to the result variable: A pointer to a UTF-16 string value owned by the state or keyboard object at the time of the call. This pointer is only valid *until* the next call to any function on this API and should be used immediately. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If non-optional parameters are null, or if the scope is invalid. `KM_CORE_STATUS_KEY_ERROR` : The key cannot be found. ------------------------------------------------------------------------------- # km_core_state_options_update() ## Description Adds or updates one or more options from a list of [km_core_option_item]s. ## Specification ``` */ KMN_API km_core_status km_core_state_options_update(km_core_state *state, km_core_option_item const *new_opts); /* ``` ## Parameters `state` : An opaque pointer to a state object. `new_opts` : An array of [km_core_option_item] objects to update or add. Must be terminated with `KM_CORE_OPTIONS_END`. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If non-optional parameters are null. `KM_CORE_STATUS_NO_MEM` : In the event an internal memory allocation fails. `KM_CORE_STATUS_KEY_ERROR` : The key cannot be found. ------------------------------------------------------------------------------- # km_core_state_options_to_json() ## Description Export the contents of a [km_core_options] array to a JSON formatted document and place it in the supplied buffer, reporting how much space was used. If null is passed as the buffer the number of bytes required is returned in `space`. If there is insufficent space to hold the document the contents of the buffer is undefined. The returned buffer uses UTF-8 encoding. ## Specification ```c */ KMN_API km_core_status km_core_state_options_to_json(km_core_state const *state, char *buf, size_t *space); /* ``` ## Parameters `state` : An opaque pointer to a state object. `buf` : A pointer to the buffer to place the C string containing the JSON document into, can be null. `space` : A pointer to a size_t variable. This variable must contain the number of bytes available in the buffer pointed to by `buf`, unless `buf` is null. On return it will hold how many bytes were used. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If non-optional parameters are null. `KM_CORE_STATUS_NO_MEM` : In the event an internal memory allocation fails. ------------------------------------------------------------------------------- --- filename: keyboards.md title: Keyboards - Keyman Core API --- A keyboard is a set of rules and transforms in a Processor specific format for transforming key events into action items. The keyboard is parsed and loaded by the processsor and made available in an immutable fashion for use with any number of state objects. ------------------------------------------------------------------------------- # km_core_keyboard_attrs struct ## Description Provides read-only information about a keyboard. ## Specification ```c */ typedef struct { km_core_cp const * version_string; km_core_cp const * id; km_core_path_name folder_path; km_core_option_item const * default_options; } km_core_keyboard_attrs; /* ``` ## Members `version_string` : Processor specific version string. `id` : Keyman keyboard ID string. `folder_path` : Path to the unpacked folder containing the keyboard and associated resources. `default_options` : Set of default values for any options included in the keyboard. ------------------------------------------------------------------------------- # km_core_keyboard_key struct ## Description Describes a single key and modifier combination that a keyboard handles, for use by the Platform layer. This is used when the Platform layer must know in advance which keys are used by a given keyboard. ## Specification ```c */ typedef struct { km_core_virtual_key key; uint32_t modifier_flag; } km_core_keyboard_key; #define KM_CORE_KEYBOARD_KEY_LIST_END { 0, 0 } /* ``` ## Members `key` : A virtual key. `modifier_flag` : A [km_core_modifier_state] bitmask. ------------------------------------------------------------------------------- # km_core_keyboard_imx struct ## Description Describes a single Input Method eXtension library and entry point. ## Specification ```c */ typedef struct { km_core_cp const * library_name; km_core_cp const * function_name; uint32_t imx_id; } km_core_keyboard_imx; #define KM_CORE_KEYBOARD_IMX_END { 0, 0, 0 } /* ``` ## Members `library_name` : The fully-qualified path and filename of the dynamically loaded library file. `function_name` : The entry point for the IMX. `imx_id` : unique identifier used to call this function ------------------------------------------------------------------------------- # km_core_keyboard_load() ## Description Parse and load keyboard from the supplied path and a pointer to the loaded keyboard into the out paramter. ## Specification ```c */ KMN_API km_core_status km_core_keyboard_load(km_core_path_name kb_path, km_core_keyboard **keyboard); /* ``` ## Parameters `kb_path` : On Windows, a UTF-16 string; on other platforms, a C string: contains a valid path to the keyboard file. `keyboard` : A pointer to result variable: A pointer to the opaque keyboard object returned by the Processor. This memory must be freed with a call to [km_core_keyboard_dispose]. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_NO_MEM` : In the event an internal memory allocation fails. `KM_CORE_STATUS_IO_ERROR` : In the event the keyboard file is unparseable for any reason `KM_CORE_STATUS_INVALID_ARGUMENT` : In the event the file doesn't exist or is inaccesible or `keyboard` is null. `KM_CORE_STATUS_OS_ERROR` : Bit 31 (high bit) set, bits 0-30 are an OS-specific error code. ------------------------------------------------------------------------------- # km_core_keyboard_dispose() ## Description Free the allocated memory belonging to an opaque keyboard object previously returned by [km_core_keyboard_load]. ## Specification ```c */ KMN_API void km_core_keyboard_dispose(km_core_keyboard *keyboard); /* ``` ## Parameters `keyboard` : A pointer to the opaque keyboard object to be disposed of. ------------------------------------------------------------------------------- # km_core_keyboard_get_attrs() ## Description Returns the const internal attributes of the keyboard. This structure is valid for the lifetime of the opaque keyboard object. Do not modify the returned data. ## Specification ```c */ KMN_API km_core_status km_core_keyboard_get_attrs(km_core_keyboard const *keyboard, km_core_keyboard_attrs const **out); /* ``` ## Parameters `keyboard` : A pointer to the opaque keyboard object to be queried. `out` : A pointer to the result: A pointer to a [km_core_keyboard_attrs] structure. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If non-optional parameters are null. ------------------------------------------------------------------------------- # km_core_keyboard_get_key_list() ## Description Returns the unordered full set of modifier+virtual keys that are handled by the keyboard. The matching dispose call needs to be called to free the memory. ## Specification ```c */ KMN_API km_core_status km_core_keyboard_get_key_list(km_core_keyboard const *keyboard, km_core_keyboard_key **out); /* ``` ## Parameters `keyboard` : A pointer to the opaque keyboard object to be queried. `out` : A pointer to an array of [km_core_keyboard_key] structures, terminated by `KM_CORE_KEYBOARD_KEY_LIST_END`. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If non-optional parameters are null. ------------------------------------------------------------------------------- # km_core_keyboard_key_list_dispose() ## Description Free the allocated memory belonging to a keyboard key list previously returned by [km_core_keyboard_get_key_list]. ## Specification ```c */ KMN_API void km_core_keyboard_key_list_dispose(km_core_keyboard_key *key_list); /* ``` ## Parameters `key_list` : A pointer to the keyboard key list to be disposed of. ------------------------------------------------------------------------------- # km_core_keyboard_get_imx_list ## Description Returns the list of IMX libraries and function names that are referenced by the keyboard. The matching dispose call needs to be called to free the memory. ## Specification ```c */ KMN_API km_core_status km_core_keyboard_get_imx_list(km_core_keyboard const *keyboard, km_core_keyboard_imx **imx_list); /* ``` ## Parameters `keyboard` : A pointer to the keyboard `imx_list` : A pointer to a variable that will contain a pointer to the IMX list. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If non-optional parameters are null. ------------------------------------------------------------------------------- # km_core_keyboard_imx_list_dispose() ## Description Disposes of the IMX list. ## Specification ```c */ KMN_API void km_core_keyboard_imx_list_dispose(km_core_keyboard_imx *imx_list); /* ``` ## Parameters `imx_list` : A pointer to the IMX list. ------------------------------------------------------------------------------- # km_core_state_imx_register_callback() ## Description Register the IMX callback endpoint for the client. ## Specification ```c */ KMN_API void km_core_state_imx_register_callback(km_core_state *state, km_core_keyboard_imx_platform imx_callback, void *callback_object); /* ``` ## Parameters `state` : A pointer to the opaque state object `imx_callback` : pointer to a function that implements the IMX callback `callback_object` : An opaque pointer that can be used to pass context information to the callback function, usually it is a user-defined data structure. ------------------------------------------------------------------------------- # km_core_state_imx_deregister_callback() ## Description De-register IMX callback endpoint for the client. ## Specification ```c */ KMN_API void km_core_state_imx_deregister_callback(km_core_state *state); /* ``` ## Parameters `state` : A pointer to the opaque state object ------------------------------------------------------------------------------- # km_core_state_create() ## Description Create a keyboard processor state object, maintaining state for the keyboard in the environment passed. ## Specification ```c */ KMN_API km_core_status km_core_state_create(km_core_keyboard *keyboard, km_core_option_item const *env, km_core_state **out); /* ``` ## Parameters `keyboard` : A pointer to the opaque keyboard object this object will hold state for. `env` : The array of [km_core_option_item] key/value pairs used to initialise the environment, terminated by `KM_CORE_OPTIONS_END`. `out` : A pointer to result variable: A pointer to the opaque state object returned by the Processor, initalised to maintain state for `keyboard`. This must be disposed of by a call to [km_core_state_dispose]. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_NO_MEM` : In the event memory is unavailable to allocate a state object. `KM_CORE_STATUS_INVALID_ARGUMENT` : In the event the `keyboard` or `out` pointer are null. ------------------------------------------------------------------------------- # km_core_state_clone() ## Description Clone an existing opaque state object. ## Specification ```c */ KMN_API km_core_status km_core_state_clone(km_core_state const *state, km_core_state **out); /* ``` ## Parameters `state` : A pointer to the opaque state object to be cloned. `out` : A pointer to result variable: A pointer to the opaque state object returned by the Processor, cloned from the existing object `state`. This must be disposed of by a call to [km_core_state_dispose]. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_NO_MEM` : In the event memory is unavailable to allocate a state object. `KM_CORE_STATUS_INVALID_ARGUMENT` : In the event the `state` or `out` pointer are null. ------------------------------------------------------------------------------- # km_core_state_dispose() ## Description Free the allocated resources belonging to a [km_core_state] object previously returned by [km_core_state_create] or [km_core_state_clone]. After this all pointers previously returned by any [km_core_state] family of calls will become invalid. ## Specification ```c */ KMN_API void km_core_state_dispose(km_core_state *state); /* ``` ## Parameters `state` : A pointer to the opaque state object to be disposed. ------------------------------------------------------------------------------- # km_core_debug_context_type enum As of version 17, the cached context is an internal property of the state, not exposed to the consumer of the API -- apart from the Keyman Developer Keyboard Debugger. However, for other debug purposes, it is helpful to be able to examine the cached context, so a debug-formatted version of the context is made available with [km_core_state_context_debug]. This is not intended to be parsed for reading the context for other purposes, and the format may change. The three context types are: cached, intermediate, and app. ## Specification ```c */ typedef enum { KM_CORE_DEBUG_CONTEXT_CACHED = 0, KM_CORE_DEBUG_CONTEXT_INTERMEDIATE = 1, KM_CORE_DEBUG_CONTEXT_APP = 2 } km_core_debug_context_type; /* ``` ## Values `KM_CORE_DEBUG_CONTEXT_CACHED` : the internal context used by Core, which may be normalized and may contain markers. This is set via [km_core_state_context_set_if_needed], and will be modified during keystroke event processing. `KM_CORE_DEBUG_CONTEXT_INTERMEDIATE` : internal context used by IMX, only valid during keystroke event processing. `KM_CORE_DEBUG_CONTEXT_APP` : an exact copy of the current context passed in to [km_core_state_context_set_if_needed], which is used to verify the precise text manipulations required when emitted changes. This input context is in "NFU" -- normalization form unknown, and may be mixed normalization so may require fixups when it is manipulated by keyboard processors that support normalization, such as the LDML keyboard processor. ------------------------------------------------------------------------------- # km_core_state_context_debug() ## Description Returns a debug formatted string of the context from the state. ## Specification ```c */ KMN_API km_core_cp * km_core_state_context_debug(km_core_state *state, km_core_debug_context_type context_type); /* ``` ## Parameters `state` : A pointer to the opaque state object to be queried. `context_type` : The type of context to retrieve from the state. ## Returns A pointer to a [km_core_cp] UTF-16 string. Must be disposed of by a call to [km_core_cp_dispose]. ------------------------------------------------------------------------------- # km_core_cp_dispose() ## Description Free the allocated memory belonging to a [km_core_cp] array previously returned by [km_core_state_context_debug]. May be `nullptr`. ## Specification ```c */ KMN_API void km_core_cp_dispose(km_core_cp *cp); /* ``` ## Parameters `cp` : A pointer to the start of the [km_core_cp] array to be disposed of. ------------------------------------------------------------------------------- # km_core_state_to_json() ## Description Export the internal state of a [km_core_state] object to a JSON format document and place it in the supplied buffer, reporting how much space was used. If null is passed as the buffer the number of bytes required is returned. If there is insufficent space to hold the document, the contents of the buffer is undefined. The encoding of the returned data is UTF-8. __WARNING__: The structure and format of the JSON document while independently versioned is not part of this API and is intended solely for use in diagnostics or by development and debugging tools which are aware of processor implementation details. ## Specification ```c */ KMN_API km_core_status km_core_state_to_json(km_core_state const *state, char *buf, size_t *space); /* ``` ## Parameters `state` : An pointer to an opaque state object. `buf` : A pointer to the buffer to place the C string containing the JSON document into. May be null. `space` : A pointer to a size_t variable. This variable must contain the number of bytes available in the buffer pointed to by `buf`, unless `buf` is null. On return it will hold how many bytes were used. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_NO_MEM` : In the event an internal memory allocation fails. ------------------------------------------------------------------------------- --- filename: processor.md title: Processor - Keyman Core API --- # km_core_event_flags enum ## Description Bit flags to be used with the `event_flags` parameter of [km_core_process_event] ## Specification ```c */ enum km_core_event_flags { KM_CORE_EVENT_FLAG_DEFAULT = 0, KM_CORE_EVENT_FLAG_TOUCH = 1, }; /* ``` ## Values `KM_CORE_EVENT_FLAG_DEFAULT` : default value: hardware `KM_CORE_EVENT_FLAG_TOUCH` : set if the event is touch, otherwise hardware ------------------------------------------------------------------------------- # km_core_process_event() ## Description Run the keyboard on an opaque state object with the provided virtual key and modifer key state. Updates the state object as appropriate and fills out its internal set of actions, which can be retrieved with [km_core_state_get_actions]. The state's actions will be cleared at the start of this call; options and context in the state may also be modified. ## Specification ```c */ KMN_API km_core_status km_core_process_event(km_core_state *state, km_core_virtual_key vk, uint16_t modifier_state, uint8_t is_key_down, uint16_t event_flags); /* ``` ## Parameters `state` : A pointer to the opaque state object. `vk` : A virtual key to be processed. `modifier_state` : The combinations of modifier keys set at the time key `vk` was pressed, bitmask from the [km_core_modifier_state] enum. `event_flags` : Event level flags, see [km_core_event_flags] ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_NO_MEM` : In the event memory is unavailable to allocate internal buffers. `KM_CORE_STATUS_INVALID_ARGUMENT` : In the event the `state` pointer is null or an invalid virtual key or modifier state is passed. ------------------------------------------------------------------------------- # km_core_event() ## Description Tell the keyboard processor that an external event has occurred, such as a keyboard being activated through the language switching UI. The keyboard processor may generate actions which should be processed by the consumer of the API. The actions will be cleared at the start of this call; options and context in the state may also be modified. ## Specification ```c */ KMN_API km_core_status km_core_event( km_core_state *state, uint32_t event, void* data ); /* ``` ## Parameters `state` : A pointer to the opaque state object. `event` : The event to be processed, from [km_core_event_code] enumeration `data` : Additional event-specific data. Currently unused, must be nullptr. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_NO_MEM` : In the event memory is unavailable to allocate internal buffers. `KM_CORE_STATUS_INVALID_ARGUMENT` : In the event the `state` pointer is null or an invalid event or data is passed. ------------------------------------------------------------------------------- # km_core_event_code enum ## Description Possible events to be passed into Keyman Core from the Platform layer. ## Specification ```c */ enum km_core_event_code { KM_CORE_EVENT_KEYBOARD_ACTIVATED = 1, //future: KM_CORE_EVENT_KEYBOARD_DEACTIVATED = 2, }; /* ``` ## Values `KM_CORE_EVENT_KEYBOARD_ACTIVATED` : A keyboard has been activated by the user. The processor may use this event, for example, to switch caps lock state or provide other UX. $EOF */ #if defined(__cplusplus) } // extern "C" #endif /* ``` */ keyman/core/include/keyman/keyman_core_api_actions.h0000664000000000000000000001225114600607066020115 0ustar /* * Keyman is copyright (C) SIL International. MIT License. * * Keyman Keyboard Processor API - Internal Action Interfaces */ #pragma once #include #include #include #include #if defined(__cplusplus) extern "C" { #endif // ---------------------------------------------------------------------------------- // Actions APIs are now available only to the keyboard debugger, IMX, and Core unit // tests (17.0) // ---------------------------------------------------------------------------------- /* ``` ### Action Items These provide the results of processing a key event to the Platform layer and should be processed by the Platform layer to issue commands to the os text services framework to transform the text store in the Client Application, among other actions. ```c */ typedef struct { uint8_t expected_type; // km_core_backspace_type uintptr_t expected_value; // used mainly in unit tests } km_core_backspace_item; enum km_core_backspace_type { KM_CORE_BT_UNKNOWN = 0, // Used at beginning of context; user-initiated backspace KM_CORE_BT_CHAR = 1, // Deleting a character prior to insertion point KM_CORE_BT_MARKER = 2, // Deleting a marker prior to insertion point KM_CORE_BT_MAX_TYPE_ID }; typedef struct { uint8_t type; uint8_t _reserved[sizeof(void*)-sizeof(uint8_t)]; union { uint32_t marker; // MARKER type km_core_option_item const * option; // OPT types km_core_usv character; // CHAR type uint8_t capsLock; // CAPSLOCK type, 1 to turn on, 0 to turn off; re name see #9833 km_core_backspace_item backspace; // BACKSPACE type }; } km_core_action_item; enum km_core_action_type { KM_CORE_IT_END = 0, // Marks end of action items list. KM_CORE_IT_CHAR = 1, // A Unicode character has been generated. KM_CORE_IT_MARKER = 2, // Correlates to kmn's "deadkey" markers. KM_CORE_IT_ALERT = 3, // The keyboard has triggered a alert/beep/bell. KM_CORE_IT_BACK = 4, // Delete the codepoint preceding the insertion point. KM_CORE_IT_PERSIST_OPT = 5, // The indicated option needs to be stored. KM_CORE_IT_EMIT_KEYSTROKE = 6, // Emit the current keystroke to the application KM_CORE_IT_INVALIDATE_CONTEXT = 7, // The processor requests that the context buffer be cleared; // for applications where context is cached, this clears the context; // for applications where context is read from the focused text store, // the context is just re-read and markers flushed. KM_CORE_IT_CAPSLOCK = 8, // Enable or disable capsLock KM_CORE_IT_MAX_TYPE_ID }; /* ``` ### `km_core_state_action_items` ##### Description: Get the list of action items generated by the last call to `km_core_process_event`. ##### Return: A pointer to a `km_core_action_item` list, of `*num_items` in length. This data becomes invalid when the state object is destroyed, or after a call to `km_core_process_event`. Do not modify the contents of this data. The returned array is terminated with a `KM_CORE_IT_END` entry. ##### Parameters: - __state__: A pointer to the opaque `km_core_state` object to be queried. - __num_items__: A pointer to a result variable: The number of items in the action item list including the `KM_CORE_IT_END` terminator. May be null if not that information is required. ```c */ KMN_API km_core_action_item const * km_core_state_action_items(km_core_state const *state, size_t *num_items); /* ``` ### `km_core_state_queue_action_items` ##### Description: Queue actions for the current keyboard processor state; normally used in IMX callbacks called during `km_core_process_event`. ##### Return: - `KM_CORE_STATUS_OK`: On success. - `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the `state` or `action_items` pointer are null. ##### Parameters: - __state__: A pointer to the opaque `km_core_state` object to be queried. - __action_items__: The action items to be added to the core queue. Must be terminated with a `KM_CORE_IT_END` entry. ```c */ KMN_API km_core_status km_core_state_queue_action_items(km_core_state *state, km_core_action_item const *action_items); /* ``` ### `km_core_process_queued_actions` ##### Description: Process the keyboard processors queued actions for the opaque state object. Updates the state object as appropriate and fills out its action list. The client can add actions externally via the `km_core_state_queue_action_items` and then request the processing of the actions with this method. The state action list will be cleared at the start of this call; options and context in the state may also be modified. ##### Return status: - `KM_CORE_STATUS_OK`: On success. - `KM_CORE_STATUS_NO_MEM`: In the event memory is unavailable to allocate internal buffers. - `KM_CORE_STATUS_INVALID_ARGUMENT`: In the event the `state` pointer is null ##### Parameters: - __state__: A pointer to the opaque state object. ```c */ KMN_API km_core_status km_core_process_queued_actions(km_core_state *state); #if defined(__cplusplus) } // extern "C" #endif keyman/core/include/keyman/keyman_core_api_bits.h0000664000000000000000000000454614600607066017426 0ustar /* Copyright: © 2018 SIL International. Description: Cross platform support macros to define API function declspec/attributes and how each supported compiler or OS allows us to specify them. Create Date: 18 Oct 2018 Authors: Tim Eves (TSE) History: 18 Oct 2018 - TSE - Imported from graphite2 project. 6 Oct 2018 - TSE - Move into keyman folder. */ #pragma once // Define API function declspec/attributes and how each supported compiler or OS // allows us to specify them. #if defined __GNUC__ #define _kmn_and , #define _kmn_tag_fn(a) __attribute__((a)) #define _kmn_deprecated_flag deprecated #define _kmn_export_flag visibility("default") #define _kmn_import_flag visibility("default") #define _kmn_static_flag visibility("hidden") #define _kmn_unused(x) UNUSED_ ## x __attribute__((__unused__)) #else #define _kmn_unused(x) UNUSED_ ## x #endif #if defined _WIN32 || defined __CYGWIN__ typedef wchar_t const * km_core_path_name; #define _KM_CORE_PATH_SEPARATOR (L'\\') #define _KM_CORE_EXT_SEPARATOR (L'.') #if defined __GNUC__ // These three will be redefined for Windows #undef _kmn_export_flag #undef _kmn_import_flag #undef _kmn_static_flag #else // How MSVC sepcifies function level attributes adn deprecation #define _kmn_and #define _kmn_tag_fn(a) __declspec(a) #define _kmn_deprecated_flag deprecated #endif #define _kmn_export_flag dllexport #define _kmn_import_flag dllimport #define _kmn_static_flag #else typedef char const * km_core_path_name; #define _KM_CORE_PATH_SEPARATOR ('/') #define _KM_CORE_EXT_SEPARATOR ('.') #endif #if defined KM_CORE_LIBRARY_STATIC #define KMN_API _kmn_tag_fn(_kmn_static_flag) #define KMN_DEPRECATED_API _kmn_tag_fn(_kmn_deprecated_flag _kmn_and _kmn_static_flag) #elif defined KM_CORE_LIBRARY_EXPORTING #define KMN_API _kmn_tag_fn(_kmn_export_flag) #define KMN_DEPRECATED_API _kmn_tag_fn(_kmn_deprecated_flag _kmn_and _kmn_export_flag) #else #define KMN_API _kmn_tag_fn(_kmn_import_flag) #define KMN_DEPRECATED_API _kmn_tag_fn(_kmn_deprecated_flag _kmn_and _kmn_import_flag) #endif #ifndef KM_CORE_LIBRARY #define KM_CORE_LIBRARY #endif #ifndef USE_CHAR16_T #define USE_CHAR16_T #endif #include keyman/core/include/keyman/keyman_core_api_consts.h0000664000000000000000000000076314600607066017773 0ustar #pragma once // Defined environment options for KMX processor #define KM_CORE_KMX_ENV_PLATFORM u"platform" #define KM_CORE_KMX_ENV_BASELAYOUT u"baseLayout" #define KM_CORE_KMX_ENV_BASELAYOUTALT u"baseLayoutAlt" #define KM_CORE_KMX_ENV_SIMULATEALTGR u"simulateAltgr" #define KM_CORE_KMX_ENV_CAPSLOCK u"capsLock" #define KM_CORE_KMX_ENV_BASELAYOUTGIVESCTRLRALTFORRALT u"baseLayoutGivesCtrlRAltForRAlt" keyman/core/include/keyman/keyman_core_api_context.h0000664000000000000000000002274614600607066020153 0ustar /* * Keyman is copyright (C) SIL International. MIT License. * * Keyman Keyboard Processor API - Context Interfaces */ #pragma once #include #include #include #include #if defined(__cplusplus) extern "C" { #endif typedef struct km_core_context km_core_context; // ---------------------------------------------------------------------------------- // Context APIs are now available only to the keyboard debugger, IMX, and Core unit // tests (17.0) // ---------------------------------------------------------------------------------- /* --- filename: context.md title: Internal Context - Keyman Core API --- The context is the text prior to the insertion point (caret, cursor). The context is constructed by the Platform layer, typically by interrogating the Client Application. The context will be updated by the engine for keystroke events. If the Platform layer code caches the context, the context should be reset when a context state change is detected. Context state changes can occur when the user uses the mouse to move the insertion point, uses cursor keys, switches applications or input fields, or presses hotkeys such as Ctrl+N to start a new document. The full set of context state change triggers is up to the Platform layer. Context can also contain positional Markers (also known as 'deadkeys' in kmn keyboards), which are transitory state flags that are erased whenever a context state change is detected. Markers are always controlled by the Engine. Contexts are always owned by their state. They may be set to a list of context_items or interrogated for their current list of context items. Core maintains and caches the context. Engine can update the context with [`km_core_state_context_set_if_needed`] and [`km_core_state_context_clear`]. These two functions are available in keyman_core_api.h. The Keyboard Debugger in Keyman Developer, and IMX in Keyman for Windows, make use of the context functionality in this header, but these functions should not be used in other places. ------------------------------------------------------------------------------- # km\_core\_context\_type enum {#km_core_context_type} ## Description [`km_core_context_item.type`](#km_core_context_item) values which identify which data value (if any) the context item carries. ## Specification ```c */ enum km_core_context_type { KM_CORE_CT_END, KM_CORE_CT_CHAR, KM_CORE_CT_MARKER }; /* ``` ## Values {#km_core_ct_type_values} `KM_CORE_CT_END` : A [`km_core_context_item`](#km_core_context_item) of this type marks the end of an array of context items. `KM_CORE_CT_CHAR` : The context item contains a Unicode Scalar Value which must be accessed through the [`km_core_context_item.character`](#km_core_context_item) union member. `KM_CORE_CT_MARKER` : The context item contains a positional marker which must be accessed through the [`km_core_context_item.marker`](#km_core_context_item) union member. ------------------------------------------------------------------------------- # km\_core\_context\_item struct {#km_core_context_item} ## Description A tagged union representing an element of context which can be either a Unicode character or a positional marker. ## Specification ```c */ typedef struct { uint8_t type; uint8_t _reserved[3]; union { km_core_usv character; uint32_t marker; }; } km_core_context_item; /* ``` ## Members `type` :Identifies the union member to access. A value of enum [`km_core_context_type`](#km_core_context_type) values. `_reserved` :Space reserved for alignment purposes and possible future use. `character` :A Unicode Scalar Value. `marker` :A marker value, only meaningful to an engine. ------------------------------------------------------------------------------- # KM\_CORE\_CONTEXT\_ITEM\_END macro ## Description Convenience macro to declare a terminating entry in a [`km_core_context_item`](#km_core_context_item) item array. ## Specification ```c */ #define KM_CORE_CONTEXT_ITEM_END {KM_CORE_CT_END, {0,}, {0,}} /* ``` ------------------------------------------------------------------------------- # km_core_state_get_intermediate_context() ## Description Get access to the state object's keyboard processor's intermediate context. This context is used during an IMX callback, part way through processing a keystroke. ## Specification ```c */ KMN_API km_core_status km_core_state_get_intermediate_context(km_core_state *state, km_core_context_item ** context_items); /* ``` ## Parameters `state` : A pointer to the opaque state object to be queried. ## Returns A pointer to an context item array. Must be disposed of by a call to `km_core_context_items_dispose`. ------------------------------------------------------------------------------- # km_core_context_items_dispose() ## Description Free the allocated memory belonging to a `km_core_context_item` array previously returned by `km_core_state_get_intermediate_context` (internally, also `context_items_from_utf16` and `km_core_context_get`) ## Specification ```c */ KMN_API void km_core_context_items_dispose(km_core_context_item *context_items); /* ``` ## Parameters `context_items` : A pointer to the start of the `km_core_context_item` array to be disposed of. ------------------------------------------------------------------------------- # km_core_state_context() ## Description Get access to the state object's cached context. ## Specification ```c */ KMN_API km_core_context * km_core_state_context(km_core_state const *state); /* ## Parameters `state` : A pointer to the opaque state object to be queried. ## Returns A pointer to an opaque context object. This pointer is valid for the lifetime of the state object. If null is passed in, then null is returned. ------------------------------------------------------------------------------- # km_core_state_app_context() ## Description Get access to the state object's application context. ## Specification ```c */ KMN_API km_core_context * km_core_state_app_context(km_core_state const *state); /* ``` ## Parameters `state` : A pointer to the opaque state object to be queried. ## Returns A pointer to an opaque context object. This pointer is valid for the lifetime of the state object. If null is passed in, then null is returned. ------------------------------------------------------------------------------- # km_core_context_set() ## Description Replace the contents of the current context with a new sequence of `km_core_context_item` entries. ## Specification ```c */ KMN_API km_core_status km_core_context_set(km_core_context *context, km_core_context_item const *context_items); /* ``` ## Parameters `context` : A pointer to an opaque context object `context_items` : A pointer to the start of the `km_core_context_item` array containing the new context. It must be terminated with an item of type `KM_CORE_CT_END`. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If non-optional parameters are null. `KM_CORE_STATUS_NO_MEM` : In the event not enough memory can be allocated to grow the context buffer internally. ------------------------------------------------------------------------------- # km_core_context_clear() ## Description Removes all context_items from the internal array. If `context` is null, has no effect. ## Specification ```c */ KMN_API void km_core_context_clear(km_core_context *); /* ``` ## Parameters `context` : A pointer to an opaque context object ------------------------------------------------------------------------------- # km_core_context_item_list_size() ## Description Return the length of a terminated `km_core_context_item` array. ## Specification ```c */ KMN_API size_t km_core_context_item_list_size(km_core_context_item const *context_items); /* ``` ## Parameters `context_items` : A pointer to a `KM_CORE_CT_END` terminated array of `km_core_context_item` values. ## Returns The number of items in the list, not including terminating item, or 0 if `context_items` is null. ------------------------------------------------------------------------------- # km_core_context_get() ## Description Copies all items in the context into a new array and returns the new array. This must be disposed of by caller using `km_core_context_items_dispose`. ## Specification ```c */ KMN_API km_core_status km_core_context_get(km_core_context const *context, km_core_context_item **out); /* ``` ## Parameters `context` : A pointer to an opaque context object `out` : pointer to the result variable: A pointer to the start of the `km_core_context_item` array containing a copy of the context. Terminated with a type of `KM_CORE_CT_END`. Must be disposed of with `km_core_context_items_dispose`. ## Returns `KM_CORE_STATUS_OK` : On success. `KM_CORE_STATUS_INVALID_ARGUMENT` : If non-optional parameters are null. `KM_CORE_STATUS_NO_MEM` : In the event not enough memory can be allocated for the output buffer. ------------------------------------------------------------------------------- # km_core_context_length() ## Description Return the number of items in the context. ## Specification ```c */ KMN_API size_t km_core_context_length(km_core_context *); /* ``` ## Parameters `context` : A pointer to an opaque context object ## Returns The number of items in the context, and will return 0 if passed a null `context` pointer. $EOF ------------------------------------------------------------------------------- */ #if defined(__cplusplus) } // extern "C" #endif keyman/core/include/keyman/keyman_core_api_debug.h0000664000000000000000000001202214600607066017537 0ustar /* * Keyman is copyright (C) SIL International. MIT License. * * Keyman Keyboard Processor API - Debugger Interfaces * * The debugger interfaces are still very dependent on .kmx * objects. * * Note: this file is subject to change; the debugger * interfaces are not stable across versions. * */ #pragma once #include #include #include #include #if defined(__cplusplus) extern "C" { #endif /** * The maximum size of context in km_core_cp units for a single debug * event. This is taken from MAXCONTEXT in keyman32 (Windows) and is purely * a convenience value. We can increase it if there is a demonstrated need. */ #define DEBUG_MAX_CONTEXT 80 /** * The number of stores that can be processed in a rule. This is taken from * MAXSTOREOFFSETS in keyman32 (Windows) and is purely a convenience value. * We can increase it if there is a demonstrated need. */ #define DEBUG_MAX_STORE_OFFSETS 20 #define DEBUG_STORE_OFFSETS_SIZE (DEBUG_MAX_STORE_OFFSETS*2+1) /** * These modifier flags are used internally in the kmx engine, so will be * exposed only in debugging modifier states. */ #define KM_CORE_MODIFIER_VIRTUALKEY 0x4000 #define KM_CORE_MODIFIER_VIRTUALCHARKEY 0x8000 /** * Input key event data. The `character` member is derived from * a US English key event for vk + modifier_state, and is 0 if * the vk + modifier_state do not generate a character. * * Used only in event type KM_CORE_DEBUG_BEGIN. */ typedef struct { uint16_t vk; uint16_t modifier_state; char16_t character; } km_core_state_debug_key_info; /** * Option event data. * * Used only in event type KM_CORE_DEBUG_SET_OPTION. */ typedef struct { void *store; // LPSTORE km_core_cp value[DEBUG_MAX_CONTEXT]; // value to be saved into the store } km_core_state_debug_kmx_option_info; /** * KMX processor data for each event. kmx_base.h defines the types that are * passed in here, read only. Warning: context may contain sentinel values * for markers, with the kmx UC_SENTINEL, CODE_CONTEXT, DEADKEY pattern. * * The context value here will be an intermediate value, and may differ * from event to event as the context can be rewritten for each rule match. * * Used in all event types except KM_CORE_DEBUG_BEGIN, KM_CORE_DEBUG_END. */ typedef struct { km_core_cp context[DEBUG_MAX_CONTEXT]; // The context matched by the rule (? may not need this?) // TODO: rename to context_matched void *group; // LPGROUP void *rule; // LPKEY uint16_t store_offsets[DEBUG_STORE_OFFSETS_SIZE]; // pairs--store, char position, terminated by 0xFFFF // TODO use a better structure here /// Track the actions index in the actions that will be returned to /// the debugger; the debugger uses this to determine when to /// execute the actions when single-stepping. uint16_t first_action; km_core_state_debug_kmx_option_info option; } km_core_state_debug_kmx_info; /** * A single debug event. */ typedef struct { uint32_t type; // 32 bits is better optimized than 8 bits uint32_t flags; km_core_state_debug_key_info key_info; km_core_state_debug_kmx_info kmx_info; } km_core_state_debug_item; /** * A single debug event. */ enum km_core_debug_type { KM_CORE_DEBUG_BEGIN = 0, //KM_CORE_DEBUG_BEGIN_ANSI = 1, // not supported; instead rewrite ansi keyboards to Unicode with mcompile KM_CORE_DEBUG_GROUP_ENTER = 2, KM_CORE_DEBUG_GROUP_EXIT = 3, KM_CORE_DEBUG_RULE_ENTER = 4, KM_CORE_DEBUG_RULE_EXIT = 5, KM_CORE_DEBUG_MATCH_ENTER = 6, KM_CORE_DEBUG_MATCH_EXIT = 7, KM_CORE_DEBUG_NOMATCH_ENTER = 8, KM_CORE_DEBUG_NOMATCH_EXIT = 9, KM_CORE_DEBUG_END = 10, KM_CORE_DEBUG_SET_OPTION = 11, }; // Flags for KM_CORE_DEBUG_GROUP_EXIT #define KM_CORE_DEBUG_FLAG_RECURSIVE_OVERFLOW 0x0001 #define KM_CORE_DEBUG_FLAG_NOMATCH 0x0002 // Flags for KM_CORE_DEBUG_BEGIN // TODO: do we need this at all? #define KM_CORE_DEBUG_FLAG_UNICODE 0x0001 // Always set // Flags for KM_CORE_DEBUG_END #define KM_CORE_DEBUG_FLAG_OUTPUTKEYSTROKE 0x0001 /** * Enable or disable debug tracing * * @param state Pointer to initialized state * @param value Set to 1 to enable debugging, 0 to disable * * @returns KM_CORE_STATUS_OK on success */ KMN_API km_core_status km_core_state_debug_set(km_core_state *state, int value); /** * Get current debug tracing status * * @param state Pointer to initialized state * * @returns 1 if debugging is enabled, 0 otherwise */ KMN_API uint8_t km_core_state_debug_get(km_core_state const *state); /** * Read current debug trace log * * @param state Pointer to initialized state * @param num_items Pointer to variable to receive size of list; may be * nullptr if not required. * * @returns pointer to read only array of debug item events, * with last entry guaranteed to be KM_CORE_DEBUG_END. */ KMN_API km_core_state_debug_item const * km_core_state_debug_items(km_core_state const *state, size_t *num_items); #if defined(__cplusplus) } // extern "C" #endif keyman/core/include/keyman/keyman_core_api_version.h.in0000664000000000000000000000077014600607066020552 0ustar #define km_core_version_stringify(x) km_core_version_to_string(x) #define km_core_version_to_string(x) #x // Product versioning #define KM_CORE_VERSION_MAJOR @majorver@ #define KM_CORE_VERSION_MINOR @minorver@ #define KM_CORE_VERSION_PATCH @patchver@ #define KM_CORE_VERSION_STRING km_core_version_stringify(@majorver@ ## . ## @minorver@ ## . ## @patchver@ ## .0) // API versioning #define KM_CORE_LIB_CURRENT @lib_curr@ #define KM_CORE_LIB_AGE @lib_age@ #define KM_CORE_LIB_REVISION @lib_rev@ keyman/core/include/keyman/keyman_core_api_vkeys.h0000664000000000000000000001637614600607066017632 0ustar /* Copyright: © 2018 SIL International. Description: API declarations for modifier keys, handy access masks and Keyman VKEY names. These follow the same keytop->code associations as the Windows API. This is a separate header to maintain readability of the primary API header. Create Date: 17 Oct 2018 Authors: Tim Eves (TSE) History: 17 Oct 2018 - TSE - Moved & refactored km_core_modifier_state from keyman_core_api.h. - Added VKey and mask definitions. 6 Oct 2018 - TSE - Move into keyman folder. */ #pragma once enum km_core_modifier_state { KM_CORE_MODIFIER_LCTRL = 1 << 0, KM_CORE_MODIFIER_RCTRL = 1 << 1, KM_CORE_MODIFIER_LALT = 1 << 2, KM_CORE_MODIFIER_RALT = 1 << 3, KM_CORE_MODIFIER_SHIFT = 1 << 4, KM_CORE_MODIFIER_CTRL = 1 << 5, KM_CORE_MODIFIER_ALT = 1 << 6, /* KM_CORE_MODIFIER_META = 1 << 7, // Either Meta-key flag (tentative). Not usable by keyboards currently // Used internally (currently, only by KMW) to ensure Meta-key // shortcuts safely bypass rules // Meta key = Command key on macOS, Windows key on Windows */ KM_CORE_MODIFIER_CAPS = 1 << 8, KM_CORE_MODIFIER_NOCAPS = 1 << 9, /* KM_CORE_MODIFIER_NUMLOCK = 1 << 10, KM_CORE_MODIFIER_NONUMLOCK = 1 << 11, KM_CORE_MODIFIER_SCROLLOCK = 1 << 12, KM_CORE_MODIFIER_NOSCROLLOCK = 1 << 13, KM_CORE_MODIFIER_VIRTUALKEY = 1 << 14, */ }; enum km_core_modifier_mask { KM_CORE_MODIFIER_MASK_ALL = 0x7f, KM_CORE_MODIFIER_MASK_ALT_GR_SIM = KM_CORE_MODIFIER_LCTRL|KM_CORE_MODIFIER_LALT, KM_CORE_MODIFIER_MASK_CHIRAL = 0x1f, KM_CORE_MODIFIER_MASK_IS_CHIRAL = 0x0f, KM_CORE_MODIFIER_MASK_NON_CHIRAL = 0x7f, KM_CORE_MODIFIER_MASK_CAPS = 0x0300, /*KM_CORE_MODIFIER_MASK_NUMLOCK = 0x0C00, KM_CORE_MODIFIER_MASK_SCROLLLOCK = 0x3000,*/ }; // These are Windows API VKEYs, using Keyman VKEY names. enum km_kpb_virtual_key { KM_CORE_VKEY__00, KM_CORE_VKEY_LBUTTON, KM_CORE_VKEY_RBUTTON, KM_CORE_VKEY_CANCEL, KM_CORE_VKEY_MBUTTON, KM_CORE_VKEY__05, KM_CORE_VKEY__06, KM_CORE_VKEY__07, KM_CORE_VKEY_BKSP, KM_CORE_VKEY_TAB, KM_CORE_VKEY__0A, KM_CORE_VKEY__0B, KM_CORE_VKEY_KP5, KM_CORE_VKEY_ENTER, KM_CORE_VKEY__0E, KM_CORE_VKEY__0F, KM_CORE_VKEY_SHIFT, KM_CORE_VKEY_CONTROL, KM_CORE_VKEY_ALT, KM_CORE_VKEY_PAUSE, KM_CORE_VKEY_CAPS, KM_CORE_VKEY__15, KM_CORE_VKEY__16, KM_CORE_VKEY__17, KM_CORE_VKEY__18, KM_CORE_VKEY__19, KM_CORE_VKEY__1A, KM_CORE_VKEY_ESC, KM_CORE_VKEY__1C, KM_CORE_VKEY__1D, KM_CORE_VKEY__1E, KM_CORE_VKEY__1F, KM_CORE_VKEY_SPACE, KM_CORE_VKEY_PGUP, KM_CORE_VKEY_PGDN, KM_CORE_VKEY_END, KM_CORE_VKEY_HOME, KM_CORE_VKEY_LEFT, KM_CORE_VKEY_UP, KM_CORE_VKEY_RIGHT, KM_CORE_VKEY_DOWN, KM_CORE_VKEY_SEL, KM_CORE_VKEY_PRINT, KM_CORE_VKEY_EXEC, KM_CORE_VKEY_PRTSCN, KM_CORE_VKEY_INS, KM_CORE_VKEY_DEL, KM_CORE_VKEY_HELP, KM_CORE_VKEY_0, KM_CORE_VKEY_1, KM_CORE_VKEY_2, KM_CORE_VKEY_3, KM_CORE_VKEY_4, KM_CORE_VKEY_5, KM_CORE_VKEY_6, KM_CORE_VKEY_7, KM_CORE_VKEY_8, KM_CORE_VKEY_9, KM_CORE_VKEY__3A, KM_CORE_VKEY__3B, KM_CORE_VKEY__3C, KM_CORE_VKEY__3D, KM_CORE_VKEY__3E, KM_CORE_VKEY__3F, KM_CORE_VKEY__40, KM_CORE_VKEY_A, KM_CORE_VKEY_B, KM_CORE_VKEY_C, KM_CORE_VKEY_D, KM_CORE_VKEY_E, KM_CORE_VKEY_F, KM_CORE_VKEY_G, KM_CORE_VKEY_H, KM_CORE_VKEY_I, KM_CORE_VKEY_J, KM_CORE_VKEY_K, KM_CORE_VKEY_L, KM_CORE_VKEY_M, KM_CORE_VKEY_N, KM_CORE_VKEY_O, KM_CORE_VKEY_P, KM_CORE_VKEY_Q, KM_CORE_VKEY_R, KM_CORE_VKEY_S, KM_CORE_VKEY_T, KM_CORE_VKEY_U, KM_CORE_VKEY_V, KM_CORE_VKEY_W, KM_CORE_VKEY_X, KM_CORE_VKEY_Y, KM_CORE_VKEY_Z, KM_CORE_VKEY__5B, KM_CORE_VKEY__5C, KM_CORE_VKEY__5D, KM_CORE_VKEY__5E, KM_CORE_VKEY__5F, KM_CORE_VKEY_NP0, KM_CORE_VKEY_NP1, KM_CORE_VKEY_NP2, KM_CORE_VKEY_NP3, KM_CORE_VKEY_NP4, KM_CORE_VKEY_NP5, KM_CORE_VKEY_NP6, KM_CORE_VKEY_NP7, KM_CORE_VKEY_NP8, KM_CORE_VKEY_NP9, KM_CORE_VKEY_NPSTAR, KM_CORE_VKEY_NPPLUS, KM_CORE_VKEY_SEPARATOR, KM_CORE_VKEY_NPMINUS, KM_CORE_VKEY_NPDOT, KM_CORE_VKEY_NPSLASH, KM_CORE_VKEY_F1, KM_CORE_VKEY_F2, KM_CORE_VKEY_F3, KM_CORE_VKEY_F4, KM_CORE_VKEY_F5, KM_CORE_VKEY_F6, KM_CORE_VKEY_F7, KM_CORE_VKEY_F8, KM_CORE_VKEY_F9, KM_CORE_VKEY_F10, KM_CORE_VKEY_F11, KM_CORE_VKEY_F12, KM_CORE_VKEY_F13, KM_CORE_VKEY_F14, KM_CORE_VKEY_F15, KM_CORE_VKEY_F16, KM_CORE_VKEY_F17, KM_CORE_VKEY_F18, KM_CORE_VKEY_F19, KM_CORE_VKEY_F20, KM_CORE_VKEY_F21, KM_CORE_VKEY_F22, KM_CORE_VKEY_F23, KM_CORE_VKEY_F24, KM_CORE_VKEY__88, KM_CORE_VKEY__89, KM_CORE_VKEY__8A, KM_CORE_VKEY__8B, KM_CORE_VKEY__8C, KM_CORE_VKEY__8D, KM_CORE_VKEY__8E, KM_CORE_VKEY__8F, KM_CORE_VKEY_NUMLOCK, KM_CORE_VKEY_SCROLL, KM_CORE_VKEY__92, KM_CORE_VKEY__93, KM_CORE_VKEY__94, KM_CORE_VKEY__95, KM_CORE_VKEY__96, KM_CORE_VKEY__97, KM_CORE_VKEY__98, KM_CORE_VKEY__99, KM_CORE_VKEY__9A, KM_CORE_VKEY__9B, KM_CORE_VKEY__9C, KM_CORE_VKEY__9D, KM_CORE_VKEY__9E, KM_CORE_VKEY__9F, KM_CORE_VKEY__A0, KM_CORE_VKEY__A1, KM_CORE_VKEY__A2, KM_CORE_VKEY__A3, KM_CORE_VKEY__A4, KM_CORE_VKEY__A5, KM_CORE_VKEY__A6, KM_CORE_VKEY__A7, KM_CORE_VKEY__A8, KM_CORE_VKEY__A9, KM_CORE_VKEY__AA, KM_CORE_VKEY__AB, KM_CORE_VKEY__AC, KM_CORE_VKEY__AD, KM_CORE_VKEY__AE, KM_CORE_VKEY__AF, KM_CORE_VKEY__B0, KM_CORE_VKEY__B1, KM_CORE_VKEY__B2, KM_CORE_VKEY__B3, KM_CORE_VKEY__B4, KM_CORE_VKEY__B5, KM_CORE_VKEY__B6, KM_CORE_VKEY__B7, KM_CORE_VKEY__B8, KM_CORE_VKEY__B9, KM_CORE_VKEY_COLON, KM_CORE_VKEY_EQUAL, KM_CORE_VKEY_COMMA, KM_CORE_VKEY_HYPHEN, KM_CORE_VKEY_PERIOD, KM_CORE_VKEY_SLASH, KM_CORE_VKEY_BKQUOTE, KM_CORE_VKEY__C1, KM_CORE_VKEY__C2, KM_CORE_VKEY__C3, KM_CORE_VKEY__C4, KM_CORE_VKEY__C5, KM_CORE_VKEY__C6, KM_CORE_VKEY__C7, KM_CORE_VKEY__C8, KM_CORE_VKEY__C9, KM_CORE_VKEY__CA, KM_CORE_VKEY__CB, KM_CORE_VKEY__CC, KM_CORE_VKEY__CD, KM_CORE_VKEY__CE, KM_CORE_VKEY__CF, KM_CORE_VKEY__D0, KM_CORE_VKEY__D1, KM_CORE_VKEY__D2, KM_CORE_VKEY__D3, KM_CORE_VKEY__D4, KM_CORE_VKEY__D5, KM_CORE_VKEY__D6, KM_CORE_VKEY__D7, KM_CORE_VKEY__D8, KM_CORE_VKEY__D9, KM_CORE_VKEY__DA, KM_CORE_VKEY_LBRKT, KM_CORE_VKEY_BKSLASH, KM_CORE_VKEY_RBRKT, KM_CORE_VKEY_QUOTE, KM_CORE_VKEY_oDF, KM_CORE_VKEY_oE0, KM_CORE_VKEY_oE1, KM_CORE_VKEY_oE2, // 102nd key on European layouts KM_CORE_VKEY_oE3, KM_CORE_VKEY_oE4, KM_CORE_VKEY__E5, KM_CORE_VKEY_oE6, KM_CORE_VKEY__E7, KM_CORE_VKEY__E8, KM_CORE_VKEY_oE9, KM_CORE_VKEY_oEA, KM_CORE_VKEY_oEB, KM_CORE_VKEY_oEC, KM_CORE_VKEY_oED, KM_CORE_VKEY_oEE, KM_CORE_VKEY_oEF, KM_CORE_VKEY_oF0, KM_CORE_VKEY_oF1, KM_CORE_VKEY_oF2, KM_CORE_VKEY_oF3, KM_CORE_VKEY_oF4, KM_CORE_VKEY_oF5, KM_CORE_VKEY__F6, KM_CORE_VKEY__F7, KM_CORE_VKEY__F8, KM_CORE_VKEY__F9, KM_CORE_VKEY__FA, KM_CORE_VKEY__FB, KM_CORE_VKEY__FC, KM_CORE_VKEY__FD, KM_CORE_VKEY__FE, KM_CORE_VKEY__FF, }; keyman/core/include/keyman/meson.build0000664000000000000000000000234114600607066015240 0ustar # Copyright: © 2018 SIL International. # Description: Cross platform build script to generate installable API header # files with versioning information templated in. # Create Date: 2 Oct 2018 # Authors: Tim Eves (TSE) # History: 6 Oct 2018 - TSE - Move into keyman folder. # ver = lib_version.split('.') project_ver = meson.project_version().split('.') cfg = configuration_data() cfg.set('lib_curr', ver[0]) cfg.set('lib_age', ver[1]) cfg.set('lib_rev', ver[2]) cfg.set('majorver', project_ver[0]) cfg.set('minorver', project_ver[1]) cfg.set('patchver', project_ver[2]) configure_file( configuration: cfg, input: 'keyman_core_api_version.h.in', output: 'keyman_core_api_version.h', ) install_headers('keyman_core_api.h', 'keyman_core_api_actions.h', 'keyman_core_api_bits.h', 'keyman_core_api_consts.h', 'keyman_core_api_context.h', 'keyman_core_api_debug.h', 'keyman_core_api_vkeys.h', join_paths(meson.current_build_dir(), 'keyman_core_api_version.h'), '../../../common/include/km_types.h', '../../../common/include/kmx_file.h', subdir: 'keyman') keyman/core/include/ldml/0000775000000000000000000000000014600607066012542 5ustar keyman/core/include/ldml/build.sh0000775000000000000000000000427014600607066014203 0ustar #!/usr/bin/env bash # # Packages the @keymanapp/ldml-keyboard-constants package. # # Exit on command failure and when using unset variables: set -eu ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" . "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE cd "$THIS_SCRIPT_PATH" . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" builder_describe "Build Keyman ldml-keyboard-constants package" \ "@/common/web/keyman-version" \ "clean" \ "configure" \ "build" \ "test" \ "pack build a local .tgz pack for testing" \ "publish publish to npm" \ "--dry-run,-n don't actually publish, just dry run" builder_describe_outputs \ configure /node_modules \ build /core/include/ldml/build/keyman_core_ldml.js builder_parse "$@" #------------------------------------------------------------------------------------------------------------------- if builder_start_action clean; then rm -rf ./build/ builder_finish_action success clean fi #------------------------------------------------------------------------------------------------------------------- if builder_start_action configure; then verify_npm_setup builder_finish_action success configure fi #------------------------------------------------------------------------------------------------------------------- if builder_start_action build; then tsc --build builder_finish_action success build fi #------------------------------------------------------------------------------------------------------------------- if builder_start_action test; then # no tests at this time builder_finish_action success test fi #------------------------------------------------------------------------------------------------------------------- if builder_start_action publish; then . "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" builder_publish_to_npm builder_finish_action success publish elif builder_start_action pack; then . "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" builder_publish_to_pack builder_finish_action success pack fi keyman/core/include/ldml/keyman_core_ldml.h0000664000000000000000000001123414600607066016220 0ustar /* Copyright: Copyright (C) 2022-2023 SIL International. Authors: srl295 This file provides constants for the KMX Plus (LDML support) binary format, to be shared between TypeScript and C++ via the generator (below) */ // // Generated File - do not edit // // This file is generated by core/tools/ldml-const-builder/build.sh // based on core/include/ldml/keyman_core_ldml.ts // #pragma once #define LDML_BKSP_FLAGS_ERROR 0x1 #define LDML_CLDR_IMPLIED_FORMS_IMPORT "45/scanCodes-implied.xml" #define LDML_CLDR_IMPLIED_KEYS_IMPORT "45/keys-Latn-implied.xml" #define LDML_CLDR_IMPORT_BASE "cldr" #define LDML_CLDR_TEST_VERSION_LATEST "techpreview" #define LDML_CLDR_VERSION_LATEST "45" #define LDML_ELEM_FLAGS_ORDER_BITSHIFT 0x10 #define LDML_ELEM_FLAGS_ORDER_MASK 0xFF0000 #define LDML_ELEM_FLAGS_PREBASE 0x8 #define LDML_ELEM_FLAGS_TERTIARY_BASE 0x4 #define LDML_ELEM_FLAGS_TERTIARY_BITSHIFT 0x18 #define LDML_ELEM_FLAGS_TERTIARY_MASK 0xFF000000 #define LDML_ELEM_FLAGS_TYPE 0x3 #define LDML_ELEM_FLAGS_TYPE_CHAR 0x0 #define LDML_ELEM_FLAGS_TYPE_STR 0x1 #define LDML_ELEM_FLAGS_TYPE_USET 0x2 #define LDML_FINL_FLAGS_ERROR 0x1 #define LDML_KEYS_KEY_FLAGS_EXTEND 0x1 #define LDML_KEYS_KEY_FLAGS_GAP 0x2 #define LDML_KEYS_MOD_ALL 0x17F #define LDML_KEYS_MOD_ALT 0x40 #define LDML_KEYS_MOD_ALTL 0x4 #define LDML_KEYS_MOD_ALTR 0x8 #define LDML_KEYS_MOD_CAPS 0x100 #define LDML_KEYS_MOD_CTRL 0x20 #define LDML_KEYS_MOD_CTRLL 0x1 #define LDML_KEYS_MOD_CTRLR 0x2 #define LDML_KEYS_MOD_NONE 0x0 #define LDML_KEYS_MOD_SHIFT 0x10 #define LDML_LAYR_LIST_HARDWARE_TOUCH "touch" #define LDML_LENGTH_BKSP 0xC #define LDML_LENGTH_BKSP_ITEM 0x10 #define LDML_LENGTH_DISP 0x10 #define LDML_LENGTH_DISP_ITEM 0xC #define LDML_LENGTH_ELEM 0xC #define LDML_LENGTH_ELEM_ITEM 0x8 #define LDML_LENGTH_ELEM_ITEM_ELEMENT 0x8 #define LDML_LENGTH_FINL 0x8 #define LDML_LENGTH_FINL_ITEM 0x10 #define LDML_LENGTH_HEADER 0x8 #define LDML_LENGTH_KEYS 0x18 #define LDML_LENGTH_KEYS_FLICK_ELEMENT 0x8 #define LDML_LENGTH_KEYS_FLICK_LIST 0xC #define LDML_LENGTH_KEYS_KEY 0x24 #define LDML_LENGTH_KEYS_KMAP 0xC #define LDML_LENGTH_LAYR 0x18 #define LDML_LENGTH_LAYR_ENTRY 0x10 #define LDML_LENGTH_LAYR_KEY 0x4 #define LDML_LENGTH_LAYR_LIST 0x10 #define LDML_LENGTH_LAYR_ROW 0x8 #define LDML_LENGTH_LIST 0x10 #define LDML_LENGTH_LIST_INDEX 0x4 #define LDML_LENGTH_LIST_ITEM 0x8 #define LDML_LENGTH_LOCA 0xC #define LDML_LENGTH_LOCA_ITEM 0x4 #define LDML_LENGTH_META 0x24 #define LDML_LENGTH_SECT 0x10 #define LDML_LENGTH_SECT_ITEM 0x8 #define LDML_LENGTH_STRS 0xC #define LDML_LENGTH_STRS_ITEM 0x8 #define LDML_LENGTH_TRAN 0x14 #define LDML_LENGTH_TRAN_GROUP 0xC #define LDML_LENGTH_TRAN_REORDER 0x8 #define LDML_LENGTH_TRAN_TRANSFORM 0x10 #define LDML_LENGTH_USET 0x10 #define LDML_LENGTH_USET_RANGE 0x8 #define LDML_LENGTH_USET_USET 0xC #define LDML_LENGTH_VARS 0x10 #define LDML_LENGTH_VARS_ITEM 0x10 #define LDML_MARKER_ANY_INDEX 0xD7FF #define LDML_MARKER_CODE 0x8 #define LDML_MARKER_MAX_COUNT 0xD7FE #define LDML_MARKER_MAX_INDEX 0xD7FE #define LDML_MARKER_MIN_INDEX 0x1 #define LDML_MARKER_NO_INDEX 0x0 #define LDML_META_SETTINGS_NORMALIZATION_DISABLED 0x1 #define LDML_SECTIONID_BKSP 0x70736B62 /* "bksp" */ #define LDML_SECTIONNAME_BKSP "bksp" #define LDML_SECTIONID_DISP 0x70736964 /* "disp" */ #define LDML_SECTIONNAME_DISP "disp" #define LDML_SECTIONID_ELEM 0x6D656C65 /* "elem" */ #define LDML_SECTIONNAME_ELEM "elem" #define LDML_SECTIONID_KEYS 0x7379656B /* "keys" */ #define LDML_SECTIONNAME_KEYS "keys" #define LDML_SECTIONID_LAYR 0x7279616C /* "layr" */ #define LDML_SECTIONNAME_LAYR "layr" #define LDML_SECTIONID_LIST 0x7473696C /* "list" */ #define LDML_SECTIONNAME_LIST "list" #define LDML_SECTIONID_LOCA 0x61636F6C /* "loca" */ #define LDML_SECTIONNAME_LOCA "loca" #define LDML_SECTIONID_META 0x6174656D /* "meta" */ #define LDML_SECTIONNAME_META "meta" #define LDML_SECTIONID_SECT 0x74636573 /* "sect" */ #define LDML_SECTIONNAME_SECT "sect" #define LDML_SECTIONID_STRS 0x73727473 /* "strs" */ #define LDML_SECTIONNAME_STRS "strs" #define LDML_SECTIONID_TRAN 0x6E617274 /* "tran" */ #define LDML_SECTIONNAME_TRAN "tran" #define LDML_SECTIONID_USET 0x74657375 /* "uset" */ #define LDML_SECTIONNAME_USET "uset" #define LDML_SECTIONID_VARS 0x73726176 /* "vars" */ #define LDML_SECTIONNAME_VARS "vars" #define LDML_TRAN_FLAGS_ERROR 0x1 #define LDML_TRAN_GROUP_TYPE_REORDER 0x1 #define LDML_TRAN_GROUP_TYPE_TRANSFORM 0x0 #define LDML_UC_SENTINEL 0xFFFF #define LDML_VARS_ENTRY_TYPE_SET 0x1 #define LDML_VARS_ENTRY_TYPE_STRING 0x0 #define LDML_VARS_ENTRY_TYPE_UNICODESET 0x2 #define LDML_VERSION "1.0" keyman/core/include/ldml/keyman_core_ldml.ts0000664000000000000000000003606414600607066016427 0ustar /* Copyright: Copyright (C) 2022 SIL International. Authors: srl295, mcdurdin This file provides constants for the KMX Plus (LDML support) binary format, to be shared between TypeScript and C++ via the generator (below) */ // NOTICE! // // If you update this file, you *must* be sure to re-run // // core/tools/ldml-const-builder/build.sh clean build run // // To update keyman_core_ldml.h, and commit the result. // // It is not updated automatically. /** * Defines the section identifiers and ensures that we include each and every * one of them in the `sections` block and gives us a type which we can iterate * through. */ export type SectionIdent = // Keep this sorted, but with `sect` as the first entry. 'sect' | 'bksp' | 'disp' | 'elem' | 'keys' | 'layr' | 'list' | 'loca' | 'meta' | 'strs' | 'tran' | 'uset' | 'vars'; type SectionMap = { [id in SectionIdent]: SectionIdent; } // TODO-LDML: namespace com.keyman.core.ldml { /** * Constants for the KMXPlus data format * These are shared between the data access layer and the compiler. * Note that the section IDs (section_keys etc.) are 32 bit hex * values that are designed to appear as text when written in little endian * format, so 0x7379656b = 'keys' */ class Constants { /** * The version of the LDML processor */ readonly version = '1.0'; /** * The current CLDR version */ readonly cldr_version_latest = '45'; /** * The version for testdata files */ readonly cldr_test_version_latest = 'techpreview'; /** * import base */ readonly cldr_import_base = 'cldr'; /** * implied keys file */ readonly cldr_implied_keys_import = `${this.cldr_version_latest}/keys-Latn-implied.xml`; /** * implied scancodes file */ readonly cldr_implied_forms_import = `${this.cldr_version_latest}/scanCodes-implied.xml`; /** * Length of a raw section header, in bytes */ readonly length_header = 8; /* ------------------------------------------------------------------ * sect section ------------------------------------------------------------------ */ /** * Minimum length of the 'sect' section, not including entries */ readonly length_sect = 16; /** * Length of each item in the 'sect' section variable part */ readonly length_sect_item = 8; /* ------------------------------------------------------------------ * bksp section ------------------------------------------------------------------ */ /** * Minimum length of the 'bksp' section, not including entries */ readonly length_bksp = 12; /** * Length of each item in the 'bksp' section variable part */ readonly length_bksp_item = 16; /** * bitwise or value for error="fail" in transform */ readonly bksp_flags_error = 0x0001; /* ------------------------------------------------------------------ * disp section ------------------------------------------------------------------ */ /** * Minimum length of the 'disp' section, not including entries */ readonly length_disp = 16; /** * Length of each entry in the 'disp' variable part */ readonly length_disp_item = 12; /* ------------------------------------------------------------------ * elem section ------------------------------------------------------------------ */ /** * Minimum length of the 'elem' section, not including entries */ readonly length_elem = 12; /** * Length of each elem string in the 'elem' section variable part */ readonly length_elem_item = 8; /** * Length of each element in an elem string */ readonly length_elem_item_element = 8; /** * bitwise or value for type in elem[elemstr][element].flags. * If bits are 00b, then 'element' is a UTF-32LE codepoint. * If bits are 01b, then 'element' is a string index. * If bits are 10b (2), then 'element' is a uset index. * * `type = flags & elem_flags_type` */ readonly elem_flags_type = 0x00000003; readonly elem_flags_type_char = 0x00000000; readonly elem_flags_type_str = 0x00000001; readonly elem_flags_type_uset = 0x00000002; /** * bitwise or value for tertiary_base in elem[elemstr][element].flags. * If bit is 1, then tertiary_base is true. * If bit is 0, then tertiary_base is false. * * Used only for `ordr`-type element strings. * * `tertiary_base = flags & elem_flags_tertiary_base` */ readonly elem_flags_tertiary_base = 0x00000004; /** * bitwise or value for tertiary_base in elem[elemstr][element].flags. * If bit is 1, then prebase is true. * If bit is 0, then prebase is false. * * Used only for `ordr`-type element strings. * * `prebase = flags & elem_flags_prebase` */ readonly elem_flags_prebase = 0x00000008; /** * bitwise mask for order in elem[elemstr][element].flags. * * Used only for `ordr`-type element strings. 1 byte signed integer. * * `order = (flags & elem_flags_order_mask) >> elem_flags_order_bitshift` */ readonly elem_flags_order_mask = 0x00FF0000; /** * bit shift for order in elem[elemstr][element].flags. * * Used only for `ordr`-type element strings. * * `order = (flags & elem_flags_order_mask) >> elem_flags_order_bitshift` */ readonly elem_flags_order_bitshift = 16; /** * bitwise mask for tertiary sort in elem[elemstr][element].flags. * * Used only for `ordr`-type element strings. 1 byte signed integer. * * `tertiary = (flags & elem_flags_tertiary_mask) >> elem_flags_tertiary_bitshift` */ readonly elem_flags_tertiary_mask = 0xFF000000; /** * bit shift for tertiary sort in elem[elemstr][element].flags. * * Used only for `ordr`-type element strings. 1 byte signed integer. * * `order = (flags & elem_flags_tertiary_mask) >> elem_flags_tertiary_bitshift` */ readonly elem_flags_tertiary_bitshift = 24; /* ------------------------------------------------------------------ * finl section ------------------------------------------------------------------ */ /** * Minimum length of the 'finl' section, not including entries */ readonly length_finl = 8; /** * Length of each item in the 'finl' section variable part */ readonly length_finl_item = 16; /** * bitwise or value for error="fail" in transform */ readonly finl_flags_error = 0x0001; /* ------------------------------------------------------------------ * keys section is now keys.kmap ------------------------------------------------------------------ */ /** * Constant for no modifiers */ readonly keys_mod_none = 0x0000; /** * bitmask for Left Alt modifier key */ readonly keys_mod_altL = 0x0004; /** * bitmask for Right Alt (AltGr) modifier key */ readonly keys_mod_altR = 0x0008; /** * bitmask for either Alt (Windows) or Option (Apple) modifier keys */ readonly keys_mod_alt = 0x0040; /** * bitmask for Caps modifier key */ readonly keys_mod_caps = 0x0100; /** * bitmask for Left control modifier key */ readonly keys_mod_ctrlL = 0x0001; /** * bitmask for Right control modifier key */ readonly keys_mod_ctrlR = 0x0002; /** * bitmask for either Control modifier key */ readonly keys_mod_ctrl = 0x0020; /** * bitmask for either shift. */ readonly keys_mod_shift = 0x0010; /** * Convenience map for modifiers */ readonly keys_mod_map: Map = new Map( [ ["none", this.keys_mod_none], ["alt", this.keys_mod_alt], ["altL", this.keys_mod_altL], ["altR", this.keys_mod_altR], ["caps", this.keys_mod_caps], ["ctrl", this.keys_mod_ctrl], ["ctrlL", this.keys_mod_ctrlL], ["ctrlR", this.keys_mod_ctrlR], ["shift", this.keys_mod_shift], ] ); /** * a mask combining all valid modifier bits */ readonly keys_mod_all: number = Array.from(this.keys_mod_map.values()).reduce((p, v) => (p | v), this.keys_mod_none); /* ------------------------------------------------------------------ * keys section ------------------------------------------------------------------ */ /** * Minimum length of the 'keys' section not including variable parts */ readonly length_keys = 24; /** * Length of each item in the 'keys' keys sub-table */ readonly length_keys_key = 36; /** * Length of each item in the 'keys' flick lists sub-table */ readonly length_keys_flick_list = 12; /** * Length of each item in the 'keys' flick elements sub-table */ readonly length_keys_flick_element = 8; /** * Length of each item in the 'keys.kmap' key map subtable */ readonly length_keys_kmap = 12; /** * 0 if to is a char, 1 if it is a string */ readonly keys_key_flags_extend = 0x00000001; /** * 1 if the key is a gap */ readonly keys_key_flags_gap = 0x00000002; /* ------------------------------------------------------------------ * layr section ------------------------------------------------------------------ */ /** * Minimum length of the 'layr' section not including variable parts */ readonly length_layr = 24; /** * Length of each layer list in the 'layr' section variable part */ readonly length_layr_list = 16; /** * for the 'hardware' field indicating a touch keyboard, non-hardware */ readonly layr_list_hardware_touch = 'touch'; /** * Length of each layer entry in the 'layr' section variable part */ readonly length_layr_entry = 16; /** * Length of each row entry in the 'layr' section variable part */ readonly length_layr_row = 8; /** * Length of each key entry in the 'layr' section variable part */ readonly length_layr_key = 4; /* ------------------------------------------------------------------ * list section ------------------------------------------------------------------ */ /** * Minimum length of the 'list' section not including variable parts */ readonly length_list = 16; /** * Length of each list item in the 'list' list section variable part */ readonly length_list_item = 8; /** * Length of each list item in the 'list' indices section variable part */ readonly length_list_index = 4; /* ------------------------------------------------------------------ * loca section ------------------------------------------------------------------ */ /** * Minimum length of the 'loca' section not including variable parts */ readonly length_loca = 12; /** * Length of each item in the 'loca' section variable part */ readonly length_loca_item = 4; /* ------------------------------------------------------------------ * meta section ------------------------------------------------------------------ */ /** * length of the 'meta' section */ readonly length_meta = 36; /** * bitwise or value for normalization=disabled in meta.settings */ readonly meta_settings_normalization_disabled = 1; /* ------------------------------------------------------------------ * strs section ------------------------------------------------------------------ */ /** * Minimum length of the 'strs' section not including variable parts */ readonly length_strs = 12; /** * Length of each item in the 'strs' section variable part */ readonly length_strs_item = 8; /* ------------------------------------------------------------------ * tran section ------------------------------------------------------------------ */ /** * Minimum length of the 'tran' section, not including entries */ readonly length_tran = 20; /** * Length of each transform group item */ readonly length_tran_group = 12; /** * Length of each transform item */ readonly length_tran_transform = 16; /** * Length of each reorder subtable item */ readonly length_tran_reorder = 8; /** * bitwise or value for error="fail" in transform */ readonly tran_flags_error = 0x0001; /** * this group is full of transform items */ readonly tran_group_type_transform = 0; /** * this group is full of reorder items */ readonly tran_group_type_reorder = 1; /* ------------------------------------------------------------------ * vars section * ------------------------------------------------------------------ */ /** * Minimum length of the 'vars' section not including variable parts */ readonly length_vars = 16; /** * Length of each item in the 'vars' section variable part */ readonly length_vars_item = 16; /** * String variable */ readonly vars_entry_type_string = 0; /** * Set variable */ readonly vars_entry_type_set = 1; /** * unicodeSet variable */ readonly vars_entry_type_unicodeSet = 2; /* ------------------------------------------------------------------ * uset section * ------------------------------------------------------------------ */ /* * Minimum length of the 'uset' section not including variable parts */ readonly length_uset = 16; /** * Length of each entry in the uset.usets subtable */ readonly length_uset_uset = 12; /** * Length of each entry in the uset.ranges subtable */ readonly length_uset_range = 8; /** * All section IDs. */ readonly section: SectionMap = { // keep this sorted bksp: 'bksp', disp: 'disp', elem: 'elem', keys: 'keys', layr: 'layr', list: 'list', loca: 'loca', meta: 'meta', sect: 'sect', strs: 'strs', tran: 'tran', uset: 'uset', vars: 'vars', }; /** * Use to convert 4-char string into hex * @param id section id such as 'sect' * @returns hex ID such as 0x74636573 */ hex_section_id(id:string) { if(!id || typeof id !== 'string' || !id.match(/^[a-z0-9]{4}$/)) { throw Error(`hex_section_id(${id}) - need a 4-character alphanumeric lower-case string`); } let r = 0; for (let i = 3; i>=0; i--) { r = (r << 8 | id.charCodeAt(i)); } return r; }; /** * Use to convert hex into 4-char string * @param hex section ID such as 0x74636573 * @returns string such as 'sect' */ str_section_id(hex:number) : string { const chars : string[] = []; for (let i = 3; i>=0; i--) { chars.push(String.fromCharCode(hex & 0xFF)); hex >>= 8; } return chars.join(''); } // ---- marker stuff ---- /** == kmx_file.UC_SENTINEL, always followed by `marker_code`, marker index 0x0001-0xfffe */ readonly uc_sentinel = 0xFFFF; /** == kmx_file.CODE_DEADKEY */ readonly marker_code = 0x0008; /** used to refer to no index */ readonly marker_no_index = 0x0000; /** minimum usable marker index */ readonly marker_min_index = 0x0001; /** index value referring to the 'any' marker match */ readonly marker_any_index = 0xD7FF; /** maximum marker index prior to the 'any' value */ readonly marker_max_index = this.marker_any_index - 1; /** maximum count of markers (not including 'any') */ readonly marker_max_count = this.marker_max_index - this.marker_min_index + 1; }; export const constants = new Constants(); // } keyman/core/include/ldml/ldml-const-builder.ts0000664000000000000000000000376314600607066016623 0ustar /* Copyright: Copyright (C) 2022 SIL International. Authors: srl295 This tool generates a .h version of the keyman_core_ldml.ts file */ import { constants } from './keyman_core_ldml.js'; const keys = Object.keys(constants); keys.sort(); console.log(` /* Copyright: Copyright (C) 2022-2023 SIL International. Authors: srl295 This file provides constants for the KMX Plus (LDML support) binary format, to be shared between TypeScript and C++ via the generator (below) */ // // Generated File - do not edit // // This file is generated by core/tools/ldml-const-builder/build.sh // based on core/include/ldml/keyman_core_ldml.ts // #pragma once `); let errs = 0; for (const key of keys) { const value: any = constants[key as keyof typeof constants]; const upkey = key.toUpperCase(); const type = typeof value; if (type === 'number') { console.log(`#define LDML_${upkey} 0x${value.toString(16).toUpperCase()}`); } else if (type === 'string') { console.log(`#define LDML_${upkey} "${value}"`); } else if (key === 'section') { // handle section table const subkeys = Object.keys(value); subkeys.sort(); for (const subkey of subkeys) { const upsubkey = subkey.toUpperCase(); const subvalue = value[subkey]; if (subvalue !== subkey) { // "can't happen" because tsc would complain console.error(`In the SectionMap: ${subkey}: '${subvalue}' - expected key and value to match.`); errs++; } const asnum = constants.hex_section_id(subkey); console.log(`#define LDML_${upkey}ID_${upsubkey} 0x${asnum.toString(16).toUpperCase()} /* "${subkey}" */`); console.log(`#define LDML_${upkey}NAME_${upsubkey} "${subkey}"`); } } else if (key.endsWith('_map') || type === 'function') { // ignored } else { console.error(`Don’t know what to do with constants[${key}] of type ${type}`); errs++; } } if (errs != 0) { throw Error(`Fail: ${errs} error(s), see above.`); } keyman/core/include/ldml/package.json0000664000000000000000000000062714600607066015035 0ustar { "name": "@keymanapp/ldml-keyboard-constants", "description": "Keyman LDML keyboard constants", "keywords": [ "keyboard", "keyman", "ldml", "unicode" ], "files": [ "/build/keyman_core_ldml.*" ], "license": "MIT", "type": "module", "main": "build/keyman_core_ldml.js", "repository": { "type": "git", "url": "git+https://github.com/keymanapp/keyman.git" } } keyman/core/include/ldml/tsconfig.build.json0000664000000000000000000000051614600607066016351 0ustar { "extends": "../../../tsconfig.base.json", "compilerOptions": { "composite": true, "declaration": true, "rootDir": ".", "outDir": "ldml-const-builder/", }, "exclude": [ "node_modules" ], "files": [ "keyman_core_ldml.ts", "ldml-const-builder.ts" ] } keyman/core/include/ldml/tsconfig.json0000664000000000000000000000044014600607066015247 0ustar { "extends": "../../../tsconfig.base.json", "compilerOptions": { "composite": true, "declaration": true, "rootDir": ".", "outDir": "build/", }, "exclude": [ "node_modules" ], "files": [ "keyman_core_ldml.ts" ] } keyman/core/include/meson.build0000664000000000000000000000061314600607066013754 0ustar # Copyright: © 2018 SIL International. # Description: Cross platform build script to generate installable API header # files with versioning information templated in. # Create Date: 2 Oct 2018 # Authors: Tim Eves (TSE) # History: 6 Oct 2018 - TSE - Move into keyman folder. # inc = include_directories('.', '../../common/include', is_system: true) subdir('keyman') keyman/core/meson.build0000664000000000000000000000254014600607066012332 0ustar # Copyright: © 2018-2022 SIL International. # Description: Cross platform build script to compile libkeymancore, documentation # and tests. # Create Date: 2 Oct 2018 # Authors: Tim Eves (TSE) # project('keyman_core', 'cpp', 'c', version: run_command(find_program('getversion.bat', 'getversion.sh'), check:true).stdout().strip(), license: 'MIT', default_options : ['buildtype=release', 'cpp_std=c++14', 'b_vscrt=static_from_buildtype', 'warning_level=2', 'debug=true'], meson_version: '>=0.57.0') # Import our standard compiler defines; this is copied from # /resources/build/standard.meson.build by build.sh, because # meson doesn't allow us to reference a file outside its root subdir('resources') fs = import('fs') lib_version = fs.read('CORE_API_VERSION.md').strip() py = import('python') python = py.find_installation() # TODO: Shared includes may use namespaces, etc which need future tidyup. # For now, we use KM_CORE_LIBRARY to inject the km::core::kmx namespace defns += ['-DKM_CORE_LIBRARY'] # #define DEBUG when we are on a debug build if get_option('buildtype') == 'debug' add_global_arguments('-DDEBUG', language : 'cpp') endif subdir('doc') subdir('include') subdir('src') subdir('tests') keyman/core/meson_options.txt0000664000000000000000000000007114600607066013622 0ustar option('keyman_core_tests', type: 'boolean', value: true)keyman/core/resources/0000775000000000000000000000000014600607117012176 5ustar keyman/core/resources/meson.build0000664000000000000000000000413114600607126014337 0ustar # # Shared configuration for all meson-based builds # # This file has the master location /resources/build/meson/standard.meson.build, # and is copied into each project's /resources/meson.build in the # configure step, so that it can be referenced by meson directly. # # Where possible, we want to use these flags everywhere # cpp_compiler = meson.get_compiler('cpp') c_compiler = meson.get_compiler('c') # Once we can assume meson 0.60 we can delete this # (https://mesonbuild.com/Release-notes-for-0-60-0.html#msvc-compiler-now-assumes-utf8-source-code-by-default) if cpp_compiler.get_id() == 'msvc' add_global_arguments('/source-charset:utf-8', language: ['c', 'cpp']) endif # # Standard informational messages for our builds # message('meson.project_version(): ' + meson.project_version()) message('host_machine.system(): ' + host_machine.system()) message('compiler.get_id(): ' + cpp_compiler.get_id()) # # Standard compiler flags for all platforms # warns = [] flags = [] links = [] defns = [] if cpp_compiler.get_id() == 'gcc' or cpp_compiler.get_id() == 'clang' warns += [ '-Wctor-dtor-privacy', '-Wdouble-promotion', '-Wendif-labels', '-Wno-unknown-pragmas', '-Wno-missing-field-initializers', '-Wnon-virtual-dtor', '-Wshadow' ] flags += [ '-fvisibility=hidden', '-fvisibility-inlines-hidden' ] if cpp_compiler.get_id() == 'clang' warns += [ '-Wimplicit-fallthrough', '-Wno-double-promotion', '-Wshorten-64-to-32' ] endif if host_machine.system() == 'darwin' # TODO: this seems to be inverting above options, is this necessary, or can # we resolve another way? warns += [ '-Wno-ctor-dtor-privacy', '-Wno-non-virtual-dtor' ] endif endif if cpp_compiler.get_id() == 'msvc' defns += [ '-D_SCL_SECURE_NO_WARNINGS', '-D_CRT_SECURE_NO_WARNINGS' ] endif if cpp_compiler.get_id() == 'emscripten' if get_option('buildtype') == 'debug' # Enable DWARF symbols for debug builds flags += ['-g'] links += ['-g'] else flags += ['-O2'] links += ['-O2'] endif endif keyman/core/src/0000775000000000000000000000000014600607066010756 5ustar keyman/core/src/action.cpp0000664000000000000000000001324414600607066012743 0ustar /* Copyright: © 2023 SIL International. Description: Implementation of the action API functions using internal data structures and functions. Create Date: 23 Oct 2023 Authors: Marc Durdin (MCD) History: 23 Oct 2023 - MCD - Initial implementation from #9720 */ #include #include #include #include #include "action.hpp" #include "state.hpp" #include "option.hpp" bool km::core::action_item_list_to_actions_object( km_core_action_item const *action_items, km_core_actions *actions ) { assert(action_items != nullptr); assert(actions != nullptr); if(action_items == nullptr || actions == nullptr) { return false; } // Set actions default values std::vector output; std::vector options; actions->code_points_to_delete = 0; actions->do_alert = KM_CORE_FALSE; actions->emit_keystroke = KM_CORE_FALSE; actions->new_caps_lock_state = KM_CORE_CAPS_UNCHANGED; // deleted_context data will be set in state::apply_actions_and_merge_app_context // because it needs access to the state's app context actions->deleted_context = nullptr; // Clear output pointers, will be set later once we have sizes actions->output = nullptr; actions->persist_options = nullptr; for (; action_items->type != KM_CORE_IT_END; ++action_items) { assert(action_items->type < KM_CORE_IT_MAX_TYPE_ID); switch(action_items->type) { case KM_CORE_IT_ALERT: actions->do_alert = KM_CORE_TRUE; break; case KM_CORE_IT_BACK: switch(action_items->backspace.expected_type) { case KM_CORE_BT_UNKNOWN: // this is equivalent to emit_keystroke, because the only time we // are allowed to do an unknown bksp is when a bksp is passed in actions->emit_keystroke = KM_CORE_TRUE; break; case KM_CORE_BT_CHAR: if(output.empty()) { actions->code_points_to_delete++; } else { auto last_context_item = output.back(); output.pop_back(); assert(last_context_item.type == KM_CORE_CT_CHAR); assert(last_context_item.character == action_items->backspace.expected_value); } break; case KM_CORE_BT_MARKER: if(output.empty()) { // deleting a marker has no effect on the application } else { auto last_context_item = output.back(); output.pop_back(); assert(last_context_item.type == KM_CORE_CT_MARKER); assert(last_context_item.marker == action_items->backspace.expected_value); } break; default: assert(false); } break; case KM_CORE_IT_CAPSLOCK: actions->new_caps_lock_state = action_items->capsLock ? KM_CORE_CAPS_ON : KM_CORE_CAPS_OFF; break; case KM_CORE_IT_CHAR: output.push_back({KM_CORE_CT_CHAR,{0},{action_items->character}}); break; case KM_CORE_IT_EMIT_KEYSTROKE: actions->emit_keystroke = KM_CORE_TRUE; break; case KM_CORE_IT_INVALIDATE_CONTEXT: // no-op break; case KM_CORE_IT_MARKER: output.push_back({KM_CORE_CT_MARKER,{0},{action_items->marker}}); break; case KM_CORE_IT_PERSIST_OPT: { // TODO: lowpri: replace existing item if already present in options vector? km::core::option opt(static_cast(action_items->option->scope), action_items->option->key, action_items->option->value ); options.push_back(opt.release()); // hand over memory management of the option item to the action struct break; } default: assert(false); } } // Strip the markers from the output, and convert to an string of UTF-32 output.push_back(KM_CORE_CONTEXT_ITEM_END); size_t buf_size; if(context_items_to_utf32(output.data(), nullptr, &buf_size) != KM_CORE_STATUS_OK) { return false; } std::unique_ptr output_usv(new km_core_usv[buf_size]); if(context_items_to_utf32(output.data(), output_usv.get(), &buf_size) != KM_CORE_STATUS_OK) { return false; } actions->output = output_usv.release(); // Create an array of the persisted options options.push_back(KM_CORE_OPTIONS_END); actions->persist_options = new km_core_option_item[options.size()]; std::copy(options.begin(), options.end(), actions->persist_options); // We now have a complete set of actions return true; } // TODO: this is effectively the inverse of action_item_list_to_actions_object, // and perhaps we should consider changing that function to be a member // of state also, so that we can move memory management into state? bool km::core::state::set_actions( km_core_actions const &actions ) { _actions.clear(); // number of codepoints (not codeunits!) to delete from app context. for(unsigned int i = 0; i < actions.code_points_to_delete; i++) { _actions.push_backspace(KM_CORE_BT_CHAR, 0); // expected value is not known } for(auto output = actions.output; *output; output++) { _actions.push_character(*output); } for(auto opt = actions.persist_options; opt->scope; opt++) { km::core::option opt0(static_cast(opt->scope), opt->key, opt->value); _actions.push_persist(opt0); } if(actions.do_alert) { _actions.push_alert(); } if(actions.emit_keystroke) { _actions.push_emit_keystroke(); } if(actions.new_caps_lock_state != KM_CORE_CAPS_UNCHANGED) { _actions.push_capslock(actions.new_caps_lock_state == KM_CORE_CAPS_ON); } return true; } keyman/core/src/action.hpp0000664000000000000000000000170414600607066012746 0ustar /* Copyright: © 2023 SIL International. Description: Internal actions methods for Keyman Core Create Date: 23 Oct 2023 Authors: Marc Durdin (MCD) History: 23 Oct 2023 - MCD - Initial implementation */ #pragma once #include "keyman_core.h" #include namespace km { namespace core { bool action_item_list_to_actions_object( km_core_action_item const *action_items, km_core_actions *actions ); bool actions_normalize( /* in */ context const *cached_context, /* in, out */ context *app_context, /* in, out */ km_core_actions &actions ); bool actions_update_app_context_nfu( /* in */ context const *cached_context, /* in, out */ context *app_context ); void actions_dispose( km_core_actions const & actions ); km_core_usv const *get_deleted_context( context const &app_context, unsigned int code_points_to_delete ); } // namespace core } // namespace km keyman/core/src/actions_normalize.cpp0000664000000000000000000002527114600607066015211 0ustar /* Copyright: © 2024 SIL International. Description: Implementation of the action output normalization. Create Date: 16 Jan 2024 Authors: Marc Durdin (MCD) History: 16 Jan 2024 - MCD - Initial implementation from #9999 */ #include #include #include #include #include "context.hpp" #include "action.hpp" #include "state.hpp" #include "option.hpp" #include "debuglog.h" #include "core_icu.h" // forward declarations icu::UnicodeString context_items_to_unicode_string(km::core::context const *context); km_core_usv *unicode_string_to_usv(icu::UnicodeString& src); /** * Normalize the output from an action to NFC, across the context | output * boundary, fixing up the app_context and the output actions to take into * account the NFU input app_context * * @param cached_context the cached context, in NFD, after transform has been * applied to it by the keyboard processor * @param app_context the app context, in NFU; transform has not been * applied, and will be applied by this function * @param actions transform to apply, in NFD, which will be converted * to NFC by this function * @return true on success, false on failure */ bool km::core::actions_normalize( /* in */ km::core::context const *cached_context, /* in, out */ km::core::context *app_context, /* in, out */ km_core_actions &actions ) { assert(cached_context != nullptr); assert(app_context != nullptr); if(cached_context == nullptr || app_context == nullptr) { return false; } /* The code_points_to_delete value at this point is in NFD. The cached_context is in NFD and has already been updated by the keyboard processor to the expected result of the action, so we need to remove the output from a string copy of the cached_context to start, in order to get it to the same position as the app_context. The app_context is in NFU. We need to figure out how many characters to remove from the end of app_context in order to correctly normalize across the boundary, without normalizing more of the string than necessary. We do not need to mutate the cached_context itself, because it is already correct. This is good, because it means we will not lose track of markers within it. The app_context will be mutated, as it will need the new output appended, in order to match the expected result. Remember that the app_context does not contain markers; these are maintained only in the cached_context. */ /* Initialization */ UErrorCode icu_status = U_ZERO_ERROR; const icu::Normalizer2 *nfc = icu::Normalizer2::getNFCInstance(icu_status); assert(U_SUCCESS(icu_status)); if(!U_SUCCESS(icu_status)) { DebugLog("getNFCInstance failed with %x", icu_status); return false; } const icu::Normalizer2 *nfd = icu::Normalizer2::getNFDInstance(icu_status); assert(U_SUCCESS(icu_status)); if(!U_SUCCESS(icu_status)) { DebugLog("getNFDInstance failed with %x", icu_status); return false; } icu::UnicodeString output = icu::UnicodeString::fromUTF32(reinterpret_cast(actions.output), -1); icu::UnicodeString cached_context_string = context_items_to_unicode_string(cached_context); icu::UnicodeString app_context_string = context_items_to_unicode_string(app_context); assert(!output.isBogus()); assert(!cached_context_string.isBogus()); assert(!app_context_string.isBogus()); if(output.isBogus() || cached_context_string.isBogus() || app_context_string.isBogus()) { return false; } int nfu_to_delete = 0; /* Further debug assertion of inputs */ assert(nfd->isNormalized(output, icu_status) && U_SUCCESS(icu_status)); assert(nfd->isNormalized(cached_context_string, icu_status) && U_SUCCESS(icu_status)); /* The keyboard processor will have updated the cached_context already, applying the transform to it, so we need to rewind this. Remove the output from cached_context_string to start */ assert(cached_context_string.length() >= output.length()); int n = cached_context_string.length() - output.length(); assert(cached_context_string.compare(n, output.length(), output) == 0); cached_context_string.remove(n); /* While cached_context is guaranteed to be normalized, actions->output may not start at a normalization boundary. In order to achieve the correct NFC normalization in our output, we now need to look for a normalization boundary prior to the intersection of the cached_context and the output. */ while(n > 0 && output[0] && !nfd->hasBoundaryBefore(output[0])) { // The output may interact with the context further in normalization. We // need to copy characters back further until we reach a normalization // boundary. // Remove last code point from the context ... n = cached_context_string.moveIndex32(n, -1); UChar32 chr = cached_context_string.char32At(n); cached_context_string.remove(n); // And prepend it to the output ... output.insert(0, chr); // And finally remember that we now need to delete an additional NFD codepoint actions.code_points_to_delete++; } /* At this point, our output and cached_context are coherent and normalization will be complete at the edit boundary. Now, we need to adjust the delete_back to match the number of characters that must actually be deleted from the applications's NFU context To adjust, we remove one character at a time from the app_context until its normalized form matches the cached_context normalized form. */ while(app_context_string.length()) { icu::UnicodeString app_context_nfd; nfd->normalize(app_context_string, app_context_nfd, icu_status); assert(U_SUCCESS(icu_status)); if(!U_SUCCESS(icu_status)) { DebugLog("nfd->normalize failed with %x", icu_status); return false; } if(app_context_nfd.compare(cached_context_string) == 0) { break; } app_context_string.remove(app_context_string.length()-1); nfu_to_delete++; } /* Normalize our output string */ icu::UnicodeString output_nfc; nfc->normalize(output, output_nfc, icu_status); assert(U_SUCCESS(icu_status)); if(!U_SUCCESS(icu_status)) { DebugLog("nfc->normalize failed with %x", icu_status); return false; } auto new_output = unicode_string_to_usv(output_nfc); if(!new_output) { // error logging handled in unicode_string_to_usv return false; } /* Final steps -- set our outputs */ // Append the new NFC output to our reduced app_context app_context_string.append(output_nfc); km_core_context_item *app_context_items = nullptr; km_core_status status = KM_CORE_STATUS_OK; if((status = context_items_from_utf16(app_context_string.getTerminatedBuffer(), &app_context_items)) != KM_CORE_STATUS_OK) { DebugLog("context_items_from_utf16 failed with %x", status); delete [] new_output; return false; } if((status = km_core_context_set(static_cast(app_context), app_context_items)) != KM_CORE_STATUS_OK) { DebugLog("km_core_context_set failed with %x", status); km_core_context_items_dispose(app_context_items); delete [] new_output; return false; } km_core_context_items_dispose(app_context_items); // Update actions with new NFC output + count of NFU code points to delete delete [] actions.output; actions.output = new_output; actions.code_points_to_delete = nfu_to_delete; return true; } /** * Helper to convert km_core_context list into a icu::UnicodeString */ icu::UnicodeString context_items_to_unicode_string(km::core::context const *context) { icu::UnicodeString nullString; nullString.setToBogus(); km_core_context_item *items = nullptr; km_core_status status; if((status = km_core_context_get(static_cast(context), &items)) != KM_CORE_STATUS_OK) { DebugLog("Failed to retrieve context with %s", status); return nullString; } size_t buf_size = 0; if((status = context_items_to_utf32(items, nullptr, &buf_size)) != KM_CORE_STATUS_OK) { DebugLog("Failed to retrieve context size with %s", status); km_core_context_items_dispose(items); return nullString; } km_core_usv *buf = new km_core_usv[buf_size]; if((status = context_items_to_utf32(items, buf, &buf_size)) != KM_CORE_STATUS_OK) { DebugLog("Failed to retrieve context with %s", status); km_core_context_items_dispose(items); delete [] buf; return nullString; } auto result = icu::UnicodeString::fromUTF32(reinterpret_cast(buf), -1); km_core_context_items_dispose(items); delete [] buf; return result; } /** * Helper to convert icu::UnicodeString to a UTF-32 km_core_usv buffer, * nul-terminated */ km_core_usv *unicode_string_to_usv(icu::UnicodeString& src) { UErrorCode icu_status = U_ZERO_ERROR; km_core_usv *dst = new km_core_usv[src.length() + 1]; src.toUTF32(reinterpret_cast(dst), src.length(), icu_status); assert(U_SUCCESS(icu_status)); if(!U_SUCCESS(icu_status)) { DebugLog("toUTF32 failed with %x", icu_status); delete[] dst; return nullptr; } dst[src.length()] = 0; return dst; } /** * Refresh app_context to match the cached_context. Does not do normalization, * unlike `actions_normalize`. Used in conjunction with keyboard processors that * do not support normalization. Resulting app context is same as the cached * context, but without markers. * * @param cached_context the cached context, in NFU, after transform has been * applied to it by the keyboard processor * @param app_context the app context, in NFU; transform has not been * applied, and will effectively be applied by this * function * @return true on success, false on failure */ bool km::core::actions_update_app_context_nfu( /* in */ km::core::context const *cached_context, /* in, out */ km::core::context *app_context ) { km_core_status status = KM_CORE_STATUS_OK; km_core_context_item *items = nullptr; if((status = km_core_context_get(static_cast(cached_context), &items)) != KM_CORE_STATUS_OK) { DebugLog("km_core_context_get failed with %d", status); return false; } // Strip markers from returned context int i, j; for(i = 0, j = 0; items[i].type != KM_CORE_CT_END; i++) { if(items[i].type != KM_CORE_CT_MARKER) { items[j] = items[i]; j++; } } items[j] = KM_CORE_CONTEXT_ITEM_END; if((status = km_core_context_set(static_cast(app_context), items)) != KM_CORE_STATUS_OK) { DebugLog("km_core_context_set failed with %d", status); } delete [] items; return status == KM_CORE_STATUS_OK; }keyman/core/src/context.hpp0000664000000000000000000002232114600607066013153 0ustar /* Copyright: © 2018 SIL International. Description: Internal context class and adaptor class for the API. Create Date: 2 Oct 2018 Authors: Tim Eves (TSE) History: 2 Oct 2018 - TSE - Refactored out of km_core_context_api.cpp */ #pragma once #include #include #include #include "keyman_core.h" // Forward declarations class json; namespace km { namespace core { // This will likely be replaced with a class implementing a more space // efficient data structure such as a ring buffer or bounded queue. class context: public std::list { public: bool has_markers = true; void push_character(km_core_usv); void push_marker(uint32_t); }; inline void context::push_character(km_core_usv usv) { emplace_back(km_core_context_item { KM_CORE_CT_CHAR, {0,}, {usv} }); } inline void context::push_marker(uint32_t marker) { assert(has_markers); if(!has_markers) return; emplace_back(km_core_context_item { KM_CORE_CT_MARKER, {0,}, {marker} }); } // Context helper functions km_core_cp* get_context_as_string(km_core_context *context); km_core_status set_context_from_string(km_core_context *context, km_core_cp const *new_context); } // namespace core } // namespace km json & operator << (json &, km::core::context const &); json & operator << (json &, km_core_context_item const &); struct km_core_context : public km::core::context { }; // The following functions were public APIs in previous versions of Keyman Core. // However, with the move of context caching responsibility to Core with 17.0, // they have been moved to internal /** * Convert a UTF16 encoded Unicode string into an array of `km_core_context_item` * structures. Allocates memory as needed. * * @return km_core_status * * `KM_CORE_STATUS_OK`: On success. * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are * null. * * `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be * allocated for the output buffer. * * `KM_CORE_STATUS_INVALID_UTF`: In the event the UTF16 string cannot * be decoded because it contains unpaired surrogate codeunits. * * @param text a pointer to a null terminated array of utf16 encoded data. * @param out_ptr a pointer to the result variable: A pointer to the start of * the `km_core_context_item` array containing the representation * of the input string. Terminated with a type of * `KM_CORE_CT_END`. Must be disposed of with * `km_core_context_items_dispose`. */ km_core_status context_items_from_utf16(km_core_cp const *text, km_core_context_item **out_ptr); /** * Convert a context item array into a UTF-16 encoded string placing it into the * supplied buffer of specified size, and return the number of code units * actually used in the conversion. If null is passed as the buffer the number * of codeunits required is returned. Any markers in the context will not be * included in the output buffer. * * @return km_core_status * * `KM_CORE_STATUS_OK`: On success. * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are * null. * * `KM_CORE_STATUS_INSUFFICENT_BUFFER`: If the buffer is not large * enough. `buf_size` will contain the space required. The contents * of the buffer are undefined. * * @param context_items A pointer to the start of an array * `km_core_context_item`. Must be terminated with a type * of `KM_CORE_CT_END`. * @param buf A pointer to the buffer to place the UTF-16 string into. * May be null to request size calculation. * @param buf_size A pointer to the result variable: The size of the * supplied buffer in codeunits if `buf` is given. On * return will be the size required if `buf` is null. */ km_core_status context_items_to_utf16(km_core_context_item const *item, km_core_cp *buf, size_t *buf_size); /** * Convert a context item array into a UTF-8 encoded string placing it into the * supplied buffer of specified size, and return the number of code units * actually used in the conversion. If null is passed as the buffer the number * of codeunits required is returned. Any markers in the context will not be * included in the output buffer. * * @return km_core_status * * `KM_CORE_STATUS_OK`: On success. * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are * null. * * `KM_CORE_STATUS_INSUFFICENT_BUFFER`: If the buffer is not large * enough. `buf_size` will contain the space required. The contents * of the buffer are undefined. * * @param context_items A pointer to the start of an array * `km_core_context_item`. Must be terminated with a type * of `KM_CORE_CT_END`. * @param buf A pointer to the buffer to place the UTF-8 string into. * May be null to request size calculation. * @param buf_size A pointer to the result variable: The size of the * supplied buffer in codeunits if `buf` is given. On * return will be the size required if `buf` is null. */ km_core_status context_items_to_utf8(km_core_context_item const *item, char *buf, size_t *buf_size); /** * Convert a context item array into a UTF-32 encoded string placing it into * the supplied buffer of specified size, and return the number of codepoints * actually used in the conversion. If null is passed as the buffer the * number of codepoints required is returned. Any markers in the context will * not be included in the output buffer. * * @return km_core_status * * `KM_CORE_STATUS_OK`: On success. * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are * null. * * `KM_CORE_STATUS_INSUFFICENT_BUFFER`: If the buffer is not large * enough. `buf_size` will contain the space required. The contents * of the buffer are undefined. * * @param context_items A pointer to the start of an array * `km_core_context_item`. Must be terminated with a type * of `KM_CORE_CT_END`. * @param buf A pointer to the buffer to place the UTF-32 string into. * May be null to request size calculation. * @param buf_size A pointer to the result variable: The size of the * supplied buffer in codepoints if `buf` is given. On * return will be the size required if `buf` is null. */ km_core_status context_items_to_utf32(km_core_context_item const *item, km_core_usv *buf, size_t *buf_size); /** * Add more items to the end (insertion point) of the context. If these exceed * the maximum context length the same number of items will be dropped from the * beginning of the context. * * @return km_core_status * * `KM_CORE_STATUS_OK`: On success. * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are * null. * * `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be * allocated to grow the context buffer internally. * * @param context A pointer to an opaque context object. * @param context_items A pointer to the start of the `KM_CORE_CT_END` * terminated array of `km_core_context_item` to append. */ km_core_status context_append(km_core_context *context, km_core_context_item const *context_items); /** * Insert items at the front of the context. * * @return km_core_status * * `KM_CORE_STATUS_OK`: On success. * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are * null. * * `KM_CORE_STATUS_NO_MEM`: In the event not enough memory can be * allocated to grow the context buffer internally. * * @param context A pointer to an opaque context object. * @param context_items A pointer to the start of the `KM_CORE_CT_END` * terminated array of `km_core_context_item` to prepend. * @param num Maximum number of `km_core_context_item` elements to prepend. */ km_core_status context_prepend(km_core_context *context, km_core_context_item const *context_items, size_t num = SIZE_MAX); /** * Remove a specified number of items from the front or end of the context. * * @return km_core_status * * `KM_CORE_STATUS_OK`: On success. * * `KM_CORE_STATUS_INVALID_ARGUMENT`: If non-optional parameters are * null. * * `KM_CORE_STATUS_NO_MEM`: in the event it cannot allocated enough * memory to grow the context internally. * * @param context A pointer to an opaque context object. * @param num The number of items to remove from the context. * @param from_end Whether to remove from the end or front of the context. */ km_core_status context_shrink(km_core_context *context, size_t num, bool from_end = true); keyman/core/src/context_helpers.cpp0000664000000000000000000000355714600607066014702 0ustar /* Copyright: © 2018-2024 SIL International. Description: Helper functions for context data type conversions Create Date: 18 Jan 2024 Authors: Marc Durdin History: 18 Jan 2024 - MCD - Refactor from km_core_state_context_set_if_needed.cpp */ #include #include "keyman_core.h" #include "context.hpp" using namespace km::core; /** * Retrieves the context as a km_core_cp string, dropping markers */ km_core_cp* km::core::get_context_as_string(km_core_context *context) { assert(context != nullptr); if(context == nullptr) { return nullptr; } size_t buf_size = 0; km_core_context_item* context_items = nullptr; if(km_core_context_get(context, &context_items) != KM_CORE_STATUS_OK) { return nullptr; } if(context_items_to_utf16(context_items, nullptr, &buf_size) != KM_CORE_STATUS_OK) { km_core_context_items_dispose(context_items); return nullptr; } km_core_cp *app_context_string = new km_core_cp[buf_size]; km_core_status status = context_items_to_utf16(context_items, app_context_string, &buf_size); km_core_context_items_dispose(context_items); if(status != KM_CORE_STATUS_OK) { return nullptr; } return app_context_string; } /** * Updates the context from the new_context km_core_cp string */ km_core_status km::core::set_context_from_string(km_core_context *context, km_core_cp const *new_context) { assert(context != nullptr); assert(new_context != nullptr); if(context == nullptr || new_context == nullptr) { return KM_CORE_STATUS_INVALID_ARGUMENT; } km_core_context_item* new_context_items = nullptr; km_core_status status = context_items_from_utf16(new_context, &new_context_items); if (status != KM_CORE_STATUS_OK) { return status; } km_core_context_set(context, new_context_items); km_core_context_items_dispose(new_context_items); return KM_CORE_STATUS_OK; } keyman/core/src/core_icu.h0000664000000000000000000000036014600607066012716 0ustar /** * ICU modules used by Keyman Core */ #pragma once #if !defined(HAVE_ICU4C) #error icu4c is required for this code #endif #define U_FALLTHROUGH #include "unicode/utypes.h" #include "unicode/unistr.h" #include "unicode/normalizer2.h" keyman/core/src/debug.hpp0000664000000000000000000000324614600607066012562 0ustar /* * Keyman is copyright (C) SIL International. MIT License. * * Keyman Core - Debug class definition */ #pragma once #include #include #include "keyman_core.h" namespace km { namespace core { class debug_items : public std::vector { private: bool _is_enabled; public: template debug_items(Args&&... args); void push_begin(km_core_state_debug_key_info *key_info, uint32_t flags); void push_end(uint16_t first_action, uint32_t flags); void assert_push_entry(); bool is_enabled() const noexcept; void set_enabled(bool value) noexcept; }; template debug_items::debug_items(Args&&... args) : std::vector(std::forward(args)...) { // Ensure the debug_items list is terminated in case the client calls // km_core_state_debug_items before they call process_event. _is_enabled = false; push_end(0, 0); } inline void debug_items::assert_push_entry() { assert(empty() || (!empty() && back().type != KM_CORE_DEBUG_END)); } inline void debug_items::push_begin(km_core_state_debug_key_info *key_info, uint32_t flags) { assert_push_entry(); emplace_back(km_core_state_debug_item{ KM_CORE_DEBUG_BEGIN, flags, {*key_info, }, { }}); } inline void debug_items::push_end(uint16_t first_action, uint32_t flags) { assert_push_entry(); emplace_back(km_core_state_debug_item{ KM_CORE_DEBUG_END, flags, { }, { u"", nullptr, nullptr, { }, first_action, {} } }); } inline bool debug_items::is_enabled() const noexcept { return _is_enabled; } inline void debug_items::set_enabled(bool value) noexcept { _is_enabled = value; } } // namespace core } // namespace km keyman/core/src/debuglog.cpp0000664000000000000000000002750214600607066013260 0ustar /* Copyright: Copyright (C) 2003-2018 SIL International. Authors: mcdurdin */ #include #include #include #include #include "debuglog.h" namespace km { namespace core { namespace kmx { #define TAB "\t" #define NL "\n" /** * \def MEDIUM_BUF_SIZ not too big, not too small */ #define MEDIUM_BUF_SIZ (128 * 7) #ifdef _MSC_VER #define _USE_WINDOWS #endif #ifdef _USE_WINDOWS #define DECLSPEC_IMPORT __declspec(dllimport) #define WINBASEAPI DECLSPEC_IMPORT #define VOID void #define WINAPI __stdcall extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( char *lpOutputString ); #else #include #endif const struct modifier_names s_modifier_names[] = { {"LCTRL", 0x0001}, // Left Control flag {"RCTRL", 0x0002}, // Right Control flag {"LALT", 0x0004}, // Left Alt flag {"RALT", 0x0008}, // Right Alt flag {"SHIFT", 0x0010}, // Either shift flag {"CTRL-do-not-use", 0x0020}, // Either ctrl flag -- don't use this for inputs {"ALT-do-not-use", 0x0040}, // Either alt flag -- don't use this for inputs {"CAPS", 0x0100}, // Caps lock on {"NCAPS", 0x0200}, // Caps lock NOT on {"NUMLOCK", 0x0400}, // Num lock on {"NNUMLOCK", 0x0800}, // Num lock NOT on {"SCROLL", 0x1000}, // Scroll lock on {"NSCROLL", 0x2000}, // Scroll lock NOT on {NULL, 0} }; const char *s_key_names[] = { // Key Codes "K_?00", // &H0 "K_LBUTTON", // &H1 "K_RBUTTON", // &H2 "K_CANCEL", // &H3 "K_MBUTTON", // &H4 "K_?05", // &H5 "K_?06", // &H6 "K_?07", // &H7 "K_BKSP", // &H8 "K_TAB", // &H9 "K_?0A", // &HA "K_?0B", // &HB "K_KP5", // &HC "K_ENTER", // &HD "K_?0E", // &HE "K_?0F", // &HF "K_SHIFT", // &H10 "K_CONTROL", // &H11 "K_ALT", // &H12 "K_PAUSE", // &H13 "K_CAPS", // &H14 "K_KANJI?15", // &H15 "K_KANJI?16", // &H16 "K_KANJI?17", // &H17 "K_KANJI?18", // &H18 "K_KANJI?19", // &H19 "K_?1A", // &H1A "K_ESC", // &H1B "K_KANJI?1C", // &H1C "K_KANJI?1D", // &H1D "K_KANJI?1E", // &H1E "K_KANJI?1F", // &H1F "K_SPACE", // &H20 "K_PGUP", // &H21 "K_PGDN", // &H22 "K_END", // &H23 "K_HOME", // &H24 "K_LEFT", // &H25 "K_UP", // &H26 "K_RIGHT", // &H27 "K_DOWN", // &H28 "K_SEL", // &H29 "K_PRINT", // &H2A "K_EXEC", // &H2B "K_PRTSCN", // &H2C "K_INS", // &H2D "K_DEL", // &H2E "K_HELP", // &H2F "K_0", // &H30 "K_1", // &H31 "K_2", // &H32 "K_3", // &H33 "K_4", // &H34 "K_5", // &H35 "K_6", // &H36 "K_7", // &H37 "K_8", // &H38 "K_9", // &H39 "K_?3A", // &H3A "K_?3B", // &H3B "K_?3C", // &H3C "K_?3D", // &H3D "K_?3E", // &H3E "K_?3F", // &H3F "K_?40", // &H40 "K_A", // &H41 "K_B", // &H42 "K_C", // &H43 "K_D", // &H44 "K_E", // &H45 "K_F", // &H46 "K_G", // &H47 "K_H", // &H48 "K_I", // &H49 "K_J", // &H4A "K_K", // &H4B "K_L", // &H4C "K_M", // &H4D "K_N", // &H4E "K_O", // &H4F "K_P", // &H50 "K_Q", // &H51 "K_R", // &H52 "K_S", // &H53 "K_T", // &H54 "K_U", // &H55 "K_V", // &H56 "K_W", // &H57 "K_X", // &H58 "K_Y", // &H59 "K_Z", // &H5A "K_?5B", // &H5B "K_?5C", // &H5C "K_?5D", // &H5D "K_?5E", // &H5E "K_?5F", // &H5F "K_NP0", // &H60 "K_NP1", // &H61 "K_NP2", // &H62 "K_NP3", // &H63 "K_NP4", // &H64 "K_NP5", // &H65 "K_NP6", // &H66 "K_NP7", // &H67 "K_NP8", // &H68 "K_NP9", // &H69 "K_NPSTAR", // &H6A "K_NPPLUS", // &H6B "K_SEPARATOR", // &H6C "K_NPMINUS", // &H6D "K_NPDOT", // &H6E "K_NPSLASH", // &H6F "K_F1", // &H70 "K_F2", // &H71 "K_F3", // &H72 "K_F4", // &H73 "K_F5", // &H74 "K_F6", // &H75 "K_F7", // &H76 "K_F8", // &H77 "K_F9", // &H78 "K_F10", // &H79 "K_F11", // &H7A "K_F12", // &H7B "K_F13", // &H7C "K_F14", // &H7D "K_F15", // &H7E "K_F16", // &H7F "K_F17", // &H80 "K_F18", // &H81 "K_F19", // &H82 "K_F20", // &H83 "K_F21", // &H84 "K_F22", // &H85 "K_F23", // &H86 "K_F24", // &H87 "K_?88", // &H88 "K_?89", // &H89 "K_?8A", // &H8A "K_?8B", // &H8B "K_?8C", // &H8C "K_?8D", // &H8D "K_?8E", // &H8E "K_?8F", // &H8F "K_NUMLOCK", // &H90 "K_SCROLL", // &H91 "K_?92", // &H92 "K_?93", // &H93 "K_?94", // &H94 "K_?95", // &H95 "K_?96", // &H96 "K_?97", // &H97 "K_?98", // &H98 "K_?99", // &H99 "K_?9A", // &H9A "K_?9B", // &H9B "K_?9C", // &H9C "K_?9D", // &H9D "K_?9E", // &H9E "K_?9F", // &H9F "K_?A0", // &HA0 "K_?A1", // &HA1 "K_?A2", // &HA2 "K_?A3", // &HA3 "K_?A4", // &HA4 "K_?A5", // &HA5 "K_?A6", // &HA6 "K_?A7", // &HA7 "K_?A8", // &HA8 "K_?A9", // &HA9 "K_?AA", // &HAA "K_?AB", // &HAB "K_?AC", // &HAC "K_?AD", // &HAD "K_?AE", // &HAE "K_?AF", // &HAF "K_?B0", // &HB0 "K_?B1", // &HB1 "K_?B2", // &HB2 "K_?B3", // &HB3 "K_?B4", // &HB4 "K_?B5", // &HB5 "K_?B6", // &HB6 "K_?B7", // &HB7 "K_?B8", // &HB8 "K_?B9", // &HB9 "K_COLON", // &HBA "K_EQUAL", // &HBB "K_COMMA", // &HBC "K_HYPHEN", // &HBD "K_PERIOD", // &HBE "K_SLASH", // &HBF "K_BKQUOTE", // &HC0 "K_?C1", // &HC1 "K_?C2", // &HC2 "K_?C3", // &HC3 "K_?C4", // &HC4 "K_?C5", // &HC5 "K_?C6", // &HC6 "K_?C7", // &HC7 "K_?C8", // &HC8 "K_?C9", // &HC9 "K_?CA", // &HCA "K_?CB", // &HCB "K_?CC", // &HCC "K_?CD", // &HCD "K_?CE", // &HCE "K_?CF", // &HCF "K_?D0", // &HD0 "K_?D1", // &HD1 "K_?D2", // &HD2 "K_?D3", // &HD3 "K_?D4", // &HD4 "K_?D5", // &HD5 "K_?D6", // &HD6 "K_?D7", // &HD7 "K_?D8", // &HD8 "K_?D9", // &HD9 "K_?DA", // &HDA "K_LBRKT", // &HDB "K_BKSLASH", // &HDC "K_RBRKT", // &HDD "K_QUOTE", // &HDE "K_oDF", // &HDF "K_oE0", // &HE0 "K_oE1", // &HE1 "K_oE2", // &HE2 "K_oE3", // &HE3 "K_oE4", // &HE4 "K_?E5", // &HE5 "K_oE6", // &HE6 "K_?E7", // &HE7 "K_?E8", // &HE8 "K_oE9", // &HE9 "K_oEA", // &HEA "K_oEB", // &HEB "K_oEC", // &HEC "K_oED", // &HED "K_oEE", // &HEE "K_oEF", // &HEF "K_oF0", // &HF0 "K_oF1", // &HF1 "K_oF2", // &HF2 "K_oF3", // &HF3 "K_oF4", // &HF4 "K_oF5", // &HF5 "K_?F6", // &HF6 "K_?F7", // &HF7 "K_?F8", // &HF8 "K_?F9", // &HF9 "K_?FA", // &HFA "K_?FB", // &HFB "K_?FC", // &HFC "K_?FD", // &HFD "K_?FE", // &HFE "K_?FF" // &HFF }; // simulation of Windows GetTickCount() unsigned long GetTickCount() { using namespace std::chrono; return (unsigned long) duration_cast(steady_clock::now().time_since_epoch()).count(); } int DebugLog_1(const char *file, int line, const char *function, const char *fmt, ...) { char fmtbuf[256]; va_list vars; va_start(vars, fmt); vsnprintf(fmtbuf, sizeof(fmtbuf) / sizeof(fmtbuf[0]), fmt, vars); // I2248 // I3547 fmtbuf[255] = 0; va_end(vars); if (!g_debug_KeymanLog) return 0; char windowinfo[1024]; snprintf(windowinfo, 1024, "%ld" TAB //"TickCount" TAB "%s:%d" TAB //"SourceFile" TAB "%s" TAB //"Function" "%s", //"Message" GetTickCount(), //"TickCount" TAB file, line, //"SourceFile" TAB function, //"Function" TAB fmtbuf); //"Message" if (g_debug_ToConsole) { // I3951 ::std::cout << windowinfo << ::std::endl; // OutputDebugStringA(windowinfo); } else { #ifdef _USE_WINDOWS ::std::cout << windowinfo << ::std::endl; // OutputDebugStringA(windowinfo); #else syslog(LOG_DEBUG, "%s", windowinfo); #endif } return 0; } const char *Debug_ModifierName(KMX_UINT modifiers) { #ifdef _MSC_VER __declspec(thread) #endif static char buf[256]; buf[0] = 0; for(int i = 0; s_modifier_names[i].name; i++) if (modifiers & s_modifier_names[i].modifier) { strcat(buf, " "); strcat(buf, s_modifier_names[i].name); } if (*buf) return buf + 1; return "Unmodified"; } const char *Debug_VirtualKey(KMX_WORD vk) { #ifdef _MSC_VER __declspec(thread) #endif static char buf[256]; if (!ShouldDebug()) { return ""; } if (vk < 256) { snprintf(buf, 256, "['%s' 0x%x]", s_key_names[vk], vk); } else { snprintf(buf, 256, "[0x%x]", vk); } return buf; } const char *Debug_UnicodeString(PKMX_WCHAR s, int x) { if (!ShouldDebug()) { return ""; } #ifdef _MSC_VER __declspec(thread) #endif static char bufout[2][MEDIUM_BUF_SIZ]; KMX_WCHAR *p; char *q; bufout[x][0] = 0; for (p = s, q = bufout[x]; *p && (p - s < 128); p++) { snprintf(q, MEDIUM_BUF_SIZ - (q - bufout[x]), "U+%4.4X ", *p); q = strchr(q, 0); } //WideCharToMultiByte(CP_ACP, 0, buf, -1, bufout, 128, NULL, NULL); return bufout[x]; } const char *Debug_UnicodeString(::std::u16string s, int x) { if (!ShouldDebug()) { return ""; } #ifdef _MSC_VER __declspec(thread) #endif static char bufout[2][MEDIUM_BUF_SIZ]; auto p = s.begin(); char *q; bufout[x][0] = 0; for (q = bufout[x]; (intptr_t)(q-bufout[x]) < (128*7) && p != s.end(); p++) { snprintf(q, MEDIUM_BUF_SIZ - (q - bufout[x]), "U+%4.4X ", *p); q = strchr(q, 0); } return bufout[x]; } const char *Debug_UnicodeString(::std::u32string s, int x) { if (!ShouldDebug()) { return ""; } #ifdef _MSC_VER __declspec(thread) #endif static char bufout[2][MEDIUM_BUF_SIZ]; auto p = s.begin(); char *q; bufout[x][0] = 0; for (q = bufout[x]; (intptr_t)(q-bufout[x]) < (128*7) && p != s.end(); p++) { snprintf(q, MEDIUM_BUF_SIZ - (q - bufout[x]), "U+%4.6X ", (unsigned int)*p); q = strchr(q, 0); } return bufout[x]; } void write_console(KMX_BOOL error, const wchar_t *fmt, ...) { if (!g_silent || error) { va_list vars; va_start(vars, fmt); vwprintf(fmt, vars); va_end(vars); } } } } } keyman/core/src/debuglog.h0000664000000000000000000000373514600607066012727 0ustar /* Debugging */ #pragma once #include namespace km { namespace core { namespace kmx { extern KMX_BOOL g_debug_ToConsole, g_debug_KeymanLog, g_silent; struct modifier_names { const char *name; uint16_t modifier; }; extern const struct modifier_names s_modifier_names[]; extern const char *s_key_names[]; #ifdef _MSC_VER #define DebugLog(msg,...) (km::core::kmx::ShouldDebug() ? km::core::kmx::DebugLog_1(__FILE__, __LINE__, __FUNCTION__, (msg),__VA_ARGS__) : 0) #define DebugLog2(file,line,function,msg,...) (km::core::kmx::ShouldDebug() ? km::core::kmx::DebugLog_1(file, line, function, (msg),__VA_ARGS__) : 0) #define console_error(msg,...) write_console(TRUE, (msg), __VA_ARGS__) #define console_log(msg,...) write_console(FALSE, (msg), __VA_ARGS__) #else #define DebugLog(msg,...) (km::core::kmx::ShouldDebug() ? km::core::kmx::DebugLog_1(__FILE__, __LINE__, __FUNCTION__, (msg), ##__VA_ARGS__) : 0) #define DebugLog2(file,line,function,msg,...) (km::core::kmx::ShouldDebug() ? km::core::kmx::DebugLog_1(file, line, function, (msg), ##__VA_ARGS__) : 0) #define console_error(msg,...) write_console(TRUE, (msg), ##__VA_ARGS__) #define console_log(msg,...) write_console(FALSE, (msg), ##__VA_ARGS__) #endif int DebugLog_1(const char *file, int line, const char *function, const char *fmt, ...); const char *Debug_VirtualKey(KMX_WORD vk); /** * @param s PKMX_WCHAR to output * @param x temporary buffer (0 or 1) to write to * @return pointer to temporary buffer */ const char *Debug_UnicodeString(PKMX_WCHAR s, int x = 0); /** * @param s std::u16string to output * @param x temporary buffer (0 or 1) to write to * @return pointer to temporary buffer */ const char *Debug_UnicodeString(std::u16string s, int x = 0); const char *Debug_UnicodeString(std::u32string s, int x = 0); const char *Debug_ModifierName(KMX_UINT modifiers); inline KMX_BOOL ShouldDebug() { return g_debug_KeymanLog; } void write_console(KMX_BOOL error, const wchar_t *fmt, ...); } } } keyman/core/src/jsonpp.cpp0000664000000000000000000000672314600607066013003 0ustar /* Copyright: © 2011,2018 SIL International. Description: JSON pretty printer for dumping debug/diagnostic data structure. Create Date: 15 Dec 2011 Authors: Tim Eves (TSE) History: 28 Sep 2018 - TSE - Imported from graphite2 project. - TSE - Refactored to use C++ std::ostream. 25 Oct 2018 - TSE - Relicensed under the MIT license for inclusion in the Keyman project. */ #include #include #include #include "jsonpp.hpp" #if defined(_MSC_VER) #define FORMAT_INTMAX "%lli" #define FORMAT_UINTMAX "%llu" #else #define FORMAT_INTMAX "%ji" #define FORMAT_UINTMAX "%ju" #endif namespace { enum { seq = ',', obj='}', member=':', empty_obj='{', arr=']', empty_arr='[' }; } const std::nullptr_t json::null = nullptr; inline void json::context(const char current) throw() { _stream << *_context; indent(); *_context = current; } void json::indent(const int d) throw() { if (*_context == member || (_flatten && _flatten < _context)) _stream.put(' '); else _stream << std::endl << std::setw(4*int(_context - _contexts + d)) << ""; } inline void json::push_context(const char prefix, const char suffix) throw() { assert(_context - _contexts < ptrdiff_t(sizeof _contexts)); if (_context == _contexts) *_context = suffix; else context(suffix); *++_context = prefix; } void json::pop_context() throw() { assert(_context > _contexts); if (*_context == seq) indent(-1); else _stream.put(*_context); _stream.put(*--_context); if (_context == _contexts) _stream << std::endl; _stream.flush(); if (_flatten >= _context) _flatten = 0; *_context = seq; } // These four functions cannot be inlined as pointers to these // functions are needed for operator << (_context_t) to work. void json::flat(json & j) throw() { if (!j._flatten) j._flatten = j._context; } void json::close(json & j) throw() { j.pop_context(); } void json::object(json & j) throw() { j.push_context('{', '}'); } void json::array(json & j) throw() { j.push_context('[', ']'); } void json::item(json & j) throw() { while (j._context > j._contexts+1 && j._context[-1] != arr) j.pop_context(); } json & json::operator << (json::string s) throw() { const char ctxt = _context[-1] == obj ? *_context == member ? seq : member : seq; context(ctxt); _stream << '"' << s << '"'; if (ctxt == member) _stream.put(' '); return *this; } json & json::operator << (json::number f) throw() { context(seq); if (std::numeric_limits::infinity() == f) _stream << "Infinity"; else if (-std::numeric_limits::infinity() == f) _stream << "-Infinity"; else if (std::numeric_limits::quiet_NaN() == f || std::numeric_limits::signaling_NaN() == f) _stream << "NaN"; else _stream << f; return *this; } json & json::operator << (json::integer d) throw() { context(seq); _stream << intmax_t(d); return *this; } json & json::operator << (json::integer_u d) throw(){ context(seq); _stream << uintmax_t(d); return *this; } json & json::operator << (json::boolean b) throw() { context(seq); _stream << (b ? "true" : "false"); return *this; } json & json::operator << (std::nullptr_t) throw() { context(seq); _stream << "null"; return *this; } keyman/core/src/jsonpp.hpp0000664000000000000000000001106614600607066013004 0ustar /* Copyright: © 2011,2018 SIL International. Description: JSON pretty printer for dumping debug/diagnostic internal state information. Create Date: 15 Dec 2011 Authors: Tim Eves (TSE) History: 28 Sep 2018 - TSE - Imported from graphite2 project. - TSE - Refactored to use C++ std::ostream. 25 Oct 2018 - TSE - Relicensed under the MIT license for inclusion in the Keyman project. */ #pragma once #include #include #include #include "utfcodec.hpp" class json { // Prevent copying json(const json &); json & operator = (const json &); typedef void (*_context_t)(json &); std::ostream& _stream; char _contexts[128], // context stack * _context, // current context (top of stack) * _flatten; // if !0 points to context above which // pretty printed output should occur. std::vector _env; void context(const char current) throw(); void indent(const int d=0) throw(); void push_context(const char, const char) throw(); void pop_context() throw(); public: class closer; using string = const char *; using number = double; enum class integer : std::intmax_t {}; enum class integer_u : std::uintmax_t {}; using boolean = bool; static const std::nullptr_t null; void setenv(unsigned int index, void *val) { _env.reserve(index + 1); if (index >= _env.size()) _env.insert(_env.end(), _env.size() - index + 1, 0); _env[index] = val; } void *getenv(unsigned int index) const { return _env[index]; } const std::vector &getenvs() const { return _env; } static void flat(json &) throw(); static void close(json &) throw(); static void object(json &) throw(); static void array(json &) throw(); static void item(json &) throw(); json(std::ostream& stream) throw(); ~json() throw (); auto & stream() const throw(); json & operator << (string) throw(); json & operator << (number) throw(); json & operator << (integer) throw(); json & operator << (integer_u) throw(); json & operator << (boolean) throw(); json & operator << (std::nullptr_t) throw(); json & operator << (_context_t) throw(); operator bool() const throw(); bool good() const throw(); bool eof() const throw(); }; class json::closer { // Prevent copying. closer(const closer &); closer & operator = (const closer &); json * const _j; public: closer(json * const j) : _j(j) {} ~closer() throw() { if (_j) *_j << close; } }; inline json::json(std::ostream& s) throw() : _stream(s), _context(_contexts), _flatten(0) { if (_stream.good()) _stream.flush(); } inline json::~json() throw () { while (_context > _contexts) pop_context(); } inline auto & json::stream() const throw() { return _stream; } inline json & json::operator << (json::_context_t ctxt) throw() { ctxt(*this); return *this; } template inline json & operator << (json & j, std::basic_string const & s) throw() { return j << json::string(convert(s).c_str()); } template inline json & operator << (json & j, C const * s) throw() { return j << json::string(convert(s).c_str()); } inline json & operator << (json & j, signed char d) throw() { return j << json::integer(d); } inline json & operator << (json & j, unsigned char d) throw() { return j << json::integer_u(d); } inline json & operator << (json & j, short int d) throw() { return j << json::integer(d); } inline json & operator << (json & j, unsigned short int d) throw() { return j << json::integer_u(d); } inline json & operator << (json & j, int d) throw() { return j << json::integer(d); } inline json & operator << (json & j, unsigned int d) throw() { return j << json::integer_u(d); } inline json & operator << (json & j, long int d) throw() { return j << json::integer(d); } inline json & operator << (json & j, unsigned long int d) throw() { return j << json::integer_u(d); } inline json & operator << (json & j, long long int d) throw() { return j << json::integer(d); } inline json & operator << (json & j, unsigned long long int d) throw() { return j << json::integer_u(d); } inline json::operator bool() const throw() { return good(); } inline bool json::good() const throw() { return _stream.good(); } inline bool json::eof() const throw() { return _stream.eof(); } keyman/core/src/keyboard.cpp0000664000000000000000000000330414600607066013262 0ustar /* Copyright: © 2018 SIL International. Description: Internal keyboard class and adaptor class for the API. Create Date: 2 Oct 2018 Authors: Tim Eves (TSE) History: 7 Oct 2018 - TSE - Refactored out of km_core_keyboard_api.cpp */ #include "keyboard.hpp" #include "jsonpp.hpp" using namespace km::core; inline void keyboard_attributes::render() { // Make attributes point to the stored values above. id = _keyboard_id.c_str(); version_string = _version_string.c_str(); folder_path = _folder_path.c_str(); default_options = _default_opts.data(); } keyboard_attributes::keyboard_attributes(std::u16string const & kbid, std::u16string const & version, path_type const & path, options_store const &opts) : _keyboard_id(kbid), _version_string(version), _folder_path(path), _default_opts(opts) { // Ensure that the default_options array will be properly terminated. _default_opts.emplace_back(); render(); } keyboard_attributes::keyboard_attributes(keyboard_attributes &&rhs) : _keyboard_id(std::move(rhs._keyboard_id)), _version_string(std::move(rhs._version_string)), _folder_path(std::move(rhs._folder_path)), _default_opts(std::move(rhs._default_opts)) { rhs.id = rhs.version_string = nullptr; render(); } keyboard_attributes & keyboard_attributes::operator = (keyboard_attributes &&rhs) { return *new (this) keyboard_attributes(std::move(rhs)); } json & km::core::operator << (json & j, km::core::keyboard_attributes const & kb) { j << json::object << "id" << kb.id << "folder" << kb._folder_path << "version" << kb.version_string << "rules" << json::array << json::close; return j << json::close; } keyman/core/src/keyboard.hpp0000664000000000000000000000334514600607066013274 0ustar /* Copyright: © 2018 SIL International. Description: Internal keyboard class and adaptor class for the API. Create Date: 2 Oct 2018 Authors: Tim Eves (TSE) History: 2 Oct 2018 - TSE - Refactored out of km_core_keyboard_api.cpp */ #pragma once #include #include #include "keyman_core.h" #include "option.hpp" #include "path.hpp" // Forward declarations class json; namespace km { namespace core { class keyboard_attributes : public km_core_keyboard_attrs { std::u16string _keyboard_id; std::u16string _version_string; core::path _folder_path; std::vector