00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
#include "precomp.h"
00019
#pragma hdrstop
00020
00021
PIMEHOTKEYOBJ DeleteImeHotKey(
PIMEHOTKEYOBJ *ppHead,
PIMEHOTKEYOBJ pDelete);
00022
VOID AddImeHotKey(
PIMEHOTKEYOBJ *ppHead,
PIMEHOTKEYOBJ pAdd);
00023
PIMEHOTKEYOBJ FindImeHotKeyByKey(
PIMEHOTKEYOBJ pHead, UINT uModifyKeys, UINT uRL, UINT uVKey);
00024
PIMEHOTKEYOBJ FindImeHotKeyByID(
PIMEHOTKEYOBJ pHead, DWORD dwHotKeyID);
00025
PIMEHOTKEYOBJ FindImeHotKeyByKeyWithLang(
PIMEHOTKEYOBJ pHead, UINT uModifyKeys, UINT uRL, UINT uVKey, LANGID langId);
00026
00027
00028 #define L_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
00029 #define L_JPN MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
00030 #define L_KOR MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT)
00031 #define L_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
00032
00033
enum {
00034
ILANG_NO_MATCH = 0,
00035
ILANG_MATCH_SYSTEM,
00036
ILANG_MATCH_THREAD,
00037
ILANG_MATCH_PERFECT,
00038 };
00039
00040
00041
00042
#if IME_CHOTKEY_FIRST != 0x10 || IME_JHOTKEY_FIRST != 0x30 || IME_KHOTKEY_FIRST != 0x50 || IME_THOTKEY_FIRST != 0x70
00043
#error unexpected IME_xHOTKEY range !
00044
#endif
00045
00046 LANGID
GetHotKeyLangID(DWORD dwHotKeyID)
00047 {
00048 LANGID langId = -1;
00049
static CONST LANGID aLangId[] = {
00050 ~0,
00051
L_CHS,
L_CHS,
00052
L_JPN,
L_JPN,
00053
L_KOR,
L_KOR,
00054
L_CHT,
L_CHT,
00055 };
00056
00057
if (dwHotKeyID >= IME_CHOTKEY_FIRST && dwHotKeyID <= IME_THOTKEY_LAST) {
00058 langId = aLangId[dwHotKeyID >> 4];
00059 }
00060
else {
00061 langId = LANG_NEUTRAL;
00062 }
00063
00064
00065 UserAssert(langId !=
L_KOR);
00066
00067
return langId;
00068 }
00069
00070
BOOL
00071 GetImeHotKey(
00072 DWORD dwHotKeyID,
00073 PUINT puModifiers,
00074 PUINT puVKey,
00075 HKL *phKL )
00076 {
00077
PIMEHOTKEYOBJ ph;
00078
00079 ph =
FindImeHotKeyByID(
gpImeHotKeyListHeader, dwHotKeyID );
00080
if ( ph ==
NULL ) {
00081 RIPERR0(ERROR_HOTKEY_NOT_REGISTERED, RIP_VERBOSE,
"No such IME hotkey");
00082
return (
FALSE);
00083 }
00084
00085
00086
00087
00088
if ( phKL ) {
00089 *phKL = ph->
hk.
hKL;
00090 }
else if ( ph->
hk.
hKL !=
NULL ) {
00091 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING,
"phKL is null");
00092
return (
FALSE);
00093 }
00094
00095 *puModifiers = ph->
hk.
uModifiers;
00096 *puVKey = ph->
hk.
uVKey;
00097
00098
return (
TRUE);
00099 }
00100
00101
00102
00103
00104
00105
BOOL
00106 SetImeHotKey(
00107 DWORD dwHotKeyID,
00108 UINT uModifiers,
00109 UINT uVKey,
00110 HKL hKL,
00111 DWORD dwAction )
00112 {
00113
PIMEHOTKEYOBJ ph;
00114
00115
switch ( dwAction ) {
00116
case ISHK_REMOVE:
00117 ph =
FindImeHotKeyByID(
gpImeHotKeyListHeader, dwHotKeyID );
00118
if ( ph !=
NULL ) {
00119
if (
DeleteImeHotKey( &
gpImeHotKeyListHeader, ph ) == ph ) {
00120 UserFreePool( ph );
00121
return (
TRUE );
00122 }
else {
00123 RIPMSG0( RIP_ERROR,
"IME hotkey list is messed up" );
00124
return FALSE;
00125 }
00126 }
else {
00127 RIPERR0( ERROR_INVALID_PARAMETER,
00128 RIP_WARNING,
00129
"no such IME hotkey registered");
00130
return FALSE;
00131 }
00132
break;
00133
00134
case ISHK_INITIALIZE:
00135 ph =
gpImeHotKeyListHeader;
00136
while ( ph !=
NULL ) {
00137
PIMEHOTKEYOBJ phNext;
00138
00139 phNext = ph->
pNext;
00140 UserFreePool( ph );
00141 ph = phNext;
00142 }
00143
gpImeHotKeyListHeader =
NULL;
00144
return TRUE;
00145
00146
case ISHK_ADD:
00147
if (dwHotKeyID >= IME_KHOTKEY_FIRST && dwHotKeyID <= IME_KHOTKEY_LAST) {
00148
00149
00150
return FALSE;
00151 }
00152
00153
if ((WORD)uVKey == VK_PACKET) {
00154
00155
00156
00157
return FALSE;
00158 }
00159
00160 ph =
FindImeHotKeyByKeyWithLang(
gpImeHotKeyListHeader,
00161 uModifiers &
MOD_MODIFY_KEYS,
00162 uModifiers &
MOD_BOTH_SIDES,
00163 uVKey,
00164
GetHotKeyLangID(dwHotKeyID));
00165
if ( ph !=
NULL ) {
00166
if ( ph->
hk.
dwHotKeyID != dwHotKeyID ) {
00167 RIPERR0( ERROR_HOTKEY_ALREADY_REGISTERED,
00168 RIP_WARNING,
00169
"There is an IME hotkey that has the same vkey/modifiers/Lang Id");
00170
return FALSE;
00171 }
00172
00173
00174
00175
00176 }
else {
00177
00178
00179
00180
00181
00182 ph =
FindImeHotKeyByID(
gpImeHotKeyListHeader, dwHotKeyID );
00183 }
00184
00185
if ( ph ==
NULL ) {
00186
00187
00188
00189 ph = (
PIMEHOTKEYOBJ)UserAllocPool(
sizeof(
IMEHOTKEYOBJ), TAG_IMEHOTKEY );
00190
if ( ph ==
NULL ) {
00191 RIPERR0( ERROR_OUTOFMEMORY,
00192 RIP_WARNING,
00193
"Memory allocation failed in SetImeHotKey");
00194
return FALSE;
00195 }
00196 ph->
hk.
dwHotKeyID = dwHotKeyID;
00197 ph->
hk.
uModifiers = uModifiers;
00198 ph->
hk.
uVKey = uVKey;
00199 ph->
hk.
hKL = hKL;
00200 ph->
pNext =
NULL;
00201
AddImeHotKey( &
gpImeHotKeyListHeader, ph );
00202
00203 }
else {
00204
00205
00206
00207 ph->
hk.
uModifiers = uModifiers;
00208 ph->
hk.
uVKey = uVKey;
00209 ph->
hk.
hKL = hKL;
00210
00211 }
00212
return TRUE;
00213 }
00214
00215
return FALSE;
00216 }
00217
00218
00219 PIMEHOTKEYOBJ DeleteImeHotKey(
PIMEHOTKEYOBJ *ppHead,
PIMEHOTKEYOBJ pDelete )
00220 {
00221
PIMEHOTKEYOBJ ph;
00222
00223
if ( pDelete == *ppHead ) {
00224 *ppHead = pDelete->
pNext;
00225
return pDelete;
00226 }
00227
00228
for ( ph = *ppHead; ph !=
NULL; ph = ph->
pNext ) {
00229
if ( ph->
pNext == pDelete ) {
00230 ph->
pNext = pDelete->
pNext;
00231
return pDelete;
00232 }
00233 }
00234
return NULL;
00235 }
00236
00237 VOID AddImeHotKey(
PIMEHOTKEYOBJ *ppHead,
PIMEHOTKEYOBJ pAdd )
00238 {
00239
PIMEHOTKEYOBJ ph;
00240
00241
if ( *ppHead ==
NULL ) {
00242 *ppHead = pAdd;
00243 }
else {
00244 ph = *ppHead;
00245
while( ph->
pNext !=
NULL )
00246 ph = ph->
pNext;
00247 ph->
pNext = pAdd;
00248 }
00249
return;
00250 }
00251
00252 VOID FreeImeHotKeys(VOID)
00253 {
00254
PIMEHOTKEYOBJ phk;
00255
00256
while (
gpImeHotKeyListHeader !=
NULL) {
00257 phk =
gpImeHotKeyListHeader->
pNext;
00258 UserFreePool(
gpImeHotKeyListHeader);
00259
gpImeHotKeyListHeader = phk;
00260 }
00261 }
00262
00263
00264 LCID
glcidSystem;
00265
00266 int GetLangIdMatchLevel(HKL hkl, LANGID langId)
00267 {
00268
00269
if (langId == LANG_NEUTRAL) {
00270
00271
00272
00273
00274
return ILANG_MATCH_PERFECT;
00275 }
00276
00277 {
00278 LCID lcid;
00279
00280
if (LOWORD(HandleToUlong(hkl)) == langId) {
00281
00282
return ILANG_MATCH_PERFECT;
00283 }
00284
00285 lcid = NtCurrentTeb()->CurrentLocale;
00286
if (LANGIDFROMLCID(lcid) == langId) {
00287
00288
return ILANG_MATCH_THREAD;
00289 }
00290
00291
if (
glcidSystem == 0) {
00292
00293 ZwQueryDefaultLocale(
FALSE, &
glcidSystem);
00294 }
00295
if (LANGIDFROMLCID(
glcidSystem) == langId) {
00296
00297
return ILANG_MATCH_SYSTEM;
00298 }
00299 }
00300
00301
return ILANG_NO_MATCH;
00302 }
00303
00305
00306
00307
00308
00309
00310
00311
00312
00314
00315 PIMEHOTKEYOBJ FindImeHotKeyByKey(
00316
PIMEHOTKEYOBJ pHead,
00317 UINT uModifyKeys,
00318 UINT uRL,
00319 UINT uVKey)
00320 {
00321
PTHREADINFO ptiCurrent =
PtiCurrent();
00322
PIMEHOTKEYOBJ phResult =
NULL;
00323
PIMEHOTKEYOBJ ph;
00324 HKL hkl =
GetActiveHKL();
00325 WORD langPrimary = PRIMARYLANGID(LOWORD(HandleToUlong(hkl)));
00326
int iLevel =
ILANG_NO_MATCH;
00327
00328
for (ph = pHead; ph !=
NULL; ph = ph->
pNext) {
00329
00330
if (ph->
hk.
uVKey == uVKey) {
00331
BOOL fDoCheck =
FALSE;
00332
00333
00334
if ((ph->
hk.
uModifiers & MOD_IGNORE_ALL_MODIFIER)) {
00335 fDoCheck =
TRUE;
00336 }
else if ((ph->
hk.
uModifiers &
MOD_MODIFY_KEYS) != uModifyKeys) {
00337
continue;
00338 }
00339
00340
if ((ph->
hk.
uModifiers &
MOD_BOTH_SIDES) == uRL ||
00341 (ph->
hk.
uModifiers &
MOD_BOTH_SIDES) & uRL) {
00342 fDoCheck =
TRUE;
00343 }
00344
00345
if (fDoCheck) {
00346 LANGID langId =
GetHotKeyLangID(ph->
hk.
dwHotKeyID);
00347
int iMatch =
GetLangIdMatchLevel(hkl, langId);
00348
00349
#if 0 // Test only
00350
if (iMatch !=
ILANG_NO_MATCH) {
00351
DbgPrint(
"GetIdMatchLevel(%X, %X)=%d\n", hkl, langId);
00352 }
00353
#endif
00354
00355
if (iMatch ==
ILANG_MATCH_PERFECT) {
00356
00357
return ph;
00358 }
00359
00360
00361 UserAssert(ph->
hk.
dwHotKeyID < IME_HOTKEY_DSWITCH_FIRST ||
00362 ph->
hk.
dwHotKeyID > IME_HOTKEY_DSWITCH_LAST);
00363
00364
if (langPrimary == LANG_KOREAN) {
00365
00366
00367
continue;
00368 }
00369
00370
if (iMatch ==
ILANG_NO_MATCH) {
00371
00372
if (ph->
hk.
dwHotKeyID == IME_CHOTKEY_IME_NONIME_TOGGLE ||
00373 ph->
hk.
dwHotKeyID == IME_THOTKEY_IME_NONIME_TOGGLE) {
00374
00375
00376
00377
00378
if (LOWORD(HandleToUlong(ptiCurrent->
hklPrev)) == langId) {
00379
#if 0 // Test only
00380
DbgPrint(
"FindImeHotKeyByKey() found CHT/CHS hotkey.\n");
00381
#endif
00382
return ph;
00383 }
00384 }
00385 }
00386
else if (iMatch > iLevel) {
00387
00388 iLevel = iMatch;
00389 phResult = ph;
00390 }
00391 }
00392 }
00393 }
00394
00395
return phResult;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 PIMEHOTKEYOBJ FindImeHotKeyByID(
PIMEHOTKEYOBJ pHead, DWORD dwHotKeyID )
00405 {
00406
PIMEHOTKEYOBJ ph;
00407
00408
for ( ph = pHead; ph !=
NULL; ph = ph->
pNext ) {
00409
if ( ph->
hk.
dwHotKeyID == dwHotKeyID )
00410
return (ph);
00411 }
00412
return (
PIMEHOTKEYOBJ)
NULL;
00413 }
00414
00415
00416
00417
00418
00419
00420
00421 PIMEHOTKEYOBJ FindImeHotKeyByKeyWithLang(
00422
PIMEHOTKEYOBJ pHead,
00423 UINT uModifyKeys,
00424 UINT uRL,
00425 UINT uVKey,
00426 LANGID langIdKey)
00427 {
00428
PIMEHOTKEYOBJ ph;
00429
00430
for (ph = pHead; ph !=
NULL; ph = ph->
pNext) {
00431
00432
if (ph->
hk.
uVKey == uVKey) {
00433
BOOL fDoCheck =
FALSE;
00434
00435
00436
if ((ph->
hk.
uModifiers & MOD_IGNORE_ALL_MODIFIER)) {
00437 fDoCheck =
TRUE;
00438 }
else if ((ph->
hk.
uModifiers &
MOD_MODIFY_KEYS) != uModifyKeys) {
00439
continue;
00440 }
00441
00442
if ((ph->
hk.
uModifiers &
MOD_BOTH_SIDES) == uRL ||
00443 (ph->
hk.
uModifiers &
MOD_BOTH_SIDES) & uRL) {
00444 fDoCheck =
TRUE;
00445 }
00446
00447
if (fDoCheck) {
00448 LANGID langId =
GetHotKeyLangID(ph->
hk.
dwHotKeyID);
00449
00450
if (langIdKey == langId || langId == LANG_NEUTRAL) {
00451
return ph;
00452 }
00453 }
00454 }
00455 }
00456
00457
return NULL;
00458 }
00459
00460
PIMEHOTKEYOBJ
00461 CheckImeHotKey(
00462
PQ pq,
00463 UINT uVKey,
00464 LPARAM lParam
00465 )
00466 {
00467
static UINT uVKeySaved = 0;
00468
PIMEHOTKEYOBJ ph;
00469
UINT uModifiers = 0;
00470
BOOL fKeyUp;
00471
00472
00473
00474
00475 fKeyUp = ( lParam & 0x80000000 ) ?
TRUE :
FALSE;
00476
if ( fKeyUp ) {
00477
00478
00479
00480
00481
00482
if ( uVKeySaved != uVKey ) {
00483 uVKeySaved = 0;
00484
return NULL;
00485 }
00486 uVKeySaved = 0;
00487
00488
00489
00490
00491
00492
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503 uModifiers |=
TestKeyStateDown(pq, VK_LSHIFT) ? (MOD_SHIFT | MOD_LEFT) : 0;
00504 uModifiers |=
TestKeyStateDown(pq, VK_RSHIFT) ? (MOD_SHIFT | MOD_RIGHT) : 0;
00505
00506 uModifiers |=
TestKeyStateDown(pq, VK_LCONTROL) ? (MOD_CONTROL | MOD_LEFT) : 0;
00507 uModifiers |=
TestKeyStateDown(pq, VK_RCONTROL) ? (MOD_CONTROL | MOD_RIGHT) : 0;
00508
00509 uModifiers |=
TestKeyStateDown(pq, VK_LMENU) ? (MOD_ALT | MOD_LEFT) : 0;
00510 uModifiers |=
TestKeyStateDown(pq, VK_RMENU) ? (MOD_ALT | MOD_RIGHT) : 0;
00511
00512 ph =
FindImeHotKeyByKey(
gpImeHotKeyListHeader,
00513 uModifiers &
MOD_MODIFY_KEYS,
00514 uModifiers &
MOD_BOTH_SIDES,
00515 uVKey );
00516
00517
if ( ph !=
NULL ) {
00518
if ( fKeyUp ) {
00519
if ( ph->
hk.
uModifiers & MOD_ON_KEYUP ) {
00520
return ph;
00521 }
00522 }
else {
00523
if ( ph->
hk.
uModifiers & MOD_ON_KEYUP ) {
00524
00525
00526
00527
00528
00529
00530
00531
00532 uVKeySaved = uVKey;
00533 }
else {
00534
return ph;
00535 }
00536 }
00537 }
00538
00539
return NULL;
00540 }