mirror of
https://github.com/keymanapp/keyman.git
synced 2026-10-24 14:57:44 +00:00
* Keyman for Windows 10.0 Open Source * Squashed 'windows/src/ext/jedi/jedi/' content from commit f444ad2 git-subtree-dir: windows/src/ext/jedi/jedi git-subtree-split: f444ad2da4693851e523f1ea6bd541f701904c24 * Squashed 'windows/src/ext/jedi/jcl/' content from commit d63d3c9fd git-subtree-dir: windows/src/ext/jedi/jcl git-subtree-split: d63d3c9fd9ff84efdd8159084ec6a60313644243 * Squashed 'windows/src/ext/jedi/jvcl/' content from commit bee19f3b4 git-subtree-dir: windows/src/ext/jedi/jvcl git-subtree-split: bee19f3b46909fde2fa92c06cd2706f41d99f6c3 * Add required .res files * Add required .res files * Add docbook files (forced) * Add required libxslt * Add required jedi files * Add installation files * Tweak .gitignore for open * CI * Remove KMW from Developer source (#122) * Remove KMW from Developer source (copies during build) * Remove KMW from Developer source (copies during build) * Remove KMW from Developer source (copies during build) * Fixup release build and copy license, readme from kmw during build * Remove obsolete build help documentation * Keyman Engine 10 on Windows regression for shift states (#129) * Improve #128 -- cleaner debug messages * Fixes #127, shift state now resets correctly; and more work for #128 * Fixes #130 (#131)
367 lines
9.9 KiB
C++
367 lines
9.9 KiB
C++
/*
|
|
Name: syskbdnt64
|
|
Copyright: Copyright (C) SIL International.
|
|
Documentation:
|
|
Description:
|
|
Create Date: 10 Sep 2008
|
|
|
|
Modified Date: 4 May 2010
|
|
Authors: mcdurdin
|
|
Related Files:
|
|
Dependencies:
|
|
|
|
Bugs:
|
|
Todo:
|
|
Notes:
|
|
History: 10 Sep 2008 - mcdurdin - I1635 - Initial version
|
|
11 Mar 2009 - mcdurdin - I1894 - Fix threading bugs introduced in I1888
|
|
30 Nov 2009 - mcdurdin - I934 - Prep for x64 - change UINT to WORD for vkeys
|
|
12 Mar 2010 - mcdurdin - I934 - x64 - Complete
|
|
12 Mar 2010 - mcdurdin - I2229 - Remove hints and warnings
|
|
04 May 2010 - mcdurdin - I2351 - Robustness - verify _td return value
|
|
*/
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Use Windows NT/2000 keyboard DLLs for mapping virtual keys to characters
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "../../engine/keyman32/kbd.h" /* DDK kbdlayout */
|
|
|
|
typedef struct {
|
|
PVK_TO_BIT pVkToBit; // Virtual Keys -> Mod bits
|
|
DWORD filler;
|
|
WORD wMaxModBits; // max Modification bit combination value
|
|
BYTE ModNumber[1]; // Mod bits -> Modification Number
|
|
} MODIFIERS_x64, *PMODIFIERS_x64;
|
|
|
|
typedef struct _VK_TO_WCHAR_TABLE_x64 {
|
|
PVK_TO_WCHARS1 pVkToWchars;
|
|
DWORD filler;
|
|
BYTE nModifications;
|
|
BYTE cbSize;
|
|
BYTE filler2[2];
|
|
DWORD filler3;
|
|
} VK_TO_WCHAR_TABLE_x64, *PVK_TO_WCHAR_TABLE_x64;
|
|
|
|
/***************************************************************************\
|
|
* VSC_VK - Associate a Virtual Scancode with a Virtual Key
|
|
* Vsc - Virtual Scancode
|
|
* Vk - Virtual Key | flags
|
|
* Used by VKFromVSC() for scancodes prefixed 0xE0 or 0xE1
|
|
\***************************************************************************/
|
|
typedef struct _VSC_VK_x64 {
|
|
BYTE Vsc;
|
|
USHORT Vk;
|
|
} VSC_VK_x64, *PVSC_VK_x64;
|
|
|
|
/***************************************************************************\
|
|
* VK_VSC - Associate a Virtual Key with a Virtual Scancode
|
|
* Vk - Virtual Key
|
|
* Vsc - Virtual Scancode
|
|
* Used by MapVirtualKey for Virtual Keys not appearing in ausVK[]
|
|
\***************************************************************************/
|
|
typedef struct _VK_VSC_x64 {
|
|
BYTE Vk;
|
|
BYTE Vsc;
|
|
} VK_VSC_x64, *PVK_VSC_x64;
|
|
|
|
|
|
typedef struct tagKdbLayer_x64
|
|
{
|
|
/*
|
|
* Modifier keys
|
|
*/
|
|
PMODIFIERS_x64 pCharModifiers;
|
|
DWORD filler1;
|
|
|
|
/*
|
|
* Characters
|
|
*/
|
|
VK_TO_WCHAR_TABLE_x64 *pVkToWcharTable; // ptr to tbl of ptrs to tbl
|
|
DWORD filler2;
|
|
|
|
/*
|
|
* Diacritics
|
|
*/
|
|
PDEADKEY pDeadKey;
|
|
DWORD filler3;
|
|
|
|
/*
|
|
* Names of Keys
|
|
*/
|
|
VSC_LPWSTR *pKeyNames;
|
|
DWORD filler4;
|
|
VSC_LPWSTR *pKeyNamesExt;
|
|
DWORD filler5;
|
|
LPWSTR *pKeyNamesDead;
|
|
DWORD filler6;
|
|
|
|
/*
|
|
* Scan codes to Virtual Keys
|
|
*/
|
|
USHORT *pusVSCtoVK;
|
|
DWORD filler7;
|
|
BYTE bMaxVSCtoVK;
|
|
DWORD filler8;
|
|
PVSC_VK_x64 pVSCtoVK_E0; // Scancode has E0 prefix
|
|
DWORD filler9;
|
|
PVSC_VK_x64 pVSCtoVK_E1; // Scancode has E1 prefix
|
|
DWORD fillerA;
|
|
|
|
/*
|
|
* Locale-specific special processing
|
|
*/
|
|
DWORD fLocaleFlags;
|
|
DWORD fillerB;
|
|
} KBDTABLES_x64, *PKBDTABLES_x64;
|
|
|
|
|
|
typedef PKBDTABLES_x64 (WINAPI *PKBDLAYERDESCRIPTORFUNC)(VOID);
|
|
|
|
static HMODULE hKbdLibrary_x64 = NULL;
|
|
static PKBDTABLES_x64 KbdTables_x64 = NULL;
|
|
|
|
BOOL LoadNewLibrary_NT_x64(PWSTR filename) {
|
|
if(hKbdLibrary_x64) FreeLibrary(hKbdLibrary_x64);
|
|
|
|
hKbdLibrary_x64 = LoadLibrary(filename);
|
|
if(!hKbdLibrary_x64) {
|
|
LogError(L"LoadNewLibrary_x64: Exit -- could not load library");
|
|
return FALSE;
|
|
}
|
|
|
|
PKBDLAYERDESCRIPTORFUNC KbdLayerDescriptorFunc = (PKBDLAYERDESCRIPTORFUNC) GetProcAddress(hKbdLibrary_x64, "KbdLayerDescriptor");
|
|
if(KbdLayerDescriptorFunc)
|
|
{
|
|
KbdTables_x64 = (*KbdLayerDescriptorFunc)();
|
|
if(KbdTables_x64) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
FreeLibrary(hKbdLibrary_x64);
|
|
|
|
hKbdLibrary_x64 = NULL;
|
|
KbdTables_x64 = NULL;
|
|
|
|
LogError(L"LoadNewLibrary_x64: Exit -- failed to find function");
|
|
return FALSE;
|
|
}
|
|
|
|
WCHAR CharFromVK_NT_x64(WORD VKey, UINT ShiftFlags, WCHAR *PDeadKey) {
|
|
PVK_TO_WCHARS1 pv;
|
|
PVK_TO_WCHAR_TABLE_x64 pvt;
|
|
int i;
|
|
|
|
/* MCD 02/12/2002: Fix bug with number pad keys when numlock is on */
|
|
|
|
if(IsNumberPadKey(VKey)) {
|
|
return 0;
|
|
}
|
|
|
|
/* Get the appropriate table column for shift state */
|
|
|
|
int shift = -1, shiftidx = 0, capslockbit = 0;
|
|
|
|
for(PVK_TO_BIT pvtb = KbdTables_x64->pCharModifiers->pVkToBit; pvtb->Vk; pvtb++) {
|
|
switch(pvtb->Vk) {
|
|
case VK_MENU:
|
|
if(ShiftFlags & (LALTFLAG|RALTFLAG)) shiftidx |= pvtb->ModBits; break;
|
|
case VK_SHIFT:
|
|
if(ShiftFlags & CAPITALFLAG) capslockbit = pvtb->ModBits;
|
|
if(ShiftFlags & (K_SHIFTFLAG)) shiftidx |= pvtb->ModBits; break;
|
|
case VK_CONTROL:
|
|
if(ShiftFlags & (LCTRLFLAG|RCTRLFLAG)) shiftidx |= pvtb->ModBits; break;
|
|
}
|
|
}
|
|
|
|
/* If the shift modifier is unused, don't produce a character */
|
|
|
|
if(shiftidx > KbdTables_x64->pCharModifiers->wMaxModBits ||
|
|
KbdTables_x64->pCharModifiers->ModNumber[shiftidx] == 0xF) {
|
|
return 0;
|
|
}
|
|
|
|
shift = KbdTables_x64->pCharModifiers->ModNumber[shiftidx];
|
|
|
|
/* Get the appropriate virtual key */
|
|
|
|
for(i = 0, pvt = KbdTables_x64->pVkToWcharTable; pvt->pVkToWchars; i++, pvt++) {
|
|
for(pv = pvt->pVkToWchars; pv->VirtualKey;) {
|
|
if(pv->VirtualKey == VKey) {
|
|
if(shift >= pvt->nModifications) {
|
|
return 0;
|
|
}
|
|
|
|
/* Check for Caps Lock */
|
|
if(ShiftFlags & CAPITALFLAG) {
|
|
if(pv->Attributes & CAPLOK) {
|
|
/* Invert the state of the SHIFT key */
|
|
shift = KbdTables_x64->pCharModifiers->ModNumber[shiftidx ^ capslockbit];
|
|
} else if(pv->Attributes & SGCAPS) {
|
|
pv++; /* Next keystroke has the appropriate capitalised character */
|
|
}
|
|
}
|
|
|
|
/* Found the keystroke combination, return the appropriate character (if existing) */
|
|
switch(pv->wch[shift]) {
|
|
case WCH_DEAD:
|
|
pv = (PVK_TO_WCHARS1) ((BYTE *)pv + pvt->cbSize);
|
|
*PDeadKey = pv->wch[shift];
|
|
return 0xFFFF; /* Don't queue as WM_KEYDOWN -- don't output either */
|
|
case WCH_NONE:
|
|
return 0x0000; /* Not a valid key, queue as WM_KEYDOWN */
|
|
}
|
|
|
|
return (pv->wch[shift] > 31 && pv->wch[shift] != 127) ? pv->wch[shift] : 0; /* Don't generate 'special chars'; I911 - fix ctrl+bksp */
|
|
}
|
|
pv = (PVK_TO_WCHARS1) ((BYTE *)pv + pvt->cbSize);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
WORD ModificationToShift_NT_x64(int mod) {
|
|
WORD ShiftFlags = 0;
|
|
|
|
int shiftidx = -1;
|
|
for(int i = 0; i <= KbdTables_x64->pCharModifiers->wMaxModBits; i++) {
|
|
if(KbdTables_x64->pCharModifiers->ModNumber[i] == mod) {
|
|
shiftidx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(shiftidx == -1) return 0xFFFF;
|
|
|
|
for(PVK_TO_BIT pvtb = KbdTables_x64->pCharModifiers->pVkToBit; pvtb->Vk; pvtb++) {
|
|
if(shiftidx & pvtb->ModBits) {
|
|
switch(pvtb->Vk) {
|
|
case VK_MENU: ShiftFlags |= RALTFLAG; break;
|
|
case VK_SHIFT: ShiftFlags |= K_SHIFTFLAG; break;
|
|
case VK_CONTROL: ShiftFlags |= LCTRLFLAG; break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ShiftFlags;
|
|
}
|
|
|
|
WORD CharToUSVK_NT_x64(WORD ch, WORD *shift)
|
|
{
|
|
PVK_TO_WCHARS1 pv;
|
|
PVK_TO_WCHAR_TABLE_x64 pvt;
|
|
int i, j;
|
|
|
|
/* Find the appropriate keyboard tables */
|
|
|
|
if(!KbdTables_x64) return 0; /* Could not load keyboard DLL */
|
|
|
|
/* Map the character back to the virtual key */
|
|
|
|
for(i = 0, pvt = KbdTables_x64->pVkToWcharTable; pvt->pVkToWchars; i++, pvt++)
|
|
for(pv = pvt->pVkToWchars; pv->VirtualKey;)
|
|
{
|
|
for(j = 0; j < pvt->nModifications; j++)
|
|
if(pv->wch[j] == ch)
|
|
{
|
|
/* Return the new virtual key */
|
|
*shift = ModificationToShift_NT_x64(j);
|
|
if(*shift == 0xFFFF) return 0;
|
|
return pv->VirtualKey;
|
|
}
|
|
pv = (PVK_TO_WCHARS1) ((BYTE *)pv + pvt->cbSize);
|
|
}
|
|
|
|
/* Remapping not found */
|
|
return 0;
|
|
}
|
|
|
|
|
|
int GetDeadkeys_NT_x64(WORD DeadKey, WORD *OutputPairs) {
|
|
WORD *p = OutputPairs, shift;
|
|
for(int i = 0; KbdTables_x64->pDeadKey[i].dwBoth; i++) {
|
|
if(HIWORD(KbdTables_x64->pDeadKey[i].dwBoth) == DeadKey) {
|
|
WORD vk = CharToUSVK_NT_x64(LOWORD(KbdTables_x64->pDeadKey[i].dwBoth), &shift);
|
|
if(vk != 0) {
|
|
*p++ = vk;
|
|
*p++ = shift;
|
|
*p++ = KbdTables_x64->pDeadKey[i].wchComposed;
|
|
} else {
|
|
LogError(L"Warning: complex deadkey not supported.");
|
|
}
|
|
}
|
|
}
|
|
*p = 0;
|
|
return (int)(p-OutputPairs);
|
|
}
|
|
|
|
WORD VKUSToVKUnderlyingLayout_NT_x64(WORD VKey) {
|
|
|
|
/* Num lock test -- MCD: 02/12/2002 Fix num lock not working bug */
|
|
|
|
if((VKey >= VK_NUMPAD0 && VKey <= VK_NUMPAD9) || VKey == VK_DECIMAL) return VKey;
|
|
|
|
/* Find the appropriate keyboard tables */
|
|
|
|
if(!KbdTables_x64) /* Could not load keyboard DLL */
|
|
return VKey;
|
|
|
|
if(VKey > 255) return VKey;
|
|
|
|
UINT scan = USVirtualKeyToScanCode[VKey];
|
|
if(scan == 0 || scan >= KbdTables_x64->bMaxVSCtoVK) return VKey;
|
|
return KbdTables_x64->pusVSCtoVK[scan];
|
|
}
|
|
|
|
WORD VKUnderlyingLayoutToVKUS_NT_x64(WORD VKey) {
|
|
|
|
/* Num lock test -- MCD: 02/12/2002 Fix num lock not working bug */
|
|
|
|
if((VKey >= VK_NUMPAD0 && VKey <= VK_NUMPAD9) || VKey == VK_DECIMAL) return VKey;
|
|
|
|
/* Find the appropriate keyboard tables */
|
|
|
|
if(!KbdTables_x64) /* Could not load keyboard DLL */
|
|
return VKey;
|
|
|
|
UINT scan;
|
|
for(scan = 1; scan <= KbdTables_x64->bMaxVSCtoVK; scan++) {
|
|
if(KbdTables_x64->pusVSCtoVK[scan] == VKey) {
|
|
break;
|
|
}
|
|
}
|
|
if(scan > KbdTables_x64->bMaxVSCtoVK || scan > 127) {
|
|
// no translation.
|
|
return VKey;
|
|
}
|
|
|
|
return ScanCodeToUSVirtualKey[scan];
|
|
}
|
|
|
|
|
|
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
|
|
|
|
LPFN_ISWOW64PROCESS
|
|
fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle(L"kernel32"),"IsWow64Process");
|
|
BOOL fStored = FALSE;
|
|
BOOL bIsWow64 = FALSE;
|
|
|
|
BOOL IsWow64() {
|
|
if(fStored) return bIsWow64;
|
|
bIsWow64 = FALSE;
|
|
|
|
if(NULL != fnIsWow64Process) {
|
|
if(!fnIsWow64Process(GetCurrentProcess(),&bIsWow64)){
|
|
// handle error
|
|
return FALSE;
|
|
}
|
|
}
|
|
fStored = TRUE;
|
|
return bIsWow64;
|
|
}
|