Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

hotkey.c

Go to the documentation of this file.
00001 /**************************************************************************\ 00002 * Module Name: hotkey.c (corresponds to Win95 hotkey.c) 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * IME hot key management routines for imm32 dll 00007 * 00008 * History: 00009 * 03-Jan-1996 wkwok Created 00010 \**************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 00016 00017 // 00018 // internal functions 00019 // 00020 BOOL CIMENonIMEToggle(HIMC hIMC, HKL hKL, HWND hWnd, LANGID langTarget); 00021 BOOL IMENonIMEToggle( HIMC hIMC, HKL hKL, HWND hWnd, BOOL fIME, LANGID langTarget); 00022 BOOL JCloseOpen( HIMC hIMC, HKL hKL, HWND hWnd); 00023 BOOL CSymbolToggle(HIMC hIMC, HKL hKL, HWND hWnd); 00024 BOOL TShapeToggle(HIMC hIMC, HKL hKL, HWND hWnd); 00025 BOOL KEnglishHangul( HIMC hIMC); 00026 BOOL KShapeToggle( HIMC hIMC); 00027 BOOL KHanjaConvert( HIMC hIMC); 00028 00029 00030 /***************************************************************************\ 00031 * ImmGetHotKey() 00032 * 00033 * Private API for IMEs and the control panel. The caller specifies 00034 * the IME hotkey ID:dwID. If a hotkey is registered with the specified 00035 * ID, this function returns the modifiers, vkey and hkl of the hotkey. 00036 * 00037 * History: 00038 * 25-Mar-1996 TakaoK Created 00039 \***************************************************************************/ 00040 BOOL WINAPI ImmGetHotKey( 00041 DWORD dwID, 00042 PUINT puModifiers, 00043 PUINT puVKey, 00044 HKL *phkl) 00045 { 00046 if (puModifiers == NULL || puVKey == NULL) { 00047 return FALSE; 00048 } 00049 return NtUserGetImeHotKey( dwID, puModifiers, puVKey, phkl ); 00050 } 00051 00052 /**********************************************************************/ 00053 /* ImmSimulateHotKey() */ 00054 /* Return Value: */ 00055 /* TRUE - successful, FALSE - failure */ 00056 /**********************************************************************/ 00057 BOOL WINAPI ImmSimulateHotKey( // simulate the functionality of that hot key 00058 HWND hAppWnd, // application window handle 00059 DWORD dwHotKeyID) 00060 { 00061 HIMC hImc; 00062 HKL hKL; 00063 BOOL fReturn; 00064 00065 hImc = ImmGetContext( hAppWnd ); 00066 hKL = GetKeyboardLayout( GetWindowThreadProcessId(hAppWnd, NULL) ); 00067 fReturn = HotKeyIDDispatcher( hAppWnd, hImc, hKL, dwHotKeyID); 00068 ImmReleaseContext( hAppWnd, hImc ); 00069 return fReturn; 00070 } 00071 00072 00073 /***************************************************************************\ 00074 * SaveImeHotKey() 00075 * 00076 * Put/Remove the specified IME hotkey entry from the registry 00077 * 00078 * History: 00079 * 25-Mar-1996 TakaoK Created 00080 \***************************************************************************/ 00081 00082 /**********************************************************************/ 00083 /* HotKeyIDDispatcher */ 00084 /* Return Value: */ 00085 /* TRUE - a hot key processed, FALSE - not processed */ 00086 /**********************************************************************/ 00087 BOOL HotKeyIDDispatcher( HWND hWnd, HIMC hImc, HKL hKlCurrent, DWORD dwHotKeyID ) 00088 { 00089 /* 00090 * Dispatch the IME hotkey event for the specified hImc 00091 * only if the calling thread owns the hImc. 00092 */ 00093 if (hImc != NULL_HIMC && 00094 GetInputContextThread(hImc) != GetCurrentThreadId()) { 00095 return FALSE; 00096 } 00097 00098 switch ( dwHotKeyID ) { 00099 case IME_CHOTKEY_IME_NONIME_TOGGLE: 00100 return CIMENonIMEToggle(hImc, hKlCurrent, hWnd, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)); 00101 00102 case IME_THOTKEY_IME_NONIME_TOGGLE: 00103 return CIMENonIMEToggle(hImc, hKlCurrent, hWnd, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)); 00104 00105 case IME_CHOTKEY_SYMBOL_TOGGLE: 00106 case IME_THOTKEY_SYMBOL_TOGGLE: 00107 return CSymbolToggle( hImc, hKlCurrent, hWnd); 00108 00109 case IME_JHOTKEY_CLOSE_OPEN: 00110 return JCloseOpen( hImc, hKlCurrent, hWnd); 00111 00112 case IME_KHOTKEY_ENGLISH: // VK_HANGUL : English/Hangul mode 00113 return KEnglishHangul( hImc ); 00114 00115 case IME_KHOTKEY_SHAPE_TOGGLE: // VK_JUNJA : full/half width 00116 return KShapeToggle( hImc ); 00117 00118 case IME_KHOTKEY_HANJACONVERT: // VK_HANJA : convert hangul to hanja 00119 return KHanjaConvert( hImc ); 00120 00121 case IME_CHOTKEY_SHAPE_TOGGLE: 00122 case IME_THOTKEY_SHAPE_TOGGLE: 00123 return TShapeToggle( hImc, hKlCurrent, hWnd); 00124 00125 default: 00126 /* 00127 * Direct swithing hotkey should have been handled in the kernel side. 00128 */ 00129 ImmAssert(dwHotKeyID < IME_HOTKEY_DSWITCH_FIRST || dwHotKeyID > IME_HOTKEY_DSWITCH_LAST); 00130 00131 if ( dwHotKeyID >= IME_HOTKEY_PRIVATE_FIRST && 00132 dwHotKeyID <= IME_HOTKEY_PRIVATE_LAST ) { 00133 00134 PIMEDPI pImeDpi; 00135 BOOL bRet = FALSE; 00136 00137 if ( (pImeDpi = ImmLockImeDpi(hKlCurrent)) != NULL ) { 00138 00139 bRet = (BOOL)(*pImeDpi->pfn.ImeEscape)( hImc, 00140 IME_ESC_PRIVATE_HOTKEY, 00141 (PVOID)&dwHotKeyID ); 00142 ImmUnlockImeDpi(pImeDpi); 00143 return bRet; 00144 } 00145 } 00146 } 00147 return (FALSE); 00148 } 00149 00150 /**********************************************************************/ 00151 /* JCloseOpen() */ 00152 /* Return Value: */ 00153 /* TRUE - a hot key processed, FALSE - not processed */ 00154 /**********************************************************************/ 00155 BOOL JCloseOpen( // open/close toggle 00156 HIMC hIMC, 00157 HKL hCurrentKL, 00158 HWND hWnd) 00159 { 00160 00161 if (ImmIsIME(hCurrentKL) && 00162 LOWORD(HandleToUlong(hCurrentKL)) == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)) { 00163 // 00164 // If current KL is IME and its language is Japanese, 00165 // we only have to switch the open/close status. 00166 // 00167 ImmSetOpenStatus( hIMC, !ImmGetOpenStatus(hIMC) ); 00168 } else { 00169 // 00170 // If current KL is not IME or its language is not Japanese, 00171 // we should find the Japanese IME and set it open. 00172 // 00173 if (IMENonIMEToggle(hIMC, hCurrentKL, hWnd, FALSE, MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT))) { 00174 // 00175 // Mark it so that later we can initialize the fOpen 00176 // as expected. 00177 // 00178 PINPUTCONTEXT pInputContext = ImmLockIMC(hIMC); 00179 00180 if (pInputContext) { 00181 pInputContext->fdwDirty |= IMSS_INIT_OPEN; 00182 ImmUnlockIMC(hIMC); 00183 } 00184 } 00185 } 00186 return TRUE; 00187 00188 #if 0 // for your reference : old code ported from Win95 00189 LPINPUTCONTEXT pInputContext; 00190 PIMEDPI pImeDpi; 00191 00192 00193 if ( (pInputContext = ImmLockIMC( hIMC )) == NULL ) { 00194 // 00195 // The return value is same as Win95. 00196 // Not happens so often any way. 00197 // 00198 return TRUE; 00199 } 00200 00201 pImeDpi = ImmLockImeDpi( hCurrentKL ); 00202 if ( pImeDpi != NULL ) { 00203 // 00204 // update Input Context 00205 // 00206 pInputContext->fOpen = !pInputContext->fOpen; 00207 00208 // 00209 // notify IME 00210 // 00211 (*pImeDpi->pfn.NotifyIME)( hIMC, 00212 NI_CONTEXTUPDATED, 00213 0L, 00214 IMC_SETOPENSTATUS ); 00215 // 00216 // inform UI 00217 // 00218 SendMessage(hWnd, WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0L); 00219 SendMessage(hWnd, WM_IME_SYSTEM, IMS_SETOPENSTATUS, 0L); 00220 00221 ImmUnlockIMC( hIMC ); 00222 ImmUnlockImeDpi(pImeDpi); 00223 return TRUE; 00224 00225 } else { 00226 00227 if ( !pInputContext->fOpen ) { 00228 pInputContext->fOpen = TRUE; 00229 SendMessage(hWnd, WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0L); 00230 SendMessage(hWnd, WM_IME_SYSTEM, IMS_SETOPENSTATUS, 0L); 00231 } 00232 ImmUnlockIMC( hIMC ); 00233 00234 return IMENonIMEToggle(hIMC, hCurrentKL, hWnd, FALSE); 00235 } 00236 #endif 00237 } 00238 00239 00240 /**********************************************************************/ 00241 /* CIMENonIMEToggle() */ 00242 /* Return Value: */ 00243 /* TRUE - a hot key processed, FALSE - not processed */ 00244 /**********************************************************************/ 00245 BOOL CIMENonIMEToggle( // non-IME and IME toggle 00246 HIMC hIMC, 00247 HKL hKlCurrent, 00248 HWND hWnd, 00249 LANGID langId) 00250 { 00251 if (hWnd == NULL) 00252 return(FALSE); 00253 00254 if (!ImmIsIME(hKlCurrent) || LOWORD(HandleToUlong(hKlCurrent)) != langId) { 00255 // 00256 // Current keyboard layout is not IME or its language does not match. 00257 // Let's try to switch to our IME. 00258 // 00259 IMENonIMEToggle(hIMC, hKlCurrent, hWnd, FALSE, langId); 00260 return TRUE; 00261 00262 } else { 00263 00264 LPINPUTCONTEXT pInputContext = ImmLockIMC( hIMC ); 00265 00266 if ( pInputContext == NULL ) { 00267 // 00268 // returning TRUE even if we didn't change 00269 // 00270 return TRUE; 00271 } 00272 if (!pInputContext->fOpen) { 00273 // 00274 // toggle close to open 00275 // 00276 ImmSetOpenStatus(hIMC, TRUE); 00277 ImmUnlockIMC(hIMC); 00278 return TRUE; 00279 } else { 00280 ImmUnlockIMC(hIMC); 00281 IMENonIMEToggle(hIMC, hKlCurrent, hWnd, TRUE, 0); 00282 return TRUE; 00283 } 00284 } 00285 } 00286 00287 /**********************************************************************/ 00288 /* IMENonIMEToggle() */ 00289 /* Return Value: */ 00290 /* TRUE - a hot key processed, FALSE - not processed */ 00291 /**********************************************************************/ 00292 BOOL IMENonIMEToggle( 00293 HIMC hIMC, 00294 HKL hCurrentKL, 00295 HWND hWnd, 00296 BOOL fCurrentIsIME, 00297 LANGID langTarget) 00298 { 00299 HKL hEnumKL[32], hTargetKL; 00300 UINT nLayouts, i; 00301 HKL hPrevKL; 00302 00303 UNREFERENCED_PARAMETER(hIMC); 00304 00305 hPrevKL = (HKL)NtUserGetThreadState( UserThreadStatePreviousKeyboardLayout ); 00306 00307 // 00308 // If we find the same layout in the layout list, let's switch to 00309 // the layout. If we fail, let's switch to a first-found good 00310 // layout. 00311 // 00312 00313 hTargetKL = NULL; 00314 nLayouts = GetKeyboardLayoutList(sizeof(hEnumKL)/sizeof(HKL), hEnumKL); 00315 00316 // LATER: 00317 // Hmm, looks like we can't simply rely on hPrevKL on multiple lanugage 00318 // environment.. 00319 // 00320 if (hPrevKL != NULL) { 00321 if (langTarget == 0 || LOWORD(HandleToUlong(hPrevKL)) == langTarget) { 00322 // 00323 // If langtarget is not specified, or 00324 // if it matches the previous langauge. 00325 // 00326 for (i = 0; i < nLayouts; i++) { 00327 // valid target HKL 00328 if (hEnumKL[i] == hPrevKL) { 00329 hTargetKL = hPrevKL; 00330 break; 00331 } 00332 } 00333 } 00334 } 00335 if (hTargetKL == NULL) { 00336 for (i = 0; i < nLayouts; i++) { 00337 // find a valid target HKL 00338 if (fCurrentIsIME ^ ImmIsIME(hEnumKL[i])) { 00339 if (langTarget != 0 && LOWORD(HandleToUlong(hEnumKL[i])) != langTarget) { 00340 // If the target language is specified, check it 00341 continue; 00342 } 00343 hTargetKL = hEnumKL[i]; 00344 break; 00345 } 00346 } 00347 } 00348 if (hTargetKL != NULL && hCurrentKL != hTargetKL) { 00349 00350 // depends on multilingual message and how to get the base charset 00351 // wait for confirmation of multiingual spec - tmp solution 00352 PostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, DEFAULT_CHARSET, (LPARAM)hTargetKL); 00353 } 00354 // 00355 // returning TRUE, even if we failed to switch 00356 // 00357 return ImmIsIME(hTargetKL); 00358 } 00359 00360 /**********************************************************************/ 00361 /* CSymbolToggle() */ 00362 /* Return Value: */ 00363 /* TRUE - a hot key processed, FALSE - not processed */ 00364 /**********************************************************************/ 00365 BOOL CSymbolToggle( // symbol & non symbol toggle 00366 HIMC hIMC, 00367 HKL hKL, 00368 HWND hWnd) 00369 { 00370 LPINPUTCONTEXT pInputContext; 00371 00372 // 00373 // Return TRUE even no layout switching - Win95 behavior 00374 // 00375 if (hWnd == NULL) 00376 return(FALSE); 00377 00378 if ( ! ImmIsIME( hKL ) ) { 00379 return (FALSE); 00380 } 00381 00382 if ( (pInputContext = ImmLockIMC( hIMC )) == NULL ) { 00383 // 00384 // The return value is same as Win95. 00385 // Not happens so often any way. 00386 // 00387 return TRUE; 00388 } 00389 00390 if (pInputContext->fOpen) { 00391 // 00392 // toggle the symbol mode 00393 // 00394 ImmSetConversionStatus(hIMC, 00395 pInputContext->fdwConversion ^ IME_CMODE_SYMBOL, 00396 pInputContext->fdwSentence); 00397 } 00398 else { 00399 // 00400 // change close -> open 00401 // 00402 ImmSetOpenStatus(hIMC, TRUE); 00403 } 00404 00405 ImmUnlockIMC(hIMC); 00406 return (TRUE); 00407 00408 } 00409 00410 /**********************************************************************/ 00411 /* TShapeToggle() */ 00412 /* Return Value: */ 00413 /* TRUE - a hot key processed, FALSE - not processed */ 00414 /**********************************************************************/ 00415 BOOL TShapeToggle( // fullshape & halfshape toggle 00416 HIMC hIMC, 00417 HKL hKL, 00418 HWND hWnd) 00419 { 00420 LPINPUTCONTEXT pInputContext; 00421 00422 // 00423 // Return TRUE even no layout switching - Win95 behavior 00424 // 00425 if (hWnd == NULL) 00426 return(FALSE); 00427 00428 if ( ! ImmIsIME( hKL ) ) { 00429 return (FALSE); 00430 } 00431 00432 if ( (pInputContext = ImmLockIMC( hIMC )) == NULL ) { 00433 // 00434 // The return value is same as Win95. 00435 // Not happens so often any way. 00436 // 00437 return TRUE; 00438 } 00439 00440 if (pInputContext->fOpen) { 00441 // 00442 // toggle the symbol mode 00443 // 00444 ImmSetConversionStatus(hIMC, 00445 pInputContext->fdwConversion ^ IME_CMODE_FULLSHAPE, 00446 pInputContext->fdwSentence); 00447 } 00448 else { 00449 // 00450 // change close -> open 00451 // 00452 ImmSetOpenStatus(hIMC, TRUE); 00453 } 00454 00455 ImmUnlockIMC(hIMC); 00456 return (TRUE); 00457 } 00458 00459 /**********************************************************************/ 00460 /* KEnglishHangul() - Egnlish & Hangeul toggle */ 00461 /* Return Value: */ 00462 /* TRUE - a hot key processed, FALSE - not processed */ 00463 /**********************************************************************/ 00464 BOOL KEnglishHangul( HIMC hImc ) 00465 { 00466 PINPUTCONTEXT pInputContext; 00467 00468 if ((pInputContext = ImmLockIMC(hImc)) != NULL) { 00469 00470 ImmSetConversionStatus(hImc, 00471 pInputContext->fdwConversion ^ IME_CMODE_HANGEUL, 00472 pInputContext->fdwSentence); 00473 00474 if ((pInputContext->fdwConversion & IME_CMODE_HANGEUL) || 00475 (pInputContext->fdwConversion & IME_CMODE_FULLSHAPE)) { 00476 ImmSetOpenStatus(hImc, TRUE); 00477 } else { 00478 ImmSetOpenStatus(hImc, FALSE); 00479 } 00480 ImmUnlockIMC(hImc); 00481 return TRUE; 00482 } 00483 00484 return FALSE; 00485 } 00486 00487 /**********************************************************************/ 00488 /* KShapeToggle() - Fullshape & Halfshape toggle */ 00489 /* Return Value: */ 00490 /* TRUE - a hot key processed, FALSE - not processed */ 00491 /**********************************************************************/ 00492 BOOL KShapeToggle( HIMC hImc ) 00493 { 00494 PINPUTCONTEXT pInputContext; 00495 00496 if ( (pInputContext = ImmLockIMC( hImc )) != NULL ) { 00497 00498 ImmSetConversionStatus(hImc, 00499 pInputContext->fdwConversion ^ IME_CMODE_FULLSHAPE, 00500 pInputContext->fdwSentence); 00501 00502 if ((pInputContext->fdwConversion & IME_CMODE_HANGEUL) 00503 || (pInputContext->fdwConversion & IME_CMODE_FULLSHAPE)) 00504 ImmSetOpenStatus(hImc, TRUE); 00505 else 00506 ImmSetOpenStatus(hImc, FALSE); 00507 ImmUnlockIMC(hImc); 00508 return TRUE; 00509 } 00510 00511 return FALSE; 00512 } 00513 00514 /**********************************************************************/ 00515 /* KHanjaConvert() - Hanja conversion toggle */ 00516 /* Return Value: */ 00517 /* TRUE - a hot key processed, FALSE - not processed */ 00518 /**********************************************************************/ 00519 BOOL KHanjaConvert( HIMC hImc ) 00520 { 00521 PINPUTCONTEXT pInputContext; 00522 00523 if ( (pInputContext = ImmLockIMC( hImc )) != NULL ) { 00524 00525 ImmSetConversionStatus( hImc, 00526 pInputContext->fdwConversion ^ IME_CMODE_HANJACONVERT, 00527 pInputContext->fdwSentence ); 00528 00529 ImmUnlockIMC( hImc ); 00530 return TRUE; 00531 } 00532 return FALSE; 00533 }

Generated on Sat May 15 19:40:18 2004 for test by doxygen 1.3.7