mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-21 15:17:40 +00:00
Merge branch 'master' into feat/developer-9446-bad-unicode-epic-ldml
This commit is contained in:
commit
02c8db9fdd
43 changed files with 1786 additions and 1106 deletions
18
HISTORY.md
18
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)
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
17.0.216
|
||||
17.0.218
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
Text Selection Tests Keyboard Change History
|
||||
====================
|
||||
|
||||
1.0 (2023-11-14)
|
||||
----------------
|
||||
* Created by Keyman Team
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Text Selection Tests Keyboard</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>Text Selection Tests Keyboard</h1>
|
||||
|
||||
<p>
|
||||
Text Selection Tests Keyboard 1.0 generated from template.
|
||||
</p>
|
||||
|
||||
<p>© Keyman Team</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -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'
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package>
|
||||
<System>
|
||||
<KeymanDeveloperVersion>16.0.142.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="">Text Selection Tests Keyboard</Name>
|
||||
<Copyright URL="">© Keyman Team</Copyright>
|
||||
<Author URL="">Keyman Team</Author>
|
||||
<Version URL=""></Version>
|
||||
</Info>
|
||||
<Files>
|
||||
<File>
|
||||
<Name>..\build\text_selection_tests_keyboard_9073.kmx</Name>
|
||||
<Description></Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.kmx</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\build\text_selection_tests_keyboard_9073.js</Name>
|
||||
<Description></Description>
|
||||
<CopyLocation>0</CopyLocation>
|
||||
<FileType>.js</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<Name>..\build\text_selection_tests_keyboard_9073.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>Text Selection Tests Keyboard</Name>
|
||||
<ID>text_selection_tests_keyboard_9073</ID>
|
||||
<Version>1.0</Version>
|
||||
<Languages>
|
||||
<Language ID="en">English</Language>
|
||||
</Languages>
|
||||
</Keyboard>
|
||||
</Keyboards>
|
||||
<Strings/>
|
||||
</Package>
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<visualkeyboard>
|
||||
<header>
|
||||
<version>10.0</version>
|
||||
<kbdname>text_selection_tests_keyboard_9073</kbdname>
|
||||
<flags/>
|
||||
</header>
|
||||
<encoding name="unicode" fontname="Arial" fontsize="-12">
|
||||
<layer shift="">
|
||||
<key vkey="K_BKQUOTE">dk(1)</key>
|
||||
<key vkey="K_1">1</key>
|
||||
<key vkey="K_2">2</key>
|
||||
<key vkey="K_3">3</key>
|
||||
<key vkey="K_4">4</key>
|
||||
<key vkey="K_5">5</key>
|
||||
<key vkey="K_6">6</key>
|
||||
<key vkey="K_7">7</key>
|
||||
<key vkey="K_8">8</key>
|
||||
<key vkey="K_9">9</key>
|
||||
<key vkey="K_0">0</key>
|
||||
<key vkey="K_HYPHEN">-</key>
|
||||
<key vkey="K_EQUAL">=</key>
|
||||
<key vkey="K_Q">q</key>
|
||||
<key vkey="K_W">w</key>
|
||||
<key vkey="K_E">e</key>
|
||||
<key vkey="K_R">r</key>
|
||||
<key vkey="K_T">t</key>
|
||||
<key vkey="K_Y">y</key>
|
||||
<key vkey="K_U">u</key>
|
||||
<key vkey="K_I">i</key>
|
||||
<key vkey="K_O">o</key>
|
||||
<key vkey="K_P">p</key>
|
||||
<key vkey="K_LBRKT">[</key>
|
||||
<key vkey="K_RBRKT">]</key>
|
||||
<key vkey="K_BKSLASH">\</key>
|
||||
<key vkey="K_A">a</key>
|
||||
<key vkey="K_S">s</key>
|
||||
<key vkey="K_D">d</key>
|
||||
<key vkey="K_F">f</key>
|
||||
<key vkey="K_G">g</key>
|
||||
<key vkey="K_H">h</key>
|
||||
<key vkey="K_J">j</key>
|
||||
<key vkey="K_K">k</key>
|
||||
<key vkey="K_L">l</key>
|
||||
<key vkey="K_COLON">;</key>
|
||||
<key vkey="K_QUOTE">'</key>
|
||||
<key vkey="K_oE2">\</key>
|
||||
<key vkey="K_Z">z</key>
|
||||
<key vkey="K_X">x</key>
|
||||
<key vkey="K_C">c</key>
|
||||
<key vkey="K_V">v</key>
|
||||
<key vkey="K_B">b</key>
|
||||
<key vkey="K_N">n</key>
|
||||
<key vkey="K_M">m</key>
|
||||
<key vkey="K_COMMA">,</key>
|
||||
<key vkey="K_PERIOD">.</key>
|
||||
<key vkey="K_SLASH">/</key>
|
||||
</layer>
|
||||
<layer shift="S">
|
||||
<key vkey="K_BKQUOTE">~</key>
|
||||
<key vkey="K_1">!</key>
|
||||
<key vkey="K_2">@</key>
|
||||
<key vkey="K_3">#</key>
|
||||
<key vkey="K_4">$</key>
|
||||
<key vkey="K_5">%</key>
|
||||
<key vkey="K_6">^</key>
|
||||
<key vkey="K_7">&</key>
|
||||
<key vkey="K_8">*</key>
|
||||
<key vkey="K_9">(</key>
|
||||
<key vkey="K_0">)</key>
|
||||
<key vkey="K_HYPHEN">_</key>
|
||||
<key vkey="K_EQUAL">+</key>
|
||||
<key vkey="K_Q">Q</key>
|
||||
<key vkey="K_W">W</key>
|
||||
<key vkey="K_E">E</key>
|
||||
<key vkey="K_R">R</key>
|
||||
<key vkey="K_T">T</key>
|
||||
<key vkey="K_Y">Y</key>
|
||||
<key vkey="K_U">U</key>
|
||||
<key vkey="K_I">I</key>
|
||||
<key vkey="K_O">O</key>
|
||||
<key vkey="K_P">P</key>
|
||||
<key vkey="K_LBRKT">{</key>
|
||||
<key vkey="K_RBRKT">}</key>
|
||||
<key vkey="K_BKSLASH">|</key>
|
||||
<key vkey="K_A">A</key>
|
||||
<key vkey="K_S">S</key>
|
||||
<key vkey="K_D">D</key>
|
||||
<key vkey="K_F">F</key>
|
||||
<key vkey="K_G">G</key>
|
||||
<key vkey="K_H">H</key>
|
||||
<key vkey="K_J">J</key>
|
||||
<key vkey="K_K">K</key>
|
||||
<key vkey="K_L">L</key>
|
||||
<key vkey="K_COLON">:</key>
|
||||
<key vkey="K_QUOTE">"</key>
|
||||
<key vkey="K_oE2">|</key>
|
||||
<key vkey="K_Z">Z</key>
|
||||
<key vkey="K_X">X</key>
|
||||
<key vkey="K_C">C</key>
|
||||
<key vkey="K_V">V</key>
|
||||
<key vkey="K_B">B</key>
|
||||
<key vkey="K_N">N</key>
|
||||
<key vkey="K_M">M</key>
|
||||
<key vkey="K_COMMA"><</key>
|
||||
<key vkey="K_PERIOD">></key>
|
||||
<key vkey="K_SLASH">?</key>
|
||||
</layer>
|
||||
</encoding>
|
||||
</visualkeyboard>
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Start Using Text Selection Tests Keyboard</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 Text Selection Tests Keyboard</h1>
|
||||
|
||||
<p>
|
||||
Text Selection Tests Keyboard 1.0 generated from template.
|
||||
</p>
|
||||
|
||||
<h1>Keyboard Layout</h1>
|
||||
|
||||
<!-- Insert Keyboard Layout Images or HTML here -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"license": "mit",
|
||||
"languages": [
|
||||
"en"
|
||||
],
|
||||
"description": "Text Selection Tests Keyboard generated from template"
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
<?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_dda967022de452e1fe199096e795f0ab</ID>
|
||||
<Filename>text_selection_tests_keyboard_9073.kmn</Filename>
|
||||
<Filepath>source\text_selection_tests_keyboard_9073.kmn</Filepath>
|
||||
<FileVersion>1.0</FileVersion>
|
||||
<FileType>.kmn</FileType>
|
||||
<Details>
|
||||
<Name>Text Selection Tests Keyboard</Name>
|
||||
<Copyright>© Keyman Team</Copyright>
|
||||
</Details>
|
||||
</File>
|
||||
<File>
|
||||
<ID>id_ba932837e6a67a86abc409a393242255</ID>
|
||||
<Filename>text_selection_tests_keyboard_9073.kps</Filename>
|
||||
<Filepath>source\text_selection_tests_keyboard_9073.kps</Filepath>
|
||||
<FileVersion></FileVersion>
|
||||
<FileType>.kps</FileType>
|
||||
<Details>
|
||||
<Name>Text Selection Tests Keyboard</Name>
|
||||
<Copyright>© Keyman Team</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_4b87bd35cc2e16f1ff8680a6f2caed52</ID>
|
||||
<Filename>text_selection_tests_keyboard_9073.keyboard_info</Filename>
|
||||
<Filepath>text_selection_tests_keyboard_9073.keyboard_info</Filepath>
|
||||
<FileVersion></FileVersion>
|
||||
<FileType>.keyboard_info</FileType>
|
||||
</File>
|
||||
<File>
|
||||
<ID>id_bbf31cea8a9cfe0cb838f67055690bf8</ID>
|
||||
<Filename>text_selection_tests_keyboard_9073.ico</Filename>
|
||||
<Filepath>source\text_selection_tests_keyboard_9073.ico</Filepath>
|
||||
<FileVersion></FileVersion>
|
||||
<FileType>.ico</FileType>
|
||||
<ParentFileID>id_dda967022de452e1fe199096e795f0ab</ParentFileID>
|
||||
</File>
|
||||
<File>
|
||||
<ID>id_b8f7a473cac52dd0436273de657cdf46</ID>
|
||||
<Filename>text_selection_tests_keyboard_9073.kmx</Filename>
|
||||
<Filepath>source\..\build\text_selection_tests_keyboard_9073.kmx</Filepath>
|
||||
<FileVersion></FileVersion>
|
||||
<FileType>.kmx</FileType>
|
||||
<ParentFileID>id_ba932837e6a67a86abc409a393242255</ParentFileID>
|
||||
</File>
|
||||
<File>
|
||||
<ID>id_73d0cd87e78d9b8d7f514809dbb36a47</ID>
|
||||
<Filename>text_selection_tests_keyboard_9073.js</Filename>
|
||||
<Filepath>source\..\build\text_selection_tests_keyboard_9073.js</Filepath>
|
||||
<FileVersion></FileVersion>
|
||||
<FileType>.js</FileType>
|
||||
<ParentFileID>id_ba932837e6a67a86abc409a393242255</ParentFileID>
|
||||
</File>
|
||||
<File>
|
||||
<ID>id_71aafc060dc3251e4bb611ea539dc8e0</ID>
|
||||
<Filename>text_selection_tests_keyboard_9073.kvk</Filename>
|
||||
<Filepath>source\..\build\text_selection_tests_keyboard_9073.kvk</Filepath>
|
||||
<FileVersion></FileVersion>
|
||||
<FileType>.kvk</FileType>
|
||||
<ParentFileID>id_ba932837e6a67a86abc409a393242255</ParentFileID>
|
||||
</File>
|
||||
<File>
|
||||
<ID>id_356e5d149c1e539356d72698c1e401a6</ID>
|
||||
<Filename>welcome.htm</Filename>
|
||||
<Filepath>source\welcome.htm</Filepath>
|
||||
<FileVersion></FileVersion>
|
||||
<FileType>.htm</FileType>
|
||||
<ParentFileID>id_ba932837e6a67a86abc409a393242255</ParentFileID>
|
||||
</File>
|
||||
<File>
|
||||
<ID>id_8da344c4cea6f467013357fe099006f5</ID>
|
||||
<Filename>readme.htm</Filename>
|
||||
<Filepath>source\readme.htm</Filepath>
|
||||
<FileVersion></FileVersion>
|
||||
<FileType>.htm</FileType>
|
||||
<ParentFileID>id_ba932837e6a67a86abc409a393242255</ParentFileID>
|
||||
</File>
|
||||
</Files>
|
||||
</KeymanDeveloperProject>
|
||||
|
|
@ -570,6 +570,9 @@ export default class KeyboardProcessor extends EventEmitter<EventMap> {
|
|||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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<km_core_option_scope>(action_items->option->scope),
|
||||
km::core::option opt(static_cast<km_core_option_scope>(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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 &)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -240,6 +240,8 @@
|
|||
|
||||
#define CHINT_UnreachableRule 0x000010AE
|
||||
|
||||
#define CWARN_VirtualKeyInOutput 0x000020AF
|
||||
|
||||
#define CERR_BufferOverflow 0x000080C0
|
||||
#define CERR_Break 0x000080C1
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
9
developer/src/kmc-kmn/test/fixtures/invalid-keyboards/warn_virtual_key_in_output.kmn
vendored
Normal file
9
developer/src/kmc-kmn/test/fixtures/invalid-keyboards/warn_virtual_key_in_output.kmn
vendored
Normal file
|
|
@ -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]
|
||||
|
|
@ -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");
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <eb1@sil.org> Wed, 22 Nov 2023 15:24:59 +0100
|
||||
|
||||
keyman (16.0.141-1) unstable; urgency=medium
|
||||
|
||||
* Work around mips64el build failure (#1041499)
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
<h2><a href="./issue6005/index.html">Tests predictive text & other handling of rule matching when the final rule group does not match (#6005)</a></h2>
|
||||
<h2><a href="./default-subkey/index.html">Tests handling of new default-subkey feature (#9430)</a></h2>
|
||||
<h2><a href="./issue9469/index.html">Test special characters rendering with keymanweb-osk.ttf (#9469)</a></h2>
|
||||
<h2><a href="./text_selection_tests_9073/index.html">Test text selection (#9073)</a></h2>
|
||||
<h1>Other</h1>
|
||||
<h2><a href="./regression-tests/index.html">Keystroke processing regression test engine.</a></h2>
|
||||
<hr>
|
||||
|
|
|
|||
78
web/src/test/manual/web/text_selection_tests_9073/index.html
Normal file
78
web/src/test/manual/web/text_selection_tests_9073/index.html
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8' />
|
||||
|
||||
<!-- Set the viewport width to match phone and tablet device widths -->
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no" />
|
||||
|
||||
<title>KeymanWeb #9073</title>
|
||||
|
||||
<!-- Your page CSS -->
|
||||
<style type='text/css'>
|
||||
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;}
|
||||
</style>
|
||||
<script src="../../../../../build/publish/debug/keymanweb.js" type="application/javascript"></script>
|
||||
<script src="../../../../../build/publish/debug/kmwuitoggle.js"></script>
|
||||
|
||||
<!-- Initialization: set paths to keyboards, resources and fonts as required -->
|
||||
<script>
|
||||
(function(kmw) {
|
||||
kmw.init({
|
||||
attachType:'auto'
|
||||
}).then(function() {
|
||||
kmw.addKeyboards({
|
||||
id:'text_selection_tests_keyboard_9073',
|
||||
name:'Text selection test cases (#9073)',
|
||||
languages:{
|
||||
id:'en',
|
||||
name:'English'
|
||||
},
|
||||
filename:'./text_selection_tests_keyboard_9073.js',
|
||||
displayName: 'Text selection test cases (#9073)'
|
||||
});
|
||||
});
|
||||
})(keyman);
|
||||
</script>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
<!-- Sample page HTML -->
|
||||
<body>
|
||||
<h2>Text Selection Test Cases (#9073)</h2>
|
||||
|
||||
<div>
|
||||
<!--
|
||||
The following DIV is used to position the Button or Toolbar User Interfaces on the page.
|
||||
If omitted, those User Interfaces will appear at the top of the document body.
|
||||
(It is ignored by other User Interfaces.)
|
||||
-->
|
||||
<div id='KeymanWebControl'></div>
|
||||
|
||||
<textarea id='ta1' class='test' placeholder='Type here'></textarea>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
<h3><a href="../index.html">Return to testing home page</a></h3>
|
||||
</body>
|
||||
|
||||
<!--
|
||||
*** DEVELOPER NOTE -- FIREFOX CONFIGURATION FOR TESTING ***
|
||||
*
|
||||
* If the URL bar starts with <b>file://</b>, Firefox may not load the font used
|
||||
* to display the special characters used in the On-Screen Keyboard.
|
||||
*
|
||||
* To work around this Firefox bug, navigate to <b>about:config</b>
|
||||
* and set <b>security.fileuri.strict_origin_policy</b> to <b>false</b>
|
||||
* while testing.
|
||||
*
|
||||
* Firefox resolves website-based CSS URI references correctly without needing
|
||||
* any configuration change, so this change should only be made for file-based testing.
|
||||
*
|
||||
***
|
||||
-->
|
||||
</html>
|
||||
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
@ -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 <g>
|
||||
*
|
||||
\****************************************************************************/
|
||||
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 <g>
|
||||
*
|
||||
\****************************************************************************/
|
||||
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 <g>
|
||||
*
|
||||
\****************************************************************************/
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -54,10 +54,6 @@
|
|||
|
||||
#include <evntprov.h>
|
||||
|
||||
#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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue