[Common] Continue refactoring, add support for supplying context from command line

This commit is contained in:
Marc Durdin 2018-11-06 20:24:43 +11:00
parent e4deaacd85
commit 3d4aff5d62
12 changed files with 119 additions and 284 deletions

View file

@ -0,0 +1,3 @@
.vs/
Debug/
x64/

View file

@ -52,6 +52,7 @@ public:
virtual void AddContext(WCHAR ch); //I2436
virtual WCHAR *ContextBuf(int n);
virtual WCHAR *ContextBufMax(int n);
void SetContext(PWCHAR ctxt);
/* Queue and sending functions */

View file

@ -40,6 +40,7 @@ typedef struct
#define QIT_DEADKEY 5
#define QIT_BELL 6
#define QIT_BACK 7
#define QIT_CAPSLOCK 8
// QueueDebugInformation ItemTypes
#define QID_BEGIN_UNICODE 0

View file

@ -305,7 +305,6 @@ PWSTR GetSystemStore(LPKEYBOARD kb, DWORD SystemID);
#ifndef _KEYMAN64_LIGHT
#include "syskbd.h"
#include "vkscancodes.h"
#include "rc4.h"
#include "crc32.h"

View file

@ -1,17 +0,0 @@
class CryptRC4
{
private:
BOOL fInitialized;
BYTE KeyData[256], KeyOrg[256];
void EncryptBuffer(PBYTE InData, PBYTE OutData, DWORD Size);
void DecryptBuffer(PBYTE InData, PBYTE OutData, DWORD Size);
public:
static BOOL SelfTest();
void Init(PBYTE Key, DWORD Size, PVOID InitVector);
void Burn();
void Reset();
void Encrypt(PBYTE InData, PBYTE OutData, DWORD Size);
void Decrypt(PBYTE InData, PBYTE OutData, DWORD Size);
};

View file

@ -75,7 +75,7 @@
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>C:\Projects\keyman\kmxtest\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
@ -91,7 +91,7 @@
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>C:\Projects\keyman\kmxtest\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
@ -105,14 +105,14 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>C:\Projects\keyman\kmxtest\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>C:\Projects\keyman\kmxtest\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
@ -121,7 +121,6 @@
<ClCompile Include="src\appint\aiWin2000Unicode.cpp" />
<ClCompile Include="src\appint\appint.cpp" />
<ClCompile Include="src\capsstate.cpp" />
<ClCompile Include="src\common\rc4.cpp" />
<ClCompile Include="src\common\registry.cpp" />
<ClCompile Include="src\common\unicode.cpp" />
<ClCompile Include="src\common\xstring.cpp" />
@ -164,7 +163,6 @@
<ClInclude Include="inc\kmxtest.h" />
<ClInclude Include="inc\onlineconstants.h" />
<ClInclude Include="inc\pch.h" />
<ClInclude Include="inc\rc4.h" />
<ClInclude Include="inc\registry.h" />
<ClInclude Include="inc\syskbd.h" />
<ClInclude Include="inc\unicode.h" />

View file

@ -57,9 +57,6 @@
<ClCompile Include="src\appint\appint.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\common\rc4.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\common\registry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -125,9 +122,6 @@
<ClInclude Include="inc\pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\rc4.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="inc\registry.h">
<Filter>Header Files</Filter>
</ClInclude>

View file

@ -57,6 +57,10 @@ AIWin2000Unicode::~AIWin2000Unicode()
void AIWin2000Unicode::ReadContext()
{
}
void AIWin2000Unicode::SetContext(WCHAR *ctxt) {
context->Set(ctxt);
}
void AIWin2000Unicode::AddContext(WCHAR ch) //I2436
{
@ -143,14 +147,22 @@ BOOL AIWin2000Unicode::PostKeys()
for(; n < QueueSize; n++)
{
switch(Queue[n].ItemType) {
case QIT_VKEYDOWN:
case QIT_CAPSLOCK:
if (Queue[n].dwData == 0) {
wprintf(L"CAPSLOCK off\n");
}
else {
wprintf(L"CAPSLOCK on\n");
}
break;
case QIT_VKEYDOWN:
if((Queue[n].dwData & QVK_KEYMASK) == 0x05) Queue[n].dwData = (Queue[n].dwData & QVK_FLAGMASK) | VK_RETURN; // I649 // I3438
/* 6.0.153.0: Fix repeat state for virtual keys */
if((Queue[n].dwData & QVK_KEYMASK) <= VK__MAX) // I3438
{
printf("KEYDOWN: %x (flags=%x)\n", Queue[n].dwData & 0xFF, (Queue[n].dwData & QVK_FLAGMASK) >> 16);
wprintf(L"KEYDOWN: %x (flags=%x)\n", Queue[n].dwData & 0xFF, (Queue[n].dwData & QVK_FLAGMASK) >> 16);
}
break;
@ -159,27 +171,27 @@ BOOL AIWin2000Unicode::PostKeys()
if((Queue[n].dwData & QVK_KEYMASK) <= VK__MAX) // I3438
{
printf("KEYUP: %x (flags=%x)\n", Queue[n].dwData & 0xFF, (Queue[n].dwData & QVK_FLAGMASK) >> 16);
wprintf(L"KEYUP: %x (flags=%x)\n", Queue[n].dwData & 0xFF, (Queue[n].dwData & QVK_FLAGMASK) >> 16);
}
break;
case QIT_VSHIFTDOWN:
printf("VSHIFTDOWN\n");
wprintf(L"VSHIFTDOWN\n");
break;
case QIT_VSHIFTUP:
printf("VSHIFTUP\n");
wprintf(L"VSHIFTUP\n");
break;
case QIT_CHAR:
wprintf(L"CHAR %x (%lc)\n", Queue[n].dwData, Queue[n].dwData);
wprintf(L"CHAR %x (%c)\n", Queue[n].dwData, Queue[n].dwData);
break;
case QIT_DEADKEY:
printf("DEADKEY\n");
wprintf(L"DEADKEY\n");
break;
case QIT_BELL:
printf("BELL\n");
wprintf(L"BELL\n");
break;
case QIT_BACK:
printf("BKSP (%x)\n", Queue[n].dwData);
wprintf(L"BKSP (%x)\n", Queue[n].dwData);
if(Queue[n].dwData == BK_DEADKEY) break;
if(Queue[n].dwData == BK_SUPP2) break; // I1389 - supp chars on vista default to single backspace //TODO: eliminate BK_SUPP2
break;

View file

@ -26,29 +26,17 @@
*/
#include "pch.h"
static BYTE kbstate[256];
extern BOOL FShouldIgnoreNextKey[256];
//extern "C" void FAR PASCAL keybd_event(void);
void ResetCapsLock(void)
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
if(!_td->lpActiveKeyboard) return;
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: enter");
if(_td->lpActiveKeyboard->Keyboard->dwFlags & KF_CAPSALWAYSOFF)
if(g_keyboard.Keyboard->dwFlags & KF_CAPSALWAYSOFF)
{
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: caps lock should be always off");
if(GetKeyState(VK_CAPITAL) & 1)
{
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: caps lock is on, switching off caps lock");
keybd_event(VK_CAPITAL, 0x3A, 0, 0);
keybd_event(VK_CAPITAL, 0x3A, 0 | KEYEVENTF_KEYUP, 0);
GetApp()->QueueAction(QIT_CAPSLOCK, 0);
}
}
SendDebugMessageFormat(0, sdmGlobal, 0, "ResetCapsLock: exit");
@ -57,24 +45,18 @@ void ResetCapsLock(void)
void KeyCapsLockPress(BOOL FIsUp) // I3284 - void // I3529
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
if(!_td->lpActiveKeyboard) return; // pass through to window
if(_td->lpActiveKeyboard->Keyboard->dwFlags & KF_CAPSONONLY)
if(g_keyboard.Keyboard->dwFlags & KF_CAPSONONLY)
{
if(FIsUp && !(GetKeyState(VK_CAPITAL) & 1)) // I267 - 24/11/2006 invert GetKeyState test
{
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, 0, 0);
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, KEYEVENTF_KEYUP, 0);
GetApp()->QueueAction(QIT_CAPSLOCK, 1);
}
}
else if(_td->lpActiveKeyboard->Keyboard->dwFlags & KF_CAPSALWAYSOFF)
else if(g_keyboard.Keyboard->dwFlags & KF_CAPSALWAYSOFF)
{
if(!FIsUp && (GetKeyState(VK_CAPITAL) & 1))
{ // I267 - 24/11/2006 invert GetKeyState test
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, KEYEVENTF_KEYUP, 0);
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, 0, 0);
GetApp()->QueueAction(QIT_CAPSLOCK, 0);
}
}
}
@ -82,18 +64,13 @@ void KeyCapsLockPress(BOOL FIsUp) // I3284 - void // I3529
void KeyShiftPress(BOOL FIsUp) // I3284 - void // I3529
{
PKEYMAN64THREADDATA _td = ThreadGlobals();
if(!_td) return;
if(!_td->lpActiveKeyboard) return; // pass through to window
if((GetKeyState(VK_CAPITAL) & 1) == 0) return;
if(_td->lpActiveKeyboard->Keyboard->dwFlags & KF_SHIFTFREESCAPS)
if(g_keyboard.Keyboard->dwFlags & KF_SHIFTFREESCAPS)
{
if(!FIsUp)
{
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, 0, 0);
keybd_event(VK_CAPITAL, SCAN_FLAG_KEYMAN_KEY_EVENT, KEYEVENTF_KEYUP, 0);
GetApp()->QueueAction(QIT_CAPSLOCK, 0);
}
}
}

View file

@ -1,196 +0,0 @@
/*
Name: rc4
Copyright: Copyright (C) SIL International.
Documentation:
Description:
Create Date: 30 Nov 2009
Modified Date: 11 Dec 2009
Authors: mcdurdin
Related Files:
Dependencies:
Bugs:
Todo:
Notes:
History: 30 Nov 2009 - mcdurdin - I934 - Prep for x64 - Unreferenced parameters
11 Dec 2009 - mcdurdin - I934 - x64 - Initial version
*/
#include "pch.h"
BOOL CryptRC4::SelfTest()
{
const BYTE Key1[5] = {0x61,0x8A,0x63,0xD2,0xFB};
const BYTE InData1[5] = {0xDC,0xEE,0x4C,0xF9,0x2C};
const BYTE OutData1[5] = {0xF1,0x38,0x29,0xC9,0xDE};
CryptRC4 rc4;
BYTE Data[5];
rc4.Init((PBYTE)Key1, sizeof(Key1)*8, NULL);
rc4.Encrypt((PBYTE)InData1,Data,sizeof(Data));
if(memcmp(Data, OutData1, sizeof(Data)) != 0) return FALSE;
rc4.Reset();
rc4.Decrypt(Data,Data,sizeof(Data));
if(memcmp(Data, InData1, sizeof(Data)) != 0) return FALSE;
rc4.Burn();
return TRUE;
}
void CryptRC4::Init(PBYTE Key, DWORD Size, PVOID InitVector)
{
UNREFERENCED_PARAMETER(InitVector);
DWORD i, j, t;
BYTE xKey[256];
if(fInitialized) Burn();
//inherited Init(Key,Size,nil);
Size /= 8;
i = 0;
while(i < 255)
{
KeyData[i] = (BYTE) i; xKey[i] = Key[i % Size];
KeyData[i+1] = (BYTE) i+1; xKey[i+1] = Key[(i+1) % Size];
KeyData[i+2] = (BYTE) i+2; xKey[i+2] = Key[(i+2) % Size];
KeyData[i+3] = (BYTE) i+3; xKey[i+3] = Key[(i+3) % Size];
KeyData[i+4] = (BYTE) i+4; xKey[i+4] = Key[(i+4) % Size];
KeyData[i+5] = (BYTE) i+5; xKey[i+5] = Key[(i+5) % Size];
KeyData[i+6] = (BYTE) i+6; xKey[i+6] = Key[(i+6) % Size];
KeyData[i+7] = (BYTE) i+7; xKey[i+7] = Key[(i+7) % Size];
i += 8;
}
j = 0;
i = 0;
while(i < 255)
{
j = (j+KeyData[i]+xKey[i]) & 0xFF;
t = KeyData[i];
KeyData[i] = KeyData[j];
KeyData[j] = (BYTE) t;
j = (j+KeyData[i+1]+xKey[i+1]) & 0xFF;
t = KeyData[i+1];
KeyData[i+1] = KeyData[j];
KeyData[j] = (BYTE) t;
j = (j+KeyData[i+2]+xKey[i+2]) & 0xFF;
t = KeyData[i+2];
KeyData[i+2] = KeyData[j];
KeyData[j] = (BYTE) t;
j = (j+KeyData[i+3]+xKey[i+3]) & 0xFF;
t = KeyData[i+3];
KeyData[i+3] = KeyData[j];
KeyData[j] = (BYTE) t;
j = (j+KeyData[i+4]+xKey[i+4]) & 0xFF;
t = KeyData[i+4];
KeyData[i+4] = KeyData[j];
KeyData[j] = (BYTE) t;
j = (j+KeyData[i+5]+xKey[i+5]) & 0xFF;
t = KeyData[i+5];
KeyData[i+5] = KeyData[j];
KeyData[j] = (BYTE) t;
j = (j+KeyData[i+6]+xKey[i+6]) & 0xFF;
t = KeyData[i+6];
KeyData[i+6] = KeyData[j];
KeyData[j] = (BYTE) t;
j = (j+KeyData[i+7]+xKey[i+7]) & 0xFF;
t = KeyData[i+7];
KeyData[i+7] = KeyData[j];
KeyData[j] = (BYTE) t;
i += 8;
}
memcpy(KeyOrg, KeyData, sizeof(KeyOrg));
fInitialized = TRUE;
}
void CryptRC4::Reset()
{
memcpy(KeyData, KeyOrg, sizeof(KeyData));
}
void CryptRC4::Burn()
{
memset(KeyOrg,0xFF,sizeof(KeyOrg));
memset(KeyData,0xFF,sizeof(KeyData));
// inherited Burn;
}
void CryptRC4::Encrypt(PBYTE InData, PBYTE OutData, DWORD Size)
{
DWORD BufferSize=8192;
DWORD i, Read;
i = 0;
while(i < Size/BufferSize)
{
Read=8192;
EncryptBuffer(InData+i*BufferSize, OutData+i*BufferSize, Read);
i++;
}
if(Size % BufferSize != 0)
{
Read=Size % BufferSize;
EncryptBuffer(InData+i*BufferSize, OutData+i*BufferSize, Read);
}
}
void CryptRC4::EncryptBuffer(PBYTE InData, PBYTE OutData, DWORD Size)
{
DWORD i, j, t, k;
if(!fInitialized) return; //raise EDCP_cipher.Create('Cipher not initialized');
i = 0; j = 0;
for(k = 0; k < Size; k++)
{
i = (i+1) & 0xFF;
t = KeyData[i];
j = (j+t) & 0xFF;
KeyData[i] = KeyData[j];
KeyData[j] = (BYTE) t;
t = (t + KeyData[i]) & 0xFF;
OutData[k] = InData[k] ^ KeyData[t];
}
}
void CryptRC4::Decrypt(PBYTE InData, PBYTE OutData, DWORD Size)
{
DWORD BufferSize=8192;
DWORD i, Read;
i = 0;
while(i < Size/BufferSize)
{
Read=8192;
DecryptBuffer(InData+i*BufferSize, OutData+i*BufferSize, Read);
i++;
}
if(Size % BufferSize != 0)
{
Read=Size % BufferSize;
DecryptBuffer(InData+i*BufferSize, OutData+i*BufferSize, Read);
}
}
void CryptRC4::DecryptBuffer(PBYTE InData, PBYTE OutData, DWORD Size)
{
DWORD i, j, t, k;
if(!fInitialized) return; //raise EDCP_cipher.Create('Cipher not initialized');
i = 0; j = 0;
for(k = 0; k < Size; k++)
{
i = (i + 1) & 0xFF;
t = KeyData[i];
j = (j + t) & 0xFF;
KeyData[i] = KeyData[j];
KeyData[j] = (BYTE) t;
t = (t + KeyData[i]) & 0xFF;
OutData[k] = InData[k] ^ KeyData[t];
}
}

View file

@ -1,5 +1,8 @@
#include "pch.h"
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
AIWin2000Unicode *g_app = NULL;
INTKEYBOARDINFO g_keyboard = { 0 };
@ -11,6 +14,8 @@ char g_baseKeyboard[16] = "kbdus.dll";
wchar_t g_baseLayout[260] = L"", g_baseLayoutAlt[34] = L"";
BOOL g_simulateAltGr = FALSE;
char g_platform[128] = "windows desktop hardware native"; // TODO
WCHAR g_context[512] = L"";
int g_contextLength = 0;
struct KeyEvent {
UINT vkey;
@ -317,16 +322,16 @@ const char *VKeyNames[256] = {
void print_default_environment() {
printf(" env.simulate_altgr=%d\n", g_simulateAltGr);
printf(" env.base_keyboard=%s\n", g_baseKeyboard);
printf(" env.base_layout=%ls\n", g_baseLayout);
printf(" env.base_layout_alt=%ls\n", g_baseLayoutAlt);
printf(" env.platform=%s\n", g_platform);
wprintf(L" env.simulate_altgr=%d\n", g_simulateAltGr);
wprintf(L" env.base_keyboard=%hs\n", g_baseKeyboard);
wprintf(L" env.base_layout=%s\n", g_baseLayout);
wprintf(L" env.base_layout_alt=%s\n", g_baseLayoutAlt);
wprintf(L" env.platform=%hs\n", g_platform);
}
BOOL addOption(char *val) {
//TODO
printf("TODO: support %s\n", val);
wprintf(L"TODO: support %hs\n", val);
return TRUE;
}
@ -501,7 +506,48 @@ BOOL setKeys(char *val) {
return TRUE;
}
BOOL addContext(DWORD ch) {
if (ch > 0x10FFFF) return FALSE;
if (ch >= 0x10000) {
g_context[g_contextLength++] = (WCHAR) Uni_UTF32ToSurrogate1(ch);
g_context[g_contextLength++] = (WCHAR) Uni_UTF32ToSurrogate2(ch);
}
else {
g_context[g_contextLength++] = (WCHAR) ch;
}
g_context[g_contextLength] = 0;
return TRUE;
}
BOOL addContextDeadkey(DWORD dk) {
g_context[g_contextLength++] = UC_SENTINEL;
g_context[g_contextLength++] = CODE_DEADKEY;
g_context[g_contextLength++] = (WCHAR) (dk + 1);
g_context[g_contextLength] = 0;
return TRUE;
}
BOOL setContext(char *val) {
while (*val) {
if (*val == '\\') {
val++;
if (*val == '\\') {
if (!addContext(*val)) return FALSE;
}
else if (*val == 'u') {
val++;
char *p = NULL;
if (!addContext(strtol(val, &p, 16))) return FALSE;
val = p;
}
else if (*val == 'd') {
val++;
char *p = NULL;
if (!addContextDeadkey(strtol(val, &p, 10))) return FALSE;
val = p;
}
}
}
return TRUE;
}
@ -509,6 +555,8 @@ int main(int argc, char *argv[]) {
char *filename = NULL;
BOOL invalid = FALSE;
_setmode(_fileno(stdout), _O_U16TEXT);
for (int i = 1; i < argc-1; i += 2) {
char *arg = argv[i], *val = argv[i + 1];
if (!strcmp(arg, "-kmx")) {
@ -531,16 +579,16 @@ int main(int argc, char *argv[]) {
}
if (invalid || g_nKeyEvents == 0 || filename == NULL) {
printf("Usage: kmxtest -kmx <file.kmx> -context context -keys key-sequence -d a=b\n");
printf(" file.kmx must exist. No translation is done for mnemonic layout, etc.\n");
printf(" context should be a string of unicode characters and/or deadkeys:\n");
printf(" e.g. \"ABC\\u1234\\dxxxx\" (where xxxx is the integer deadkey value or deadkey name if keyboard is compiled with debug)\n");
printf(" key-sequence is one or more Keyman keystrokes:\n");
printf(" e.g. \"[SHIFT K_A] [K_B]\"\n");
printf(" -d allows for definition of environment and keyboard options\n");
printf(" keyboard option is opt.store_name=\"value\"\n");
printf(" environment is env.name=\"\"\n");
printf(" default environment is:\n");
wprintf(L"Usage: kmxtest -kmx <file.kmx> -context context -keys key-sequence -d a=b\n");
wprintf(L" file.kmx must exist. No translation is done for mnemonic layout, etc.\n");
wprintf(L" context should be a string of unicode characters and/or deadkeys:\n");
wprintf(L" e.g. \"ABC\\u1234\\dxxxx\\d{name}\" (where xxxx is the integer deadkey value or {name} is the deadkey name if keyboard is compiled with debug)\n");
wprintf(L" key-sequence is one or more Keyman keystrokes:\n");
wprintf(L" e.g. \"[SHIFT K_A] [K_B]\"\n");
wprintf(L" -d allows for definition of environment and keyboard options\n");
wprintf(L" keyboard option is opt.store_name=\"value\"\n");
wprintf(L" environment is env.name=\"\"\n");
wprintf(L" default environment is:\n");
print_default_environment();
return 2;
@ -554,14 +602,23 @@ int main(int argc, char *argv[]) {
// run;
if (!LoadlpKeyboard(filename)) {
printf("Failed to load %s\n", filename);
wprintf(L"Failed to load %hs\n", filename);
return 1;
}
PKEYMAN64THREADDATA _td = ThreadGlobals();
g_app->SetContext(g_context);
wprintf(L"============ Starting test ============\n");
for (int i = 0; i < g_nKeyEvents; i++) {
printf("== [%d] == %x\n", i, g_keyEvents[i].vkey);
if (g_keyEvents[i].vkey < 256) {
wprintf(L"[%d] == %hs\n", i, VKeyNames[g_keyEvents[i].vkey]);
}
else {
wprintf(L"[%d] == %x\n", i, g_keyEvents[i].vkey);
}
_td->state.vkey = g_keyEvents[i].vkey;
_td->state.charCode = VKeyToChar(g_keyEvents[i].vkey);
g_shiftState = g_keyEvents[i].modifiers;
@ -569,6 +626,8 @@ int main(int argc, char *argv[]) {
ProcessHook();
}
wprintf(L"============ Stopping test ============\n");
delete g_app;
return 0;
}

View file

@ -0,0 +1,4 @@
@echo off
debug\kmxtest -kmx khmer_angkor.kmx -keys "xEjmr"
debug\kmxtest -kmx khmer_angkor.kmx -keys "jmr" -context "\u1781\u17c2"