diff --git a/HISTORY.md b/HISTORY.md
index b0587ac8fa..ec21fd7509 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -1,5 +1,23 @@
# Keyman Version History
+## 17.0.217 alpha 2023-11-24
+
+* feat(developer): warn on usage of virtual keys in rule output (#10062)
+* fix(core): memory management of options in action struct (#10073)
+* chore(linux): Update debian changelog (#10047)
+* chore(core): Add test keyboard for text selection tests (#10026)
+
+## 17.0.216 alpha 2023-11-23
+
+* fix(common): kmx struct alignment (#9977)
+* fix(developer): vis kbd callbacks instead of throw (#9979)
+* fix(core): dx: ldml: startContext should be optional in ldml test data (#10021)
+* chore(windows): remove `wm_keymandebug` messages and functions (#10055)
+* chore(windows): remove legacy LoadKeyboard (#10057)
+* chore(windows): remove unused globals relating to old keyboard debugging (#10058)
+* chore(core): remove vkey output from kmx processor (#10060)
+* fix(web): app/webview did not clear deadkeys on context-reset (#10039)
+
## 17.0.215 alpha 2023-11-22
* feat(core): ldml marker normalization (#9761)
diff --git a/VERSION.md b/VERSION.md
index 1a17e0d6c0..84c38c9084 100644
--- a/VERSION.md
+++ b/VERSION.md
@@ -1 +1 @@
-17.0.216
\ No newline at end of file
+17.0.218
\ No newline at end of file
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/HISTORY.md b/common/test/keyboards/text_selection_tests_keyboard_9073/HISTORY.md
new file mode 100644
index 0000000000..e7e7675aa4
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/HISTORY.md
@@ -0,0 +1,6 @@
+Text Selection Tests Keyboard Change History
+====================
+
+1.0 (2023-11-14)
+----------------
+* Created by Keyman Team
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/LICENSE.md b/common/test/keyboards/text_selection_tests_keyboard_9073/LICENSE.md
new file mode 100644
index 0000000000..f199066a02
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+© 2023 Keyman Team
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/README.md b/common/test/keyboards/text_selection_tests_keyboard_9073/README.md
new file mode 100644
index 0000000000..1ab216d60f
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/README.md
@@ -0,0 +1,31 @@
+Text Selection Tests Keyboard keyboard
+==============
+
+Version 1.0
+
+Description
+-----------
+Text Selection Tests Keyboard generated from template
+
+Links
+-----
+https://github.com/keymanapp/keyman/issues/9073
+
+Copyright
+---------
+See [LICENSE.md](LICENSE.md)
+
+Supported Platforms
+-------------------
+ * Windows
+ * macOS
+ * Linux
+ * Web
+ * iPhone
+ * iPad
+ * Android phone
+ * Android tablet
+ * Mobile devices
+ * Desktop devices
+ * Tablet devices
+
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/source/readme.htm b/common/test/keyboards/text_selection_tests_keyboard_9073/source/readme.htm
new file mode 100644
index 0000000000..1d87395da8
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/source/readme.htm
@@ -0,0 +1,24 @@
+
+
+
+
+
+ Text Selection Tests Keyboard
+
+
+
+
+Text Selection Tests Keyboard
+
+
+ Text Selection Tests Keyboard 1.0 generated from template.
+
+
+© Keyman Team
+
+
+
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.ico b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.ico
new file mode 100644
index 0000000000..6a5271df0c
Binary files /dev/null and b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.ico differ
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.keyman-touch-layout b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.keyman-touch-layout
new file mode 100644
index 0000000000..6d02edfad8
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.keyman-touch-layout
@@ -0,0 +1,532 @@
+{
+ "tablet": {
+ "displayUnderlying": false,
+ "layer": [
+ {
+ "id": "default",
+ "row": [
+ {
+ "id": 1,
+ "key": [
+ {
+ "id": "K_1",
+ "text": "1",
+ "nextlayer": "shift"
+ },
+ {
+ "id": "K_2",
+ "text": "2"
+ },
+ {
+ "id": "K_3",
+ "text": "3"
+ },
+ {
+ "id": "K_4",
+ "text": "4"
+ },
+ {
+ "id": "K_5",
+ "text": "5"
+ },
+ {
+ "id": "K_6",
+ "text": "6"
+ },
+ {
+ "id": "K_7",
+ "text": "7"
+ },
+ {
+ "id": "K_8",
+ "text": "8"
+ },
+ {
+ "id": "K_9",
+ "text": "9"
+ },
+ {
+ "id": "K_0",
+ "text": "0"
+ },
+ {
+ "id": "K_HYPHEN",
+ "text": "-"
+ },
+ {
+ "id": "K_EQUAL",
+ "text": "="
+ },
+ {
+ "id": "K_BKSP",
+ "text": "*BkSp*",
+ "width": 100,
+ "sp": 1
+ }
+ ]
+ },
+ {
+ "id": 2,
+ "key": [
+ {
+ "id": "K_Q",
+ "text": "q",
+ "pad": 75
+ },
+ {
+ "id": "K_W",
+ "text": "w"
+ },
+ {
+ "id": "K_E",
+ "text": "e"
+ },
+ {
+ "id": "K_R",
+ "text": "r"
+ },
+ {
+ "id": "K_T",
+ "text": "t"
+ },
+ {
+ "id": "K_Y",
+ "text": "y"
+ },
+ {
+ "id": "K_U",
+ "text": "u"
+ },
+ {
+ "id": "K_I",
+ "text": "i"
+ },
+ {
+ "id": "K_O",
+ "text": "o"
+ },
+ {
+ "id": "K_P",
+ "text": "p"
+ },
+ {
+ "id": "K_LBRKT",
+ "text": "["
+ },
+ {
+ "id": "K_RBRKT",
+ "text": "]"
+ },
+ {
+ "id": "T_new_136",
+ "width": 10,
+ "sp": 10
+ }
+ ]
+ },
+ {
+ "id": 3,
+ "key": [
+ {
+ "id": "K_BKQUOTE",
+ "text": "dk(1)"
+ },
+ {
+ "id": "K_A",
+ "text": "a"
+ },
+ {
+ "id": "K_S",
+ "text": "s"
+ },
+ {
+ "id": "K_D",
+ "text": "d"
+ },
+ {
+ "id": "K_F",
+ "text": "f"
+ },
+ {
+ "id": "K_G",
+ "text": "g"
+ },
+ {
+ "id": "K_H",
+ "text": "h"
+ },
+ {
+ "id": "K_J",
+ "text": "j"
+ },
+ {
+ "id": "K_K",
+ "text": "k"
+ },
+ {
+ "id": "K_L",
+ "text": "l"
+ },
+ {
+ "id": "K_COLON",
+ "text": ";"
+ },
+ {
+ "id": "K_QUOTE",
+ "text": "'"
+ },
+ {
+ "id": "K_BKSLASH",
+ "text": "\\"
+ }
+ ]
+ },
+ {
+ "id": 4,
+ "key": [
+ {
+ "id": "K_SHIFT",
+ "text": "*Shift*",
+ "width": 160,
+ "sp": 1,
+ "nextlayer": "shift"
+ },
+ {
+ "id": "K_oE2",
+ "text": "\\"
+ },
+ {
+ "id": "K_Z",
+ "text": "z"
+ },
+ {
+ "id": "K_X",
+ "text": "x"
+ },
+ {
+ "id": "K_C",
+ "text": "c"
+ },
+ {
+ "id": "K_V",
+ "text": "v"
+ },
+ {
+ "id": "K_B",
+ "text": "b"
+ },
+ {
+ "id": "K_N",
+ "text": "n"
+ },
+ {
+ "id": "K_M",
+ "text": "m"
+ },
+ {
+ "id": "K_COMMA",
+ "text": ","
+ },
+ {
+ "id": "K_PERIOD",
+ "text": "."
+ },
+ {
+ "id": "K_SLASH",
+ "text": "/"
+ },
+ {
+ "id": "T_new_162",
+ "width": 10,
+ "sp": 10
+ }
+ ]
+ },
+ {
+ "id": 5,
+ "key": [
+ {
+ "id": "K_LOPT",
+ "text": "*Menu*",
+ "width": 140,
+ "sp": 1
+ },
+ {
+ "id": "K_SPACE",
+ "width": 930
+ },
+ {
+ "id": "K_ENTER",
+ "text": "*Enter*",
+ "width": 145,
+ "sp": 1
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "shift",
+ "row": [
+ {
+ "id": 1,
+ "key": [
+ {
+ "id": "K_1",
+ "text": "!"
+ },
+ {
+ "id": "K_2",
+ "text": "@"
+ },
+ {
+ "id": "K_3",
+ "text": "#"
+ },
+ {
+ "id": "K_4",
+ "text": "$"
+ },
+ {
+ "id": "K_5",
+ "text": "%"
+ },
+ {
+ "id": "K_6",
+ "text": "^"
+ },
+ {
+ "id": "K_7",
+ "text": "&"
+ },
+ {
+ "id": "K_8",
+ "text": "*"
+ },
+ {
+ "id": "K_9",
+ "text": "("
+ },
+ {
+ "id": "K_0",
+ "text": ")"
+ },
+ {
+ "id": "K_HYPHEN",
+ "text": "_"
+ },
+ {
+ "id": "K_EQUAL",
+ "text": "+"
+ },
+ {
+ "id": "K_BKSP",
+ "text": "*BkSp*",
+ "width": 100,
+ "sp": 1
+ }
+ ]
+ },
+ {
+ "id": 2,
+ "key": [
+ {
+ "id": "K_Q",
+ "text": "Q",
+ "pad": 75
+ },
+ {
+ "id": "K_W",
+ "text": "W"
+ },
+ {
+ "id": "K_E",
+ "text": "E"
+ },
+ {
+ "id": "K_R",
+ "text": "R"
+ },
+ {
+ "id": "K_T",
+ "text": "T"
+ },
+ {
+ "id": "K_Y",
+ "text": "Y"
+ },
+ {
+ "id": "K_U",
+ "text": "U"
+ },
+ {
+ "id": "K_I",
+ "text": "I"
+ },
+ {
+ "id": "K_O",
+ "text": "O"
+ },
+ {
+ "id": "K_P",
+ "text": "P"
+ },
+ {
+ "id": "K_LBRKT",
+ "text": "{"
+ },
+ {
+ "id": "K_RBRKT",
+ "text": "}"
+ },
+ {
+ "id": "T_new_246",
+ "width": 10,
+ "sp": 10
+ }
+ ]
+ },
+ {
+ "id": 3,
+ "key": [
+ {
+ "id": "K_BKQUOTE",
+ "text": "~"
+ },
+ {
+ "id": "K_A",
+ "text": "A"
+ },
+ {
+ "id": "K_S",
+ "text": "S"
+ },
+ {
+ "id": "K_D",
+ "text": "D"
+ },
+ {
+ "id": "K_F",
+ "text": "F"
+ },
+ {
+ "id": "K_G",
+ "text": "G"
+ },
+ {
+ "id": "K_H",
+ "text": "H"
+ },
+ {
+ "id": "K_J",
+ "text": "J"
+ },
+ {
+ "id": "K_K",
+ "text": "K"
+ },
+ {
+ "id": "K_L",
+ "text": "L"
+ },
+ {
+ "id": "K_COLON",
+ "text": ":"
+ },
+ {
+ "id": "K_QUOTE",
+ "text": "\""
+ },
+ {
+ "id": "K_BKSLASH",
+ "text": "|"
+ }
+ ]
+ },
+ {
+ "id": 4,
+ "key": [
+ {
+ "id": "K_SHIFT",
+ "text": "*Shift*",
+ "width": 160,
+ "sp": 1,
+ "nextlayer": "default"
+ },
+ {
+ "id": "K_oE2",
+ "text": "|"
+ },
+ {
+ "id": "K_Z",
+ "text": "Z"
+ },
+ {
+ "id": "K_X",
+ "text": "X"
+ },
+ {
+ "id": "K_C",
+ "text": "C"
+ },
+ {
+ "id": "K_V",
+ "text": "V"
+ },
+ {
+ "id": "K_B",
+ "text": "B"
+ },
+ {
+ "id": "K_N",
+ "text": "N"
+ },
+ {
+ "id": "K_M",
+ "text": "M"
+ },
+ {
+ "id": "K_COMMA",
+ "text": "<"
+ },
+ {
+ "id": "K_PERIOD",
+ "text": ">"
+ },
+ {
+ "id": "K_SLASH",
+ "text": "?"
+ },
+ {
+ "id": "T_new_272",
+ "width": 10,
+ "sp": 10
+ }
+ ]
+ },
+ {
+ "id": 5,
+ "key": [
+ {
+ "id": "K_LOPT",
+ "text": "*Menu*",
+ "width": 140,
+ "sp": 1
+ },
+ {
+ "id": "K_SPACE",
+ "width": 930
+ },
+ {
+ "id": "K_ENTER",
+ "text": "*Enter*",
+ "width": 145,
+ "sp": 1
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kmn b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kmn
new file mode 100644
index 0000000000..b40278a930
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kmn
@@ -0,0 +1,26 @@
+c text_selection_tests_keyboard_9073 generated from template at 2023-11-14 15:23:49
+c with name "Text Selection Tests Keyboard"
+store(&VERSION) '10.0'
+store(&NAME) 'Text Selection Tests Keyboard'
+store(©RIGHT) '© Keyman Team'
+store(&KEYBOARDVERSION) '1.0'
+store(&TARGETS) 'any'
+store(&BITMAP) 'text_selection_tests_keyboard_9073.ico'
+store(&VISUALKEYBOARD) 'text_selection_tests_keyboard_9073.kvks'
+store(&LAYOUTFILE) 'text_selection_tests_keyboard_9073.keyman-touch-layout'
+
+begin Unicode > use(main)
+
+group(main) using keys
+'^' + [K_A] > 'â'
+'^' + [SHIFT K_A] > 'Â'
+'^' + [K_BKSP] > 'foo'
+
++ '`' > dk(1)
+
++ [K_T] > U+0009 c TAB
+
+'a' dk(1) 'b' + [K_BKSP] > 'ok1'
+'a' 'b' + [K_BKSP] > 'fail1'
+'a' dk(1) + [K_BKSP] > 'fail2'
+dk(1) + 'o' > 'ok3'
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kps b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kps
new file mode 100644
index 0000000000..999160d84d
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kps
@@ -0,0 +1,67 @@
+
+
+
+ 16.0.142.0
+ 7.0
+
+
+
+ readme.htm
+
+
+
+
+
+
+
+
+
+ Text Selection Tests Keyboard
+ © Keyman Team
+ Keyman Team
+
+
+
+
+ ..\build\text_selection_tests_keyboard_9073.kmx
+
+ 0
+ .kmx
+
+
+ ..\build\text_selection_tests_keyboard_9073.js
+
+ 0
+ .js
+
+
+ ..\build\text_selection_tests_keyboard_9073.kvk
+
+ 0
+ .kvk
+
+
+ welcome.htm
+
+ 0
+ .htm
+
+
+ readme.htm
+
+ 0
+ .htm
+
+
+
+
+ Text Selection Tests Keyboard
+ text_selection_tests_keyboard_9073
+ 1.0
+
+ English
+
+
+
+
+
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kvks b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kvks
new file mode 100644
index 0000000000..9b69397b35
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/source/text_selection_tests_keyboard_9073.kvks
@@ -0,0 +1,110 @@
+
+
+
+ 10.0
+ text_selection_tests_keyboard_9073
+
+
+
+
+ dk(1)
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 0
+ -
+ =
+ q
+ w
+ e
+ r
+ t
+ y
+ u
+ i
+ o
+ p
+ [
+ ]
+ \
+ a
+ s
+ d
+ f
+ g
+ h
+ j
+ k
+ l
+ ;
+ '
+ \
+ z
+ x
+ c
+ v
+ b
+ n
+ m
+ ,
+ .
+ /
+
+
+ ~
+ !
+ @
+ #
+ $
+ %
+ ^
+ &
+ *
+ (
+ )
+ _
+ +
+ Q
+ W
+ E
+ R
+ T
+ Y
+ U
+ I
+ O
+ P
+ {
+ }
+ |
+ A
+ S
+ D
+ F
+ G
+ H
+ J
+ K
+ L
+ :
+ "
+ |
+ Z
+ X
+ C
+ V
+ B
+ N
+ M
+ <
+ >
+ ?
+
+
+
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/source/welcome.htm b/common/test/keyboards/text_selection_tests_keyboard_9073/source/welcome.htm
new file mode 100644
index 0000000000..18b821f8c9
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/source/welcome.htm
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Start Using Text Selection Tests Keyboard
+
+
+
+
+Start Using Text Selection Tests Keyboard
+
+
+ Text Selection Tests Keyboard 1.0 generated from template.
+
+
+Keyboard Layout
+
+
+
+
+
\ No newline at end of file
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.keyboard_info b/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.keyboard_info
new file mode 100644
index 0000000000..db0a8bf7bd
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.keyboard_info
@@ -0,0 +1,7 @@
+{
+ "license": "mit",
+ "languages": [
+ "en"
+ ],
+ "description": "Text Selection Tests Keyboard generated from template"
+}
diff --git a/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.kpj b/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.kpj
new file mode 100644
index 0000000000..98b9ad7e0e
--- /dev/null
+++ b/common/test/keyboards/text_selection_tests_keyboard_9073/text_selection_tests_keyboard_9073.kpj
@@ -0,0 +1,110 @@
+
+
+
+ $PROJECTPATH\build
+ True
+ True
+ True
+ keyboard
+
+
+
+ id_dda967022de452e1fe199096e795f0ab
+ text_selection_tests_keyboard_9073.kmn
+ source\text_selection_tests_keyboard_9073.kmn
+ 1.0
+ .kmn
+
+ Text Selection Tests Keyboard
+ © Keyman Team
+
+
+
+ id_ba932837e6a67a86abc409a393242255
+ text_selection_tests_keyboard_9073.kps
+ source\text_selection_tests_keyboard_9073.kps
+
+ .kps
+
+ Text Selection Tests Keyboard
+ © Keyman Team
+
+
+
+ id_ede98e4633e239f933cbfd1f4e1b766c
+ HISTORY.md
+ HISTORY.md
+
+ .md
+
+
+ id_53e892b8b41cc4caece1cfd5ef21d6e7
+ LICENSE.md
+ LICENSE.md
+
+ .md
+
+
+ id_0730bb7c2e8f9ea2438b52e419dd86c9
+ README.md
+ README.md
+
+ .md
+
+
+ id_4b87bd35cc2e16f1ff8680a6f2caed52
+ text_selection_tests_keyboard_9073.keyboard_info
+ text_selection_tests_keyboard_9073.keyboard_info
+
+ .keyboard_info
+
+
+ id_bbf31cea8a9cfe0cb838f67055690bf8
+ text_selection_tests_keyboard_9073.ico
+ source\text_selection_tests_keyboard_9073.ico
+
+ .ico
+ id_dda967022de452e1fe199096e795f0ab
+
+
+ id_b8f7a473cac52dd0436273de657cdf46
+ text_selection_tests_keyboard_9073.kmx
+ source\..\build\text_selection_tests_keyboard_9073.kmx
+
+ .kmx
+ id_ba932837e6a67a86abc409a393242255
+
+
+ id_73d0cd87e78d9b8d7f514809dbb36a47
+ text_selection_tests_keyboard_9073.js
+ source\..\build\text_selection_tests_keyboard_9073.js
+
+ .js
+ id_ba932837e6a67a86abc409a393242255
+
+
+ id_71aafc060dc3251e4bb611ea539dc8e0
+ text_selection_tests_keyboard_9073.kvk
+ source\..\build\text_selection_tests_keyboard_9073.kvk
+
+ .kvk
+ id_ba932837e6a67a86abc409a393242255
+
+
+ id_356e5d149c1e539356d72698c1e401a6
+ welcome.htm
+ source\welcome.htm
+
+ .htm
+ id_ba932837e6a67a86abc409a393242255
+
+
+ id_8da344c4cea6f467013357fe099006f5
+ readme.htm
+ source\readme.htm
+
+ .htm
+ id_ba932837e6a67a86abc409a393242255
+
+
+
diff --git a/common/web/keyboard-processor/src/text/keyboardProcessor.ts b/common/web/keyboard-processor/src/text/keyboardProcessor.ts
index 2a2dc0bb70..14e819a56d 100644
--- a/common/web/keyboard-processor/src/text/keyboardProcessor.ts
+++ b/common/web/keyboard-processor/src/text/keyboardProcessor.ts
@@ -570,6 +570,9 @@ export default class KeyboardProcessor extends EventEmitter {
resetContext(target?: OutputTarget) {
this.layerId = 'default';
+
+ // Make sure all deadkeys for the context get cleared properly.
+ target?.resetContext();
this.keyboardInterface.resetContextCache();
// May be null if it's a keyboard swap.
diff --git a/core/src/action.cpp b/core/src/action.cpp
index 3387d8f85d..4c018cabbd 100644
--- a/core/src/action.cpp
+++ b/core/src/action.cpp
@@ -95,13 +95,15 @@ km_core_actions * km::core::action_item_list_to_actions_object(
output.push_back({KM_CORE_CT_MARKER,{0},{action_items->marker}});
break;
case KM_CORE_IT_PERSIST_OPT:
+ {
// TODO: lowpri: replace existing item if already present in options vector?
- options.push_back(km::core::option(
- static_cast(action_items->option->scope),
+ km::core::option opt(static_cast(action_items->option->scope),
action_items->option->key,
action_items->option->value
- ));
+ );
+ options.push_back(opt.release()); // hand over memory management of the option item to the action struct
break;
+ }
default:
assert(false);
}
diff --git a/core/src/kmx/kmx_actions.cpp b/core/src/kmx/kmx_actions.cpp
index 4e3f613357..5ea5f4e8a1 100644
--- a/core/src/kmx/kmx_actions.cpp
+++ b/core/src/kmx/kmx_actions.cpp
@@ -35,9 +35,6 @@ KMX_BOOL KMX_Actions::QueueAction(int ItemType, KMX_DWORD dwData)
switch(ItemType)
{
- case QIT_VKEYDOWN:
- break;
-
case QIT_DEADKEY:
m_context->Add(UC_SENTINEL);
m_context->Add(CODE_DEADKEY);
diff --git a/core/src/kmx/kmx_actions.h b/core/src/kmx/kmx_actions.h
index b536a3018a..c2ec61f43e 100644
--- a/core/src/kmx/kmx_actions.h
+++ b/core/src/kmx/kmx_actions.h
@@ -20,10 +20,10 @@ typedef struct
} KMX_Action;
// QueueAction ItemTypes
-#define QIT_VKEYDOWN 0
-#define QIT_VKEYUP 1
-#define QIT_VSHIFTDOWN 2
-#define QIT_VSHIFTUP 3
+// QIT_VKEYDOWN 0 Not supported by Core, legacy Windows-only, see #10049
+// QIT_VKEYUP 1 Not supported by Core, legacy Windows-only, see #10049
+// QIT_VSHIFTDOWN 2 Not supported by Core, legacy Windows-only, see #10049
+// QIT_VSHIFTUP 3 Not supported by Core, legacy Windows-only, see #10049
#define QIT_CHAR 4
#define QIT_DEADKEY 5
#define QIT_BELL 6
@@ -35,10 +35,6 @@ typedef struct
#define QIT_MAX 11
-#define QVK_EXTENDED 0x00010000 // Flag for QIT_VKEYDOWN to indicate an extended key
-#define QVK_KEYMASK 0x0000FFFF
-#define QVK_FLAGMASK 0xFFFF0000
-
class KMX_Actions
{
private:
diff --git a/core/src/kmx/kmx_processevent.cpp b/core/src/kmx/kmx_processevent.cpp
index 8e07e963c0..4b98312c36 100644
--- a/core/src/kmx/kmx_processevent.cpp
+++ b/core/src/kmx/kmx_processevent.cpp
@@ -434,7 +434,7 @@ int KMX_ProcessEvent::PostString(PKMX_WCHAR str, LPKEYBOARD lpkb, PKMX_WCHAR end
PKMX_WCHAR p, q, temp;
LPSTORE s;
int n1, n2;
- int i, n, shift;
+ int i, n;
KMX_BOOL FoundUse = FALSE;
// TODO: Refactor to use incxstr
for(p = str; *p && (p < endstr || !endstr); p++)
@@ -443,21 +443,10 @@ int KMX_ProcessEvent::PostString(PKMX_WCHAR str, LPKEYBOARD lpkb, PKMX_WCHAR end
switch(*(++p))
{
case CODE_EXTENDED: // Start of a virtual key section w/shift codes
- p++;
-
- shift = *p; //(*p<<8) | *(p+1);
- m_actions.QueueAction(QIT_VSHIFTDOWN, shift);
-
- p++;
-
- m_actions.QueueAction(QIT_VKEYDOWN, *p);
- m_actions.QueueAction(QIT_VKEYUP, *p);
-
- m_actions.QueueAction(QIT_VSHIFTUP, shift);
-
+ // virtual keys in output are not supported
+ p++; // modifier
+ p++; // vkey
p++; // CODE_EXTENDEDEND
- ////// CODE_EXTENDEDEND will be incremented by loop
-
break;
case CODE_DEADKEY: // A deadkey to be output
diff --git a/core/src/kmx/kmx_processor.cpp b/core/src/kmx/kmx_processor.cpp
index bb18db9edd..c72d2fe857 100644
--- a/core/src/kmx/kmx_processor.cpp
+++ b/core/src/kmx/kmx_processor.cpp
@@ -205,12 +205,6 @@ kmx_processor::internal_process_queued_actions(km_core_state *state) {
case QIT_EMIT_KEYSTROKE:
state->actions().push_emit_keystroke();
break;
- case QIT_VKEYDOWN:
- case QIT_VKEYUP:
- case QIT_VSHIFTDOWN:
- case QIT_VSHIFTUP:
- // TODO: eliminate??
- break;
case QIT_CHAR:
state->context().push_character(a.dwData);
state->actions().push_character(a.dwData);
diff --git a/core/src/option.cpp b/core/src/option.cpp
index dd9242ef0a..71cb395ddf 100644
--- a/core/src/option.cpp
+++ b/core/src/option.cpp
@@ -43,6 +43,14 @@ option::option(km_core_option_scope s, char16_t const *k, char16_t const *v)
}
}
+km_core_option_item
+option::release() {
+ km_core_option_item opt = *this;
+ key = nullptr;
+ value = nullptr;
+ return opt;
+}
+
// TODO: Relocate this and fix it
json & km::core::operator << (json &j, abstract_processor const &)
{
diff --git a/core/src/option.hpp b/core/src/option.hpp
index cbfbf76436..43f3397049 100644
--- a/core/src/option.hpp
+++ b/core/src/option.hpp
@@ -34,10 +34,15 @@ namespace core
option & operator=(option const & rhs);
option & operator=(option && rhs);
+ /**
+ * Returns contents of this object as a C struct, releasing memory
+ * management of key and value, and invalidates this object.
+ */
+ km_core_option_item release();
+
bool empty() const;
};
-
inline
option::option(km_core_option_scope s,
std::u16string const & k, std::u16string const & v)
diff --git a/core/tests/unit/kmnkbd/action_api.cpp b/core/tests/unit/kmnkbd/action_api.cpp
index 79512352a3..fc04a3ee11 100644
--- a/core/tests/unit/kmnkbd/action_api.cpp
+++ b/core/tests/unit/kmnkbd/action_api.cpp
@@ -374,6 +374,7 @@ int main(int argc, char *argv []) {
test_alert();
test_emit_keystroke();
test_invalidate_context();
+ test_persist_opt();
// context -- todo move to another file
test_context_set_if_needed();
diff --git a/developer/src/common/include/kmn_compiler_errors.h b/developer/src/common/include/kmn_compiler_errors.h
index fe7ba11a15..e0bea39549 100644
--- a/developer/src/common/include/kmn_compiler_errors.h
+++ b/developer/src/common/include/kmn_compiler_errors.h
@@ -240,6 +240,8 @@
#define CHINT_UnreachableRule 0x000010AE
+#define CWARN_VirtualKeyInOutput 0x000020AF
+
#define CERR_BufferOverflow 0x000080C0
#define CERR_Break 0x000080C1
diff --git a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts
index 2995c8f016..4ad9d02598 100644
--- a/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts
+++ b/developer/src/kmc-kmn/src/compiler/kmn-compiler-messages.ts
@@ -302,6 +302,8 @@ export class KmnCompilerMessages {
static HINT_UnreachableRule = SevHint | 0x0AE;
+ static WARN_VirtualKeyInOutput = SevWarn | 0x0AF;
+
static FATAL_BufferOverflow = SevFatal | 0x0C0;
static FATAL_Break = SevFatal | 0x0C1;
};
diff --git a/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/warn_virtual_key_in_output.kmn b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/warn_virtual_key_in_output.kmn
new file mode 100644
index 0000000000..e4919689b1
--- /dev/null
+++ b/developer/src/kmc-kmn/test/fixtures/invalid-keyboards/warn_virtual_key_in_output.kmn
@@ -0,0 +1,9 @@
+store(&NAME) 'WARN_VirtualKeyInOutput'
+store(&VERSION) '9.0'
+
+begin Unicode > use(main)
+
+group(main) using keys
+
+c WARN_VirtualKeyInOutput
++ 'a' > [K_BKQUOTE]
diff --git a/developer/src/kmc-kmn/test/test-messages.ts b/developer/src/kmc-kmn/test/test-messages.ts
index 6970b99741..51e6894daa 100644
--- a/developer/src/kmc-kmn/test/test-messages.ts
+++ b/developer/src/kmc-kmn/test/test-messages.ts
@@ -87,4 +87,11 @@ describe('CompilerMessages', function () {
assert.equal(callbacks.messages[0].message, "Statement 'return' is not currently supported in output for web and touch targets");
});
+ // WARN_VirtualKeyInOutput
+
+ it('should generate WARN_VirtualKeyInOutput if a virtual key is found in the output part of a rule', async function() {
+ await testForMessage(this, ['invalid-keyboards', 'warn_virtual_key_in_output.kmn'], KmnCompilerMessages.WARN_VirtualKeyInOutput);
+ assert.equal(callbacks.messages[0].message, "Virtual keys are not supported in output");
+ });
+
});
diff --git a/developer/src/kmcmplib/src/CompMsg.cpp b/developer/src/kmcmplib/src/CompMsg.cpp
index 8ab5db81f6..715750d4f2 100644
--- a/developer/src/kmcmplib/src/CompMsg.cpp
+++ b/developer/src/kmcmplib/src/CompMsg.cpp
@@ -143,6 +143,7 @@ const struct CompilerError CompilerErrors[] = {
{ CWARN_NulNotFirstStatementInContext , "nul must be the first statement in the context"},
{ CWARN_IfShouldBeAtStartOfContext , "if, platform and baselayout should be at start of context (after nul, if present)"},
{ CWARN_KeyShouldIncludeNCaps , "Other rules which reference this key include CAPS or NCAPS modifiers, so this rule must include NCAPS modifier to avoid inconsistent matches"},
+ { CWARN_VirtualKeyInOutput , "Virtual keys are not supported in output"},
{ 0, nullptr }
};
diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp
index e2720f8608..045b1c39ad 100644
--- a/developer/src/kmcmplib/src/Compiler.cpp
+++ b/developer/src/kmcmplib/src/Compiler.cpp
@@ -1331,6 +1331,7 @@ KMX_BOOL CheckContextStatementPositions(PKMX_WCHAR context) {
return TRUE;
}
+
/**
* Checks if a use() statement is followed by other content in the output of a rule
*/
@@ -1348,6 +1349,22 @@ KMX_DWORD CheckUseStatementsInOutput(PKMX_WCHAR output) {
return CERR_None;
}
+/**
+ * Warn if output has virtual keys in it, which is not supported by Core at all,
+ * but was unofficially supported, but never worked properly, in Keyman for
+ * Windows for many years
+ */
+KMX_DWORD CheckVirtualKeysInOutput(PKMX_WCHAR output) {
+ PKMX_WCHAR p;
+ for (p = output; *p; p = incxstr(p)) {
+ if (*p == UC_SENTINEL && *(p + 1) == CODE_EXTENDED) {
+ AddWarning(CWARN_VirtualKeyInOutput);
+ break;
+ }
+ }
+ return CERR_None;
+}
+
/**
* Adds implicit `context` to start of output of rules for readonly groups
*/
@@ -1472,6 +1489,11 @@ KMX_DWORD ProcessKeyLineImpl(PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX_BOOL IsUnico
return msg; // I4867
}
+ // Warn if virtual keys are used in the output, as they are unsupported by Core
+ if ((msg = CheckVirtualKeysInOutput(pklOut)) != CERR_None) {
+ return msg;
+ }
+
if (gp->fReadOnly) {
// Ensure no output is made from the rule, and that
// use() statements meet required readonly semantics
diff --git a/linux/debian/changelog b/linux/debian/changelog
index 1ad0f861fb..431728feb1 100644
--- a/linux/debian/changelog
+++ b/linux/debian/changelog
@@ -1,3 +1,11 @@
+keyman (16.0.143-1) unstable; urgency=medium
+
+ * Fix failure to build source after successful build (Closes #1046776)
+ * New upstream release.
+ * Re-release to Debian
+
+ -- Eberhard Beilharz Wed, 22 Nov 2023 15:24:59 +0100
+
keyman (16.0.141-1) unstable; urgency=medium
* Work around mips64el build failure (#1041499)
diff --git a/web/src/engine/main/src/keymanEngine.ts b/web/src/engine/main/src/keymanEngine.ts
index 99495a263a..5c94b30f48 100644
--- a/web/src/engine/main/src/keymanEngine.ts
+++ b/web/src/engine/main/src/keymanEngine.ts
@@ -202,6 +202,8 @@ export default class KeymanEngine<
this.contextManager.configure({
resetContext: (target) => {
+ // Could reset the target's deadkeys here, but it's really more of a 'core' task.
+ // So we delegate that to keyboard-processor.
this.core.resetContext(target);
},
predictionContext: new PredictionContext(this.core.languageProcessor, this.core.keyboardProcessor),
diff --git a/web/src/test/manual/web/index.html b/web/src/test/manual/web/index.html
index 61ee99d2de..e98979f094 100644
--- a/web/src/test/manual/web/index.html
+++ b/web/src/test/manual/web/index.html
@@ -66,6 +66,7 @@
+
Other
diff --git a/web/src/test/manual/web/text_selection_tests_9073/index.html b/web/src/test/manual/web/text_selection_tests_9073/index.html
new file mode 100644
index 0000000000..20bd3cda68
--- /dev/null
+++ b/web/src/test/manual/web/text_selection_tests_9073/index.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+ KeymanWeb #9073
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Text Selection Test Cases (#9073)
+
+
+
+
+
+
+
+
+
diff --git a/web/src/test/manual/web/text_selection_tests_9073/text_selection_tests_keyboard_9073.js b/web/src/test/manual/web/text_selection_tests_9073/text_selection_tests_keyboard_9073.js
new file mode 100644
index 0000000000..f1e93eb48e
--- /dev/null
+++ b/web/src/test/manual/web/text_selection_tests_9073/text_selection_tests_keyboard_9073.js
@@ -0,0 +1,641 @@
+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_text_selection_tests_keyboard_9073());
+}
+function Keyboard_text_selection_tests_keyboard_9073()
+{
+ 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_text_selection_tests_keyboard_9073";
+ this.KN="Text Selection Tests Keyboard";
+ this.KMINVER="10.0";
+ this.KV={F:' 1em "Arial"',K102:0};
+ this.KV.KLS={
+ "default": ["dk(1)","1","2","3","4","5","6","7","8","9","0","-","=","","","","q","w","e","r","t","y","u","i","o","p","[","]","\\","","","","a","s","d","f","g","h","j","k","l",";","'","","","","","","\\","z","x","c","v","b","n","m",",",".","/","","","","","",""],
+ "shift": ["~","!","@","#","$","%","^","&","*","(",")","_","+","","","","Q","W","E","R","T","Y","U","I","O","P","{","}","|","","","","A","S","D","F","G","H","J","K","L",":","\"","","","","","","|","Z","X","C","V","B","N","M","<",">","?","","","","","",""]
+ };
+ 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=modCodes.SHIFT /* 0x0010 */;
+ this.KVKL={
+ "tablet": {
+ "displayUnderlying": false,
+ "layer": [
+ {
+ "id": "default",
+ "row": [
+ {
+ "id": "1",
+ "key": [
+ {
+ "nextlayer": "shift",
+ "id": "K_1",
+ "text": "1"
+ },
+ {
+ "id": "K_2",
+ "text": "2"
+ },
+ {
+ "id": "K_3",
+ "text": "3"
+ },
+ {
+ "id": "K_4",
+ "text": "4"
+ },
+ {
+ "id": "K_5",
+ "text": "5"
+ },
+ {
+ "id": "K_6",
+ "text": "6"
+ },
+ {
+ "id": "K_7",
+ "text": "7"
+ },
+ {
+ "id": "K_8",
+ "text": "8"
+ },
+ {
+ "id": "K_9",
+ "text": "9"
+ },
+ {
+ "id": "K_0",
+ "text": "0"
+ },
+ {
+ "id": "K_HYPHEN",
+ "text": "-"
+ },
+ {
+ "id": "K_EQUAL",
+ "text": "="
+ },
+ {
+ "width": "100",
+ "id": "K_BKSP",
+ "sp": "1",
+ "text": "*BkSp*"
+ }
+ ]
+ },
+ {
+ "id": "2",
+ "key": [
+ {
+ "id": "K_Q",
+ "pad": "75",
+ "text": "q"
+ },
+ {
+ "id": "K_W",
+ "text": "w"
+ },
+ {
+ "id": "K_E",
+ "text": "e"
+ },
+ {
+ "id": "K_R",
+ "text": "r"
+ },
+ {
+ "id": "K_T",
+ "text": "t"
+ },
+ {
+ "id": "K_Y",
+ "text": "y"
+ },
+ {
+ "id": "K_U",
+ "text": "u"
+ },
+ {
+ "id": "K_I",
+ "text": "i"
+ },
+ {
+ "id": "K_O",
+ "text": "o"
+ },
+ {
+ "id": "K_P",
+ "text": "p"
+ },
+ {
+ "id": "K_LBRKT",
+ "text": "["
+ },
+ {
+ "id": "K_RBRKT",
+ "text": "]"
+ },
+ {
+ "width": "10",
+ "id": "T_new_136",
+ "sp": "10"
+ }
+ ]
+ },
+ {
+ "id": "3",
+ "key": [
+ {
+ "id": "K_BKQUOTE",
+ "text": "dk(1)"
+ },
+ {
+ "id": "K_A",
+ "text": "a"
+ },
+ {
+ "id": "K_S",
+ "text": "s"
+ },
+ {
+ "id": "K_D",
+ "text": "d"
+ },
+ {
+ "id": "K_F",
+ "text": "f"
+ },
+ {
+ "id": "K_G",
+ "text": "g"
+ },
+ {
+ "id": "K_H",
+ "text": "h"
+ },
+ {
+ "id": "K_J",
+ "text": "j"
+ },
+ {
+ "id": "K_K",
+ "text": "k"
+ },
+ {
+ "id": "K_L",
+ "text": "l"
+ },
+ {
+ "id": "K_COLON",
+ "text": ";"
+ },
+ {
+ "id": "K_QUOTE",
+ "text": "'"
+ },
+ {
+ "id": "K_BKSLASH",
+ "text": "\\"
+ }
+ ]
+ },
+ {
+ "id": "4",
+ "key": [
+ {
+ "nextlayer": "shift",
+ "width": "160",
+ "id": "K_SHIFT",
+ "sp": "1",
+ "text": "*Shift*"
+ },
+ {
+ "id": "K_oE2",
+ "text": "\\"
+ },
+ {
+ "id": "K_Z",
+ "text": "z"
+ },
+ {
+ "id": "K_X",
+ "text": "x"
+ },
+ {
+ "id": "K_C",
+ "text": "c"
+ },
+ {
+ "id": "K_V",
+ "text": "v"
+ },
+ {
+ "id": "K_B",
+ "text": "b"
+ },
+ {
+ "id": "K_N",
+ "text": "n"
+ },
+ {
+ "id": "K_M",
+ "text": "m"
+ },
+ {
+ "id": "K_COMMA",
+ "text": ","
+ },
+ {
+ "id": "K_PERIOD",
+ "text": "."
+ },
+ {
+ "id": "K_SLASH",
+ "text": "/"
+ },
+ {
+ "width": "10",
+ "id": "T_new_162",
+ "sp": "10"
+ }
+ ]
+ },
+ {
+ "id": "5",
+ "key": [
+ {
+ "width": "140",
+ "id": "K_LOPT",
+ "sp": "1",
+ "text": "*Menu*"
+ },
+ {
+ "width": "930",
+ "id": "K_SPACE"
+ },
+ {
+ "width": "145",
+ "id": "K_ENTER",
+ "sp": "1",
+ "text": "*Enter*"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "id": "shift",
+ "row": [
+ {
+ "id": "1",
+ "key": [
+ {
+ "id": "K_1",
+ "text": "!"
+ },
+ {
+ "id": "K_2",
+ "text": "@"
+ },
+ {
+ "id": "K_3",
+ "text": "#"
+ },
+ {
+ "id": "K_4",
+ "text": "$"
+ },
+ {
+ "id": "K_5",
+ "text": "%"
+ },
+ {
+ "id": "K_6",
+ "text": "^"
+ },
+ {
+ "id": "K_7",
+ "text": "&"
+ },
+ {
+ "id": "K_8",
+ "text": "*"
+ },
+ {
+ "id": "K_9",
+ "text": "("
+ },
+ {
+ "id": "K_0",
+ "text": ")"
+ },
+ {
+ "id": "K_HYPHEN",
+ "text": "_"
+ },
+ {
+ "id": "K_EQUAL",
+ "text": "+"
+ },
+ {
+ "width": "100",
+ "id": "K_BKSP",
+ "sp": "1",
+ "text": "*BkSp*"
+ }
+ ]
+ },
+ {
+ "id": "2",
+ "key": [
+ {
+ "id": "K_Q",
+ "pad": "75",
+ "text": "Q"
+ },
+ {
+ "id": "K_W",
+ "text": "W"
+ },
+ {
+ "id": "K_E",
+ "text": "E"
+ },
+ {
+ "id": "K_R",
+ "text": "R"
+ },
+ {
+ "id": "K_T",
+ "text": "T"
+ },
+ {
+ "id": "K_Y",
+ "text": "Y"
+ },
+ {
+ "id": "K_U",
+ "text": "U"
+ },
+ {
+ "id": "K_I",
+ "text": "I"
+ },
+ {
+ "id": "K_O",
+ "text": "O"
+ },
+ {
+ "id": "K_P",
+ "text": "P"
+ },
+ {
+ "id": "K_LBRKT",
+ "text": "{"
+ },
+ {
+ "id": "K_RBRKT",
+ "text": "}"
+ },
+ {
+ "width": "10",
+ "id": "T_new_246",
+ "sp": "10"
+ }
+ ]
+ },
+ {
+ "id": "3",
+ "key": [
+ {
+ "id": "K_BKQUOTE",
+ "text": "~"
+ },
+ {
+ "id": "K_A",
+ "text": "A"
+ },
+ {
+ "id": "K_S",
+ "text": "S"
+ },
+ {
+ "id": "K_D",
+ "text": "D"
+ },
+ {
+ "id": "K_F",
+ "text": "F"
+ },
+ {
+ "id": "K_G",
+ "text": "G"
+ },
+ {
+ "id": "K_H",
+ "text": "H"
+ },
+ {
+ "id": "K_J",
+ "text": "J"
+ },
+ {
+ "id": "K_K",
+ "text": "K"
+ },
+ {
+ "id": "K_L",
+ "text": "L"
+ },
+ {
+ "id": "K_COLON",
+ "text": ":"
+ },
+ {
+ "id": "K_QUOTE",
+ "text": "\""
+ },
+ {
+ "id": "K_BKSLASH",
+ "text": "|"
+ }
+ ]
+ },
+ {
+ "id": "4",
+ "key": [
+ {
+ "nextlayer": "default",
+ "width": "160",
+ "id": "K_SHIFT",
+ "sp": "1",
+ "text": "*Shift*"
+ },
+ {
+ "id": "K_oE2",
+ "text": "|"
+ },
+ {
+ "id": "K_Z",
+ "text": "Z"
+ },
+ {
+ "id": "K_X",
+ "text": "X"
+ },
+ {
+ "id": "K_C",
+ "text": "C"
+ },
+ {
+ "id": "K_V",
+ "text": "V"
+ },
+ {
+ "id": "K_B",
+ "text": "B"
+ },
+ {
+ "id": "K_N",
+ "text": "N"
+ },
+ {
+ "id": "K_M",
+ "text": "M"
+ },
+ {
+ "id": "K_COMMA",
+ "text": "<"
+ },
+ {
+ "id": "K_PERIOD",
+ "text": ">"
+ },
+ {
+ "id": "K_SLASH",
+ "text": "?"
+ },
+ {
+ "width": "10",
+ "id": "T_new_272",
+ "sp": "10"
+ }
+ ]
+ },
+ {
+ "id": "5",
+ "key": [
+ {
+ "width": "140",
+ "id": "K_LOPT",
+ "sp": "1",
+ "text": "*Menu*"
+ },
+ {
+ "width": "930",
+ "id": "K_SPACE"
+ },
+ {
+ "width": "145",
+ "id": "K_ENTER",
+ "sp": "1",
+ "text": "*Enter*"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+}
+;
+ this.KVER="16.0.142.0";
+ this.KVS=[];
+ this.gs=function(t,e) {
+ return this.g_main_0(t,e);
+ };
+ 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_BKSP /* 0x08 */)) {
+ if(k.KFCM(3,t,['a',{t:'d',d:0},'b'])){
+ r=m=1; // Line 23
+ k.KDC(3,t);
+ k.KO(-1,t,"ok1");
+ }
+ else if(k.KFCM(2,t,['a','b'])){
+ r=m=1; // Line 24
+ k.KDC(2,t);
+ k.KO(-1,t,"fail1");
+ }
+ else if(k.KFCM(2,t,['a',{t:'d',d:0}])){
+ r=m=1; // Line 25
+ k.KDC(2,t);
+ k.KO(-1,t,"fail2");
+ }
+ else if(k.KFCM(1,t,['^'])){
+ r=m=1; // Line 17
+ k.KDC(1,t);
+ k.KO(-1,t,"foo");
+ }
+ }
+ else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_A /* 0x41 */)) {
+ if(k.KFCM(1,t,['^'])){
+ r=m=1; // Line 16
+ k.KDC(1,t);
+ k.KO(-1,t,"Â");
+ }
+ }
+ else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKQUOTE /* 0xC0 */)) {
+ if(1){
+ r=m=1; // Line 19
+ k.KDC(0,t);
+ k.KDO(-1,t,0);
+ }
+ }
+ else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) {
+ if(k.KFCM(1,t,['^'])){
+ r=m=1; // Line 15
+ k.KDC(1,t);
+ k.KO(-1,t,"â");
+ }
+ }
+ else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_O /* 0x4F */)) {
+ if(k.KFCM(1,t,[{t:'d',d:0}])){
+ r=m=1; // Line 26
+ k.KDC(1,t);
+ k.KO(-1,t,"ok3");
+ }
+ }
+ else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_T /* 0x54 */)) {
+ if(1){
+ r=m=1; // Line 21
+ k.KDC(0,t);
+ k.KO(-1,t,"\t");
+ }
+ }
+ return r;
+ };
+}
diff --git a/windows/src/engine/keyman32/K32_load.cpp b/windows/src/engine/keyman32/K32_load.cpp
index 999d8941c9..9917e7edbf 100644
--- a/windows/src/engine/keyman32/K32_load.cpp
+++ b/windows/src/engine/keyman32/K32_load.cpp
@@ -30,17 +30,6 @@
#include "pch.h"
-HBITMAP LoadBitmapFile(LPBYTE data, DWORD sz);
-BOOL VerifyKeyboard(LPBYTE filebase);
-
-#ifdef _WIN64
-LPKEYBOARD CopyKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize);
-#else
-LPKEYBOARD FixupKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize);
-#endif
-
-HBITMAP LoadBitmapFileEx(PBYTE filebase);
-
BOOL GetKeyboardFileName(LPSTR kbname, LPSTR buf, int nbuf)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
@@ -128,768 +117,3 @@ BOOL LoadlpKeyboard(int i)
return TRUE;
}
-
-/*
- * Instead of performing a straightforward calculation of the 32 bit
- * CRC using a series of logical operations, this program uses the
- * faster table lookup method. This routine is called once when the
- * program starts up to build the table which will be used later
- * when calculating the CRC values.
- */
-
-#define CRC32_POLYNOMIAL 0xEDB88320L
-
-unsigned long CRCTable[256];
-
-void BuildCRCTable(void)
-{
- static BOOL TableBuilt = FALSE;
- int i;
- int j;
- unsigned long crc;
-
- if(!TableBuilt)
- {
- for(i = 0; i <= 255; i++)
- {
- crc = i;
-
- for(j = 8; j > 0; j--)
- if(crc & 1) crc = (crc >> 1) ^ CRC32_POLYNOMIAL; else crc >>= 1;
-
- CRCTable[i] = crc;
- }
- }
-}
-
-
-/*
- * This routine calculates the CRC for a block of data using the
- * table lookup method. It accepts an original value for the crc,
- * and returns the updated value.
- */
-
-unsigned long CalculateBufferCRC(unsigned long count, BYTE *p)
-{
- unsigned long temp1;
- unsigned long temp2;
- unsigned long crc = 0xFFFFFFFFL;
-
- BuildCRCTable();
-
- while (count-- != 0)
- {
- temp1 = ( crc >> 8 ) & 0x00FFFFFFL;
- temp2 = CRCTable[((int) crc ^ *p++) & 0xff];
- crc = temp1 ^ temp2;
- }
-
- return crc;
-}
-
-//#define Err(s)
-
-void Err(char *s)
-{
- SendDebugMessageFormat(0, sdmLoad, 0, "LoadKeyboard: %s", s);
-}
-
-BOOL LoadKeyboard(LPSTR fileName, LPKEYBOARD *lpKeyboard)
-{
- DWORD sz;
- LPBYTE buf;
- HANDLE hFile;
- LPKEYBOARD kbp;
- PBYTE filebase;
-
- if(!fileName || !lpKeyboard)
- {
- Err("Bad Filename");
- return FALSE;
- }
-
- hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
- if(hFile == INVALID_HANDLE_VALUE)
- {
- Err("Could not open file");
- return FALSE;
- }
-
- sz = GetFileSize(hFile, NULL);
-
-#ifdef _WIN64
- // allocate enough memory for expanded data structure + original data.
- // Expanded data structure is double the size of data on disk (8-byte
- // pointers) - on disk the "pointers" are relative to the beginning of
- // the file.
- // We save the original data at the end of buf; we don't copy strings, so
- // those will remain in the location at the end of the buffer.
- buf = new BYTE[sz * 3];
-#else
- buf = new BYTE[sz];
-#endif
-
- if(!buf)
- {
- CloseHandle(hFile);
- Err("Not allocmem");
- return FALSE;
- }
-#ifdef _WIN64
- filebase = buf + sz*2;
-#else
- filebase = buf;
-#endif
-
- ReadFile(hFile, filebase, sz, &sz, NULL);
- CloseHandle(hFile);
-
- PKEYMAN64THREADDATA _td = ThreadGlobals();
- if (!_td) {
- delete[] buf;
- return FALSE;
- }
-
- if(*LPDWORD(filebase) != FILEID_COMPILED)
- {
- delete[] buf;
- Err("Invalid file");
- return FALSE;
- }
-
- if(!VerifyKeyboard(filebase)) return FALSE;
-
-#ifdef _WIN64
- kbp = CopyKeyboard(buf, filebase, sz);
-#else
- kbp = FixupKeyboard(buf, filebase, sz);
-#endif
-
- if(!kbp) return FALSE;
-
- if(kbp->dwIdentifier != FILEID_COMPILED) { delete buf; Err("errNotFileID"); return FALSE; }
-
- kbp->hBitmap = LoadBitmapFileEx(filebase);
-
- *lpKeyboard = kbp;
-
- return TRUE;
-}
-
-
-
-// These next two structs represent how the icon information is stored
-// in an ICO file.
-typedef struct
-{
- BYTE bWidth; // Width of the image
- BYTE bHeight; // Height of the image (times 2)
- BYTE bColorCount; // Number of colors in image (0 if >=8bpp)
- BYTE bReserved; // Reserved
- WORD wPlanes; // Color Planes
- WORD wBitCount; // Bits per pixel
- DWORD dwBytesInRes; // how many bytes in this resource?
- DWORD dwImageOffset; // where in the file is this image
-} ICONDIRENTRY, *LPICONDIRENTRY;
-typedef struct
-{
- WORD idReserved; // Reserved
- WORD idType; // resource type (1 for icons)
- WORD idCount; // how many images?
- ICONDIRENTRY idEntries[1]; // the entries for each image
-} ICONDIR, *LPICONDIR;
-
-// The following two structs are for the use of this program in
-// manipulating icons. They are more closely tied to the operation
-// of this program than the structures listed above. One of the
-// main differences is that they provide a pointer to the DIB
-// information of the masks.
-typedef struct
-{
- UINT Width, Height, Colors; // Width, Height and bpp
- LPBYTE lpBits; // ptr to DIB bits
- DWORD dwNumBytes; // how many bytes?
- LPBITMAPINFO lpbi; // ptr to header
- LPBYTE lpXOR; // ptr to XOR image bits
- LPBYTE lpAND; // ptr to AND image bits
-} ICONIMAGE, *LPICONIMAGE;
-typedef struct
-{
- UINT nNumImages; // How many images?
- ICONIMAGE IconImages[1]; // Image entries
-} ICONRESOURCE, *LPICONRESOURCE;
-/****************************************************************************/
-LPICONRESOURCE ReadIconFromICOFile( PBYTE buf, int sz );
-void FreeIconResource(LPICONRESOURCE lpIR);
-HICON MakeIconFromResource( LPICONIMAGE lpIcon );
-
-HBITMAP LoadBitmapFile(LPBYTE data, DWORD sz)
-{
- BITMAPFILEHEADER *bmfh;
- BITMAPINFO *bmi;
- HBITMAP hBitmap, hBitmap2, hOldBmp1, hOldBmp2;
- HDC hDC, hSrcDC, hSrcDC2;
- LPICONRESOURCE lpir = NULL;
-
- bmfh = (BITMAPFILEHEADER *) data;
-
- if(bmfh->bfType == 0x4D42)
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "LoadKeyboard: Bitmap found");
- bmi = (BITMAPINFO *) (data + sizeof(BITMAPFILEHEADER));
-
- hDC = GetDC(GetDesktopWindow());
- hSrcDC = CreateCompatibleDC(hDC);
- hSrcDC2 = CreateCompatibleDC(hDC);
- hBitmap = CreateDIBitmap(hDC, &bmi->bmiHeader, CBM_INIT, data + bmfh->bfOffBits, bmi, DIB_RGB_COLORS);
- hBitmap2 = CreateCompatibleBitmap(hDC, 16, 16);
- ReleaseDC(GetDesktopWindow(), hDC);
-
- hOldBmp1 = (HBITMAP) SelectObject(hSrcDC, hBitmap);
- hOldBmp2 = (HBITMAP) SelectObject(hSrcDC2, hBitmap2);
- BitBlt(hSrcDC2, 0, 0, 16, 16, hSrcDC, 0, 0, SRCCOPY);
- SelectObject(hSrcDC, hOldBmp1);
- SelectObject(hSrcDC2, hOldBmp2);
- DeleteDC(hSrcDC);
- DeleteDC(hSrcDC2);
- DeleteObject(hBitmap);
- }
- else
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "LoadKeyboard: Icon found");
-
- lpir = ReadIconFromICOFile(data, sz);
- if(!lpir)
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "LoadKeyboard: icon not loaded");
- return 0;
- }
-
- if(lpir->nNumImages == 0)
- {
- FreeIconResource(lpir);
- return 0;
- }
-
- HICON hIcon = MakeIconFromResource(&lpir->IconImages[0]);
- //HICON hIcon = CreateIcon(GetModuleHandle(LIBRARY_NAME), lpir->IconImages[0].Width, lpir->IconImages[0].Height,
- // 1, lpir->IconImages[0].Colors, lpir->IconImages[0].lpAND, lpir->IconImages[0].lpXOR);
- FreeIconResource(lpir);
-
-
- if(hIcon == 0)
- {
- DebugLastError("MakeIconFromResource");
- return 0;
- }
- hDC = GetDC(GetDesktopWindow());
-
- hBitmap2 = CreateCompatibleBitmap(hDC, 16, 16);
- hSrcDC = CreateCompatibleDC(hDC);
- ReleaseDC(GetDesktopWindow(), hDC);
-
- hOldBmp2 = (HBITMAP) SelectObject(hSrcDC, hBitmap2);
- DrawIconEx(hSrcDC, 0, 0, hIcon, 16, 16, 0, NULL, DI_NORMAL);
- SelectObject(hSrcDC, hOldBmp2);
- DeleteDC(hSrcDC);
-
- DestroyIcon(hIcon);
-
- }
- return hBitmap2;
-}
-
-
-
-/****************************************************************************
-*
-* FUNCTION: ReadICOHeader
-*
-* PURPOSE: Reads the header from an ICO file
-*
-* PARAMS: HANDLE hFile - handle to the file
-*
-* RETURNS: UINT - Number of images in file, -1 for failure
-*
-* History:
-* July '95 - Created
-*
-\****************************************************************************/
-UINT ReadICOHeader( PBYTE buf )
-{
- if(*(PWORD)(buf) != 0) return (UINT)-1;
- if(*(PWORD)(buf+2) != 1) return (UINT)-1;
- return *(PWORD)(buf+4);
-}
-/* End ReadICOHeader() ****************************************************/
-
-
-
-
-/****************************************************************************
-*
-* FUNCTION: DIBNumColors
-*
-* PURPOSE: Calculates the number of entries in the color table.
-*
-* PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
-*
-* RETURNS: WORD - Number of entries in the color table.
-*
-* History:
-* July '95 - Copied
-*
-\****************************************************************************/
-WORD DIBNumColors( LPSTR lpbi )
-{
- WORD wBitCount;
- DWORD dwClrUsed;
-
- dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
-
- if (dwClrUsed)
- return (WORD) dwClrUsed;
-
- wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
-
- switch (wBitCount)
- {
- case 1: return 2;
- case 4: return 16;
- case 8: return 256;
- }
- return 0;
-}
-/* End DIBNumColors() ******************************************************/
-
-
-
-/****************************************************************************
-*
-* FUNCTION: PaletteSize
-*
-* PURPOSE: Calculates the number of bytes in the color table.
-*
-* PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
-*
-* RETURNS: WORD - number of bytes in the color table
-*
-*
-* History:
-* July '95 - Copied
-*
-\****************************************************************************/
-WORD PaletteSize( LPSTR lpbi )
-{
- return ( DIBNumColors( lpbi ) * sizeof( RGBQUAD ) );
-}
-/* End PaletteSize() ********************************************************/
-
-/****************************************************************************
-*
-* FUNCTION: FindDIBits
-*
-* PURPOSE: Locate the image bits in a CF_DIB format DIB.
-*
-* PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
-*
-* RETURNS: LPSTR - pointer to the image bits
-*
-* History:
-* July '95 - Copied
-*
-\****************************************************************************/
-LPSTR FindDIBBits( LPSTR lpbi )
-{
- return ( lpbi + *(LPDWORD)lpbi + PaletteSize( lpbi ) );
-}
-/* End FindDIBits() *********************************************************/
-
-
-
-// How wide, in bytes, would this many bits be, DWORD aligned?
-#define WIDTHBYTES(bits) ((((bits) + 31)>>5)<<2)
-
-/****************************************************************************
-*
-* FUNCTION: BytesPerLine
-*
-* PURPOSE: Calculates the number of bytes in one scan line.
-*
-* PARAMS: LPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER
-* that begins the CF_DIB block
-*
-* RETURNS: DWORD - number of bytes in one scan line (DWORD aligned)
-*
-* History:
-* July '95 - Created
-*
-\****************************************************************************/
-DWORD BytesPerLine( LPBITMAPINFOHEADER lpBMIH )
-{
- return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);
-}
-/* End BytesPerLine() ********************************************************/
-
-
-/****************************************************************************
-*
-* FUNCTION: AdjustIconImagePointers
-*
-* PURPOSE: Adjusts internal pointers in icon resource struct
-*
-* PARAMS: LPICONIMAGE lpImage - the resource to handle
-*
-* RETURNS: BOOL - TRUE for success, FALSE for failure
-*
-* History:
-* July '95 - Created
-*
-\****************************************************************************/
-BOOL AdjustIconImagePointers( LPICONIMAGE lpImage )
-{
- // Sanity check
- if( lpImage==NULL )
- return FALSE;
- // BITMAPINFO is at beginning of bits
- lpImage->lpbi = (LPBITMAPINFO)lpImage->lpBits;
- // Width - simple enough
- lpImage->Width = lpImage->lpbi->bmiHeader.biWidth;
- // Icons are stored in funky format where height is doubled - account for it
- lpImage->Height = (lpImage->lpbi->bmiHeader.biHeight)/2;
- // How many colors?
- lpImage->Colors = lpImage->lpbi->bmiHeader.biPlanes * lpImage->lpbi->bmiHeader.biBitCount;
- // XOR bits follow the header and color table
- lpImage->lpXOR = (LPBYTE) FindDIBBits((LPSTR)lpImage->lpbi);
- // AND bits follow the XOR bits
- lpImage->lpAND = lpImage->lpXOR + (lpImage->Height*BytesPerLine((LPBITMAPINFOHEADER)(lpImage->lpbi)));
- return TRUE;
-}
-/* End AdjustIconImagePointers() *******************************************/
-
-/****************************************************************************
-*
-* FUNCTION: ReadIconFromICOFile
-*
-* PURPOSE: Reads an Icon Resource from an ICO file
-*
-* PARAMS: LPCTSTR szFileName - Name of the ICO file
-*
-* RETURNS: LPICONRESOURCE - pointer to the resource, NULL for failure
-*
-* History:
-* July '95 - Created
-*
-\****************************************************************************/
-LPICONRESOURCE ReadIconFromICOFile( PBYTE buf, int sz )
-{
- UNREFERENCED_PARAMETER(sz);
- LPICONRESOURCE lpIR = NULL, lpNew = NULL;
- HANDLE hFile = NULL;
- //LPRESOURCEPOSINFO lpRPI = NULL;
- UINT i;
- LPICONDIRENTRY lpIDE = NULL;
-
- // Allocate memory for the resource structure
- if( (lpIR = (LPICONRESOURCE) malloc( sizeof(ICONRESOURCE) )) == NULL )
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "Error Allocating Memory");
- return NULL;
- }
-
- // Read in the header
- if( (lpIR->nNumImages = ReadICOHeader(buf)) == (UINT)-1 )
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "Error Reading File Header");
- free( lpIR );
- return NULL;
- }
- // Adjust the size of the struct to account for the images
- if( (lpNew = (LPICONRESOURCE) realloc( lpIR, sizeof(ICONRESOURCE) + ((lpIR->nNumImages-1) * sizeof(ICONIMAGE)) )) == NULL )
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "Error Allocating Memory");
- CloseHandle( hFile );
- free( lpIR );
- return NULL;
- }
- lpIR = lpNew;
- // Store the original name
-
- // Allocate enough memory for the icon directory entries
- if( (lpIDE = (LPICONDIRENTRY) malloc( lpIR->nNumImages * sizeof( ICONDIRENTRY ) ) ) == NULL )
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "Error Allocating Memory");
- free( lpIR );
- return NULL;
- }
- memcpy(lpIDE, buf + 6, lpIR->nNumImages * sizeof( ICONDIRENTRY ));
-
- // Loop through and read in each image
- for( i = 0; i < lpIR->nNumImages; i++ )
- {
- // Allocate memory for the resource
- if( (lpIR->IconImages[i].lpBits = (LPBYTE) malloc(lpIDE[i].dwBytesInRes)) == NULL )
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "Error Allocating Memory");
- free( lpIR );
- free( lpIDE );
- return NULL;
- }
- lpIR->IconImages[i].dwNumBytes = lpIDE[i].dwBytesInRes;
- // Seek to beginning of this image
- memcpy(lpIR->IconImages[i].lpBits, buf + lpIDE[i].dwImageOffset, lpIDE[i].dwBytesInRes);
-
- // Set the internal pointers appropriately
- if( ! AdjustIconImagePointers( &(lpIR->IconImages[i]) ) )
- {
- SendDebugMessageFormat(0, sdmLoad, 0, "Error Converting to Internal Format");
- free( lpIDE );
- free( lpIR );
- return NULL;
- }
- }
- // Clean up
- free( lpIDE );
- //free( lpRPI );
- return lpIR;
-}
-/* End ReadIconFromICOFile() **********************************************/
-
-void FreeIconResource(LPICONRESOURCE lpIR)
-{
- for( UINT i = 0; i < lpIR->nNumImages; i++ )
- // Allocate memory for the resource
- free(lpIR->IconImages[i].lpBits);
- free( lpIR );
-}
-
-/****************************************************************************
-*
-* FUNCTION: MakeIconFromResource
-*
-* PURPOSE: Makes an HICON from an icon resource
-*
-* PARAMS: LPICONIMAGE lpIcon - pointer to the icon resource
-*
-* RETURNS: HICON - handle to the new icon, NULL for failure
-*
-* History:
-* July '95 - Created
-*
-\****************************************************************************/
-HICON MakeIconFromResource( LPICONIMAGE lpIcon )
-{
- HICON hIcon = NULL;
-
- // Sanity Check
- if( lpIcon == NULL )
- return NULL;
- if( lpIcon->lpBits == NULL )
- return NULL;
- // Let the OS do the real work :)
- hIcon = CreateIconFromResourceEx( lpIcon->lpBits, lpIcon->dwNumBytes, TRUE, 0x00030000,
- (*(LPBITMAPINFOHEADER)(lpIcon->lpBits)).biWidth, (*(LPBITMAPINFOHEADER)(lpIcon->lpBits)).biHeight/2, 0 );
-
- // It failed, odds are good we're on NT so try the non-Ex way
- if( hIcon == NULL )
- {
- // We would break on NT if we try with a 16bpp image
- if(lpIcon->lpbi->bmiHeader.biBitCount != 16)
- {
- hIcon = CreateIconFromResource( lpIcon->lpBits, lpIcon->dwNumBytes, TRUE, 0x00030000 );
- }
- }
- return hIcon;
-}
-/* End MakeIconFromResource() **********************************************/
-
-PWCHAR StringOffset(PBYTE base, DWORD offset)
-{
- if(offset == 0) return NULL;
- return (PWCHAR)(base + offset);
-}
-
-#ifdef _WIN64
-
-/**
- CopyKeyboard will copy the data read into bufp from x86-sized structures into
- x64-sized structures starting at `base`
- * After this function finishes, we still need to keep the original data because
- we don't copy the strings
- This method is used on 64-bit architectures.
-*/
-LPKEYBOARD CopyKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize)
-{
- UNREFERENCED_PARAMETER(dwFileSize);
-
- PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) base;
-
- /* Copy keyboard structure */
-
- LPKEYBOARD kbp = (LPKEYBOARD) bufp;
- bufp += sizeof(KEYBOARD);
-
- kbp->dwIdentifier = ckbp->dwIdentifier;
- kbp->dwFileVersion = ckbp->dwFileVersion;
- kbp->dwCheckSum = ckbp->dwCheckSum;
- kbp->xxkbdlayout = ckbp->KeyboardID;
- kbp->IsRegistered = ckbp->IsRegistered;
- kbp->version = ckbp->version;
- kbp->cxStoreArray = ckbp->cxStoreArray;
- kbp->cxGroupArray = ckbp->cxGroupArray;
- kbp->StartGroup[0] = ckbp->StartGroup[0];
- kbp->StartGroup[1] = ckbp->StartGroup[1];
- kbp->dwFlags = ckbp->dwFlags;
- kbp->dwHotKey = ckbp->dwHotKey;
- kbp->hBitmap = 0; // will be built later
-
- kbp->dpStoreArray = (LPSTORE) bufp;
- bufp += sizeof(STORE) * kbp->cxStoreArray;
-
- kbp->dpGroupArray = (LPGROUP) bufp;
- bufp += sizeof(GROUP) * kbp->cxGroupArray;
-
- PCOMP_STORE csp;
- LPSTORE sp;
- DWORD i;
-
- for(
- csp = (PCOMP_STORE)(base + ckbp->dpStoreArray), sp = kbp->dpStoreArray, i = 0;
- i < kbp->cxStoreArray;
- i++, sp++, csp++)
- {
- sp->dwSystemID = csp->dwSystemID;
- sp->dpName = StringOffset(base, csp->dpName);
- sp->dpString = StringOffset(base, csp->dpString);
- }
-
- PCOMP_GROUP cgp;
- LPGROUP gp;
-
- for(
- cgp = (PCOMP_GROUP)(base + ckbp->dpGroupArray), gp = kbp->dpGroupArray, i = 0;
- i < kbp->cxGroupArray;
- i++, gp++, cgp++)
- {
- gp->dpName = StringOffset(base, cgp->dpName);
- gp->dpKeyArray = cgp->cxKeyArray > 0 ? (LPKEY) bufp : NULL;
- gp->cxKeyArray = cgp->cxKeyArray;
- bufp += sizeof(KEY) * gp->cxKeyArray;
- gp->dpMatch = StringOffset(base, cgp->dpMatch);
- gp->dpNoMatch = StringOffset(base, cgp->dpNoMatch);
- gp->fUsingKeys = cgp->fUsingKeys;
-
- PCOMP_KEY ckp;
- LPKEY kp;
- DWORD j;
-
- for(
- ckp = (PCOMP_KEY)(base + cgp->dpKeyArray), kp = gp->dpKeyArray, j = 0;
- j < gp->cxKeyArray;
- j++, kp++, ckp++)
- {
- kp->Key = ckp->Key;
- kp->Line = ckp->Line;
- kp->ShiftFlags = ckp->ShiftFlags;
- kp->dpOutput = StringOffset(base, ckp->dpOutput);
- kp->dpContext = StringOffset(base, ckp->dpContext);
- }
- }
-
- return kbp;
-}
-
-#else
-
-/**
- Fixup the keyboard by expanding pointers. On disk the pointers are stored relative to the
- beginning of the file, but we need real pointers. This method is used on 32-bit architectures.
-*/
-LPKEYBOARD FixupKeyboard(PBYTE bufp, PBYTE base, DWORD dwFileSize)
-{
- UNREFERENCED_PARAMETER(dwFileSize);
-
- DWORD i, j;
- PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) base;
- PCOMP_GROUP cgp;
- PCOMP_STORE csp;
- PCOMP_KEY ckp;
- LPKEYBOARD kbp = (LPKEYBOARD) bufp;
- LPSTORE sp;
- LPGROUP gp;
- LPKEY kp;
-
- kbp->dpStoreArray = (LPSTORE) (base + ckbp->dpStoreArray);
- kbp->dpGroupArray = (LPGROUP) (base + ckbp->dpGroupArray);
-
-/*if( ckbp->dwBitmapSize > 0 )
- kbp->hBitmap = LoadBitmapFile((buf + ckbp->dpBitmapOffset), ckbp->dwBitmapSize);
- else
- kbp->hBitmap = NULL;
-*/
-
- for(sp = kbp->dpStoreArray, csp = (PCOMP_STORE) sp, i = 0; i < kbp->cxStoreArray; i++, sp++, csp++)
- {
- sp->dpName = StringOffset(base, csp->dpName);
- sp->dpString = StringOffset(base, csp->dpString);
- }
-
- for(gp = kbp->dpGroupArray, cgp = (PCOMP_GROUP) gp, i = 0; i < kbp->cxGroupArray; i++, gp++, cgp++)
- {
- gp->dpName = StringOffset(base, cgp->dpName);
- gp->dpKeyArray = cgp->cxKeyArray > 0 ? (LPKEY) (base + cgp->dpKeyArray) : NULL;
- gp->dpMatch = StringOffset(base, cgp->dpMatch);
- gp->dpNoMatch = StringOffset(base, cgp->dpNoMatch);
-
- for(kp = gp->dpKeyArray, ckp = (PCOMP_KEY) kp, j = 0; j < gp->cxKeyArray; j++, kp++, ckp++)
- {
- kp->dpOutput = StringOffset(base, ckp->dpOutput);
- kp->dpContext = StringOffset(base, ckp->dpContext);
- }
- }
-
- return kbp;
-}
-
-#endif
-
-HBITMAP LoadBitmapFileEx(PBYTE filebase)
-{
- PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) filebase;
-
- if( ckbp->dwBitmapSize > 0 )
- return LoadBitmapFile(filebase + ckbp->dpBitmapOffset, ckbp->dwBitmapSize);
- else
- return NULL;
-}
-
-
-BOOL VerifyKeyboard(LPBYTE filebase)
-{
- DWORD i;
- PCOMP_KEYBOARD ckbp = (PCOMP_KEYBOARD) filebase;
- PCOMP_STORE csp;
-
- /* Check file version */
-
- if(ckbp->dwFileVersion < VERSION_MIN ||
- ckbp->dwFileVersion > VERSION_MAX)
- {
- for(csp = (PCOMP_STORE)(filebase + ckbp->dpStoreArray), i = 0; i < ckbp->cxStoreArray; i++, csp++) {
- if(csp->dwSystemID == TSS_COMPILEDVERSION)
- {
- char buf2[256];
- if(csp->dpString == 0)
- wsprintf(buf2, "errWrongFileVersion:NULL");
- else
- wsprintf(buf2, "errWrongFileVersion:%10.10ls", StringOffset(filebase, csp->dpString));
- Err(buf2);
- return FALSE;
- }
- }
- Err("errWrongFileVersion");
- return FALSE;
- }
-
- return TRUE;
-}
diff --git a/windows/src/engine/keyman32/appint/aiTIP.cpp b/windows/src/engine/keyman32/appint/aiTIP.cpp
index b6f591845b..a7faa7170f 100644
--- a/windows/src/engine/keyman32/appint/aiTIP.cpp
+++ b/windows/src/engine/keyman32/appint/aiTIP.cpp
@@ -234,14 +234,7 @@ extern "C" __declspec(dllexport) BOOL WINAPI TIPProcessKey(WPARAM wParam, LPARAM
AITIP::AITIP() {
::AIWin2000Unicode(); // I3574
- FIsDebugControlWindow = FALSE;
useLegacy = FALSE;
-
- WM_KEYMANDEBUG_CANDEBUG = RegisterWindowMessage("WM_KEYMANDEBUG_CANDEBUG");
- WM_KEYMANDEBUG_GETUNICODESTATUS = RegisterWindowMessage("WM_KEYMANDEBUG_GETUNICODESTATUS");
- WM_KEYMANDEBUG_GETCONTEXT = RegisterWindowMessage("WM_KEYMANDEBUG_GETCONTEXT");
- WM_KEYMANDEBUG_ACTION = RegisterWindowMessage("WM_KEYMANDEBUG_ACTION");
- WM_KEYMANDEBUG_RULEMATCH = RegisterWindowMessage("WM_KEYMANDEBUG_RULEMATCH");
}
AITIP::~AITIP() {
@@ -254,15 +247,6 @@ BOOL AITIP::CanHandleWindow(HWND ahwnd) {
return TRUE; // I3574
}
-BOOL AITIP::HandleWindow(HWND ahwnd) {
- FIsDebugControlWindow = IsDebugControlWindow(ahwnd);
- return AIWin2000Unicode::HandleWindow(ahwnd); // I3574
-}
-
-BOOL AITIP::IsWindowHandled(HWND ahwnd) {
- return AIWin2000Unicode::IsWindowHandled(ahwnd); // I3574
-}
-
BOOL AITIP::IsUnicode() {
return TRUE;
}
@@ -335,11 +319,6 @@ void AITIP::MergeContextWithCache(PWSTR buf, AppContext *local_context) { // I
}
void AITIP::ReadContext() {
- if(DebugControlled()) {
- Debug_FillContextBuffer();
- return;
- }
-
WCHAR buf[MAXCONTEXT];
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
@@ -376,44 +355,7 @@ void AITIP::RestoreContextOnly(AppContext *savedContext) {
/* Output actions */
-BOOL AITIP::QueueAction(int ItemType, DWORD dwData) {
- if(DebugControlled()) {
- switch(ItemType) {
- case QIT_VKEYDOWN:
- if((dwData & QVK_KEYMASK) <= VK__MAX && VKContextReset[(BYTE) dwData]) context->Reset(); // I3438 // I4370
- break;
-
- case QIT_DEADKEY:
- context->Add(UC_SENTINEL); // I4370
- context->Add(CODE_DEADKEY); // I4370
- context->Add((WORD) dwData); // I4370
- break;
-
- case QIT_CHAR:
- context->Add((WORD) dwData); // I4370
- break;
-
- case QIT_BACK:
- if(dwData & BK_BACKSPACE)
- while(context->CharIsDeadkey()) context->Delete(); // I4370
- context->Delete(); // I4370
- if(dwData & BK_BACKSPACE)
- while(context->CharIsDeadkey()) context->Delete(); // I4370
- break;
- }
-
- SendMessage(GetDebugControlWindow(), WM_KEYMANDEBUG_ACTION, ItemType, dwData);
- return TRUE;
- }
-
- return AIWin2000Unicode::QueueAction(ItemType, dwData); // I3575
-}
-
BOOL AITIP::SendActions() { // I4196
- if(DebugControlled()) {
- return TRUE;
- }
-
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return FALSE;
@@ -504,89 +446,3 @@ DWORD TSFShiftToShift(LPARAM shift) // I3588
if(shift & TF_MOD_RCONTROL) res |= RCTRLFLAG;
return res;
}
-
-/* Debug Integration */
-
-BOOL AITIP::IsDebugControlWindow(HWND hwnd)
-{
- static int WM_KEYMANDEBUG_CANDEBUG = RegisterWindowMessage("WM_KEYMANDEBUG_CANDEBUG");
- DWORD_PTR dwResult;
- SendMessageTimeout(hwnd, WM_KEYMANDEBUG_CANDEBUG, 0, 0, SMTO_BLOCK, 50, &dwResult);
- return dwResult != 0;
-}
-
-HWND AITIP::GetDebugControlWindow()
-{
- if(!FIsDebugControlWindow) return NULL;
- return hwnd;
-}
-
-BOOL AITIP::DebugControlled()
-{
- return FIsDebugControlWindow;
-}
-
-void AITIP::Debug_FillContextBuffer()
-{
- WCHAR buf[MAXCONTEXT];
- if(DebugControlled() &&
- SendMessage(GetDebugControlWindow(), WM_KEYMANDEBUG_GETCONTEXT, MAXCONTEXT, (LPARAM) buf))
- {
- context->Set(buf); // I4370
- SendDebugMessageFormat(0, sdmKeyboard, 0, "AIDebugger::FillContextBuffer(%ls)", buf);
- }
- else
- {
- context->Reset(); // I4370
- SendDebugMessageFormat(0, sdmKeyboard, 0, "AIDebugger::FillContextBuffer()-Reset");
- }
-}
-
-#define MAXSTOREOFFSETS 20
-
-struct AIDEBUGINFO
-{
- int cbSize;
- int ItemType;
- PWSTR Context, Output;
- LPKEY Rule;
- LPGROUP Group;
- DWORD_PTR Flags;
- WORD StoreOffsets[MAXSTOREOFFSETS*2+1]; // pairs--store, char position, terminated by 0xFFFF
-};
-
-void FillStoreOffsets(AIDEBUGINFO *di)
-{
- int i, n;
- PWSTR p;
-
- PKEYMAN64THREADDATA _td = ThreadGlobals();
- if(!_td) return;
-
- for(i = n = 0, p = di->Rule->dpContext; *p; p = incxstr(p), i++)
- {
- if(*p == UC_SENTINEL && (*(p+1) == CODE_ANY || *(p+1) == CODE_NOTANY))
- {
- di->StoreOffsets[n++] = *(p+2) - 1;
- di->StoreOffsets[n++] = _td->IndexStack[i];
- }
- if(*p == UC_SENTINEL && *(p+1) == CODE_INDEX)
- {
- di->StoreOffsets[n++] = *(p+2) - 1;
- di->StoreOffsets[n++] = _td->IndexStack[*(p+3) - 1];
- }
- if(n == MAXSTOREOFFSETS*2) break;
- }
-
- if(n < MAXSTOREOFFSETS*2 - 1)
- for(p = di->Rule->dpOutput; *p; p = incxstr(p))
- {
- if(*p == UC_SENTINEL && *(p+1) == CODE_INDEX)
- {
- di->StoreOffsets[n++] = *(p+2) - 1;
- di->StoreOffsets[n++] = _td->IndexStack[*(p+3) - 1];
- }
- if(n == MAXSTOREOFFSETS*2) break;
- }
- di->StoreOffsets[n] = 0xFFFF;
-}
diff --git a/windows/src/engine/keyman32/appint/aiTIP.h b/windows/src/engine/keyman32/appint/aiTIP.h
index 3c6fd9b698..93c9acd4ab 100644
--- a/windows/src/engine/keyman32/appint/aiTIP.h
+++ b/windows/src/engine/keyman32/appint/aiTIP.h
@@ -35,30 +35,11 @@
// This can be customised with HKLM\Software\Keyman\Keyman Engine\zap virtual key code
#define _VK_PREFIX_DEFAULT 0x0E
-struct AIDEBUGKEYINFO
-{
- UINT VirtualKey;
- DWORD shiftFlags;
- WCHAR Character, DeadKeyCharacter;
- BOOL IsUp;
-};
-
class AITIP : public AIWin2000Unicode
{
private:
- int WM_KEYMANDEBUG_CANDEBUG,
- WM_KEYMANDEBUG_GETUNICODESTATUS,
- WM_KEYMANDEBUG_GETCONTEXT,
- WM_KEYMANDEBUG_ACTION,
- WM_KEYMANDEBUG_RULEMATCH;
-
- BOOL FIsDebugControlWindow;
- HWND GetDebugControlWindow();
- void Debug_FillContextBuffer();
void MergeContextWithCache(PWSTR buf, AppContext *context); // I4262
- static BOOL IsDebugControlWindow(HWND hwnd);
-
private:
BOOL useLegacy;
@@ -69,8 +50,6 @@ public:
AITIP();
~AITIP();
- BOOL DebugControlled();
-
/**
* Copy the member context
*
@@ -85,13 +64,9 @@ public:
*/
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);
virtual BOOL IsUnicode();
/* Context functions */
diff --git a/windows/src/engine/keyman32/globals.h b/windows/src/engine/keyman32/globals.h
index 320ef811de..8f1dfc4c90 100644
--- a/windows/src/engine/keyman32/globals.h
+++ b/windows/src/engine/keyman32/globals.h
@@ -54,10 +54,6 @@
#include
-#define GLOBAL_ContextStackSize 80
-#define GLOBAL_MsgStackSize 80
-#define GLOBAL_MaxKeyboards 32
-
#include "serialkeyeventclient.h"
#include "SharedBuffers.h"
@@ -66,8 +62,6 @@
class Globals
{
public:
- //static INI *Ini();
-
static HHOOK *hhookGetMessage();
static HHOOK *hhookCallWndProc();
@@ -196,16 +190,9 @@ typedef struct tagKEYMAN64THREADDATA
LPINTKEYBOARDINFO lpKeyboards; // keyboard definitions
LPINTKEYBOARDINFO lpActiveKeyboard;
- // I3616
- LPMSG msgbuf; // Message buffer (alloc at runtime)
-
int nKeyboards; // nLoadedKeyboards
int nLanguages; // I1087 //TODO UNUSED
- LPWORD IndexStack;
- LPWSTR miniContext;
- int miniContextIfLen;
-
KMSTATE state;
AITIP *app;
@@ -263,12 +250,10 @@ typedef struct tagKEYMAN64THREADDATA
extern UINT
wm_keyman, // user message - ignore msg
- wm_kmdebug, // " " " " - debugging
wm_keyman_control, // messages to main Keyman window - replaces WM_USER+*
wm_keyman_control_internal, // messages to all windows to notify of changes to Keyman // I4412
wm_keymankeydown,
wm_keymankeyup,
- wm_keymandebug,
wm_keyman_grabwindowproc,
wm_keyman_refresh,
wm_kmgetactivekeymanid,
diff --git a/windows/src/engine/keyman32/k32_globals.cpp b/windows/src/engine/keyman32/k32_globals.cpp
index 989a787f95..fb82735377 100644
--- a/windows/src/engine/keyman32/k32_globals.cpp
+++ b/windows/src/engine/keyman32/k32_globals.cpp
@@ -72,7 +72,6 @@
UINT
//TODO: consolidate these messages -- they are probably not all required now
wm_keyman = 0, // user message - ignore msg // I3594
- wm_kmdebug = 0, // " " " " - debugging
wm_keymankeydown = 0,
wm_keymankeyup = 0,
@@ -218,9 +217,6 @@ BOOL Globals_ProcessInitialised()
#pragma data_seg(".SHARDATA")
-//static INI // I3158 // I3524
-// f_Ini = {0}; // KEYMAN.INI options
-
static HHOOK
f_hhookGetMessage = NULL, // GETMESSAGE hook handle
f_hhookCallWndProc = NULL; // CALLWNDPROC hook handle
@@ -296,8 +292,6 @@ DWORD //static
HANDLE f_hLockMutex = 0;
-//INI *Globals::Ini() { return &f_Ini; } // I3158 // I3524
-
HHOOK *Globals::hhookGetMessage() { return &f_hhookGetMessage; }
HHOOK *Globals::hhookCallWndProc() { return &f_hhookCallWndProc; }
@@ -428,11 +422,6 @@ BOOL Globals::ResetControllers() // I3092
f_MasterController = NULL;
f_MaxControllerThreads = 0;
- /* I3158 // I3524
- f_Ini.ContextStackSize = 0;
- f_Ini.MaxKeyboards = 0;
- f_Ini.MsgStackSize = 0;
- */
f_hhookCallWndProc = NULL;
f_hhookGetMessage = NULL;
#ifndef _WIN64
diff --git a/windows/src/engine/keyman32/keyman32.cpp b/windows/src/engine/keyman32/keyman32.cpp
index 5dfdaab079..9dbd692525 100644
--- a/windows/src/engine/keyman32/keyman32.cpp
+++ b/windows/src/engine/keyman32/keyman32.cpp
@@ -157,27 +157,9 @@ void UninitDebuggingEx();
BOOL UninitialiseProcess(BOOL Lock)
{
if(!Globals_ProcessInitialised()) return TRUE;
-
- ReleaseKeyboards(Lock);
-
- UninitDebuggingEx();
-
- PKEYMAN64THREADDATA _td = ThreadGlobals(); // This is safe because of Globals_ProcessInitialised call above
- if(_td)
- {
- if(_td->msgbuf) delete _td->msgbuf;
- _td->msgbuf = NULL;
-
- if(_td->IndexStack) delete _td->IndexStack;
- _td->IndexStack = NULL;
-
- if (_td->miniContext) delete _td->miniContext;
- _td->miniContext = NULL;
-
- if (_td->msgbuf) delete _td->msgbuf;
- _td->msgbuf = NULL;
- }
- return TRUE;
+ ReleaseKeyboards(Lock);
+ UninitDebuggingEx();
+ return TRUE;
}
LONG FStartedInitialise = FALSE;
@@ -239,34 +221,8 @@ BOOL InitThread(HWND hwnd)
// I2448 - Removed "|| _td->FInitialised" -- this should not be included because sometimes it can be re-initialised.
}
- // TODO: Check if we are initialising again and don't reallocate memory. This can happen if Keyman is restarted
-
_td->FInitialising = TRUE; // Control re-entrancy, this is thread safe because the variable is per-thread
- _td->IndexStack = new WORD[GLOBAL_ContextStackSize]; //Globals::Ini()->ContextStackSize]; // I3158 // I3524
- if(!_td->IndexStack)
- {
- SendDebugMessage(hwnd, sdmGlobal, 0, "InitialiseProcess: Failed to allocate memory for IndexStack");
- SetLastError(ERROR_KEYMAN_MEMORY_ALLOCATION_FAILED); // I3143 // I3523
- return FALSE;
- }
-
- _td->miniContext = new WCHAR[GLOBAL_ContextStackSize]; //Globals::Ini()->ContextStackSize]; // I3158 // I3524
- if(!_td->miniContext)
- {
- SendDebugMessage(hwnd, sdmGlobal, 0, "InitialiseProcess: Failed to allocate memory for miniContext");
- SetLastError(ERROR_KEYMAN_MEMORY_ALLOCATION_FAILED); // I3143 // I3523
- return FALSE;
- }
-
- _td->msgbuf = new MSG[GLOBAL_MsgStackSize]; //Globals::Ini()->MsgStackSize]; // I3158 // I3524
- if(!_td->msgbuf)
- {
- SendDebugMessage(hwnd, sdmGlobal, 0, "InitialiseProcess: Failed to allocate memory for msgbuf");
- SetLastError(ERROR_KEYMAN_MEMORY_ALLOCATION_FAILED); // I3143 // I3523
- return FALSE;
- }
-
RefreshKeyboards(TRUE);
SendDebugMessageFormat(hwnd, sdmGlobal, 0, "--InitialiseProcess LEAVE--");
@@ -316,10 +272,6 @@ BOOL InitialiseProcess(HWND hwnd)
DoChangeWindowMessageFilter();
- //GetINIAdvanced(); /* I163x - Fix crash due to memory corruption - Globals::Ini not initialized before use - only appeared to happen on x64? */ // I3158 // I3524
-
- SendDebugMessageFormat(hwnd, sdmGlobal, 0, "ContextStackSize: %d", GLOBAL_ContextStackSize); // Globals::Ini()->ContextStackSize); // I3158 // I3524
-
return InitThread(hwnd);
}
@@ -461,13 +413,6 @@ extern "C" BOOL _declspec(dllexport) WINAPI Keyman_Initialise(HWND Handle, BOOL
return TRUE;
}
-/*void GetINIAdvanced(void) // I3158 // I3524
-{
- Globals::Ini()->ContextStackSize = 80;
- Globals::Ini()->MsgStackSize = 80;
- Globals::Ini()->MaxKeyboards = 32;
-}*/
-
extern "C" BOOL _declspec(dllexport) WINAPI Keyman_StartExit(void) // I3092
{
*Globals::Keyman_Shutdown() = TRUE;
diff --git a/windows/src/engine/keyman32/keymanengine.h b/windows/src/engine/keyman32/keymanengine.h
index c563210a76..3c6e2d3aff 100644
--- a/windows/src/engine/keyman32/keymanengine.h
+++ b/windows/src/engine/keyman32/keymanengine.h
@@ -92,13 +92,6 @@ typedef struct tagINTKEYBOARDINFO
km_core_keyboard_imx* lpIMXList;
} INTKEYBOARDINFO, * LPINTKEYBOARDINFO;
-typedef struct tagINI
-{
- int MsgStackSize;
- int MaxKeyboards;
- int ContextStackSize;
-} INI;
-
typedef struct tagKMSTATE
{
BOOL NoMatches;
@@ -124,14 +117,7 @@ LRESULT CALLBACK kmnLowLevelKeyboardProc( // I4124
BOOL ReleaseStateMemoryCore(km_core_state** state);
BOOL ReleaseKeyboardMemoryCore(km_core_keyboard** kbd);
-void PostGETNEXT(HWND hwnd);
-BOOL CompareMsg(LPMSG MsgA, LPMSG MsgB);
BOOL ProcessHook(); // returns FALSE on error or key not matched [only for AITip]
-BOOL ProcessMessage( LPMSG mp );
-BOOL ProcessGroup(LPGROUP gp);
-BOOL ContextMatch(LPKEY kkp);
-int PostString(PWSTR str, LPMSG mp, LPKEYBOARD lpkb, PWSTR endstr);
-BOOL LoadAllKeymanKeyboards(DWORD layout);
BOOL IsSysTrayWindow(HWND hwnd);
@@ -149,7 +135,6 @@ BOOL SelectKeyboard(DWORD KeymanID);
extern "C" DWORD _declspec(dllexport) WINAPI GetActiveKeymanID();
BOOL GetKeyboardFileName(LPSTR kbname, LPSTR buf, int nbuf);
-BOOL LoadKeyboard(LPSTR fileName, LPKEYBOARD *lpKeyboard);
BOOL LoadlpKeyboard(int i);
PSTR wstrtostr(PCWSTR in);
diff --git a/windows/src/engine/keyman32/kmhook_getmessage.cpp b/windows/src/engine/keyman32/kmhook_getmessage.cpp
index e129a0b8da..d4d1177ced 100644
--- a/windows/src/engine/keyman32/kmhook_getmessage.cpp
+++ b/windows/src/engine/keyman32/kmhook_getmessage.cpp
@@ -266,11 +266,6 @@ LRESULT _kmnGetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
SendDebugMessageFormat(0, sdmInternat, 0, "GetMessage: wm_keymanshift %x %x", mp->wParam, mp->lParam);
SelectApplicationIntegration();
if(!_td->app->IsWindowHandled(mp->hwnd)) _td->app->HandleWindow(mp->hwnd);
- if(_td->app->DebugControlled())
- {
- if(mp->wParam == 1) *Globals::ShiftState() = (DWORD) mp->lParam;
- else *Globals::ShiftState() = 0;
- }
return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam);
}
diff --git a/windows/src/engine/keyman32/kmprocess.cpp b/windows/src/engine/keyman32/kmprocess.cpp
index 5772836de2..7e5e807056 100644
--- a/windows/src/engine/keyman32/kmprocess.cpp
+++ b/windows/src/engine/keyman32/kmprocess.cpp
@@ -138,16 +138,7 @@ BOOL ProcessHook()
if(!_td) return FALSE;
fOutputKeystroke = FALSE; // TODO: 5442 no longer needs to be global once we use core processor
- //
- // If we are running in the debugger, don't do a second run through
- //
- if(_td->app->DebugControlled() && !_td->TIPFUpdateable) { // I4287
- if(_td->state.vkey == VK_ESCAPE || (_td->state.vkey >= VK_PRIOR && _td->state.vkey <= VK_DOWN) || (_td->state.vkey == VK_DELETE)) return FALSE; // I4033 // I4826 // I4845
- else return TRUE;
- }
-
- //app->NoSetShift = FALSE;
_td->app->ReadContext();
if(_td->state.msg.message == wm_keymankeydown) { // I4827
@@ -216,17 +207,6 @@ BOOL ProcessHook()
}
}
- if (fOutputKeystroke && _td->app->DebugControlled()) {
- // The debug memo does not receive default key events because
- // we capture them all here. So we synthesize the key event for
- // the debugger.
- _td->app->QueueAction(QIT_VSHIFTDOWN, Globals::get_ShiftState());
- _td->app->QueueAction(QIT_VKEYDOWN, _td->state.vkey);
- _td->app->QueueAction(QIT_VKEYUP, _td->state.vkey);
- _td->app->QueueAction(QIT_VSHIFTUP, Globals::get_ShiftState());
- fOutputKeystroke = FALSE;
- }
-
if(*Globals::hwndIM() == 0 || *Globals::hwndIMAlways())
{
_td->app->SetCurrentShiftState(Globals::get_ShiftState());