00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
#include "precomp.h"
00011
#pragma hdrstop
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #define ISCAPSLOCKON(pf) (TestKeyToggleBit(pf, VK_CAPITAL) != 0)
00022 #define ISNUMLOCKON(pf) (TestKeyToggleBit(pf, VK_NUMLOCK) != 0)
00023 #define ISSHIFTDOWN(w) (w & 0x01)
00024 #define ISKANALOCKON(pf) (TestKeyToggleBit(pf, VK_KANA) != 0)
00025
00026 WCHAR
xxxClientCharToWchar(
00027 IN WORD CodePage,
00028 IN WORD wch);
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 int xxxToUnicodeEx(
00041 UINT wVirtKey,
00042 UINT wScanCode,
00043 CONST BYTE *pbKeyState,
00044 LPWSTR pwszBuff,
00045
int cchBuff,
00046 UINT wKeyFlags,
00047 HKL hkl)
00048 {
00049
int i;
00050
BYTE afKeyState[
CBKEYSTATE];
00051
DWORD dwDummy;
00052
00053
00054
00055
00056
00057
00058
00059
00060
for (i = 0; i < 256; i++, pbKeyState++) {
00061
if (*pbKeyState & 0x80) {
00062
SetKeyDownBit(afKeyState, i);
00063 }
else {
00064
ClearKeyDownBit(afKeyState, i);
00065 }
00066
00067
if (*pbKeyState & 0x01) {
00068
SetKeyToggleBit(afKeyState, i);
00069 }
else {
00070
ClearKeyToggleBit(afKeyState, i);
00071 }
00072 }
00073
00074 i =
xxxInternalToUnicode(wVirtKey, wScanCode, afKeyState, pwszBuff, cchBuff,
00075 wKeyFlags, &dwDummy, hkl);
00076
00077
00078
return i;
00079 }
00080
00081 int ComposeDeadKeys(
00082
PKL pkl,
00083 PDEADKEY pDeadKey,
00084 WCHAR wchTyped,
00085 WORD *pUniChar,
00086 INT cChar,
00087 BOOL bBreak)
00088 {
00089
00090
00091
00092
DWORD dwBoth;
00093
00094 TAGMSG4(DBGTAG_ToUnicode | RIP_THERESMORE,
00095
"ComposeDeadKeys dead '%C'(%x)+base '%C'(%x)",
00096 pkl->
wchDiacritic, pkl->
wchDiacritic,
00097 wchTyped, wchTyped);
00098 TAGMSG2(DBGTAG_ToUnicode | RIP_NONAME | RIP_THERESMORE,
00099
"cChar = %d, bBreak = %d", cChar, bBreak);
00100 UserAssert(pDeadKey);
00101
00102
if (cChar < 1) {
00103 TAGMSG0(DBGTAG_ToUnicode | RIP_NONAME,
00104
"return 0 because cChar < 1");
00105
return 0;
00106 }
00107
00108
00109
00110
00111 dwBoth = MAKELONG(wchTyped, pkl->
wchDiacritic);
00112
00113
if (pDeadKey !=
NULL) {
00114
00115
00116
00117
00118
00119
if (!bBreak) {
00120 pkl->
wchDiacritic = 0;
00121 }
00122
while (pDeadKey->dwBoth != 0) {
00123
if (pDeadKey->dwBoth == dwBoth) {
00124
00125
00126
00127
if (pDeadKey->uFlags & DKF_DEAD) {
00128
00129
00130
00131
if (!bBreak) {
00132 pkl->
wchDiacritic = (WORD)pDeadKey->wchComposed;
00133 }
00134 TAGMSG2(DBGTAG_ToUnicode | RIP_NONAME,
00135
"return -1 with dead char '%C'(%x)",
00136 pkl->
wchDiacritic, pkl->
wchDiacritic);
00137
return -1;
00138 }
00139 *pUniChar = (WORD)pDeadKey->wchComposed;
00140 TAGMSG2(DBGTAG_ToUnicode | RIP_NONAME,
00141
"return 1 with char '%C'(%x)",
00142 *pUniChar, *pUniChar);
00143
return 1;
00144 }
00145 pDeadKey++;
00146 }
00147 }
00148 *pUniChar++ = HIWORD(dwBoth);
00149
if (cChar > 1) {
00150 *pUniChar = LOWORD(dwBoth);
00151 TAGMSG4(DBGTAG_ToUnicode | RIP_NONAME,
00152
"return 2 with uncomposed chars '%C'(%x), '%C'(%x)",
00153 *(pUniChar-1), *(pUniChar-1), *pUniChar, *pUniChar);
00154
return 2;
00155 }
00156 TAGMSG2(DBGTAG_ToUnicode | RIP_NONAME | RIP_THERESMORE,
00157
"return 1 - only one char '%C'(%x) because cChar is 1, '%C'(%x)",
00158 *(pUniChar-1), *(pUniChar-1));
00159 TAGMSG2(DBGTAG_ToUnicode | RIP_NONAME,
00160
" the second char would have been '%C'(%x)",
00161 LOWORD(dwBoth), LOWORD(dwBoth));
00162
return 1;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 int TranslateInjectedVKey(
00186 IN UINT uScanCode,
00187 OUT PWCHAR awchChars,
00188 IN UINT uiTMFlags)
00189 {
00190 UserAssert(
LOBYTE(uScanCode) == 0);
00191
if (!(uScanCode & KBDBREAK) || (uiTMFlags & TM_POSTCHARBREAKS)) {
00192 awchChars[0] =
PtiCurrent()->wchInjected;
00193
return 1;
00194 }
00195
return 0;
00196 }
00197
00198
00199
00200
enum {
00201
NUMPADCONV_OEMCP = 0,
00202
NUMPADCONV_HKLCP,
00203
NUMPADCONV_HEX_HKLCP,
00204
NUMPADCONV_HEX_UNICODE,
00205 };
00206
00207 #define NUMPADSPC_INVALID (-1)
00208
00209 int NumPadScanCodeToHex(UINT uScanCode, UINT uVirKey)
00210 {
00211
if (uScanCode >= SCANCODE_NUMPAD_FIRST && uScanCode <= SCANCODE_NUMPAD_LAST) {
00212
int digit =
aVkNumpad[uScanCode - SCANCODE_NUMPAD_FIRST];
00213
00214
if (digit != 0xff) {
00215
return digit - VK_NUMPAD0;
00216 }
00217
return NUMPADSPC_INVALID;
00218 }
00219
00220
if (
gfInNumpadHexInput &
NUMPAD_HEXMODE_HL) {
00221
00222
00223
00224
if (uVirKey >=
L'A' && uVirKey <=
L'F') {
00225
return uVirKey -
L'A' + 0xa;
00226 }
00227
if (uVirKey >=
L'0' && uVirKey <=
L'9') {
00228
return uVirKey -
L'0';
00229 }
00230 }
00231
00232
return NUMPADSPC_INVALID;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 BOOL IsDbcsExemptionForHighAnsi(
00245 WORD wCodePage,
00246 WORD wNumpadChar)
00247 {
00248 UserAssert(
HIBYTE(wNumpadChar) == 0);
00249
00250
if (wCodePage ==
CP_JAPANESE &&
IS_JPN_1BYTE_KATAKANA(wNumpadChar)) {
00251
00252
00253
00254
00255
return FALSE;
00256 }
00257
else if (wNumpadChar >= 0x80 && wNumpadChar <= 0xff) {
00258
00259
00260
00261
00262
return TRUE;
00263 }
00264
00265
00266
00267
00268
00269
00270
return FALSE;
00271 }
00272
00273
#undef MODIFIER_FOR_ALT_NUMPAD
00274
00275 #define MODIFIER_FOR_ALT_NUMPAD(wModBit) \
00276
((((wModBits) & ~KBDKANA) == KBDALT) || (((wModBits) & ~KBDKANA) == (KBDALT | KBDSHIFT)))
00277
00278
00279 int xxxInternalToUnicode(
00280 IN UINT uVirtKey,
00281 IN UINT uScanCode,
00282 CONST IN PBYTE pfvk,
00283 OUT PWCHAR awchChars,
00284 IN INT cChar,
00285 IN UINT uiTMFlags,
00286 OUT PDWORD pdwKeyFlags,
00287 IN HKL hkl)
00288 {
00289 WORD wModBits;
00290 WORD nShift;
00291 WCHAR *pUniChar;
00292 PVK_TO_WCHARS1 pVK;
00293 PVK_TO_WCHAR_TABLE pVKT;
00294
static WORD NumpadChar;
00295
static WORD VKLastDown;
00296
static BYTE ConvMode;
00297
PTHREADINFO ptiCurrent =
PtiCurrentShared();
00298
PKL pkl;
00299 PKBDTABLES pKbdTbl;
00300 PLIGATURE1 pLigature;
00301
00302 *pdwKeyFlags = (uScanCode & KBDBREAK);
00303
00304
if ((hkl ==
NULL) && ptiCurrent->
spklActive) {
00305 pkl = ptiCurrent->
spklActive;
00306 pKbdTbl = pkl->
spkf->
pKbdTbl;
00307 }
else {
00308 pkl =
HKLtoPKL(ptiCurrent, hkl);
00309
if (!pkl) {
00310
return 0;
00311 }
00312 pKbdTbl = pkl->
spkf->
pKbdTbl;
00313 }
00314 UserAssert(pkl !=
NULL);
00315 UserAssert(pKbdTbl !=
NULL);
00316
00317 pUniChar = awchChars;
00318
00319 uScanCode &= (0xFF | KBDEXT);
00320
00321
if (*pdwKeyFlags & KBDBREAK) {
00322
00323
00324
00325
00326
if (uVirtKey == VK_MENU) {
00327
if (NumpadChar) {
00328
if (ConvMode ==
NUMPADCONV_HEX_UNICODE) {
00329 *pUniChar = NumpadChar;
00330 }
else if (ConvMode ==
NUMPADCONV_OEMCP &&
00331 (ptiCurrent->
TIF_flags &
TIF_CSRSSTHREAD)) {
00332
00333
00334
00335
00336
00337 *pdwKeyFlags |= ALTNUMPAD_BIT;
00338 *pUniChar = NumpadChar;
00339 }
else {
00340
00341
00342
00343 WORD wCodePage;
00344
00345
if (ConvMode ==
NUMPADCONV_OEMCP) {
00346
00347
extern __declspec(dllimport)
USHORT NlsOemCodePage;
00348
00349 wCodePage = (WORD)
NlsOemCodePage;
00350 }
else {
00351 wCodePage = pkl->
CodePage;
00352 }
00353
if (
IS_DBCS_CODEPAGE(wCodePage)) {
00354
if (NumpadChar & (WORD)~0xff) {
00355
00356
00357
00358
00359
00360 NumpadChar = MAKEWORD(
HIBYTE(NumpadChar),
LOBYTE(NumpadChar));
00361 }
else if (
IsDbcsExemptionForHighAnsi(wCodePage, NumpadChar)) {
00362
00363
00364
00365
00366
00367 wCodePage = 1252;
00368 }
00369 }
else {
00370
00371
00372
00373
00374 NumpadChar &= 0xff;
00375 }
00376
00377 *pUniChar =
xxxClientCharToWchar(wCodePage, NumpadChar);
00378 }
00379
00380
00381
00382
00383 VKLastDown = 0;
00384 ConvMode =
NUMPADCONV_OEMCP;
00385 NumpadChar = 0;
00386
gfInNumpadHexInput &= ~
NUMPAD_HEXMODE_HL;
00387
00388
return 1;
00389 }
else if (ConvMode !=
NUMPADCONV_OEMCP) {
00390 ConvMode =
NUMPADCONV_OEMCP;
00391 }
00392 }
else if (uVirtKey == VKLastDown) {
00393
00394
00395
00396
00397 VKLastDown = 0;
00398 }
00399 }
00400
00401
if (!(*pdwKeyFlags & KBDBREAK) || (uiTMFlags & TM_POSTCHARBREAKS)) {
00402
00403
00404
00405
00406
00407
00408 wModBits =
GetModifierBits(pKbdTbl->pCharModifiers, pfvk);
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
if (!(*pdwKeyFlags & KBDBREAK) &&
MODIFIER_FOR_ALT_NUMPAD(wModBits)) {
00430
00431
00432
00433
if ((uiTMFlags & TM_INMENUMODE) == 0) {
00434
if (
gfEnableHexNumpad && uScanCode ==
SCANCODE_NUMPAD_DOT) {
00435
if ((
gfInNumpadHexInput &
NUMPAD_HEXMODE_HL) == 0) {
00436
00437
00438
00439
00440 ConvMode =
NUMPADCONV_HEX_HKLCP;
00441
00442
00443
00444
00445
gfInNumpadHexInput |=
NUMPAD_HEXMODE_HL;
00446 TAGMSG0(DBGTAG_ToUnicode,
"NUMPADCONV_HEX_HKLCP");
00447 }
else {
00448
goto ExitNumpadMode;
00449 }
00450 }
else if (
gfEnableHexNumpad && uScanCode ==
SCANCODE_NUMPAD_PLUS) {
00451
if ((
gfInNumpadHexInput &
NUMPAD_HEXMODE_HL) == 0) {
00452
00453
00454
00455
00456 ConvMode =
NUMPADCONV_HEX_UNICODE;
00457
00458
00459
00460
00461
gfInNumpadHexInput |=
NUMPAD_HEXMODE_HL;
00462 TAGMSG0(DBGTAG_ToUnicode,
"NUMPADCONV_HEX_UNICODE");
00463 }
else {
00464
goto ExitNumpadMode;
00465 }
00466 }
else {
00467
int digit =
NumPadScanCodeToHex(uScanCode, uVirtKey);
00468
00469
if (digit < 0) {
00470
goto ExitNumpadMode;
00471 }
00472
00473
00474
00475
00476
if (VKLastDown == uVirtKey) {
00477
return 0;
00478 }
00479
00480
switch (ConvMode) {
00481
case NUMPADCONV_HEX_HKLCP:
00482
case NUMPADCONV_HEX_UNICODE:
00483
00484
00485
00486 TAGMSG1(DBGTAG_ToUnicode,
"->NUMPADCONV_HEX_*: old NumpadChar=%02x\n", NumpadChar);
00487 NumpadChar = NumpadChar * 0x10 + digit;
00488 TAGMSG1(DBGTAG_ToUnicode,
"<-NUMPADCONV_HEX_*: new NumpadChar=%02x\n", NumpadChar);
00489
break;
00490
default:
00491
00492
00493
00494 NumpadChar = NumpadChar * 10 + digit;
00495
00496
00497
00498
00499
if (NumpadChar == 0 && digit == 0) {
00500 ConvMode =
NUMPADCONV_HKLCP;
00501 }
00502
break;
00503 }
00504 }
00505 VKLastDown = (WORD)uVirtKey;
00506 }
else {
00507 ExitNumpadMode:
00508
00509
00510
00511 VKLastDown = 0;
00512 ConvMode =
NUMPADCONV_OEMCP;
00513 NumpadChar = 0;
00514 wModBits &= ~KBDALT;
00515
gfInNumpadHexInput &= ~
NUMPAD_HEXMODE_HL;
00516 }
00517 }
00518
00519
00520
00521
00522
if ((uVirtKey == VK_BACK) && (pKbdTbl->fLocaleFlags & KLLF_LRM_RLM)) {
00523
if (
TestKeyDownBit(pfvk, VK_LSHIFT)) {
00524 *pUniChar = 0x200E;
00525
return 1;
00526 }
else if (
TestKeyDownBit(pfvk, VK_RSHIFT)) {
00527 *pUniChar = 0x200F;
00528
return 1;
00529 }
00530 }
else if (((WORD)uVirtKey == VK_PACKET) && (
LOBYTE(uScanCode) == 0)) {
00531
return TranslateInjectedVKey(uScanCode, awchChars, uiTMFlags);
00532 }
00533
00534
00535
00536
00537
00538
for (pVKT = pKbdTbl->pVkToWcharTable; pVKT->pVkToWchars !=
NULL; pVKT++) {
00539 pVK = pVKT->pVkToWchars;
00540
while (pVK->VirtualKey != 0) {
00541
if (pVK->VirtualKey == (
BYTE)uVirtKey) {
00542
goto VK_Found;
00543 }
00544 pVK = (PVK_TO_WCHARS1)((
PBYTE)pVK + pVKT->cbSize);
00545 }
00546 }
00547
00548
00549
00550
00551
goto ReturnBadCharacter;
00552
00553 VK_Found:
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
if ((pVK->Attributes & KANALOK) && (
ISKANALOCKON(pfvk))) {
00565 wModBits |= KBDKANA;
00566 }
else
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
if ((pVK->Attributes & CAPLOK) && ((wModBits & ~KBDSHIFT) == 0) &&
00577
ISCAPSLOCKON(pfvk)) {
00578 wModBits ^= KBDSHIFT;
00579 }
else if ((pVK->Attributes & CAPLOKALTGR) &&
00580 ((wModBits & (KBDALT | KBDCTRL)) == (KBDALT | KBDCTRL)) &&
00581
ISCAPSLOCKON(pfvk)) {
00582 wModBits ^= KBDSHIFT;
00583 }
00584
00585
00586
00587
00588
00589
00590
if ((pVK->Attributes & SGCAPS) && ((wModBits & ~KBDSHIFT) == 0) &&
00591
ISCAPSLOCKON(pfvk)) {
00592 pVK = (PVK_TO_WCHARS1)((
PBYTE)pVK + pVKT->cbSize);
00593 }
00594
00595
00596
00597
00598
00599 nShift =
GetModificationNumber(pKbdTbl->pCharModifiers, wModBits);
00600
00601
if (nShift == SHFT_INVALID) {
00602
00603
00604
00605
goto ReturnBadCharacter;
00606
00607 }
else if ((nShift < pVKT->nModifications) &&
00608 (pVK->wch[nShift] != WCH_NONE)) {
00609
00610
00611
00612
00613
if (pVK->wch[nShift] == WCH_DEAD) {
00614
00615
00616
00617
00618 pVK = (PVK_TO_WCHARS1)((
PBYTE)pVK + pVKT->cbSize);
00619
00620
00621
00622
00623
if (pkl->
wchDiacritic == 0) {
00624 TAGMSG2(DBGTAG_ToUnicode,
00625
"xxxInternalToUnicode: new dead char '%C'(%x), goto ReturnDeadCharacter",
00626 pVK->wch[nShift], pVK->wch[nShift]);
00627
goto ReturnDeadCharacter;
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 TAGMSG4(DBGTAG_ToUnicode,
00639
"xxxInternalToUnicode: 2 dead chars '%C'(%x)+'%C'(%x)",
00640 pkl->
wchDiacritic, pkl->
wchDiacritic,
00641 pVK->wch[nShift], pVK->wch[nShift]);
00642
if (
GetAppCompatFlags2(
VER40) & GACF2_NOCHAR_DEADKEY) {
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
goto ReturnDeadCharacter;
00657 }
00658
00659
goto ReturnGoodCharacter;
00660
00661 }
else if (pVK->wch[nShift] == WCH_LGTR) {
00662
00663
00664
00665
if ((GET_KBD_VERSION(pKbdTbl) == 0) || ((pLigature = pKbdTbl->pLigature) ==
NULL)) {
00666
00667
00668
00669
xxxMessageBeep(0);
00670
goto ReturnBadCharacter;
00671 }
00672
00673
while (pLigature->VirtualKey != 0) {
00674
int iLig = 0;
00675
int cwchT = 0;
00676
00677
if ((pLigature->VirtualKey == pVK->VirtualKey) &&
00678 (pLigature->ModificationNumber == nShift)) {
00679
00680
00681
00682
while ((iLig < pKbdTbl->nLgMax) && (cwchT < cChar)) {
00683
if (pLigature->wch[iLig] == WCH_NONE) {
00684
00685
00686
00687
return cwchT;
00688 }
00689
if (pkl->
wchDiacritic != 0) {
00690
int cComposed;
00691
00692
00693
00694
00695
00696
00697 cComposed =
ComposeDeadKeys(
00698 pkl,
00699 pKbdTbl->pDeadKey,
00700 pLigature->wch[iLig],
00701 pUniChar + cwchT,
00702 cChar - cwchT,
00703 *pdwKeyFlags & KBDBREAK
00704 );
00705
if (cComposed > 0) {
00706 cwchT += cComposed;
00707 }
else {
00708 RIPMSG2(RIP_ERROR,
00709
"InternalToUnicode: dead+lig(%x)->dead(%x)",
00710 pLigature->wch[0], pkl->
wchDiacritic);
00711 }
00712 }
else {
00713 pUniChar[cwchT++] = pLigature->wch[iLig];
00714 }
00715 iLig++;
00716 }
00717
return cwchT;
00718 }
00719
00720
00721
00722 pLigature = (PLIGATURE1)((
PBYTE)pLigature + pKbdTbl->cbLgEntry);
00723 }
00724
00725
00726
00727
xxxMessageBeep(0);
00728
goto ReturnBadCharacter;
00729 }
00730
00731
00732
00733
00734 TAGMSG2(DBGTAG_ToUnicode,
00735
"xxxInternalToUnicode: Match found '%C'(%x), goto ReturnGoodChar",
00736 pVK->wch[nShift], pVK->wch[nShift]);
00737
goto ReturnGoodCharacter;
00738
00739 }
else if ((wModBits == KBDCTRL) || (wModBits == (KBDCTRL|KBDSHIFT)) ||
00740 (wModBits == (KBDKANA|KBDCTRL)) || (wModBits == (KBDKANA|KBDCTRL|KBDSHIFT))) {
00741
00742
00743
00744
00745
00746
if ((uVirtKey >=
'A') && (uVirtKey <=
'Z')) {
00747
00748
00749
00750
00751
00752
00753 *pUniChar = (WORD)(uVirtKey & 0x1f);
00754
return 1;
00755 }
else if ((uVirtKey >= 0xFF61) && (uVirtKey <= 0xFF91)) {
00756
00757
00758
00759
00760
00761 *pUniChar = (WORD)(
InternalVkKeyScanEx((WCHAR)uVirtKey,pKbdTbl) & 0x1f);
00762
return 1;
00763 }
00764 }
00765 }
00766
00767 ReturnBadCharacter:
00768
00769
return 0;
00770
00771 ReturnDeadCharacter:
00772 *pUniChar = pVK->wch[nShift];
00773
00774
00775
00776
00777
if (!(*pdwKeyFlags & KBDBREAK)) {
00778 pkl->
wchDiacritic = *pUniChar;
00779 }
00780
00781 UserAssert(pKbdTbl->pDeadKey);
00782
00783
00784
00785
00786
return -1;
00787
00788 ReturnGoodCharacter:
00789
if ((pKbdTbl->pDeadKey !=
NULL) && (pkl->
wchDiacritic != 0)) {
00790
return ComposeDeadKeys(
00791 pkl,
00792 pKbdTbl->pDeadKey,
00793 pVK->wch[nShift],
00794 pUniChar,
00795 cChar,
00796 *pdwKeyFlags & KBDBREAK
00797 );
00798 }
00799 *pUniChar = (WORD)pVK->wch[nShift];
00800
return 1;
00801 }
00802
00803 SHORT InternalVkKeyScanEx(
00804 WCHAR wchChar,
00805 PKBDTABLES pKbdTbl)
00806 {
00807 PVK_TO_WCHARS1 pVK;
00808 PVK_TO_WCHAR_TABLE pVKT;
00809
BYTE nShift;
00810 WORD wModBits;
00811 WORD wModNumCtrl, wModNumShiftCtrl;
00812
SHORT shRetvalCtrl = 0;
00813
SHORT shRetvalShiftCtrl = 0;
00814
00815
if (pKbdTbl ==
NULL) {
00816 pKbdTbl =
gspklBaseLayout->
spkf->
pKbdTbl;
00817 }
00818
00819
00820
00821
00822
00823
00824
00825 wModNumCtrl =
GetModificationNumber(pKbdTbl->pCharModifiers, KBDCTRL);
00826 wModNumShiftCtrl =
GetModificationNumber(pKbdTbl->pCharModifiers, KBDSHIFT | KBDCTRL);
00827
00828
for (pVKT = pKbdTbl->pVkToWcharTable; pVKT->pVkToWchars !=
NULL; pVKT++) {
00829
for (pVK = pVKT->pVkToWchars;
00830 pVK->VirtualKey != 0;
00831 pVK = (PVK_TO_WCHARS1)((
PBYTE)pVK + pVKT->cbSize)) {
00832
for (nShift = 0; nShift < pVKT->nModifications; nShift++) {
00833
if (pVK->wch[nShift] == wchChar) {
00834
00835
00836
00837
if (pVK->VirtualKey == 0xff) {
00838
00839
00840
00841 pVK = (PVK_TO_WCHARS1)((
PBYTE)pVK - pVKT->cbSize);
00842 }
00843
00844
00845
00846
00847
00848
00849
if (nShift == wModNumCtrl) {
00850
if (shRetvalCtrl == 0) {
00851 shRetvalCtrl = (
SHORT)MAKEWORD(pVK->VirtualKey, KBDCTRL);
00852 }
00853 }
else if (nShift == wModNumShiftCtrl) {
00854
if (shRetvalShiftCtrl == 0) {
00855 shRetvalShiftCtrl = (
SHORT)MAKEWORD(pVK->VirtualKey, KBDCTRL | KBDSHIFT);
00856 }
00857 }
else {
00858
00859
00860
00861
goto GoodMatchFound;
00862 }
00863 }
00864 }
00865 }
00866 }
00867
00868
00869
00870
00871
if (shRetvalCtrl) {
00872
return shRetvalCtrl;
00873 }
00874
if (shRetvalShiftCtrl) {
00875
return shRetvalShiftCtrl;
00876 }
00877
00878
00879
00880
00881
if (wchChar < 0x0020) {
00882
00883
00884
00885
return (
SHORT)MAKEWORD((wchChar + 0x40), KBDCTRL);
00886 }
00887
return -1;
00888
00889 GoodMatchFound:
00890
00891
00892
00893
00894
00895
for (wModBits = 0;
00896 wModBits <= pKbdTbl->pCharModifiers->wMaxModBits;
00897 wModBits++)
00898 {
00899
if (pKbdTbl->pCharModifiers->ModNumber[wModBits] == nShift) {
00900
if (pVK->VirtualKey == 0xff) {
00901
00902
00903
00904 pVK = (PVK_TO_WCHARS1)((
PBYTE)pVK - pVKT->cbSize);
00905 }
00906
return (
SHORT)MAKEWORD(pVK->VirtualKey, wModBits);
00907 }
00908 }
00909
00910
00911
00912
00913 UserAssertMsg1(
FALSE,
"InternalVkKeyScanEx error: wchChar = 0x%x", wchChar);
00914
return -1;
00915 }