Merge remote-tracking branch 'origin/master' into chore/developer/update-jszip

This commit is contained in:
Darcy Wong 2021-10-04 08:15:01 +07:00
commit 488309eb76
136 changed files with 3090 additions and 443 deletions

View file

@ -64,4 +64,4 @@ labels:
- label: 'cherry-pick'
matcher:
title: '\(🍒|:cherries:\)'
title: '(🍒|:cherries:)'

View file

@ -12,7 +12,7 @@ jobs:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
- name: Update labels based on PR title
id: labeler
uses: fuxingloh/multi-labeler@8afa186ed03230c98fe24ebf9fe35093072ad46e
uses: fuxingloh/multi-labeler@8afa186ed03230c98fe24ebf9fe35093072ad46e # v1.4.0
with:
github-token: ${{secrets.GITHUB_TOKEN}}
config-path: .github/multi-labeler.yml

View file

@ -1,5 +1,24 @@
# Keyman Version History
## 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)

View file

@ -1 +1 @@
15.0.121
15.0.124

View file

@ -18,6 +18,10 @@
<string name="action_install_updates" comment="Menu notification that keyboard or dictionary updates available">ማሻሻያዎችን ይጫኑ</string>
<!-- Context: Title -->
<string name="title_version" comment="Title of Keyman for Android version">ስሪት %1$s</string>
<!-- Context: Text label when old Chrome version installed -->
<string name="text_require_chrome_57" comment="Banner text when old version of Chrome is installed">ኪይማን የክሮም ስሪትን 57 ወይም አዲስ ይፈልጋል።</string>
<!-- Context: Button label -->
<string name="button_update_chrome" comment="Prompt to upgrade Chrome in the Play Store">ክሮምን ማዘመን</string>
<!-- Context: Textfield prompt (&#8230; is the ellipsis character "...") -->
<string name="textview_hint" comment="Prompt to start typing">እዚህ ጋር መጻፍ ይጀምሩ &#8230;</string>
<!-- Context: Splash screen (version/copyright info currently disabled -->
@ -37,11 +41,11 @@
<!-- Context: Get Started menu -->
<string name="enable_system_keyboard" comment="Menu item to enable Keyman as system keyboard">ኪይማኑን ለሲስተም ኪቦርድ እንዲሆን ያድርጉ</string>
<!-- Context: Get Started menu -->
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">ኪማኑን መደበና የፊደል ገበታ ይሰይሙ</string>
<string name="set_keyman_as_default" comment="Menu item to set Keyman as default system keyboard">ኪማኑን መደበኛ የፊደል ገበታ ይሰይሙ</string>
<!-- Context: Get Started menu -->
<string name="more_info" comment="Open the Keyman for Android help page">ተጨማሪ መረጃ</string>
<!-- Context: Get Started menu -->
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">በሚነሳበት ሰአት ይታይ\"%1$s\"</string>
<string name="show_get_started" comment="Show the &quot;Get Started&quot; menu on startup">በሚነሳበት ሰአት ይታይ \"%1$s\"</string>
<!-- Context: Android Storage Permission -->
<string name="request_storage_permission" comment="Request storage permission to access keyboard packages">የፊደል ገበታውን ሰሌዳ ጥቅሎችን ለመጫን ለኪይማኑ ውጫዊ ማከማቻ ለማንበብ ፈቃድ ይስጡት።</string>
<!-- Context: Android Storage Permission -->
@ -50,13 +54,33 @@
<string name="keyman_settings" comment="Settings menu title">አደረጃጀት</string>
<!-- Context: Keyman Settings menu -->
<plurals name="installed_languages">
<item quantity="one">የተጫኑ ቋንዎች (%1$d)</item>
<item quantity="one">የተጫኑ ቋንቋዎች (%1$d)</item>
<item quantity="other">የተጫኑ ቋንዎች (%1$d)</item>
</plurals>
<!-- Context: Keyman Settings menu -->
<string name="install_keyboard_or_dictionary" comment="Menu item to install keyboard or dictionary">የተጫነ የፊደል ገበታ ወይም መዝገበ ቃላት</string>
<!-- Context: Keyman Settings menu -->
<string name="change_display_language" comment="Menu action to change interface language">የኪማኑን የገጽታ ቋንቋ ይቀይሩ</string>
<string name="change_display_language" comment="Menu action to change interface language">የገጽታ ቋንቋ</string>
<!-- Context: Keyman Settings menu -->
<string name="adjust_keyboard_height" comment="Menu action to adjust keyboard height">የቋንቋ ገበታውን ቁመት ማስተካከል</string>
<!-- Context: Keyman Settings menu -->
<string name="spacebar_caption" comment="Menu action to set the spacebar caption">የስፔስባሩ መግለጫ ጽሁፍ</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_keyboard" comment="Spacebar caption option - keyboard">የፊደል ገበታ</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language" comment="Spacebar caption option - language">ቋንቋ</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_language_keyboard" comment="Spacebar caption option - language + keyboard">ቋንቋና የፊደል ገበታ</string>
<!-- Context: Keyman Settings menu / Spacebar caption -->
<string name="spacebar_caption_blank" comment="Spacebar caption option - blank">ባዶ</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_keyboard" comment="Spacebar caption hint - keyboard">የፊደል ገበታ ሰሌዳውን በስፔስ ባሩ ላይ አሳይ</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language" comment="Spacebar caption hint - language">የቋንቋውን ስም በስፔስ ባሩ ላይ አሳይ</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_language_keyboard" comment="Spacebar caption hint - language + keyboard">ቋንቋና የፊደል ገበታውን በስፔስ ባሩ ላይ</string>
<!-- Context: Keyman Settings menu / Spacebar caption hint -->
<string name="spacebar_caption_hint_blank" comment="Spacebar caption hint - blank">የስፔስባሩ መግለጫ ጽሁፍ አታሳይ</string>
<!-- Context: Keyman Settings menu -->
<string name="show_banner" comment="text suggestions banner">ሁልጊዜ ባነሩን አሳይ</string>
<!-- Context: Keyman Settings menu -->
@ -87,6 +111,12 @@
<string name="added_language_to_keyboard" comment="Notification that a language name is added to a keyboard">%1$s የተጨመረ ቋንቋ %2$s</string>
<!-- Context: Select Package and Select Languages menu -->
<string name="all_languages_installed" comment="Text when all languages from a keyboard package have been installed">ሁሉም ቋንቋዎች ቀደም ሲል ተጭኗል</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="drag_the_keyboard" comment="First line of adjusting keyboard height">የፊደል ገበታ ሰሌዳውን በመጎተት ቁመቱን አስተካክል</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="rotate_the_device" comment="Second line of adjusting keyboard height">ዲቫይሱን በማሽከርከር ፖርትሬቱንና ላንድስኬፑን አስተካክል</string>
<!-- Context: Adjust Keyboard Height menu -->
<string name="reset_to_defaults" comment="Button to reset to default heights">ወደ ቀደመው ሴቲንግ መልስ</string>
<!-- Context: Keyman Web Browser -->
<string name="hint_text" comment="Prompt to type in the browser search bar">ፈልግ ወይም URL ጻፍ</string>
<!-- Context: Keyman Web Browser -->

View file

@ -24,6 +24,10 @@
<!-- Context: Button label -->
<string name="label_close_keyman" comment="Close the Keyman application">ኪይማኑን ዝጋ</string>
<!-- Context: Button label -->
<string name="label_forward" comment="Button to go forward">ወደፊት</string>
<!-- Context: Button label -->
<string name="label_next_input_method" comment="Switch to next input method (replaces label_close_keyman)">የሚቀጥለውን የመቀበያ ዘዴ</string>
<!-- Context: Button label -->
<string name="label_download" comment="Button to confirm downloading an item">ወርዷል</string>
<!-- Context: Button label -->
<string name="label_install" comment="Confirmation to install a package">ጫን</string>
@ -69,6 +73,8 @@
<string name="fileprovider_undefined" comment="FileProvider library needed to view help file">የእገዛ ፋይልን ለማየት ፋይል ፕሮቫይደሩ ቤተ መጽሐፍት ያስፈልገዋል %1$s</string>
<!-- Context: Fatal keyboard error. Will load default keyboard -->
<string name="fatal_keyboard_error" comment="Fatal keyboard error (keyboard ID::packageID for language). Will load default keyboard">የገበታ ሰሌዳ ፋታል ችግር ዝርዝር %1$s:%2$s ለ %3$s ቋንቋ፤ መደበኛ ቋንቋ ጭኗል።</string>
<!-- Context: Fatal keyboard error. -->
<string name="fatal_keyboard_error_short" comment="Error in keyboard (keyboard ID::packageID for language).">የፊደል ገበታ ሰሌዳው ችግር %1$s:%2$s ለ %3$s ቋንቋ።</string>
<!-- Context: Query for associated dictionary -->
<string name="query_associated_model" comment="Check if there's an available dictionary to download">ተያያዥነት ያለውን መዝገበ ቃላት ለመጫን እየፈተሸ ነው።</string>
<!-- Context: Model Updates -->

View file

@ -70,14 +70,7 @@ cd %KEYMAN_ROOT%\common\core\desktop
set BUILDTYPE=%2
if "%3" == "--static" (
set STATIC_LIBRARY=--default-library static
shift
) else (
set STATIC_LIBRARY=
)
echo "Is static build = !STATIC_LIBRARY! (%3)"
set STATIC_LIBRARY=--default-library both
if "%3" == "build" (
echo === Calling meson build for Windows !ARCH! !BUILDTYPE! ===

View file

@ -9,7 +9,8 @@ project('keyboardprocessor', 'cpp', 'c',
version: run_command(find_program('getversion.bat', 'getversion.sh')).stdout().strip(),
license: 'MIT',
default_options : ['buildtype=release',
'cpp_std=c++14'])
'cpp_std=c++14',
'b_vscrt=static_from_buildtype'])
message('meson.project_version(): ' + meson.project_version() + '\n')
compiler = meson.get_compiler('cpp')

View file

@ -59,7 +59,7 @@ const unsigned long CRCTable[256] = {
* and returns the updated value.
*/
unsigned long CalculateBufferCRC(unsigned long count, KMX_BYTE *p)
static unsigned long CalculateBufferCRC(unsigned long count, KMX_BYTE *p)
{
unsigned long temp1;
unsigned long temp2;

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/input-processor",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/input-processor",
"version": "15.0.121",
"version": "15.0.124",
"description": "The core text and prediction processing engine for KeymanWeb",
"repository": {
"type": "git",
@ -18,8 +18,8 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/lexical-model-compiler": "^15.0.121",
"@keymanapp/resources-gosh": "^15.0.121",
"@keymanapp/lexical-model-compiler": "^15.0.124",
"@keymanapp/resources-gosh": "^15.0.124",
"@types/node": "^11.9.4",
"chai": "^4.3.4",
"mocha": "^8.4.0",
@ -34,11 +34,11 @@
"mocha": "mocha"
},
"dependencies": {
"@keymanapp/keyboard-processor": "^15.0.121",
"@keymanapp/lexical-model-layer": "^15.0.121",
"@keymanapp/models-types": "^15.0.121",
"@keymanapp/web-environment": "^15.0.121",
"@keymanapp/web-utils": "^15.0.121",
"@keymanapp/keyboard-processor": "^15.0.124",
"@keymanapp/lexical-model-layer": "^15.0.124",
"@keymanapp/models-types": "^15.0.124",
"@keymanapp/web-environment": "^15.0.124",
"@keymanapp/web-utils": "^15.0.124",
"eventemitter3": "^4.0.0"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/keyboard-processor",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/keyboard-processor",
"version": "15.0.121",
"version": "15.0.124",
"description": "Core module for Keyman keyboard support in KeymanWeb.",
"repository": {
"type": "git",
@ -18,7 +18,7 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/resources-gosh": "^15.0.121",
"@keymanapp/resources-gosh": "^15.0.124",
"chai": "^4.3.4",
"mocha": "^8.4.0",
"mocha-teamcity-reporter": "^4.0.0",
@ -32,9 +32,9 @@
"mocha": "mocha"
},
"dependencies": {
"@keymanapp/models-types": "^15.0.121",
"@keymanapp/web-environment": "^15.0.121",
"@keymanapp/web-utils": "^15.0.121",
"@keymanapp/models-types": "^15.0.124",
"@keymanapp/web-environment": "^15.0.124",
"@keymanapp/web-utils": "^15.0.124",
"@types/node": "^11.9.4"
}
}

View file

@ -20,9 +20,14 @@ namespace com.keyman.keyboards {
CALIBRATED = 2
}
export interface VariableStoreDictionary {
[name: string]: string;
};
/**
* Acts as a wrapper class for Keyman keyboards compiled to JS, providing type information
* and keyboard-centered functionality in an object-oriented way without modifying the
* and keyboard-centered functionality in an object-oriented way without modifying the
* wrapped keyboard itself.
*/
export class Keyboard {
@ -37,7 +42,7 @@ namespace com.keyman.keyboards {
/**
* This is the object provided to KeyboardInterface.registerKeyboard - that is, the keyboard
* being wrapped.
*
*
* TODO: Make this private instead. But there are a LOT of references that must be rooted out first.
*/
public readonly scriptObject: any;
@ -71,6 +76,51 @@ namespace com.keyman.keyboards {
return this.scriptObject['KN'];
}
/**
* Cache variable store values
*
* Primarily used for predictive text to prevent variable store
* values from being changed in 'fat finger' processing.
*
* KVS is available in keyboards compiled with Keyman Developer 15
* and later versions. See #2924.
*
* @returns an object with each property referencing a variable store
*/
get variableStores(): VariableStoreDictionary {
const storeNames = this.scriptObject['KVS'];
let values = {};
if(Array.isArray(storeNames)) {
for(let store of storeNames) {
values[store] = this.scriptObject[store];
}
}
return values;
}
/**
* Restore variable store values from cache
*
* KVS is available in keyboards compiled with Keyman Developer 15
* and later versions. See #2924.
*
* @param values name-value pairs for each store value
*/
set variableStores(values: VariableStoreDictionary) {
const storeNames = this.scriptObject['KVS'];
if(Array.isArray(storeNames)) {
for(let store of storeNames) {
// If the value is not present in the cache, don't overwrite it;
// while this is not used in initial implementation, we could use
// it in future to update a single variable store value rather than
// the whole cache.
if(typeof values[store] == 'string') {
this.scriptObject[store] = values[store];
}
}
}
}
// TODO: Better typing.
private get _legacyLayoutSpec(): any {
return this.scriptObject['KV']; // used with buildDefaultLayout; layout must be constructed at runtime.
@ -99,7 +149,7 @@ namespace com.keyman.keyboards {
/**
* HTML help text, as specified by either the &kmw_helptext or &kmw_helpfile system stores.
*
*
* Reference: https://help.keyman.com/developer/language/reference/kmw_helptext,
* https://help.keyman.com/developer/language/reference/kmw_helpfile
*/
@ -121,7 +171,7 @@ namespace com.keyman.keyboards {
* Embeds a custom script for use by the OSK, which may be interactive (like with sil_euro_latin).
* Note: this must be called AFTER any contents of `helpText` have been inserted into the DOM.
* (See sil_euro_latin's source -> sil_euro_latin_js.txt)
*
*
* Reference: https://help.keyman.com/developer/language/reference/kmw_embedjs
*/
embedScript(e: any) {
@ -136,10 +186,10 @@ namespace com.keyman.keyboards {
/**
* true if this keyboard uses a (legacy) pick list (Chinese, Japanese, Korean, etc.)
*
*
* TODO: Make a property on keyboards (say, `isPickList` / `KPL`) to signal this when we
* get around to better, generalized picker-list support.
*/
*/
get isCJK(): boolean { // I3363 (Build 301)
var lg: string;
if(typeof(this.scriptObject['KLC']) != 'undefined') {
@ -147,7 +197,7 @@ namespace com.keyman.keyboards {
} else if(typeof(this.scriptObject['LanguageCode']) != 'undefined') {
lg = this.scriptObject['LanguageCode'];
}
// While some of these aren't proper BCP-47 language codes, the CJK keyboards predate our use of BCP-47.
// So, we preserve the old ISO 639-3 codes, as that's what the keyboards are matching against.
return ((lg == 'cmn') || (lg == 'jpn') || (lg == 'kor'));
@ -186,7 +236,7 @@ namespace com.keyman.keyboards {
this.scriptObject['_kmw'] = tag;
}
return tag;
return tag;
}
get explodedStores(): {[storeName: string]: text.ComplexKeyboardStore} {
@ -209,7 +259,7 @@ namespace com.keyman.keyboards {
if(this._legacyLayoutSpec == null) {
return false;
}
// Only exists in KMW 10.0+, but before that Web had no chirality support, so... return false.
let layers = this._legacyLayoutSpec['KLS'];
if(!layers) {
@ -219,18 +269,18 @@ namespace com.keyman.keyboards {
var emulationMask = modifierCodes['LCTRL'] | modifierCodes['LALT'];
var unshiftedEmulationLayer = layers[Layouts.getLayerId(emulationMask)];
var shiftedEmulationLayer = layers[Layouts.getLayerId(modifierCodes['SHIFT'] | emulationMask)];
// buildDefaultLayout ensures that these are aliased to the original modifier set being emulated.
// As a result, we can directly test for reference equality.
//
// This allows us to still return `true` after creating the layers for emulation; during keyboard
// construction, the two layers should be null for AltGr emulation to succeed.
if(unshiftedEmulationLayer != null &&
if(unshiftedEmulationLayer != null &&
unshiftedEmulationLayer != layers[Layouts.getLayerId(modifierCodes['RALT'])]) {
return false;
}
if(shiftedEmulationLayer != null &&
if(shiftedEmulationLayer != null &&
shiftedEmulationLayer != layers[Layouts.getLayerId(modifierCodes['RALT'] | modifierCodes['SHIFT'])]) {
return false;
}
@ -273,9 +323,9 @@ namespace com.keyman.keyboards {
/**
* @param {number} _PCommand event code (16,17,18) or 0
* @param {Object} _PTarget target element
* @param {number} _PData 1 or 0
* @param {number} _PData 1 or 0
* Notifies keyboard of keystroke or other event
*/
*/
notify(_PCommand: number, _PTarget: text.OutputTarget, _PData: number) { // I2187
// Good example use case - the Japanese CJK-picker keyboard
if(typeof(this.scriptObject['KNS']) == 'function') {
@ -318,7 +368,7 @@ namespace com.keyman.keyboards {
rawSpecifications = {'F':'Tahoma', 'BK': Layouts.dfltText};
}
// Regardless of success, we'll want to initialize the field that backs the property;
// Regardless of success, we'll want to initialize the field that backs the property;
// may as well cache the default layout we just built, or a 'null' if it shouldn't exist..
if(!this._layouts) {
this._layouts = {};
@ -339,7 +389,7 @@ namespace com.keyman.keyboards {
/**
* Returns an ActiveLayout object representing the keyboard's layout for this form factor. May return null if a custom desktop "help" OSK is defined, as with sil_euro_latin.
*
*
* In such cases, please use either `helpText` or `insertHelpHTML` instead.
* @param formFactor {string} The desired form factor for the layout.
*/

View file

@ -972,6 +972,9 @@ namespace com.keyman.text {
// Capture the initial state of the OutputTarget before any rules are matched.
let preInput = Mock.from(outputTarget);
// Capture the initial state of any variable stores
const cachedVariableStores = this.activeKeyboard.variableStores;
// Establishes the results object, allowing corresponding commands to set values here as appropriate.
this.ruleBehavior = new RuleBehavior();
@ -987,6 +990,12 @@ namespace com.keyman.text {
// Finalize the rule's results.
this.ruleBehavior.transcription = outputTarget.buildTranscriptionFrom(preInput, keystroke);
// We always backup the changes to variable stores to the RuleBehavior, to
// be applied during finalization, then restore them to the cached initial
// values to avoid side-effects with predictive text mocks.
this.ruleBehavior.variableStores = this.activeKeyboard.variableStores;
this.activeKeyboard.variableStores = cachedVariableStores;
// `matched` refers to whether or not the FINAL rule (from any group) matched, rather than
// whether or not ANY rule matched. If the final rule doesn't match, we trigger the key's
// default behavior (if appropriate).
@ -1001,6 +1010,19 @@ namespace com.keyman.text {
return behavior;
}
/**
* Applies the dictionary of variable store values to the active keyboard
*
* Has no effect on keyboards compiled with 14.0 or earlier; system store
* names are not exposed unless compiled with Developer 15.0 or later.
*
* @param stores A dictionary of stores which should be found in the
* keyboard
*/
applyVariableStores(stores: com.keyman.keyboards.VariableStoreDictionary): void {
this.activeKeyboard.variableStores = stores;
}
/**
* Publishes the KeyboardInterface's shorthand API names. As this assigns the current functions
* held by the longform versions, note that this should be called after replacing any of them via

View file

@ -24,6 +24,11 @@ namespace com.keyman.text {
*/
saveStore: {[name: string]: VariableStore} = {};
/**
* A set of variable stores with possible changes to be applied during finalization.
*/
variableStores: keyboards.VariableStoreDictionary = {};
/**
* Denotes a non-output default behavior; this should be evaluated later, against the true keystroke.
*/
@ -46,9 +51,9 @@ namespace com.keyman.text {
/**
* In reference to https://github.com/keymanapp/keyman/pull/4350#issuecomment-768753852:
*
* If the final group processed is a context and keystroke group (using keys),
* and there is no nomatch rule, and the keystroke is not matched in the group,
*
* If the final group processed is a context and keystroke group (using keys),
* and there is no nomatch rule, and the keystroke is not matched in the group,
* the keystroke's default behavior should trigger, regardless of whether or not any
* rules in prior groups matched.
*/
@ -78,6 +83,8 @@ namespace com.keyman.text {
}
}
processor.keyboardInterface.applyVariableStores(this.variableStores);
if(processor.keyboardInterface.variableStoreSerializer) {
for(let storeID in this.saveStore) {
processor.keyboardInterface.variableStoreSerializer.saveStore(processor.activeKeyboard.id, storeID, this.saveStore[storeID]);
@ -99,13 +106,13 @@ namespace com.keyman.text {
/**
* Merges default-related behaviors from another RuleBehavior into this one. Assumes that the current instance
* "came first" chronologically. Both RuleBehaviors must be sourced from the same keystroke.
*
*
* Intended use: merging rule-based behavior with default key behavior during scenarios like those described
* at https://github.com/keymanapp/keyman/pull/4350#issuecomment-768753852.
*
*
* This function does not attempt a "complete" merge for two fully-constructed RuleBehaviors! Things
* WILL break for unintended uses.
* @param other
* @param other
*/
mergeInDefaults(other: RuleBehavior) {
let keystroke = this.transcription.keystroke;
@ -115,7 +122,7 @@ namespace com.keyman.text {
}
this.triggersDefaultCommand = this.triggersDefaultCommand || other.triggersDefaultCommand;
let mergingMock = Mock.from(this.transcription.preInput);
mergingMock.apply(this.transcription.transform);
mergingMock.apply(other.transcription.transform);

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/recorder-core",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/recorder-core",
"version": "15.0.121",
"version": "15.0.124",
"description": "Core classes used to develop KeymanWeb test cases based on keystrokes",
"main": "index.js",
"scripts": {
@ -17,10 +17,10 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"dependencies": {
"@keymanapp/keyboard-processor": "^15.0.121",
"@keymanapp/models-types": "^15.0.121",
"@keymanapp/web-environment": "^15.0.121",
"@keymanapp/web-utils": "^15.0.121",
"@keymanapp/keyboard-processor": "^15.0.124",
"@keymanapp/models-types": "^15.0.124",
"@keymanapp/web-environment": "^15.0.124",
"@keymanapp/web-utils": "^15.0.124",
"@types/node": "^11.9.4"
},
"devDependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-sentry-manager",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-sentry-manager",
"version": "15.0.121",
"version": "15.0.124",
"description": "Common setup for KeymanWeb's Sentry-based error reporting",
"main": "dist/index.js",
"scripts": {
@ -20,7 +20,7 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@keymanapp/web-environment": "^15.0.121",
"@keymanapp/web-environment": "^15.0.124",
"@sentry/browser": "^5.27.4"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-utils",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-utils",
"version": "15.0.121",
"version": "15.0.124",
"description": "Common utility functions used throughout other Keyman packages",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
@ -20,8 +20,8 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/resources-gosh": "^15.0.121",
"@keymanapp/web-environment": "^15.0.121",
"@keymanapp/resources-gosh": "^15.0.124",
"@keymanapp/web-environment": "^15.0.124",
"@types/node": "^14.0.5",
"typescript": "^3.8.3"
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-templates",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-templates",
"version": "15.0.121",
"version": "15.0.124",
"description": "Backing model implementations (templates) for Keyman's modelling layer",
"keywords": [
"lm",
@ -42,8 +42,8 @@
"url": "https://github.com/keymanapp/keyman/issues"
},
"devDependencies": {
"@keymanapp/models-types": "^15.0.121",
"@keymanapp/web-utils": "^15.0.121",
"@keymanapp/models-types": "^15.0.124",
"@keymanapp/web-utils": "^15.0.124",
"@types/chai": "^4.2.11",
"@types/mocha": "^7.0.2",
"@types/node": "^14.0.4",
@ -52,6 +52,6 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@keymanapp/models-wordbreakers": "^15.0.121"
"@keymanapp/models-wordbreakers": "^15.0.124"
}
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-types",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-types",
"version": "15.0.121",
"version": "15.0.124",
"description": "Type definitions in used in the modeling (lexical model/predictive text) component of Keyman.",
"types": "./index.d.ts",
"scripts": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-wordbreakers",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/models-wordbreakers",
"version": "15.0.121",
"version": "15.0.124",
"description": "Word breakers bundled in the modeling layer",
"keywords": [
"lexical model",
@ -40,7 +40,7 @@
"url": "https://github.com/keymanapp/keyman/issues"
},
"devDependencies": {
"@keymanapp/models-types": "^15.0.121",
"@keymanapp/models-types": "^15.0.124",
"@types/chai": "^4.2.11",
"@types/mocha": "^7.0.2",
"chai": "^4.3.4",

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-layer",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-layer",
"version": "15.0.121",
"version": "15.0.124",
"description": "Keyman/Predictive Text integration layer",
"main": "build/index.js",
"scripts": {
@ -21,8 +21,8 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/models-types": "^15.0.121",
"@keymanapp/resources-gosh": "^15.0.121",
"@keymanapp/models-types": "^15.0.124",
"@keymanapp/resources-gosh": "^15.0.124",
"@types/node": "^10.17.21",
"chai": "^4.3.4",
"karma": "^6.3.4",
@ -46,10 +46,10 @@
"typescript": "^3.8.3"
},
"dependencies": {
"@keymanapp/models-templates": "^15.0.121",
"@keymanapp/models-wordbreakers": "^15.0.121",
"@keymanapp/web-environment": "^15.0.121",
"@keymanapp/web-utils": "^15.0.121",
"@keymanapp/models-templates": "^15.0.124",
"@keymanapp/models-wordbreakers": "^15.0.124",
"@keymanapp/web-environment": "^15.0.124",
"@keymanapp/web-utils": "^15.0.124",
"es6-shim": "^0.35.5",
"string.prototype.codepointat": "^0.2.1",
"string.prototype.startswith": "^0.2.0"

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-compiler",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/lexical-model-compiler",
"version": "15.0.121",
"version": "15.0.124",
"description": "Keyman Developer lexical model compiler",
"keywords": [
"keyboard",
@ -37,14 +37,14 @@
"node": ">=12.0.0"
},
"dependencies": {
"@keymanapp/models-types": "^15.0.121",
"@keymanapp/models-types": "^15.0.124",
"commander": "^3.0.0",
"typescript": "^3.8.3",
"xml2js": "^0.4.19"
},
"devDependencies": {
"@keymanapp/models-templates": "^15.0.121",
"@keymanapp/models-wordbreakers": "^15.0.121",
"@keymanapp/models-templates": "^15.0.124",
"@keymanapp/models-wordbreakers": "^15.0.124",
"@types/chai": "^4.1.7",
"@types/mocha": "^5.2.7",
"@types/node": "^10.14.6",

View file

@ -49,6 +49,12 @@
/* Confirmation text to display before uninstalling a lexical model */
"command-uninstall-lexical-model-confirm" = "ይህንን መዝገበ ቃላት ልታጠፋው ትፈልጋለህ?";
/* Text for error when a keyboard cannot load properly */
"error-loading-keyboard" = "የተጠየቀው የፊደል ገበታ ሰሌዳውን ሊጫን አልተቻለም";
/* Text for error when a lexical model cannot load properly */
"error-loading-lexical-model" = "የተጠየቀው ዲክሽናሪ ሊጫን አልተቻለም";
/* Text for error when an installed file is unexpectedly missing */
"error-missing-file" = "የእርዳታ ሰነዱን ማግኘት አልተቻለም።";
@ -181,6 +187,36 @@
/* Title for the main Settings menu */
"menu-settings-title" = "የኪይማን ቅንብሮች";
/* Secondary text showing current setting for spacebar caption - blank */
"menu-settings-spacebar-hint-blank" = "የስፔስባሩ መግለጫ ጽሁፍ አታሳይ";
/* Secondary text showing current setting for spacebar caption - keyboard */
"menu-settings-spacebar-hint-keyboard" = "የፊደል ገበታ ሰሌዳውን ስም በስፔስ ባሩ ላይ አሳይ";
/* Secondary text showing current setting for spacebar caption - language */
"menu-settings-spacebar-hint-language" = "የቋንቋውን ስም በስፔስ ባሩ ላይ አሳይ";
/* Secondary text showing current setting for spacebar caption - language + keyboard */
"menu-settings-spacebar-hint-languageKeyboard" = "ቋንቋና የፊደል ገበታውን በስፔስ ባሩ ላይ";
/* Label for the "Spacebar Caption" item on the main settings screen */
"menu-settings-spacebar-text" = "የስፔስባሩ መግለጫ ጽሁፍ";
/* Title for the "Spacebar Caption" settings screen */
"menu-settings-spacebar-title" = "የስፔስባሩ መግለጫ ጽሁፍ";
/* Text showing name of spacebar caption - blank */
"menu-settings-spacebar-item-blank" = "ባዶ";
/* Text showing name of spacebar caption - keyboard */
"menu-settings-spacebar-item-keyboard" = "የፊደል ገበታ ሰሌዳ";
/* Text showing name of spacebar caption - language */
"menu-settings-spacebar-item-language" = "ቋንቋ";
/* Text showing name of spacebar caption - language + keyboard */
"menu-settings-spacebar-item-languageKeyboard" = "ቋንቋና የፊደል ገበታ";
/* Short text for notification: download failure for keyboard */
"notification-download-failure-keyboard" = "የፊደል ገበታ ሰሌዳ መውረድ አልቻለም";

View file

@ -20,5 +20,5 @@
"ts-node",
"typescript"
],
"version": "15.0.121"
"version": "15.0.124"
}

View file

@ -31,7 +31,7 @@ for proj in ${projects}; do
downloadSource debianpackage
cd ${proj}-${version}
if [ -n $DIST ]; then
if [ -n "$DIST" ]; then
EXTRA_ARGS="--distribution $DIST --force-distribution"
fi
dch --newversion ${version}-1 ${EXTRA_ARGS} "Re-release to Debian"

View file

@ -32,6 +32,18 @@ Apple Disk Image (.dmg) file. It should be installed according to the following
5. Now you can start typing with the selected keyboard in any text editor or
application that uses standard macOS input methods.
---
If you're using Homebrew, you can also install Keyman with the command:
1.
```
brew install --cask keyman
```
2. Configure the macOS [security permissions](../troubleshooting/configure-security) for Keyman to run.
----
## How To - Updating Keyman for macOS
When a new version of Keyman is released, you can update by following the instructions

View file

@ -1,5 +1,5 @@
{
"name": "@keymanapp/resources-gosh",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 1
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/resources-gosh",
"version": "15.0.121",
"version": "15.0.124",
"description": "Good Ol' Shell",
"author": "Marc Durdin <marc@keyman.com> (https://github.com/mcdurdin)",
"contributors": [

View file

@ -1,5 +1,5 @@
{
"name": "@keymanapp/web-environment",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 1
}

View file

@ -1,6 +1,6 @@
{
"name": "@keymanapp/web-environment",
"version": "15.0.121",
"version": "15.0.124",
"description": "A compilation utility for passing select environment variables into our TS builds",
"author": "Joshua Horton <joshua_horton@sil.org> (https://github.com/jahorton)",
"homepage": "https://github.com/keymanapp/keyman",
@ -17,6 +17,6 @@
"url": "https://github.com/keymanapp/keyman/issues"
},
"devDependencies": {
"@keymanapp/resources-gosh": "^15.0.121"
"@keymanapp/resources-gosh": "^15.0.124"
}
}

2
web/package-lock.json generated
View file

@ -1,6 +1,6 @@
{
"name": "keyman",
"version": "15.0.121",
"version": "15.0.124",
"lockfileVersion": 2,
"requires": true,
"packages": {

View file

@ -1,6 +1,6 @@
{
"name": "keyman",
"version": "15.0.121",
"version": "15.0.124",
"description": "Facilitates text input in any language.",
"repository": {
"type": "git",
@ -18,8 +18,8 @@
},
"homepage": "https://github.com/keymanapp/keyman#readme",
"devDependencies": {
"@keymanapp/resources-gosh": "^15.0.121",
"@keymanapp/web-sentry-manager": "^15.0.121",
"@keymanapp/resources-gosh": "^15.0.124",
"@keymanapp/web-sentry-manager": "^15.0.124",
"@sentry/cli": "^1.52.3",
"chai": "^4.3.4",
"google-closure-compiler-java": "^20200224.0.0",
@ -52,13 +52,13 @@
"sentry-cli": "sentry-cli"
},
"dependencies": {
"@keymanapp/input-processor": "^15.0.121",
"@keymanapp/keyboard-processor": "^15.0.121",
"@keymanapp/lexical-model-layer": "^15.0.121",
"@keymanapp/models-types": "^15.0.121",
"@keymanapp/recorder-core": "^15.0.121",
"@keymanapp/web-environment": "^15.0.121",
"@keymanapp/web-utils": "^15.0.121",
"@keymanapp/input-processor": "^15.0.124",
"@keymanapp/keyboard-processor": "^15.0.124",
"@keymanapp/lexical-model-layer": "^15.0.124",
"@keymanapp/models-types": "^15.0.124",
"@keymanapp/recorder-core": "^15.0.124",
"@keymanapp/web-environment": "^15.0.124",
"@keymanapp/web-utils": "^15.0.124",
"@types/node": "^11.9.4",
"es6-shim": "^0.35.5",
"eventemitter3": "^4.0.0"

View file

@ -0,0 +1,22 @@
body {
font-family: Tahoma,helvetica;
}
h3 {
font-size: 1em;
font-weight:normal;
color: darkred;
margin-bottom: 4px
}
.test {
font-size: 1.5em;
width:80%;
min-height:30px;
border: 1px solid gray;
}
#KeymanWebControl {
width:50%;
min-width:600px;
}

View file

@ -59,6 +59,7 @@
<h2><a href="./issue917-context-and-notany/">Test page for context() and notany() interaction</a></h2>
<h2><a href="./spacebar-text/">Test SpacebarText APIs (#949)</a></h2>
<h2><a href="./inline-osk/">Test inline OSK (#5665)</a></h2>
<h2><a href="./issue2924/">Test variable stores and predictive text (#2924)</a></h2>
<p><a href="../">Return to main index.</a>
</body>
</html>

View file

@ -0,0 +1,55 @@
(function() {
'use strict';
var definitions = {
defaults: {
version: "undefined",
applyCasing: function defaultApplyCasing(casing, text) {
switch (casing) {
case 'lower':
return text.toLowerCase();
case 'upper':
return text.toUpperCase();
case 'initial':
var headCode = text.charCodeAt(0);
// The length of the first code unit, as measured in code points.
var headUnitLength = 1;
// Is the first character a high surrogate, indicating possible use of UTF-16
// surrogate pairs? Also, is the string long enough for there to BE a pair?
if (text.length > 1 && headCode >= 0xD800 && headCode <= 0xDBFF) {
// It's possible, so now we check for low surrogates.
var lowSurrogateCode = text.charCodeAt(1);
if (lowSurrogateCode >= 0xDC00 && lowSurrogateCode <= 0xDFFF) {
// We have a surrogate pair; this pair is the 'first' character.
headUnitLength++;
}
}
// Capitalizes the first code unit of the string, leaving the rest intact.
return text.substring(0, headUnitLength).toUpperCase() // head - uppercased
.concat(text.substring(headUnitLength)); // tail - lowercased
}
}
}, model: {
searchTermToKey: function defaultCasedSearchTermToKey(wordform, applyCasing) {
// While this is a bit WET, as the basic `defaultSearchTermToKey` exists and performs some of
// the same functions, repetition is the easiest way to allow the function to be safely compiled
// with ease by use of `.toString()`.
return Array.from(wordform
.normalize('NFKD')
// Remove any combining diacritics (if input is in NFKD)
.replace(/[\u0300-\u036F]/g, '')) // end of `Array.from`
.map(function (c) { return applyCasing('lower', c); })
.join('');
}
},
applyCasing: function(caseToApply, text) {
return definitions.defaults.applyCasing(caseToApply, text);
},
searchTermToKey: function(text) {
return definitions.model.searchTermToKey(text, definitions.applyCasing);
}
};
LMLayerWorker.loadModel(new models.TrieModel({"totalWeight":126,"root":{"type":"internal","weight":100,"values":["t","h","w","e"],"children":{"t":{"type":"leaf","weight":100,"entries":[{"key":"the","weight":100,"content":"the"}]},"e":{"type":"leaf","weight":5,"entries":[{"key":"example","weight":5,"content":"example"}]},"h":{"type":"leaf","weight":10,"entries":[{"key":"hello","weight":10,"content":"hello"}]},"w":{"type":"internal","weight":8,"values":["o"],"children":{"o":{"type":"internal","weight":8,"values":["r"],"children":{"r":{"type":"internal","weight":8,"values":["l","d"],"children":{"l":{"type":"leaf","weight":8,"entries":[{"key":"world","weight":8,"content":"world"}]},"d":{"type":"leaf","weight":3,"entries":[{"key":"wordlist","weight":3,"content":"wordlist"}]}}}}}}}}}}, {
wordBreaker: wordBreakers['default'],
searchTermToKey: definitions.searchTermToKey,
}));
})();

View file

@ -0,0 +1,43 @@
keyman.init({
attachType: 'auto'
});
window.addEventListener('load', function() {
keyman.addKeyboards({
id: 'testvariable',
name: 'testvariable',
languages: [{
id:'en', name:'English'
}],
filename: './testvariable.js'
});
keyman.addKeyboards({
id: 'oldtestvariable',
name: 'oldtestvariable',
languages: [{
id:'en', name:'English'
}],
filename: './oldtestvariable.js'
});
keyman.addKeyboards({
id: 'us',
name: 'English US',
languages: [{
id: 'en',
name: 'English'
}],
filename: '../us-1.0.js'
});
const pageRef = (window.location.protocol == 'file:')
? window.location.href.substr(0, window.location.href.lastIndexOf('/')+1)
: window.location.href;
keyman.modelManager.register({
id: 'nrc.en.mtnt',
languages: ['en'],
path: pageRef + 'dmg.dv.test.model.js'
});
}, false);

View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<meta name="viewport" content="width=device-width,user-scalable=no" />
<title>KeymanWeb Issue 2924 - Variable Stores and Predictive Text</title>
<link rel='stylesheet' href='../common/test.css' />
<script src="../../release/unminified/web/keymanweb.js" type="application/javascript"></script>
<script src="../../release/unminified/web/kmwuitoggle.js"></script>
<script src="./header.js"></script>
</head>
<body>
<h2>KeymanWeb Test Page - Variable Stores and Predictive Text</h2>
<p>Ref: <a href='https://github.com/keymanapp/keyman/issues/2924'>issue #2924</a></p>
<hr/>
<div>
<div id='KeymanWebControl'></div>
<h3>Type in your language in this text area:</h3>
<textarea id='ta1' class='test' placeholder='Type here'></textarea>
</div>
<hr/>
<h3><a href="../index.html">Return to testing home page</a></h3>
</body>
</html>

View file

@ -0,0 +1,136 @@
if(typeof keyman === 'undefined') {
console.log('Keyboard requires KeymanWeb 10.0 or later');
if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");
} else {
KeymanWeb.KR(new Keyboard_oldtestvariable());
}
function Keyboard_oldtestvariable()
{
var modCodes = keyman.osk.modifierCodes;
var keyCodes = keyman.osk.keyCodes;
this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;
this.KI="Keyboard_oldtestvariable";
this.KN="oldtestvariable";
this.KMINVER="10.0";
this.KV={F:' 1em "Arial"',K102:0};
this.KV.KLS={
"default": ["","","","","","","","","","","","","","","","","","","","Reveal","","","","","","","","","","","","","","Set","","","","","","","","","","","","","","","","","","Clear","","","","","","","","","","","","",""]
};
this.KV.BK=(function(x){
var
empty=Array.apply(null, Array(65)).map(String.prototype.valueOf,""),
result=[], v, i,
modifiers=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt'];
for(i=modifiers.length-1;i>=0;i--) {
v = x[modifiers[i]];
if(v || result.length > 0) {
result=(v ? v : empty).slice().concat(result);
}
}
return result;
})(this.KV.KLS);
this.KDU=0;
this.KH='';
this.KM=0;
this.KBVER="1.0";
this.KMBM=0 /* 0x0000 */;
this.KVKL={
"tablet": {
"displayUnderlying": false,
"layer": [
{
"id": "default",
"row": [
{
"id": "1",
"key": [
{
"id": "K_S",
"text": "Set"
},
{
"id": "K_C",
"text": "Clear"
},
{
"id": "K_R",
"text": "Reveal"
},
{
"width": "100",
"id": "K_BKSP",
"sp": "1",
"text": "*BkSp*"
}
]
},
{
"id": "2",
"key": [
{
"width": "140",
"id": "K_LOPT",
"sp": "1",
"text": "*Menu*"
},
{
"id": "K_SPACE"
},
{
"width": "145",
"id": "K_ENTER",
"sp": "1",
"text": "*Enter*"
}
]
}
]
}
]
}
}
;
this.s_myVar_9=KeymanWeb.KLOAD(this.KI,"myVar","1");
this.s13="1";
this.s14="0";
this.s15="1";
this.s16="1";
this.KVER="15.0.105.0";
//this.KVS=['s_myVar_9']; <-- manually stubbed out to demonstrate old behaviour
this.gs=function(t,e) {
return this.g_main_0(t,e);
};
this.g_main_0=function(t,e) {
var k=KeymanWeb,r=0,m=0;
if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) {
if(1){
r=m=1; // Line 16
k.KDC(0,t);
k.KO(-1,t,"(-)");
this.s_myVar_9=this.s14;
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_R /* 0x52 */)) {
if(this.s_myVar_9===this.s15){
r=m=1; // Line 17
k.KDC(0,t);
k.KO(-1,t,"+");
}
else if(this.s_myVar_9!==this.s16){
r=m=1; // Line 18
k.KDC(0,t);
k.KO(-1,t,"-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_S /* 0x53 */)) {
if(1){
r=m=1; // Line 15
k.KDC(0,t);
k.KO(-1,t,"(+)");
this.s_myVar_9=this.s13;
}
}
return r;
};
}

View file

@ -0,0 +1,6 @@
test Change History
====================
1.0 (2020-05-27)
----------------
* Created by dmg

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
© 2020 dmg
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.

View file

@ -0,0 +1,29 @@
test lexical model
===================
© 2020 dmg
Version 1.0
Description
-----------
test generated from template
Links
-----
Supported Platforms
-------------------
* Windows
* macOS
* Linux
* Web
* iPhone
* iPad
* Android phone
* Android tablet
* Mobile devices
* Desktop devices
* Tablet devices

View file

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="utf-8"?>
<KeymanDeveloperProject>
<Options>
<BuildPath>$PROJECTPATH\build</BuildPath>
<CompilerWarningsAsErrors>True</CompilerWarningsAsErrors>
<WarnDeprecatedCode>True</WarnDeprecatedCode>
<CheckFilenameConventions>True</CheckFilenameConventions>
<ProjectType>lexicalmodel</ProjectType>
</Options>
<Files>
<File>
<ID>id_6d8c9bbe8c11c08cca045e5e87c342c6</ID>
<Filename>dmg.dv.test.model.ts</Filename>
<Filepath>source\dmg.dv.test.model.ts</Filepath>
<FileVersion>1.0</FileVersion>
<FileType>.ts</FileType>
</File>
<File>
<ID>id_521f7de068a80527c98d0c04c05faa94</ID>
<Filename>dmg.dv.test.model.kps</Filename>
<Filepath>source\dmg.dv.test.model.kps</Filepath>
<FileVersion>1.0</FileVersion>
<FileType>.kps</FileType>
<Details>
<Name>test</Name>
<Copyright>© 2020 dmg</Copyright>
<Version>1.0</Version>
</Details>
</File>
<File>
<ID>id_ede98e4633e239f933cbfd1f4e1b766c</ID>
<Filename>HISTORY.md</Filename>
<Filepath>HISTORY.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_53e892b8b41cc4caece1cfd5ef21d6e7</ID>
<Filename>LICENSE.md</Filename>
<Filepath>LICENSE.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_0730bb7c2e8f9ea2438b52e419dd86c9</ID>
<Filename>README.md</Filename>
<Filepath>README.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_4b12eec2a4d0bfc7b5441a4a59691eab</ID>
<Filename>dmg.dv.test.model_info</Filename>
<Filepath>dmg.dv.test.model_info</Filepath>
<FileVersion></FileVersion>
<FileType>.model_info</FileType>
</File>
<File>
<ID>id_6ee5fa96871fb96ecebf2cbe9ec7425b</ID>
<Filename>dmg.dv.test.model.js</Filename>
<Filepath>source\..\build\dmg.dv.test.model.js</Filepath>
<FileVersion></FileVersion>
<FileType>.js</FileType>
<ParentFileID>id_521f7de068a80527c98d0c04c05faa94</ParentFileID>
</File>
<File>
<ID>id_356e5d149c1e539356d72698c1e401a6</ID>
<Filename>welcome.htm</Filename>
<Filepath>source\welcome.htm</Filepath>
<FileVersion></FileVersion>
<FileType>.htm</FileType>
<ParentFileID>id_521f7de068a80527c98d0c04c05faa94</ParentFileID>
</File>
<File>
<ID>id_8da344c4cea6f467013357fe099006f5</ID>
<Filename>readme.htm</Filename>
<Filepath>source\readme.htm</Filepath>
<FileVersion></FileVersion>
<FileType>.htm</FileType>
<ParentFileID>id_521f7de068a80527c98d0c04c05faa94</ParentFileID>
</File>
</Files>
</KeymanDeveloperProject>

View file

@ -0,0 +1,7 @@
{
"license": "mit",
"languages": [
"dv"
],
"description": "test generated from template"
}

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<Package>
<System>
<KeymanDeveloperVersion>13.0.108.0</KeymanDeveloperVersion>
<FileVersion>12.0</FileVersion>
</System>
<Options>
<ExecuteProgram></ExecuteProgram>
<ReadMeFile>readme.htm</ReadMeFile>
<MSIFileName></MSIFileName>
<MSIOptions></MSIOptions>
</Options>
<StartMenu>
<Folder></Folder>
<Items/>
</StartMenu>
<Info>
<Name URL="">test</Name>
<Copyright URL="">© 2020 dmg</Copyright>
<Author URL="">dmg</Author>
<Version URL="">1.0</Version>
</Info>
<Files>
<File>
<Name>..\build\dmg.dv.test.model.js</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.js</FileType>
</File>
<File>
<Name>welcome.htm</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.htm</FileType>
</File>
<File>
<Name>readme.htm</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.htm</FileType>
</File>
</Files>
<Keyboards/>
<LexicalModels>
<LexicalModel>
<Name>test</Name>
<ID>dmg.dv.test</ID>
<Languages>
<Language ID="dv">Dhivehi</Language>
</Languages>
</LexicalModel>
</LexicalModels>
<Strings/>
</Package>

View file

@ -0,0 +1,14 @@
/*
test 1.0 generated from template.
This is a minimal lexical model source that uses a tab delimited wordlist.
See documentation online at https://help.keyman.com/developer/ for
additional parameters.
*/
const source: LexicalModelSource = {
format: 'trie-1.0',
wordBreaker: 'default',
sources: ['wordlist.tsv'],
};
export default source;

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>test</title>
<style type="text/css">
p { font: 10pt Tahoma; }
h1 { font: bold 16pt Tahoma; color: #4444cc; margin-bottom: 2px }
h2 { font: bold 12pt Tahoma; color: #4444cc; }
</style>
</head>
<body>
<h1>test</h1>
<p>
test 1.0 generated from template.
</p>
<p>© 2020 dmg</p>
</body>
</html>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Start Using test</title>
<style type="text/css">
p { font: 10pt Tahoma; }
h1 { font: bold 16pt Tahoma; color: #4444cc; margin-bottom: 2px }
h2 { font: bold 12pt Tahoma; color: #4444cc; }
</style>
</head>
<body>
<h1>Start Using test</h1>
<p>
test 1.0 generated from template.
</p>
<h1>Wordlist Model Documentation</h1>
<!-- Insert HTML documentation here -->
<p>© 2020 dmg</p>
</body>
</html>

View file

@ -0,0 +1,16 @@
#
# test 1.0 generated from template.
#
# This is an example tab-separated wordlist file that can be edited in a spreadsheet
# program or regenerated from a wordlist tool. See lexical model documentation at
# https://help.keyman.com/developer/ for tools.
#
# Columns
# =======
# WORD FREQUENCY (Optional)NOTES
#
the 100
example 5
hello 10
world 8
wordlist 3
Can't render this file because it has a wrong number of fields in line 10.

View file

@ -0,0 +1,6 @@
testvariable Change History
====================
1.0 (2020-05-26)
----------------
* Created by

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
©
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.

View file

@ -0,0 +1,29 @@
testvariable keyboard
==============
©
Version 1.0
Description
-----------
testvariable generated from template
Links
-----
Supported Platforms
-------------------
* Windows
* macOS
* Linux
* Web
* iPhone
* iPad
* Android phone
* Android tablet
* Mobile devices
* Desktop devices
* Tablet devices

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>testvariable</title>
<style type="text/css">
p { font: 10pt Tahoma; }
h1 { font: bold 16pt Tahoma; color: #4444cc; margin-bottom: 2px }
h2 { font: bold 12pt Tahoma; color: #4444cc; }
</style>
</head>
<body>
<h1>testvariable</h1>
<p>
testvariable 1.0 generated from template.
</p>
<p>©</p>
</body>
</html>

View file

@ -0,0 +1,57 @@
{
"tablet": {
"displayUnderlying": false,
"layer": [
{
"id": "default",
"row": [
{
"id": 1,
"key": [
{
"id": "K_S",
"text": "Set"
},
{
"id": "K_C",
"text": "Clear"
},
{
"id": "K_R",
"text": "Reveal"
},
{
"id": "K_BKSP",
"text": "*BkSp*",
"width": "100",
"sp": "1"
}
]
},
{
"id": 2,
"key": [
{
"id": "K_LOPT",
"text": "*Menu*",
"width": "140",
"sp": "1"
},
{
"id": "K_SPACE",
"text": "",
"width": ""
},
{
"id": "K_ENTER",
"text": "*Enter*",
"width": "145",
"sp": "1"
}
]
}
]
}
]
}
}

View file

@ -0,0 +1,18 @@
store(&VERSION) '10.0'
store(&NAME) 'testvariable'
store(&COPYRIGHT) '©'
store(&KEYBOARDVERSION) '1.0'
store(&TARGETS) 'any'
store(&LAYOUTFILE) 'testvariable.keyman-touch-layout'
store (myVar) "1"
store(&VISUALKEYBOARD) 'testvariable.kvks'
begin Unicode > use(main)
group(main) using keys
+ [K_S] > "(+)" set(myVar="1") c S will Set the variable, and output (+)
+ [K_C] > "(-)" set(myVar="0") c C will Clear the variable, and output (-)
if (myVar = "1") + [K_R] > "+" c R will Reveal the variable's state with + or -
if (myVar!= "1") + [K_R] > "-"

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<Package>
<System>
<KeymanDeveloperVersion>13.0.108.0</KeymanDeveloperVersion>
<FileVersion>7.0</FileVersion>
</System>
<Options>
<ExecuteProgram></ExecuteProgram>
<ReadMeFile>readme.htm</ReadMeFile>
<MSIFileName></MSIFileName>
<MSIOptions></MSIOptions>
<FollowKeyboardVersion/>
</Options>
<StartMenu>
<Folder></Folder>
<Items/>
</StartMenu>
<Info>
<Name URL="">testvariable</Name>
<Copyright URL="">©</Copyright>
<Author URL=""></Author>
<Version URL=""></Version>
</Info>
<Files>
<File>
<Name>..\build\testvariable.kmx</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.kmx</FileType>
</File>
<File>
<Name>..\build\testvariable.js</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.js</FileType>
</File>
<File>
<Name>..\build\testvariable.kvk</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.kvk</FileType>
</File>
<File>
<Name>welcome.htm</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.htm</FileType>
</File>
<File>
<Name>readme.htm</Name>
<Description></Description>
<CopyLocation>0</CopyLocation>
<FileType>.htm</FileType>
</File>
</Files>
<Keyboards>
<Keyboard>
<Name>testvariable</Name>
<ID>testvariable</ID>
<Version>1.0</Version>
<Languages>
<Language ID="dv">Dhivehi</Language>
</Languages>
</Keyboard>
</Keyboards>
<Strings/>
</Package>

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<visualkeyboard>
<header>
<version>10.0</version>
<kbdname>testvariable</kbdname>
<flags/>
</header>
<encoding name="unicode" fontname="Arial" fontsize="-12">
<layer shift="">
<key vkey="K_C">Clear</key>
<key vkey="K_R">Reveal</key>
<key vkey="K_S">Set</key>
</layer>
</encoding>
</visualkeyboard>

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Start Using testvariable</title>
<style type="text/css">
p { font: 10pt Tahoma; }
h1 { font: bold 16pt Tahoma; color: #4444cc; margin-bottom: 2px }
h2 { font: bold 12pt Tahoma; color: #4444cc; }
</style>
</head>
<body>
<h1>Start Using testvariable</h1>
<p>
testvariable 1.0 generated from template.
</p>
<h1>Keyboard Layout</h1>
<!-- Insert Keyboard Layout Images or HTML here -->
<p>©</p>
</body>
</html>

View file

@ -0,0 +1,7 @@
{
"license": "mit",
"languages": [
"en"
],
"description": "testvariable generated from template"
}

View file

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<KeymanDeveloperProject>
<Options>
<BuildPath>$PROJECTPATH\build</BuildPath>
<CompilerWarningsAsErrors>True</CompilerWarningsAsErrors>
<WarnDeprecatedCode>True</WarnDeprecatedCode>
<CheckFilenameConventions>True</CheckFilenameConventions>
<ProjectType>keyboard</ProjectType>
</Options>
<Files>
<File>
<ID>id_a8c52d62d9f15eb62fde81d1a591d3b7</ID>
<Filename>testvariable.kmn</Filename>
<Filepath>source\testvariable.kmn</Filepath>
<FileVersion>1.0</FileVersion>
<FileType>.kmn</FileType>
<Details>
<Name>testvariable</Name>
<Copyright>©</Copyright>
</Details>
</File>
<File>
<ID>id_25e4c084428d0ee657e7a56c3ad5dc3c</ID>
<Filename>testvariable.kps</Filename>
<Filepath>source\testvariable.kps</Filepath>
<FileVersion></FileVersion>
<FileType>.kps</FileType>
<Details>
<Name>testvariable</Name>
<Copyright>©</Copyright>
</Details>
</File>
<File>
<ID>id_ede98e4633e239f933cbfd1f4e1b766c</ID>
<Filename>HISTORY.md</Filename>
<Filepath>HISTORY.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_53e892b8b41cc4caece1cfd5ef21d6e7</ID>
<Filename>LICENSE.md</Filename>
<Filepath>LICENSE.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_0730bb7c2e8f9ea2438b52e419dd86c9</ID>
<Filename>README.md</Filename>
<Filepath>README.md</Filepath>
<FileVersion></FileVersion>
<FileType>.md</FileType>
</File>
<File>
<ID>id_efaa79249320cda8d8e2886ddbf0475e</ID>
<Filename>testvariable.keyboard_info</Filename>
<Filepath>testvariable.keyboard_info</Filepath>
<FileVersion></FileVersion>
<FileType>.keyboard_info</FileType>
</File>
<File>
<ID>id_0c280146c90477c06029a32b48581f90</ID>
<Filename>testvariable.kmx</Filename>
<Filepath>source\..\build\testvariable.kmx</Filepath>
<FileVersion></FileVersion>
<FileType>.kmx</FileType>
<ParentFileID>id_25e4c084428d0ee657e7a56c3ad5dc3c</ParentFileID>
</File>
<File>
<ID>id_694dbba5eb4cd5c4f122133b889f7eb4</ID>
<Filename>testvariable.js</Filename>
<Filepath>source\..\build\testvariable.js</Filepath>
<FileVersion></FileVersion>
<FileType>.js</FileType>
<ParentFileID>id_25e4c084428d0ee657e7a56c3ad5dc3c</ParentFileID>
</File>
<File>
<ID>id_6c3d7ac2bff7cba3383a3d6ca5e2a2ef</ID>
<Filename>testvariable.kvk</Filename>
<Filepath>source\..\build\testvariable.kvk</Filepath>
<FileVersion></FileVersion>
<FileType>.kvk</FileType>
<ParentFileID>id_25e4c084428d0ee657e7a56c3ad5dc3c</ParentFileID>
</File>
<File>
<ID>id_356e5d149c1e539356d72698c1e401a6</ID>
<Filename>welcome.htm</Filename>
<Filepath>source\welcome.htm</Filepath>
<FileVersion></FileVersion>
<FileType>.htm</FileType>
<ParentFileID>id_25e4c084428d0ee657e7a56c3ad5dc3c</ParentFileID>
</File>
<File>
<ID>id_8da344c4cea6f467013357fe099006f5</ID>
<Filename>readme.htm</Filename>
<Filepath>source\readme.htm</Filepath>
<FileVersion></FileVersion>
<FileType>.htm</FileType>
<ParentFileID>id_25e4c084428d0ee657e7a56c3ad5dc3c</ParentFileID>
</File>
</Files>
</KeymanDeveloperProject>

View file

@ -0,0 +1,136 @@
if(typeof keyman === 'undefined') {
console.log('Keyboard requires KeymanWeb 10.0 or later');
if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");
} else {
KeymanWeb.KR(new Keyboard_testvariable());
}
function Keyboard_testvariable()
{
var modCodes = keyman.osk.modifierCodes;
var keyCodes = keyman.osk.keyCodes;
this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;
this.KI="Keyboard_testvariable";
this.KN="testvariable";
this.KMINVER="10.0";
this.KV={F:' 1em "Arial"',K102:0};
this.KV.KLS={
"default": ["","","","","","","","","","","","","","","","","","","","Reveal","","","","","","","","","","","","","","Set","","","","","","","","","","","","","","","","","","Clear","","","","","","","","","","","","",""]
};
this.KV.BK=(function(x){
var
empty=Array.apply(null, Array(65)).map(String.prototype.valueOf,""),
result=[], v, i,
modifiers=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt'];
for(i=modifiers.length-1;i>=0;i--) {
v = x[modifiers[i]];
if(v || result.length > 0) {
result=(v ? v : empty).slice().concat(result);
}
}
return result;
})(this.KV.KLS);
this.KDU=0;
this.KH='';
this.KM=0;
this.KBVER="1.0";
this.KMBM=0 /* 0x0000 */;
this.KVKL={
"tablet": {
"displayUnderlying": false,
"layer": [
{
"id": "default",
"row": [
{
"id": "1",
"key": [
{
"id": "K_S",
"text": "Set"
},
{
"id": "K_C",
"text": "Clear"
},
{
"id": "K_R",
"text": "Reveal"
},
{
"width": "100",
"id": "K_BKSP",
"sp": "1",
"text": "*BkSp*"
}
]
},
{
"id": "2",
"key": [
{
"width": "140",
"id": "K_LOPT",
"sp": "1",
"text": "*Menu*"
},
{
"id": "K_SPACE"
},
{
"width": "145",
"id": "K_ENTER",
"sp": "1",
"text": "*Enter*"
}
]
}
]
}
]
}
}
;
this.s_myVar_9=KeymanWeb.KLOAD(this.KI,"myVar","1");
this.s13="1";
this.s14="0";
this.s15="1";
this.s16="1";
this.KVER="15.0.105.0";
this.KVS=['s_myVar_9'];
this.gs=function(t,e) {
return this.g_main_0(t,e);
};
this.g_main_0=function(t,e) {
var k=KeymanWeb,r=0,m=0;
if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) {
if(1){
r=m=1; // Line 16
k.KDC(0,t);
k.KO(-1,t,"(-)");
this.s_myVar_9=this.s14;
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_R /* 0x52 */)) {
if(this.s_myVar_9===this.s15){
r=m=1; // Line 17
k.KDC(0,t);
k.KO(-1,t,"+");
}
else if(this.s_myVar_9!==this.s16){
r=m=1; // Line 18
k.KDC(0,t);
k.KO(-1,t,"-");
}
}
else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_S /* 0x53 */)) {
if(1){
r=m=1; // Line 15
k.KDC(0,t);
k.KO(-1,t,"(+)");
this.s_myVar_9=this.s13;
}
}
return r;
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View file

@ -125,6 +125,10 @@
<File Id="trayicon.ico" Name="trayicon.ico" Source="..\..\desktop\branding\trayicon.ico" KeyPath="yes" />
</Component>
<Component>
<File Id="core.ico" Name="core.ico" Source="..\..\desktop\branding\core.ico" KeyPath="yes" />
</Component>
<Component>
<File Id="appicon.ico" Name="appicon.ico" Source="..\..\global\res\90\desktop\appicon.ico" KeyPath="yes" />
</Component>
@ -242,6 +246,7 @@
<ComponentRef Id="menu.txt" />
<ComponentRef Id="messages.txt" />
<ComponentRef Id="trayicon.ico" />
<ComponentRef Id="core.ico" />
<ComponentRef Id="KeymanDesktop.chm" />
<ComponentRef Id="appicon.ico" />
<ComponentRef Id="cfgicon.ico" />

View file

@ -33,7 +33,11 @@ type
class function GetFirstLanguage(Keyboard: IKeymanKeyboardFile): string; overload;
/// <summary>Get the BCP47 tag for the user's default language</summary>
class function GetUserDefaultLanguage: string; static;
class function GetUserDefaultLanguage: string; overload; static;
class procedure GetUserDefaultLanguage(var BCP47: string; var LangID: Integer); overload; static;
/// <summary>Get the -default-lang parameter string for kmshell</summary>
class function GetUserDefaultLangParameterString: string; static;
private
class function GetKeyboardLanguage(const KeyboardID,
BCP47Tag: string): IKeymanKeyboardLanguageInstalled; static;
@ -48,6 +52,7 @@ uses
Keyman.System.LanguageCodeUtils,
KLog,
BCP47Tag,
glossary,
kmint,
@ -63,9 +68,14 @@ var
i: Integer;
begin
Result := True;
for i := 0 to Packages.Count - 1 do
// We'll attempt every package but return failure if any of them have issues
Result := InstallTipForPackage(Packages.Names[i], Packages.ValueFromIndex[i]) and Result;
KL.MethodEnter(nil, 'TTIPMaintenance.InstallTipsForPackages', [Packages.Text]);
try
for i := 0 to Packages.Count - 1 do
// We'll attempt every package but return failure if any of them have issues
Result := InstallTipForPackage(Packages.Names[i], Packages.ValueFromIndex[i]) and Result;
finally
KL.MethodExit(nil, 'TTIPMaintenance.InstallTipsForPackages', [Result]);
end;
end;
class function TTIPMaintenance.InstallTipForPackage(const PackageFilename, BCP47Tag: string): Boolean;
@ -74,23 +84,29 @@ var
n: Integer;
pack: IKeymanPackageInstalled;
begin
// This function has a known limitation: if a package contains more than one keyboard,
// then the BCP47 association will be made only for the first keyboard. This is
// considered an acceptable limitation at this time
Result := False;
KL.MethodEnter(nil, 'TTIPMaintenance.InstallTipForPackage', [PackageFilename, BCP47Tag]);
try
// This function has a known limitation: if a package contains more than one keyboard,
// then the BCP47 association will be made only for the first keyboard. This is
// considered an acceptable limitation at this time
PackageID := ChangeFileExt(ExtractFileName(PackageFilename), '');
n := kmcom.Packages.IndexOf(PackageID);
if n < 0 then
Exit(False);
PackageID := ChangeFileExt(ExtractFileName(PackageFilename), '');
n := kmcom.Packages.IndexOf(PackageID);
if n < 0 then
Exit(False);
pack := kmcom.Packages[n];
pack := kmcom.Packages[n];
if pack.Keyboards.Count = 0 then
Exit(False);
if pack.Keyboards.Count = 0 then
Exit(False);
if BCP47Tag = ''
then Result := DoInstall(pack.Keyboards[0].ID, GetFirstLanguage(pack.Keyboards[0] as IKeymanKeyboardInstalled))
else Result := DoInstall(pack.Keyboards[0].ID, BCP47Tag);
if BCP47Tag = ''
then Result := DoInstall(pack.Keyboards[0].ID, GetFirstLanguage(pack.Keyboards[0] as IKeymanKeyboardInstalled))
else Result := DoInstall(pack.Keyboards[0].ID, BCP47Tag);
finally
KL.MethodExit(nil, 'TTIPMaintenance.InstallTipForPackage', [Result]);
end;
end;
class function TTIPMaintenance.InstallTip(LangID: Integer; const KeyboardID, BCP47Tag,
@ -98,13 +114,19 @@ class function TTIPMaintenance.InstallTip(LangID: Integer; const KeyboardID, BCP
var
lang: IKeymanKeyboardLanguageInstalled;
begin
lang := GetKeyboardLanguage(KeyboardID, BCP47Tag);
if lang = nil then
Exit(False);
Result := False;
KL.MethodEnter(nil, 'TTIPMaintenance.InstallTip', [LangID, KeyboardID, BCP47Tag, KeyboardToRemove]);
try
lang := GetKeyboardLanguage(KeyboardID, BCP47Tag);
if lang = nil then
Exit(False);
// TODO: can this fail?
(lang as IKeymanKeyboardLanguageInstalled2).InstallTip(LangID, KeyboardToRemove);
Result := True;
// TODO: can this fail?
(lang as IKeymanKeyboardLanguageInstalled2).InstallTip(LangID, KeyboardToRemove);
Result := True;
finally
KL.MethodExit(nil, 'TTIPMaintenance.InstallTip', [Result]);
end;
end;
class function TTIPMaintenance.RegisterTip(LangID: Integer; const KeyboardID,
@ -112,13 +134,19 @@ class function TTIPMaintenance.RegisterTip(LangID: Integer; const KeyboardID,
var
lang: IKeymanKeyboardLanguageInstalled;
begin
lang := GetKeyboardLanguage(KeyboardID, BCP47Tag);
if lang = nil then
Exit(False);
Result := False;
KL.MethodEnter(nil, 'TTIPMaintenance.RegisterTip', [KeyboardID, BCP47Tag]);
try
lang := GetKeyboardLanguage(KeyboardID, BCP47Tag);
if lang = nil then
Exit(False);
// TODO: can this fail?
(lang as IKeymanKeyboardLanguageInstalled2).RegisterTip(LangID);
Result := True;
// TODO: can this fail?
(lang as IKeymanKeyboardLanguageInstalled2).RegisterTip(LangID);
Result := True;
finally
KL.MethodExit(nil, 'TTIPMaintenance.RegisterTip', [Result]);
end;
end;
class function TTIPMaintenance.DoInstall(const KeyboardID,
@ -129,44 +157,59 @@ var
TemporaryKeyboardID: WideString;
LangID: Integer;
childExitCode: Cardinal;
CanonicalTag, Command: string;
begin
lang := GetKeyboardLanguage(KeyboardID, (kmcom as IKeymanBCP47Canonicalization).GetCanonicalTag(BCP47Tag));
if lang = nil then
// The keyboard was not found
Exit(False);
if lang.IsInstalled then
// After canonicalization, we may find the language is already installed
Exit(True);
TemporaryKeyboardID := '';
LangID := 0;
RegistrationRequired := False;
if not (lang as IKeymanKeyboardLanguageInstalled2).FindInstallationLangID(LangID, TemporaryKeyboardID, RegistrationRequired, kifInstallTransientLanguage) then
begin
// We were not able to find a TIP, perhaps all transient TIPs have been used
Exit(False);
end;
if RegistrationRequired then
begin
// This calls back into TTIPMaintenance.RegisterTip
if WaitForElevatedConfiguration(0, '-register-tip '+IntToHex(LangID,4)+' "'+KeyboardID+'" "'+lang.BCP47Code+'"') <> 0 then
Result := False;
KL.MethodEnter(nil, 'TTIPMaintenance.DoInstall', [KeyboardID, BCP47Tag]);
try
CanonicalTag := (kmcom as IKeymanBCP47Canonicalization).GetCanonicalTag(BCP47Tag);
lang := GetKeyboardLanguage(KeyboardID, CanonicalTag);
KL.Log('BCP47Tag = %s, CanonicalTag = %s, lang.BCP47Code = %s', [BCP47Tag, CanonicalTag, lang.BCP47Code]);
if lang = nil then
// The keyboard was not found
Exit(False);
end;
// This calls back into TTIPMaintenance.InstallTip
if not TUtilExecute.WaitForProcess('"'+ParamStr(0)+'" -install-tip '+IntToHex(LangID,4)+' "'+KeyboardID+'" "'+lang.BCP47Code+'" "'+TemporaryKeyboardID+'"',
GetCurrentDir, childExitCode) or
(childExitCode <> 0) then
begin
if lang.IsInstalled then
// After canonicalization, we may find the language is already installed
Exit(True);
TemporaryKeyboardID := '';
LangID := 0;
RegistrationRequired := False;
if not (lang as IKeymanKeyboardLanguageInstalled2).FindInstallationLangID(LangID, TemporaryKeyboardID, RegistrationRequired, kifInstallTransientLanguage) then
begin
KL.Log('Failed to find installation langid');
// We were not able to find a TIP, perhaps all transient TIPs have been used
Exit(False);
end;
KL.Log('LangID=%x, TemporaryKeyboardID=%s, RegistrationRequired=%s', [LangID, TemporaryKeyboardID, BoolToStr(RegistrationRequired, True)]);
if RegistrationRequired then
begin
Command := '-register-tip '+IntToHex(LangID,4)+' "'+KeyboardID+'" "'+lang.BCP47Code+'" '+GetUserDefaultLangParameterString;
KL.Log('Calling elevated kmshell %s', [Command]);
// This calls back into TTIPMaintenance.RegisterTip
if WaitForElevatedConfiguration(0, Command) <> 0 then
Exit(False);
end;
Command := '-install-tip '+IntToHex(LangID,4)+' "'+KeyboardID+'" "'+lang.BCP47Code+'" "'+TemporaryKeyboardID+'"';
KL.Log('Calling user kmshell %s', [Command]);
// This calls back into TTIPMaintenance.InstallTip
if not TUtilExecute.WaitForProcess('"'+ParamStr(0)+'" '+Command, GetCurrentDir, childExitCode) or
(childExitCode <> 0) then
begin
kmcom.Refresh;
Exit(False);
end;
kmcom.Refresh;
Exit(False);
Result := True;
finally
KL.MethodExit(nil, 'TTIPMaintenance.DoInstall', [Result]);
end;
kmcom.Refresh;
Result := True;
end;
function GetDefaultHKL: HKL;
@ -183,79 +226,149 @@ var
TemporaryKeyboardID: WideString;
RegistrationRequired: WordBool;
begin
lang := GetKeyboardLanguage(KeyboardID, (kmcom as IKeymanBCP47Canonicalization).GetCanonicalTag(BCP47Tag));
if lang = nil then
// The keyboard was not found
Exit(False);
Result := False;
KL.MethodEnter(nil, 'TTIPMaintenance.DoRegister', [KeyboardID, BCP47Tag]);
try
lang := GetKeyboardLanguage(KeyboardID, (kmcom as IKeymanBCP47Canonicalization).GetCanonicalTag(BCP47Tag));
if lang = nil then
// The keyboard was not found
Exit(False);
if lang.IsInstalled or (lang as IKeymanKeyboardLanguageInstalled2).IsRegistered then
// After canonicalization, we may find the language is already installed
Exit(True);
if lang.IsInstalled or (lang as IKeymanKeyboardLanguageInstalled2).IsRegistered then
// After canonicalization, we may find the language is already installed
Exit(True);
TemporaryKeyboardID := '';
LangID := 0;
RegistrationRequired := False;
TemporaryKeyboardID := '';
LangID := 0;
RegistrationRequired := False;
if (lang as IKeymanKeyboardLanguageInstalled2).FindInstallationLangID(LangID, TemporaryKeyboardID, RegistrationRequired, 0) then
begin
Result := not RegistrationRequired or RegisterTip(LangID, KeyboardID, lang.BCP47Code);
end
else
Result := False;
if (lang as IKeymanKeyboardLanguageInstalled2).FindInstallationLangID(LangID, TemporaryKeyboardID, RegistrationRequired, 0) then
begin
Result := not RegistrationRequired or RegisterTip(LangID, KeyboardID, lang.BCP47Code);
end
else
Result := False;
finally
KL.MethodExit(nil, 'TTIPMaintenance.DoRegister', [Result]);
end;
end;
class function TTIPMaintenance.GetUserDefaultLangParameterString: string;
var
LangID: Integer;
BCP47: string;
begin
KL.MethodEnter(nil, 'TTIPMaintenance.GetUserDefaultLangParameterString', []);
try
GetUserDefaultLanguage(BCP47, LangID);
Result := '-default-lang '+BCP47+' '+IntToHex(LangID,4);
finally
KL.MethodExit(nil, 'TTIPMaintenance.GetUserDefaultLangParameterString', [Result]);
end;
end;
class function TTIPMaintenance.GetUserDefaultLanguage: string;
var
LangID: Integer;
begin
KL.MethodEnter(nil, 'TTIPMaintenance.GetUserDefaultLanguage', []);
try
GetUserDefaultLanguage(Result, LangID);
finally
KL.MethodExit(nil, 'TTIPMaintenance.GetUserDefaultLanguage', [Result]);
end;
end;
class procedure TTIPMaintenance.GetUserDefaultLanguage(var BCP47: string; var LangID: Integer);
var
r: TRegistry;
tags: TStringList;
v: string;
keys: TStringList;
key: string;
begin
// Fallback result
Result := TLanguageCodeUtils.TranslateWindowsLanguagesToBCP47(HKLToLanguageID(GetDefaultHKL));
// For Win10, look in CPL/International/UserProfile
r := TRegistry.Create;
function GetLangIDFromValueName: Integer;
var
values: TStringList;
v: string;
begin
// In HKCU\Control Panel\International\User Profile\<bcp47>, already opened
// by the caller, look for a value name such as '0453:00000453' or
// '0804:{81D4E9C9-1D3B-41BC-9E6C-4B40BF79E35E}{FA550B04-5AD7-411F-A5AC-CA038EC515D7}'
// and grab the LangID from there.
values := TStringList.Create;
try
r.GetValueNames(values);
for v in values do
begin
if Copy(v, 5, 1) = ':' then
begin
Result := StrToIntDef('$' + Copy(v, 1, 4), 0);
if Result > 0 then
Exit;
end;
end;
finally
values.Free;
end;
Result := 0;
end;
begin
KL.MethodEnter(nil, 'TTIPMaintenance.GetUserDefaultLanguage', []);
try
if not r.OpenKeyReadOnly(SRegKey_ControlPanelInternationalUserProfile) then
Exit;
if r.ValueExists(SRegValue_CPIUP_InputMethodOverride) then
begin
// Lookup the override input method BCP 47 tag
v := r.ReadString(SRegValue_CPIUP_InputMethodOverride);
keys := TStringList.Create;
try
r.GetKeyNames(keys);
for key in keys do
begin
if r.OpenKeyReadOnly('\' + SRegKey_ControlPanelInternationalUserProfile + '\' + key) and
r.ValueExists(v) then
// Fallback result
LangID := HKLToLanguageID(GetDefaultHKL);
BCP47 := TLanguageCodeUtils.TranslateWindowsLanguagesToBCP47(LangID);
// For Win10, look in CPL/International/UserProfile
r := TRegistry.Create;
try
if not r.OpenKeyReadOnly(SRegKey_ControlPanelInternationalUserProfile) then
Exit;
if r.ValueExists(SRegValue_CPIUP_InputMethodOverride) then
begin
// Lookup the override input method BCP 47 tag
v := r.ReadString(SRegValue_CPIUP_InputMethodOverride);
keys := TStringList.Create;
try
r.GetKeyNames(keys);
for key in keys do
begin
Result := key;
Break;
if r.OpenKeyReadOnly('\' + SRegKey_ControlPanelInternationalUserProfile + '\' + key) and
r.ValueExists(v) then
begin
BCP47 := key;
LangID := GetLangIDFromValueName;
Break;
end;
end;
finally
keys.Free;
end;
finally
keys.Free;
end;
end
else if r.ValueExists(SRegValue_CPIUP_Languages) then
begin
// The first tag is the default language tag
tags := TStringList.Create;
try
r.ReadMultiString(SRegValue_CPIUP_Languages, tags);
if tags.Count > 0 then
begin
Result := tags[0].Trim;
end
else if r.ValueExists(SRegValue_CPIUP_Languages) then
begin
// The first tag is the default language tag
tags := TStringList.Create;
try
r.ReadMultiString(SRegValue_CPIUP_Languages, tags);
if tags.Count > 0 then
begin
BCP47 := tags[0].Trim;
if r.OpenKeyReadOnly('\' + SRegKey_ControlPanelInternationalUserProfile + '\' + BCP47) then
LangID := GetLangIDFromValueName;
end;
finally
tags.Free;
end;
finally
tags.Free;
end;
finally
r.Free;
end;
finally
r.Free;
KL.Log('TTIPMaintenance.GetUserDefaultLanguage = BCP47:%s LangID:%d', [BCP47, LangID]);
KL.MethodExit(nil, 'TTIPMaintenance.GetUserDefaultLanguage');
end;
end;

View file

@ -169,12 +169,12 @@ begin
if Length(FilenameBCP47) > 1
then RegisterKeyboardPackageLanguage(FPackage, FilenameBCP47[1])
else RegisterKeyboardPackageLanguage(FPackage, '');
// The keyboard will be installed for current user as a separate step
// The keyboard will be installed for current user as a separate step
end
else
begin
FKeyboard := (kmcom.Keyboards as IKeymanKeyboardsInstalled2).Install2(FileName, True);
if Length(FilenameBCP47) > 1
if (Length(FilenameBCP47) > 1) and (Trim(FilenameBCP47[1]) <> '')
then BCP47Tag := FilenameBCP47[1]
else BCP47Tag := TTIPMaintenance.GetFirstLanguage(FKeyboard);
TTIPMaintenance.DoRegister(FKeyboard.ID, BCP47Tag);

View file

@ -118,6 +118,7 @@ uses
System.Win.ComObj,
Winapi.ShellApi,
KLog,
custinterfaces,
GetOSVersion,
MessageIdentifierConsts,
@ -270,7 +271,6 @@ end;
procedure TfrmInstallKeyboard.FireCommand(const command: WideString; params: TStringList);
var
t: TTempFile;
BCP47Tag: string;
begin
BCP47Tag := '';
@ -297,27 +297,38 @@ begin
BCP47Tag := params.ValueFromIndex[0];
TfrmProgress.Execute(Self,
function(Manager: IProgressManager): Boolean
var
t: TTempFile;
ExecParams: string;
begin
Manager.Title := 'Installing Keyboard';
Manager.CanCancel := False;
Manager.UpdateProgress('Installing Keyboard', 0, 0);
t := TTempFileManager.Get('.log');
KL.MethodEnter(Self, '"keyboard_install"', [params.Text]);
try
if WaitForElevatedConfiguration(GetForegroundWindow, '-log "'+t.Name+'" -s -i "'+FInstallFile+'='+BCP47Tag+'" -nowelcome') = 0 then
begin
// install the keyboard tip
if not InstallTipForKeyboard(BCP47Tag) then
Exit(False);
Manager.Title := 'Installing Keyboard';
Manager.CanCancel := False;
Manager.UpdateProgress('Installing Keyboard', 0, 0);
t := TTempFileManager.Get('.log');
try
ExecParams := '-log "'+t.Name+'" -s -i "'+FInstallFile+'='+BCP47Tag+'"'+
' -nowelcome '+TTIPMaintenance.GetUserDefaultLangParameterString;
KL.Log('Calling elevated kmshell %s', [ExecParams]);
if WaitForElevatedConfiguration(GetForegroundWindow, ExecParams) = 0 then
begin
// install the keyboard tip
if not InstallTipForKeyboard(BCP47Tag) then
Exit(False);
CheckForMitigationWarningFor_Win10_1803(False, '');
ModalResult := mrOk;
end
else
ModalResult := mrCancel;
CheckForMitigationWarningFor_Win10_1803(False, '');
ModalResult := mrOk;
end
else
ModalResult := mrCancel;
CheckLogFileForWarnings(t.Name, False);
CheckLogFileForWarnings(t.Name, False);
finally
t.Free;
end;
finally
t.Free;
KL.MethodExit(Self, '"keyboard_install"');
end;
Result := True;
end

View file

@ -215,7 +215,7 @@
<!-- Context: Configuration Dialog - Footer -->
<!-- String Type: PlainText -->
<!-- Introduced: 7.0.230.0 -->
<string name="S_Button_InstallKeyboard" comment="Keyboard Layouts - install keyboard button">የፊደል ገበታ ሰሌዳን ጫን...</string>
<string name="S_Button_InstallKeyboard" comment="Keyboard Layouts - install keyboard button">የፊደል ገበታ ሰሌዳ ጫን...</string>
<!-- Context: Configuration Dialog - Footer -->
<!-- String Type: PlainText -->
<!-- Introduced: 7.0.230.0 -->
@ -276,7 +276,7 @@
<!-- Context: Configuration Dialog - Options tab -->
<!-- String Type: FormatString -->
<!-- Introduced: 9.0.480.0 -->
<string name="koDeadkeyConversion" comment="Advanced options - Base keyboard deadkeys are treated as normal keys">የሃርድዌር ዴድኪዎችን እንደ ተራ ቁልፍ አድርገው ይይዟቸው</string>
<string name="koDeadkeyConversion" comment="Advanced options - Base keyboard deadkeys are treated as normal keys">የሃርድዌር ዴድኪዎችን እንደ ተራ ቁልፍ አድርገው ይያዟቸው</string>
<!-- Context: Configuration Dialog - Options tab -->
<!-- String Type: FormatString -->
<!-- Introduced: 7.0.244.0 -->
@ -312,7 +312,7 @@
<!-- Context: Configuration Dialog - Options tab -->
<!-- String Type: FormatString -->
<!-- Introduced: 7.0.236.0 -->
<string name="koReleaseShiftKeysAfterKeyPress" comment="OSK options - Releases shift/ctrl/alt on OSK after key press">የስክሪን ላይ ኪቦርዱን ፊደሉን ከተጫኑ በኋላ Shift/Ctrl/Alt ይልቀቁ</string>
<string name="koReleaseShiftKeysAfterKeyPress" comment="OSK options - Releases shift/ctrl/alt on OSK after key press">የስክሪን ኪቦርድ ላይ ያለውን ፊደል ከተጫኑ በኋላ Shift/Ctrl/Alt ይልቀቁ</string>
<!-- Context: Configuration Dialog - Options tab -->
<!-- String Type: FormatString -->
<!-- Introduced: 7.0.244.0 -->
@ -365,11 +365,11 @@
<!-- Context: Configuration Dialog - Hotkeys tab -->
<!-- String Type: PlainText -->
<!-- Introduced: 7.0.230.0 -->
<string name="S_Hotkey_TurnKeymanOff" comment="Hotkey - Turn Product Off">ኪይማኑን ያጥፉ</string>
<string name="S_Hotkey_TurnKeymanOff" comment="Hotkey - Turn Product Off">ኪይማኑን አጥፋ</string>
<!-- Context: Configuration Dialog - Hotkeys tab -->
<!-- String Type: PlainText -->
<!-- Introduced: 7.0.230.0 -->
<string name="S_Hotkey_OpenKeyboardMenu" comment="Hotkey - Open Keyman system tray menu">የፊደል ገበታውን ዝርዝር ይክፈቱ</string>
<string name="S_Hotkey_OpenKeyboardMenu" comment="Hotkey - Open Keyman system tray menu">የፊደል ገበታውን ዝርዝር ክፈት</string>
<!-- Context: Configuration Dialog - Hotkeys tab -->
<!-- String Type: PlainText -->
<!-- Introduced: 7.0.230.0 -->
@ -629,7 +629,7 @@
<!-- Context: _LanguageInfo -->
<!-- String Type: PlainText -->
<!-- Introduced: 8.0.278.0 -->
<string name="S_DisplayIn" comment="'Display In' text label for UI language menu">በውስጥ አሳይ</string>
<string name="S_DisplayIn" comment="'Display In' text label for UI language menu">ቋንቋ በ</string>
<!-- Context: _LanguageInfo -->
<!-- String Type: PlainText -->
<!-- Introduced: 8.0.278.0 -->
@ -733,7 +733,7 @@
<!-- Context: System Tray Menu Items -->
<!-- String Type: PlainText -->
<!-- Introduced: 7.0.230.0 -->
<string name="S_Menu_SwitchKeymanOff" comment="Systray item - Switch Keyman Off [&amp; precedes alt + access-character]">ኪይማኑን ያጥፉ</string>
<string name="S_Menu_SwitchKeymanOff" comment="Systray item - Switch Keyman Off [&amp; precedes alt + access-character]">ኪይማኑን አጥፋ (&amp;O)</string>
<!-- Context: System Tray Menu Items -->
<!-- String Type: PlainText -->
<!-- Introduced: 7.0.230.0 -->

View file

@ -195,7 +195,8 @@ begin
end;
function Init(var FMode: TKMShellMode; KeyboardFileNames: TStrings; var FSilent, FForce, FNoWelcome: Boolean;
var FLogFile, FQuery: string; var FDisablePackages, FDefaultUILanguage: string; var FStartWithConfiguration: Boolean; var FParentWindow: THandle): Boolean;
var FLogFile, FQuery: string; var FDisablePackages, FDefaultUILanguage: string; var FStartWithConfiguration: Boolean;
var FParentWindow: THandle; var FDefaultBCP47: string; var FDefaultLangID: Integer): Boolean;
var
s: string;
i: Integer;
@ -269,7 +270,13 @@ begin
FQuery := Trim(FQuery);
end
else if Copy(s, 1, 3) = '-ur' then UnRegCRC := StrToIntDef('$'+Copy(s, 4, 8), 0)
else if s = '-default-lang' then
begin
Inc(i);
FDefaultBCP47 := ParamStr(i);
Inc(i);
FDefaultLangID := StrToIntDef('$'+ParamStr(i), 0);
end
// Controls from Keyman Engine
else if s = '-showhint' then FMode := fmShowHint
else if s = '-parentwindow' then
@ -301,7 +308,8 @@ begin
end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle); forward;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle;
const FDefaultBCP47: string; FDefaultLangID: Integer); forward;
procedure Run;
var
@ -312,7 +320,8 @@ var
FForce: Boolean;
FParentWindow: THandle;
FLogFile: string;
FDisablePackages, FDefaultUILanguage: string;
FDefaultLangID: Integer;
FDefaultBCP47, FDisablePackages, FDefaultUILanguage: string;
FStartWithConfiguration: Boolean;
begin
RegisterControlClasses;
@ -320,7 +329,7 @@ begin
KeyboardFileNames := TStringList.Create;
try
FParentWindow := 0;
if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow) then
if not Init(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID) then
begin
//TODO: TUtilExecute.Shell(PChar('hh.exe mk:@MSITStore:'+ExtractFilePath(KMShellExe)+'keyman.chm::/context/keyman_usage.html'), SW_SHOWNORMAL);
Exit;
@ -328,7 +337,7 @@ begin
if not LoadKMCOM then Exit;
try
RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow);
RunKMCOM(FMode, KeyboardFileNames, FSilent, FForce, FNoWelcome, FLogFile, FQuery, FDisablePackages, FDefaultUILanguage, FStartWithConfiguration, FParentWindow, FDefaultBCP47, FDefaultLangID);
finally
kmcom := nil;
end;
@ -366,8 +375,10 @@ begin
end;
procedure RunKMCOM(FMode: TKMShellMode; KeyboardFileNames: TStrings; FSilent, FForce, FNoWelcome: Boolean;
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean; FParentWindow: THandle);
FLogFile, FQuery: string; FDisablePackages, FDefaultUILanguage: string; FStartWithConfiguration: Boolean;
FParentWindow: THandle; const FDefaultBCP47: string; FDefaultLangID: Integer);
var
kdl: IKeymanDefaultLanguage;
FIcon: string;
FMutex: TKeymanMutex; // I2720
function FirstKeyboardFileName: WideString;
@ -440,6 +451,12 @@ begin
if FileExists(FIcon) then
Application.Icon.LoadFromFile(FIcon);
if (FDefaultBCP47 <> '') or (FDefaultLangID <> 0) then
begin
if Supports(kmcom, IKeymanDefaultLanguage, kdl) then
kdl.SetDefaultLanguage(FDefaultBCP47, FDefaultLangID);
end;
case FMode of
fmKeyboardWelcome: // I2569
ShowKeyboardWelcome(FirstKeyboardFileName);

View file

@ -1856,6 +1856,7 @@ var
HasRules: Boolean;
sModifierBitmask: string;
fDisplayUnderlying: Boolean;
FOptionStores: string;
begin
Result := '';//UTF16SignatureW; // + '// compiled by Keyman Developer'+nl; // I3474
{ Locate the name of the keyboard }
@ -2067,6 +2068,7 @@ begin
Result := Result + Format('%sthis.KCSS="%s";%s', [FTabStop, RequotedString(sEmbedCSS), nl]);
{ Write the stores out }
FOptionStores := '';
fsp := fk.dpStoreArray;
for i := 0 to fk.cxStoreArray - 1 do
begin
@ -2081,18 +2083,26 @@ begin
//else if fsp.dwSystemID = TSS_VKDICTIONARY then // I3438, required for vkdictionary
// Result := Result + Format('%sthis.s%s=%s;%s', [FTabStop, JavaScript_Name(i, fsp.szName), JavaScript_Store(fsp.line, fsp.dpString), nl])
else if fsp.fIsOption and not fsp.fIsReserved then
begin
Result := Result + Format('%sthis.s%s=KeymanWeb.KLOAD(this.KI,"%s",%s);%s',
[FTabstop,
JavaScript_Name(i,fsp.szName),
JavaScript_Name(i,fsp.szName,True),
JavaScript_Store(fsp.line, fsp.dpString),
nl]) // I3429
else if fsp.dwSystemID = TSS_NONE then
nl]); // I3429
if FOptionStores <> '' then
FOptionStores := FOptionStores + ',';
FOptionStores := FOptionStores + Format('''s%s''', [JavaScript_Name(i,fsp.szName)]);
end
else if fsp.dwSystemID = TSS_NONE {aka not fsp.fIsReserved} then
Result := Result + Format('%sthis.s%s=%s;%s', [FTabStop, JavaScript_Name(i, fsp.szName), JavaScript_Store(fsp.line, fsp.dpString), nl]); // I3681
end;
Inc(fsp);
end;
Result := Result + Format('%sthis.KVS=[%s];%s', [FTabStop, FOptionStores, nl]);
{ Write the groups out }
// I853 - begin unicode missing causes crash

View file

@ -377,7 +377,7 @@
{"id": "K_2","layer":"shift","text": "@"},
{"id": "K_3","layer":"shift","text": "#"},
{"id": "K_5","layer":"shift","text": "%"},
{"id": "K_6","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": "|"},

View file

@ -22,7 +22,7 @@
{"id": "K_EQUAL","text": "="},
{"id": "K_BKSP","text": "*BkSp*","width": "100","sp": "1"}
]
},
},
{
"id": 2,
"key": [
@ -38,7 +38,7 @@
{"id": "K_P","text":"p"},
{"id": "K_LBRKT","text":"["},
{"id": "K_RBRKT","text":"]"},
{"sp":"10","width":"10"}
{"sp":"10","width":"10"}
]
},
{
@ -84,7 +84,7 @@
{"id": "K_LALT","text": "*Alt*","width": "130","sp": "1"},
{"id": "K_SPACE","text": "","width": "675","sp": "0"},
{"id": "K_RALT","text": "*AltGr*","width": "130","sp": "1"},
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "1"}
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "1"}
]
}
]
@ -109,7 +109,7 @@
{"id": "K_EQUAL","text": "+"},
{"id": "K_BKSP","text": "*BkSp*","width": "100","sp": "1"}
]
},
},
{
"id": 2,
"key": [
@ -125,7 +125,7 @@
{"id": "K_P","text":"P"},
{"id": "K_LBRKT","text":"{"},
{"id": "K_RBRKT","text":"}"},
{"sp":"10","width":"10"}
{"sp":"10","width":"10"}
]
},
{
@ -171,7 +171,7 @@
{"id": "K_LALT","text": "*Alt*","width": "130","sp": "1"},
{"id": "K_SPACE","text": "","width": "675","sp": "0"},
{"id": "K_RALT","text": "*AltGr*","width": "130","sp": "1"},
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "1"}
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "1"}
]
}
]
@ -196,7 +196,7 @@
{"id": "K_EQUAL"},
{"id": "K_BKSP","text": "*BkSp*","width": "100","sp": "1"}
]
},
},
{
"id": 2,
"key": [
@ -212,7 +212,7 @@
{"id": "K_P"},
{"id": "K_LBRKT"},
{"id": "K_RBRKT"},
{"sp":"10","width":"10"}
{"sp":"10","width":"10"}
]
},
{
@ -258,7 +258,7 @@
{"id": "K_LALT","text": "*Alt*","width": "130","sp": "1"},
{"id": "K_SPACE","text": "","width": "675","sp": "0"},
{"id": "K_RALT","text": "*AltGr*","width": "130","sp": "1"},
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "2"}
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "2"}
]
}
]
@ -283,7 +283,7 @@
{"id": "K_EQUAL"},
{"id": "K_BKSP","text": "*BkSp*","width": "100","sp": "1"}
]
},
},
{
"id": 2,
"key": [
@ -299,7 +299,7 @@
{"id": "K_P"},
{"id": "K_LBRKT"},
{"id": "K_RBRKT"},
{"sp":"10","width":"10"}
{"sp":"10","width":"10"}
]
},
{
@ -345,7 +345,7 @@
{"id": "K_LALT","text": "*Alt*","width": "130","sp": "1"},
{"id": "K_SPACE","text": "","width": "675","sp": "0"},
{"id": "K_RALT","text": "*AltGr*","width": "130","sp": "1"},
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "2"}
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "2"}
]
}
]
@ -370,7 +370,7 @@
{"id": "K_EQUAL"},
{"id": "K_BKSP","text": "*BkSp*","width": "100","sp": "1"}
]
},
},
{
"id": 2,
"key": [
@ -386,7 +386,7 @@
{"id": "K_P"},
{"id": "K_LBRKT"},
{"id": "K_RBRKT"},
{"sp":"10","width":"10"}
{"sp":"10","width":"10"}
]
},
{
@ -432,7 +432,7 @@
{"id": "K_LALT","text": "*Alt*","width": "130","sp": "2"},
{"id": "K_SPACE","text": "","width": "675","sp": "0"},
{"id": "K_RALT","text": "*AltGr*","width": "130","sp": "2"},
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "1"}
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "1"}
]
}
]
@ -457,7 +457,7 @@
{"id": "K_EQUAL"},
{"id": "K_BKSP","text": "*BkSp*","width": "100","sp": "1"}
]
},
},
{
"id": 2,
"key": [
@ -473,7 +473,7 @@
{"id": "K_P"},
{"id": "K_LBRKT"},
{"id": "K_RBRKT"},
{"sp":"10","width":"10"}
{"sp":"10","width":"10"}
]
},
{
@ -519,7 +519,7 @@
{"id": "K_LALT","text": "*Alt*","width": "130","sp": "2"},
{"id": "K_SPACE","text": "","width": "675","sp": "0"},
{"id": "K_RALT","text": "*AltGr*","width": "130","sp": "2"},
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "1"}
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "1"}
]
}
]
@ -544,7 +544,7 @@
{"id": "K_EQUAL"},
{"id": "K_BKSP","text": "*BkSp*","width": "100","sp": "1"}
]
},
},
{
"id": 2,
"key": [
@ -560,7 +560,7 @@
{"id": "K_P"},
{"id": "K_LBRKT"},
{"id": "K_RBRKT"},
{"sp":"10","width":"10"}
{"sp":"10","width":"10"}
]
},
{
@ -606,7 +606,7 @@
{"id": "K_LALT","text": "*Alt*","width": "130","sp": "2"},
{"id": "K_SPACE","text": "","width": "675","sp": "0"},
{"id": "K_RALT","text": "*AltGr*","width": "130","sp": "2"},
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "2"}
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "2"}
]
}
]
@ -631,7 +631,7 @@
{"id": "K_EQUAL"},
{"id": "K_BKSP","text": "*BkSp*","width": "100","sp": "1"}
]
},
},
{
"id": 2,
"key": [
@ -647,7 +647,7 @@
{"id": "K_P"},
{"id": "K_LBRKT"},
{"id": "K_RBRKT"},
{"sp":"10","width":"10"}
{"sp":"10","width":"10"}
]
},
{
@ -693,7 +693,7 @@
{"id": "K_LALT","text": "*Alt*","width": "130","sp": "2"},
{"id": "K_SPACE","text": "","width": "675","sp": "0"},
{"id": "K_RALT","text": "*AltGr*","width": "130","sp": "2"},
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "2"}
{"id": "K_RCONTROL","text": "*Ctrl*","width": "130","sp": "2"}
]
}
]
@ -733,7 +733,7 @@
{"id": "K_J","text":"j"},
{"id": "K_K","text":"k"},
{"id": "K_L","text":"l"},
{"text": "","width": "10","sp": "10"}
{"text": "","width": "10","sp": "10"}
]
},
{
@ -802,7 +802,7 @@
{"id": "K_J","text":"J"},
{"id": "K_K","text":"K"},
{"id": "K_L","text":"L"},
{"text": "","width": "10","sp": "10"}
{"text": "","width": "10","sp": "10"}
]
},
{
@ -866,7 +866,7 @@
{"id": "K_2","layer":"shift","text": "@"},
{"id": "K_3","layer":"shift","text": "#"},
{"id": "K_5","layer":"shift","text": "%"},
{"id": "K_6","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": "|"},

View file

@ -179,8 +179,8 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\..\Projects\keyman\open\windows\src\global\inc\keyman64.h" />
<ClInclude Include="..\..\ext\sentry\sentry.h" />
<ClInclude Include="..\..\global\inc\keyman64.h" />
<ClInclude Include="..\..\global\inc\keymansentry.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
@ -207,4 +207,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

@ -18,15 +18,15 @@
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\Projects\keyman\open\windows\src\global\inc\keyman64.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\global\inc\keymansentry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\ext\sentry\sentry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\global\inc\keyman64.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">

View file

@ -54,9 +54,11 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(ProjectDir)obj\$(Platform)\$(Configuration)\</IntDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IncludePath>$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Midl>

View file

@ -15,7 +15,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mcompile", "mcompile\mcompi
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "kmrefresh", "kmrefresh\kmrefresh.vcxproj", "{A3B8F75F-E63E-434E-8A2A-034AD9B66571}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "keyman32-tests", "keyman32\tests\keyman32-tests\keyman32-tests.vcxproj", "{46399ED7-79A1-4E7E-BD96-4B1AEEC838AE}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "keyman-engine-tests", "keyman32\tests\keyman-engine-tests\keyman-engine-tests.vcxproj", "{46399ED7-79A1-4E7E-BD96-4B1AEEC838AE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "keyman-engine", "keyman32\keyman-engine.vcxproj", "{A7069186-5AE7-4504-8926-861B7A34BA9E}"
EndProject

View file

@ -208,6 +208,7 @@ type
procedure tmrCheckInputPaneTimer(Sender: TObject);
procedure tmrRefreshTimer(Sender: TObject);
private
FCoreTrayIcon: TKeymanTrayIcon;
InMenuLoop: Integer; // I1082 - Avoid menu nasty flicker with rapid click
FClosingApp: Boolean;
FRunningProduct: TRunningProduct;
@ -301,6 +302,7 @@ type
procedure HotkeyWndProc(var Message: TMessage);
procedure DoLanguageHotkey(Index: Integer);
procedure CreateCoreTrayIcon;
protected
procedure DoInterfaceHotkey(Target: Integer);
@ -502,6 +504,38 @@ begin
end;
end;
procedure TfrmKeyman7Main.CreateCoreTrayIcon;
var
cust: IKeymanCustomisation;
istrm: IStream;
olestrm: TOleStream;
begin
if not Reg_GetDebugFlag(SRegValue_Flag_UseKeymanCore, True) then
Exit;
FCoreTrayIcon := TKeymanTrayIcon.Create(Self);
cust := kmint.KeymanCustomisation;
istrm := cust.CustFile['core.ico'];
if istrm <> nil then
begin
olestrm := TOLEStream.Create(istrm);
try
// In some situations, launching the app multiple times rapidly can
// cause the icon to be loaded multiple times. Make sure we reset the
// stream position before we try and read.
olestrm.Position := 0;
FCoreTrayIcon.Icon.LoadFromStream(olestrm);
FCoreTrayIcon.Hint := 'Keyman Engine is using Keyman Core library ("engine.compatibility.use_keyman_core" system setting)';
FCoreTrayIcon.Visible := True;
finally
olestrm.Free;
istrm := nil;
end;
end;
end;
procedure TfrmKeyman7Main.FormCreate(Sender: TObject);
begin
if GetOs in [osVista, osWin7] then // I4576
@ -1283,6 +1317,7 @@ begin
end;
end;
CreateCoreTrayIcon;
//Windows.MessageBox(Handle, PChar(IntToStr(kmcom._AddRef)), 'RefCount+1', MB_OK);
try

View file

@ -75,12 +75,63 @@ BOOL GetKeyboardFileName(LPSTR kbname, LPSTR buf, int nbuf)
return n;
}
BOOL LoadlpKeyboardCore(int i)
{
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: Enter ---");
PKEYMAN64THREADDATA _td = ThreadGlobals();
if (!_td) return FALSE;
if (_td->lpKeyboards[i].lpCoreKeyboard) return TRUE;
if (_td->lpActiveKeyboard == &_td->lpKeyboards[i]) _td->lpActiveKeyboard = NULL; // I822 TSF not working
if (_td->lpKeyboards[i].lpCoreKeyboardState) {
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: a keyboard km_kbp_state exits without matching keyboard - disposing of state");
km_kbp_state_dispose(_td->lpKeyboards[i].lpCoreKeyboardState);
_td->lpKeyboards[i].lpCoreKeyboardState = NULL;
}
char buf[256];
if (!GetKeyboardFileName(_td->lpKeyboards[i].Name, buf, 255)) return FALSE;
PWCHAR keyboardPath = strtowstr(buf);
km_kbp_status err_status = km_kbp_keyboard_load(keyboardPath, &_td->lpKeyboards[i].lpCoreKeyboard);
if (err_status != KM_KBP_STATUS_OK) {
SendDebugMessageFormat(0, sdmLoad, 0, "LoadlpKeyboardCore: km_kbp_keyboard_load failed for %ls with error status [%d]", keyboardPath, err_status);
delete keyboardPath;
return FALSE;
}
delete keyboardPath;
// TODO: 5650 handle dlls
//LoadDLLs(&_td->lpKeyboards[i]);
const km_kbp_option_item test_env_opts[] =
{
KM_KBP_OPTIONS_END
};
err_status = km_kbp_state_create(_td->lpKeyboards[i].lpCoreKeyboard, test_env_opts, &_td->lpKeyboards[i].lpCoreKeyboardState);
if (err_status != KM_KBP_STATUS_OK) {
SendDebugMessageFormat(
0, sdmLoad, 0, "LoadlpKeyboardCore: km_kbp_state_create failed with error status [%d]", err_status);
// Dispose of the keyboard to leave us in a consistent state
ReleaseKeyboardMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboard);
return FALSE;
}
LoadKeyboardOptionsREGCore(&_td->lpKeyboards[i], _td->lpKeyboards[i].lpCoreKeyboardState);
return TRUE;
}
BOOL LoadlpKeyboard(int i)
{
if (Globals::get_CoreIntegration())
{
return LoadlpKeyboardCore(i);
}
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
if(_td->lpKeyboards[i].Keyboard) return TRUE;
if(_td->lpActiveKeyboard == &_td->lpKeyboards[i]) _td->lpActiveKeyboard = NULL; // I822 TSF not working
char buf[256];

View file

@ -565,18 +565,46 @@ extern "C" BOOL _declspec(dllexport) WINAPI Keyman_ForceKeyboard(PCSTR FileName
_td->lpActiveKeyboard->IMDLLs = NULL;
_td->lpActiveKeyboard->KeyboardOptions = NULL;*/
_splitpath_s(FileName, NULL, 0, NULL, 0, _td->lpActiveKeyboard->Name, sizeof(_td->lpActiveKeyboard->Name), NULL, 0);
if(LoadKeyboard(_td->ForceFileName, &_td->lpActiveKeyboard->Keyboard))
{
SendDebugMessageFormat(0,sdmGlobal,0,"Keyman_ForceKeyboard: %s OK", FileName);
ResetCapsLock();
LoadDLLs(_td->lpActiveKeyboard);
ActivateDLLs(_td->lpActiveKeyboard);
LoadKeyboardOptions(_td->lpActiveKeyboard); // I2437 - Crash unloading keyboard due to keyboard options not set
// TODO: 5442 - remove if/ else as there will no longer be the old LoadKeyboard option
if (Globals::get_CoreIntegration()) {
PWCHAR keyboardPath = strtowstr(_td->ForceFileName);
km_kbp_status err_status = km_kbp_keyboard_load(keyboardPath, &_td->lpActiveKeyboard->lpCoreKeyboard);
if (err_status != KM_KBP_STATUS_OK) {
SendDebugMessageFormat(0, sdmGlobal, 0, "Keyman_ForceKeyboard Core: km_kbp_keyboard_load failed for %ls with error status [%d]", keyboardPath, err_status); // TODO: 5442 - remove word Core
delete keyboardPath;
return FALSE;
}
delete keyboardPath;
SendDebugMessageFormat(0, sdmGlobal, 0, "Keyman_ForceKeyboard Core: %s OK", FileName); // TODO: 5442 - remove word Core
// TODO: #5650 Equivalent for common core
// LoadDLLs(&_td->lpKeyboards[i]);
const km_kbp_option_item test_env_opts[] = {KM_KBP_OPTIONS_END};
err_status =
km_kbp_state_create(_td->lpActiveKeyboard->lpCoreKeyboard, test_env_opts, &_td->lpActiveKeyboard->lpCoreKeyboardState);
if (err_status != KM_KBP_STATUS_OK) {
SendDebugMessageFormat(
0, sdmGlobal, 0, "Keyman_ForceKeyboard Core: km_kbp_state_create failed with error status [%d]", err_status);
// Dispose of the keyboard to leave us in a consitent state
ReleaseKeyboardMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboard);
return FALSE;
}
// TODO: 5650 LoadDLLs
// TODO: 5652 verify - ResetCapsLock();
ResetCapsLock();
LoadKeyboardOptionsREGCore(_td->lpActiveKeyboard, _td->lpActiveKeyboard->lpCoreKeyboardState);
RefreshPreservedKeys(TRUE);
return TRUE;
}
return TRUE;
} else {
if (LoadKeyboard(_td->ForceFileName, &_td->lpActiveKeyboard->Keyboard)) {
SendDebugMessageFormat(0, sdmGlobal, 0, "Keyman_ForceKeyboard: %s OK", FileName);
ResetCapsLock();
LoadDLLs(_td->lpActiveKeyboard);
ActivateDLLs(_td->lpActiveKeyboard);
LoadKeyboardOptions(_td->lpActiveKeyboard); // I2437 - Crash unloading keyboard due to keyboard options not set
RefreshPreservedKeys(TRUE);
return TRUE;
}
}
SendDebugMessageFormat(0,sdmGlobal,0,"Keyman_ForceKeyboard: %s FAIL", FileName);
delete _td->lpActiveKeyboard;
@ -609,6 +637,8 @@ extern "C" BOOL _declspec(dllexport) WINAPI Keyman_StopForcingKeyboard()
_td->ForceFileName[0] = 0;
FreeKeyboardOptions(_td->lpActiveKeyboard);
ReleaseKeyboardMemory(_td->lpActiveKeyboard->Keyboard);
ReleaseStateMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboardState);
ReleaseKeyboardMemoryCore(&_td->lpActiveKeyboard->lpCoreKeyboard);
RefreshPreservedKeys(FALSE);
delete _td->lpActiveKeyboard;
_td->lpActiveKeyboard = NULL;
@ -653,6 +683,21 @@ BOOL ReleaseKeyboardMemory(LPKEYBOARD kbd)
return TRUE;
}
BOOL ReleaseStateMemoryCore(km_kbp_state **state) {
if (!*state) return TRUE;
km_kbp_state_dispose(*state);
*state = NULL;
return TRUE;
}
BOOL ReleaseKeyboardMemoryCore(km_kbp_keyboard **kbd) {
if (!*kbd)
return TRUE;
km_kbp_keyboard_dispose(*kbd);
*kbd = NULL;
return TRUE;
}
//---------------------------------------------------------------------------------------------------------
//
// Selecting Keyman Keyboards
@ -982,6 +1027,9 @@ void ReleaseKeyboards(BOOL Lock)
if(Lock) UnloadDLLs(&_td->lpKeyboards[i]);
FreeKeyboardOptions(&_td->lpKeyboards[i]);
ReleaseKeyboardMemory(_td->lpKeyboards[i].Keyboard);
ReleaseStateMemoryCore(&_td->lpKeyboards[i].lpCoreKeyboardState);
ReleaseKeyboardMemoryCore(&_td->lpKeyboards[i].lpCoreKeyboard);
if(_td->lpKeyboards[i].Profiles) delete _td->lpKeyboards[i].Profiles; // I3581
}

View file

@ -55,11 +55,11 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LibraryPath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x86\$(Configuration);$(LibraryPath)</LibraryPath>
<IncludePath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\include;$(IncludePath)</IncludePath>
<IncludePath>$(ProjectDir)..\..\..\..\common\core\desktop\include;$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\src;$(ProjectDir)..\..\..\..\common\core\desktop\build\rust\x86\$(Configuration);$(LibraryPath)</LibraryPath>
<IncludePath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\include;$(IncludePath)</IncludePath>
<IncludePath>$(ProjectDir)..\..\..\..\common\core\desktop\build\x86\$(Configuration)\include;$(ProjectDir)..\..\..\..\common\core\desktop\include;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Midl>
@ -95,7 +95,7 @@
</ResourceCompile>
<Link>
<AdditionalOptions>/verbose:lib /section:.SHARDATA,rws %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>kmnkbp0.lib;keyman_keyboard_processor_native.lib;psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libkmnkbp0.a;keyman_keyboard_processor_native.lib;psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ModuleDefinitionFile>keyman32.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -151,7 +151,7 @@
</ResourceCompile>
<Link>
<AdditionalOptions>/verbose:lib /section:.SHARDATA,rws %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>kmnkbp0.lib;keyman_keyboard_processor_native.lib;psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>libkmnkbp0.a;keyman_keyboard_processor_native.lib;psapi.lib;rpcrt4.lib;version.lib;setupapi.lib;iphlpapi.lib;imm32.lib;crypt32.lib;wintrust.lib;imagehlp.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<ModuleDefinitionFile>keyman32.def</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -295,6 +295,7 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="kmprocessactions.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
@ -371,6 +372,7 @@
<ClInclude Include="capsstate.h" />
<ClInclude Include="..\..\global\inc\Compiler.h" />
<ClInclude Include="globals.h" />
<ClInclude Include="kmprocessactions.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="hotkeys.h" />
<ClInclude Include="k32_tsf.h" />

View file

@ -135,6 +135,9 @@
<ClCompile Include="DebugEventTrace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="kmprocessactions.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="KEYMAN32.DEF">
@ -243,8 +246,11 @@
<ClInclude Include="..\..\global\inc\keymanengine.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="kmprocessactions.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="keyman-debug-etw.man" />
</ItemGroup>
</Project>
</Project>

View file

@ -198,6 +198,7 @@ extern "C" __declspec(dllexport) BOOL WINAPI TIPProcessKey(WPARAM wParam, LPARAM
*Globals::ShiftState() = (LocalShiftState & K_NOTMODIFIERFLAG) | NewShiftState; // I3588
}
BOOL isUsingCoreProcessor = Globals::get_CoreIntegration();
_td->TIPFUpdateable = Updateable;
_td->TIPFPreserved = Preserved; // I4290
@ -206,35 +207,58 @@ extern "C" __declspec(dllexport) BOOL WINAPI TIPProcessKey(WPARAM wParam, LPARAM
_td->state.msg.message = wm_keymankeydown;
_td->state.vkey = (WORD) wParam;
_td->state.lpkb = _td->lpActiveKeyboard->Keyboard;
if (isUsingCoreProcessor) {
_td->state.lpCoreKb = _td->lpActiveKeyboard->lpCoreKeyboard;
} else {
_td->state.lpkb = _td->lpActiveKeyboard->Keyboard;
_td->state.startgroup = &_td->state.lpkb->dpGroupArray[_td->state.lpkb->StartGroup[BEGIN_UNICODE]];
_td->state.NoMatches = TRUE;
_td->state.LoopTimes = 0;
_td->state.StopOutput = FALSE;
}
_td->state.windowunicode = TRUE;
_td->state.startgroup = &_td->state.lpkb->dpGroupArray[_td->state.lpkb->StartGroup[BEGIN_UNICODE]];
_td->state.NoMatches = TRUE;
_td->state.LoopTimes = 0;
_td->state.StopOutput = FALSE;
_td->state.charCode = CharFromVK(&_td->state.vkey, Globals::get_ShiftState()); // I4582
_td->TIPProcessOutput = outfunc;
_td->TIPGetContext = ctfunc;
AppContextWithStores *savedContext = NULL; // I4370 // I4978
if(!Updateable) { // I4370
savedContext = new AppContextWithStores(_td->lpActiveKeyboard->Keyboard->cxStoreArray); // I4978
_td->app->SaveContext(savedContext);
AppContextWithStores *savedContext = NULL; // I4370 // I4978
AppContext *savedContextUsingCore = NULL; // used for common core
km_kbp_option_item *SavedKBDOptions = NULL; // used for common core
if (!Updateable) {
if (isUsingCoreProcessor) {
savedContextUsingCore = new AppContext();
_td->app->CopyContext(savedContextUsingCore);
SavedKBDOptions = SaveKeyboardOptionsCore(_td->lpActiveKeyboard);
} else { // I4370
savedContext = new AppContextWithStores(_td->lpActiveKeyboard->Keyboard->cxStoreArray); // I4978
_td->app->SaveContext(savedContext);
}
}
BOOL res = ProcessHook();
BOOL res = ProcessHook();
if(!Updateable) { // I4370
if(res) { // I4585
// Reset the context if match found
_td->app->RestoreContext(savedContext);
if (!Updateable) {
if (isUsingCoreProcessor) {
if (res) {
// Reset the context if match found
_td->app->RestoreContextOnly(savedContextUsingCore);
RestoreKeyboardOptionsCore(_td->lpActiveKeyboard->lpCoreKeyboardState, SavedKBDOptions);
DisposeKeyboardOptionsCore(&SavedKBDOptions);
delete savedContextUsingCore;
savedContextUsingCore = NULL;
}
} else { // I4370
if (res) { // I4585
// Reset the context if match found
_td->app->RestoreContext(savedContext);
delete savedContext;
savedContext = NULL;
}
}
delete savedContext;
savedContext = NULL;
}
_td->TIPProcessOutput = NULL;
@ -454,6 +478,14 @@ void AITIP::RestoreContext(AppContextWithStores *savedContext) { // I4370 //
}
}
void AITIP::CopyContext(AppContext *savedContext) {
savedContext->CopyFrom(context);
}
void AITIP::RestoreContextOnly(AppContext *savedContext) {
context->CopyFrom(savedContext);
}
/* Output actions */
BOOL AITIP::QueueAction(int ItemType, DWORD dwData) {

View file

@ -1,18 +1,18 @@
/*
Name: aiTIP
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Documentation:
Description:
Create Date: 11 Dec 2009
Modified Date: 23 Feb 2016
Authors: mcdurdin
Related Files:
Dependencies:
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
Bugs:
Todo:
Notes:
History: 11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
24 Jun 2010 - mcdurdin - I2436 - Add space to context for AIWin2000Unicode when not matched
24 Apr 2014 - mcdurdin - I4196 - V9.0 - wm_kmmoreposting must be refactored for TIP work as it is not sequential
@ -71,14 +71,29 @@ public:
BOOL DebugControlled();
// TODO: 5442 This would be better to called SaveContextWithStores or SaveContextWithKbdOptions
// Will be removed with 5442 when removing window core
void SaveContext(AppContextWithStores *savedContext); // I4370 // I4978
void RestoreContext(AppContextWithStores *savedContext); // I4370 // I4978
/**
* Copy the member context
*
* @param[out] savedContext the copied context
*/
void CopyContext(AppContext *savedContext);
/**
* Restore the passed context to the member context
*
* @param savedContext the context to restore
*/
void RestoreContextOnly(AppContext *savedContext);
virtual BOOL QueueAction(int ItemType, DWORD dwData);
/* Information functions */
virtual BOOL CanHandleWindow(HWND ahwnd);
virtual BOOL IsWindowHandled(HWND ahwnd);
virtual BOOL HandleWindow(HWND ahwnd);
@ -89,7 +104,7 @@ public:
virtual void ReadContext();
/* Queue and sending functions */
virtual BOOL SendActions(); // I4196
virtual BOOL QueueDebugInformation(int ItemType, LPGROUP Group, LPKEY Rule, PWSTR fcontext, PWSTR foutput, DWORD_PTR dwExtraFlags);

View file

@ -116,6 +116,11 @@ WCHAR *AIWin2000Unicode::ContextBufMax(int n)
{
return context->BufMax(n);
}
void AIWin2000Unicode::SetContext(const WCHAR* buf)
{
return context->Set(buf);
}
BYTE SavedKbdState[256];

View file

@ -12,7 +12,7 @@
Bugs:
Todo:
Notes:
Notes:
History: 27 Jan 2009 - mcdurdin - I1797 - Add fallback for AIWin2000 app integration
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
24 Jun 2010 - mcdurdin - I2436 - Add space to context for AIWin2000Unicode when not matched
@ -43,7 +43,7 @@ public:
virtual BOOL QueueAction(int ItemType, DWORD dwData);
/* Information functions */
virtual BOOL CanHandleWindow(HWND ahwnd);
virtual BOOL IsWindowHandled(HWND ahwnd);
virtual BOOL HandleWindow(HWND ahwnd);
@ -56,9 +56,10 @@ public:
virtual void AddContext(WCHAR ch); //I2436
virtual WCHAR *ContextBuf(int n);
virtual WCHAR *ContextBufMax(int n);
virtual void SetContext(const WCHAR* buf);
/* Queue and sending functions */
virtual BOOL SendActions(); // I4196
virtual BOOL QueueDebugInformation(int ItemType, LPGROUP Group, LPKEY Rule, PWSTR fcontext, PWSTR foutput, DWORD_PTR dwExtraFlags);
};

View file

@ -203,3 +203,33 @@ AppIntegration::AppIntegration()
hwnd = NULL;
FShiftFlags = 0;
}
BOOL ContextItemsFromAppContext(WCHAR const* buf, km_kbp_context_item** outPtr)
{
assert(buf);
assert(outPtr);
km_kbp_context_item* context_items = new km_kbp_context_item[wcslen(buf) + 1];
WCHAR const *p = buf;
uint8_t contextIndex = 0;
while (*p) {
if (*p == UC_SENTINEL) {
assert(*(p + 1) == CODE_DEADKEY);
// we know the only uc_sentinel code in the context is code_deadkey, which has only 1 parameter: uc_sentinel code_deadkey <deadkey_id>
// setup dead key context item
p += 2;
context_items[contextIndex++] = km_kbp_context_item{ KM_KBP_CT_MARKER, {0,}, {*p} };
} else if (Uni_IsSurrogate1(*p) && Uni_IsSurrogate2(*(p + 1))) {
// handle surrogate
context_items[contextIndex++] = km_kbp_context_item{ KM_KBP_CT_CHAR, {0,}, {(char32_t)Uni_SurrogateToUTF32(*p, *(p + 1))} };
p++;
} else {
context_items[contextIndex++] = km_kbp_context_item{ KM_KBP_CT_CHAR, {0,}, {*p} };
}
p++;
}
// terminate the context_items array.
context_items[contextIndex] = km_kbp_context_item KM_KBP_CONTEXT_ITEM_END;
*outPtr = context_items;
return true;
}

View file

@ -208,6 +208,16 @@ public:
virtual BOOL SendActions() = 0; // I4196
};
/**
* Convert AppContext array into an array of core context items.
* Caller is responsible for freeing the memory.
*
* @param buf appcontext character array
* @param outPtr The ouput array of context items. caller to free memory
* @return BOOL True if array created succesfully
*/
BOOL ContextItemsFromAppContext(WCHAR const* buf, km_kbp_context_item** outPtr);
extern const LPSTR ItemTypes[];
#endif

View file

@ -143,7 +143,8 @@ BOOL LoadDLLs(LPINTKEYBOARDINFO lpkbi)
if(lpkbi->nIMDLLs > 0) if(!UnloadDLLs(lpkbi)) return FALSE;
if(!GetKeyboardFileName(lpkbi->Name, fullname, _MAX_PATH)) return FALSE;
if(!GetKeyboardFileName(lpkbi->Name, fullname, _MAX_PATH)) return FALSE;
if (!lpkbi->Keyboard) return FALSE;
for(DWORD i = 0; i < lpkbi->Keyboard->cxStoreArray; i++)
{
@ -224,8 +225,8 @@ BOOL DeactivateDLLs(LPINTKEYBOARDINFO lpkbi)
void CallDLL(LPINTKEYBOARDINFO lpkbi, DWORD storenum)
{
//SendDebugMessageFormat(0, sdmKeyboard, 0, "CallDll: Enter");
if(storenum >= lpkbi->Keyboard->cxStoreArray) return;
if (!lpkbi->Keyboard) return;
if(storenum >= lpkbi->Keyboard->cxStoreArray) return;
LPSTORE s = &lpkbi->Keyboard->dpStoreArray[storenum];
if(s->dwSystemID != TSS_CALLDEFINITION) return;

View file

@ -34,8 +34,8 @@ void ResetCapsLock(void)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if (!_td) return;
if (!_td->lpActiveKeyboard) return;
if (!_td->lpActiveKeyboard->Keyboard) return;
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: enter");
@ -58,6 +58,7 @@ void KeyCapsLockPress(BOOL FIsUp) // I3284 - void // I3529
PKEYMAN64THREADDATA _td = ThreadGlobals();
if (!_td) return;
if (!_td->lpActiveKeyboard) return; // pass through to window
if (!_td->lpActiveKeyboard->Keyboard) return;
if (_td->lpActiveKeyboard->Keyboard->dwFlags & KF_CAPSONONLY)
{
@ -85,6 +86,7 @@ void KeyShiftPress(BOOL FIsUp) // I3284 - void // I3529
PKEYMAN64THREADDATA _td = ThreadGlobals();
if (!_td) return;
if (!_td->lpActiveKeyboard) return; // pass through to window
if (!_td->lpActiveKeyboard->Keyboard) return;
if (_td->lpActiveKeyboard->Keyboard->dwFlags & KF_SHIFTFREESCAPS)
{

View file

@ -149,6 +149,7 @@ public:
static BOOL get_debug_KeymanLog();
static BOOL get_debug_ToConsole();
static BOOL get_CoreIntegration();
static void LoadDebugSettings();
};
@ -191,6 +192,7 @@ typedef struct tagKEYMAN64THREADDATA
{
LPINTKEYBOARDINFO lpKeyboards; // keyboard definitions
LPINTKEYBOARDINFO lpActiveKeyboard;
// I3616
LPMSG msgbuf; // Message buffer (alloc at runtime)

View file

@ -306,6 +306,18 @@ char *Debug_UnicodeString(PWSTR s, int x) {
return bufout[x];
}
BOOL DebugAssert_1(BOOL condition, char *message, char *file, int line)
{
if (!(condition)) {
SendDebugMessage_1(0, sdmGlobal, 0, file, line, message);
if (IsDebugAssertEnabled()) {
assert(condition);
}
return FALSE;
}
return TRUE;
}
#ifdef _DEBUG
void _OutputThreadDebugString(char *s) {
char buf[256];
@ -314,6 +326,15 @@ void _OutputThreadDebugString(char *s) {
}
#endif
BOOL IsDebugAssertEnabled()
{
#ifdef _DEBUG
return IsDebuggerPresent();
#else
return FALSE;
#endif
}
void WINAPI Keyman_Diagnostic(int mode) {
if (mode == 0) {
RaiseException(0xDEADBEEF, EXCEPTION_NONCONTINUABLE, 0, NULL);

View file

@ -287,6 +287,9 @@ static BOOL
f_debug_KeymanLog = FALSE,
f_debug_ToConsole = FALSE;
static BOOL
f_CoreIntegration = TRUE;
#pragma data_seg()
/***************************************************************************/
@ -361,6 +364,8 @@ BOOL Globals::get_MnemonicDeadkeyConversionMode() { return f_MnemonicDeadkeyConv
BOOL Globals::get_debug_KeymanLog() { return f_debug_KeymanLog; }
BOOL Globals::get_debug_ToConsole() { return f_debug_ToConsole; }
BOOL Globals::get_CoreIntegration() { return f_CoreIntegration; }
void Globals::SetBaseKeyboardName(wchar_t *baseKeyboardName, wchar_t *baseKeyboardNameAlt) { // I4583
wcscpy_s(f_BaseKeyboardName, baseKeyboardName);
wcscpy_s(f_BaseKeyboardNameAlt, baseKeyboardNameAlt);
@ -379,6 +384,9 @@ void Globals::SetBaseKeyboardFlags(char *baseKeyboard, BOOL simulateAltGr, BOOL
be changed until Keyman is restarted.
*/
BOOL Globals::InitSettings() {
/* Check for common core vs windows core */
f_CoreIntegration = Reg_GetDebugFlag(REGSZ_Flag_UseKeymanCore, TRUE);
SendDebugMessageFormat(0, sdmAIDefault, 0, "Globals::InitSettings - Coreintegration set in '" REGSZ_Flag_UseKeymanCore "' to %x", f_CoreIntegration);
f_vk_prefix = _VK_PREFIX_DEFAULT;
RegistryReadOnly reg(HKEY_LOCAL_MACHINE);
if (reg.OpenKeyReadOnly(REGSZ_KeymanLM) &&

Some files were not shown because too many files have changed in this diff Show more