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

input.c

Go to the documentation of this file.
00001 /**************************************************************************\ 00002 * Module Name: input.c 00003 * 00004 * Copyright (c) 1985 - 1999, Microsoft Corporation 00005 * 00006 * IME key input management routines for imm32 dll 00007 * 00008 * History: 00009 * 01-Apr-1996 takaok split from hotkey.c 00010 \**************************************************************************/ 00011 00012 #include "precomp.h" 00013 #pragma hdrstop 00014 00015 #ifdef HIRO_DEBUG 00016 #define D(x) x 00017 #else 00018 #define D(x) 00019 #endif 00020 00021 /***************************************************************************\ 00022 * ImmProcessKey (Callback from Win32K.SYS) 00023 * 00024 * Call ImeProcessKey and IME hotkey handler 00025 * 00026 * History: 00027 * 01-Mar-1996 TakaoK Created 00028 \***************************************************************************/ 00029 00030 DWORD WINAPI ImmProcessKey( 00031 HWND hWnd, 00032 HKL hkl, 00033 UINT uVKey, 00034 LPARAM lParam, 00035 DWORD dwHotKeyID) 00036 { 00037 HIMC hIMC = ImmGetContext(hWnd); 00038 PIMEDPI pImeDpi = ImmLockImeDpi(hkl); 00039 DWORD dwReturn = 0; 00040 #if DBG 00041 if (dwHotKeyID >= IME_KHOTKEY_FIRST && dwHotKeyID <= IME_KHOTKEY_LAST) { 00042 TAGMSG2(DBGTAG_IMM, "ImmProcessKey: Kor IME Hotkeys should not come here: dwHotKeyID=%x, uVKey=%x", dwHotKeyID, uVKey); 00043 } 00044 #endif 00045 00046 ImmAssert(dwHotKeyID != IME_KHOTKEY_ENGLISH && 00047 dwHotKeyID != IME_KHOTKEY_SHAPE_TOGGLE && 00048 dwHotKeyID != IME_KHOTKEY_HANJACONVERT); 00049 00050 // 00051 // call ImeProcessKey 00052 // 00053 if (pImeDpi != NULL) { 00054 PINPUTCONTEXT pInputContext = ImmLockIMC(hIMC); 00055 00056 if (pInputContext != NULL) { 00057 BOOLEAN fTruncateWideVK = FALSE; 00058 BOOLEAN fCallIme = TRUE; 00059 BOOLEAN fSkipThisKey = FALSE; 00060 00061 #ifdef LATER 00062 00063 // 00064 // if the current imc is not open and IME doesn't need 00065 // keys when being closed, we don't pass any keyboard 00066 // input to ime except hotkey and keys that change 00067 // the keyboard status. 00068 // 00069 if ((pImeDpi->fdwProperty & IME_PROP_NO_KEYS_ON_CLOSE) && 00070 !pInputContext->fOpen && 00071 uVKey != VK_SHIFT && 00072 uVKey != VK_CONTROL && 00073 uVKey != VK_CAPITAL && 00074 uVKey != VK_KANA && 00075 uVKey != VK_NUMLOCK && 00076 uVKey != VK_SCROLL) { 00077 // Check if Korea Hanja conversion mode 00078 if(!(pimc->fdwConvMode & IME_CMODE_HANJACONVERT)) { 00079 fCallIme = FALSE; 00080 } 00081 } 00082 else 00083 #endif 00084 // 00085 // Protect IMEs which are unaware of wide virtual keys. 00086 // 00087 if ((BYTE)uVKey == VK_PACKET && 00088 (pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY) == 0) { 00089 00090 if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) { 00091 // 00092 // Since this IME is not ready to accept wide VKey, we should 00093 // truncate it. 00094 // 00095 fTruncateWideVK = TRUE; 00096 } 00097 else { 00098 // 00099 // Hmm, this guy is ANSI IME, and does not declare Wide Vkey awareness. 00100 // Let's guess this one is not ready to accept Wide Vkey, so let's not 00101 // pass it to this guy. 00102 // And if it is opened, we'd better skip this key for safety. 00103 // 00104 fCallIme = FALSE; 00105 if (pInputContext->fOpen) { 00106 fSkipThisKey = TRUE; 00107 } 00108 } 00109 } 00110 00111 if (fCallIme) { 00112 PBYTE pbKeyState = (PBYTE)ImmLocalAlloc(0, 256); 00113 00114 ImmAssert(fSkipThisKey == FALSE); 00115 00116 if (pbKeyState != NULL) { 00117 if (GetKeyboardState(pbKeyState)) { 00118 UINT uVKeyIme = uVKey; 00119 if (fTruncateWideVK) { 00120 uVKeyIme &= 0xffff; 00121 } 00122 if ( (*pImeDpi->pfn.ImeProcessKey)(hIMC, uVKeyIme, lParam, pbKeyState) ) { 00123 // 00124 // if the return value of ImeProcessKey is TRUE, 00125 // it means the key is the one that the ime is 00126 // waiting for. 00127 // 00128 pInputContext->fChgMsg = TRUE; 00129 pInputContext->uSavedVKey = uVKey; 00130 dwReturn |= IPHK_PROCESSBYIME; 00131 } 00132 } 00133 ImmLocalFree(pbKeyState); 00134 } 00135 } 00136 else if (fSkipThisKey) { 00137 dwReturn |= IPHK_SKIPTHISKEY; 00138 ImmAssert((dwReturn & (IPHK_PROCESSBYIME | IPHK_HOTKEY)) == 0); 00139 } 00140 ImmUnlockIMC(hIMC); 00141 } 00142 ImmUnlockImeDpi(pImeDpi); 00143 } 00144 00145 // 00146 // call hotkey handler 00147 // 00148 if (dwHotKeyID != IME_INVALID_HOTKEY && HotKeyIDDispatcher(hWnd, hIMC, hkl, dwHotKeyID)) { 00149 // Backward compat: 00150 // On Japanese system, some applications may want VK_KANJI. 00151 if ((uVKey != VK_KANJI) || 00152 (dwHotKeyID != IME_JHOTKEY_CLOSE_OPEN)) { 00153 dwReturn |= IPHK_HOTKEY; 00154 } 00155 } 00156 00157 // 00158 // some 3.x application doesn't like to see 00159 // VK_PROCESSKEY. 00160 // 00161 if (dwReturn & IPHK_PROCESSBYIME) { 00162 00163 DWORD dwImeCompat = ImmGetAppCompatFlags(hIMC); 00164 00165 if (dwImeCompat & IMECOMPAT_NOVKPROCESSKEY) { 00166 00167 // Korea 3.x application doesn't like to see dummy finalize VK_PROCESSKEY 00168 // and IME hot key. 00169 00170 if ( PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_KOREAN && 00171 ( (uVKey == VK_PROCESSKEY) || (dwReturn & IPHK_HOTKEY) ) ) { 00172 ImmReleaseContext(hWnd, hIMC); 00173 return dwReturn; 00174 } 00175 00176 ImmTranslateMessage(hWnd, WM_KEYDOWN, VK_PROCESSKEY, lParam); 00177 dwReturn &= ~IPHK_PROCESSBYIME; 00178 dwReturn |= IPHK_SKIPTHISKEY; 00179 } 00180 } 00181 ImmReleaseContext(hWnd, hIMC); 00182 00183 return dwReturn; 00184 } 00185 00186 #define TRANSMSGCOUNT 256 00187 00188 /***************************************************************************\ 00189 * ImmTranslateMessage (Called from user\client\ntstubs.c\TranslateMessage()) 00190 * 00191 * Call ImeToAsciiEx() 00192 * 00193 * History: 00194 * 01-Mar-1996 TakaoK Created 00195 \***************************************************************************/ 00196 BOOL ImmTranslateMessage( 00197 HWND hwnd, 00198 UINT message, 00199 WPARAM wParam, 00200 LPARAM lParam) 00201 { 00202 HIMC hImc; 00203 PINPUTCONTEXT pInputContext; 00204 BOOL fReturn = FALSE; 00205 HKL hkl; 00206 PIMEDPI pImeDpi = NULL; 00207 PBYTE pbKeyState; 00208 PTRANSMSG pTransMsg; 00209 PTRANSMSGLIST pTransMsgList; 00210 DWORD dwSize; 00211 UINT uVKey; 00212 INT iNum; 00213 00214 UNREFERENCED_PARAMETER(wParam); 00215 00216 // 00217 // we're interested in only those keyboard messages. 00218 // 00219 switch (message) { 00220 case WM_KEYDOWN: 00221 case WM_KEYUP: 00222 case WM_SYSKEYDOWN: 00223 case WM_SYSKEYUP: 00224 break; 00225 default: 00226 return FALSE; 00227 } 00228 00229 // 00230 // input context is necessary for further handling 00231 // 00232 hImc = ImmGetContext(hwnd); 00233 pInputContext = ImmLockIMC(hImc); 00234 if (pInputContext == NULL) { 00235 ImmReleaseContext(hwnd, hImc); 00236 return FALSE; 00237 } 00238 00239 // 00240 // At first, handle VK_PROCESSKEY generated by IME. 00241 // 00242 if (!pInputContext->fChgMsg) { 00243 00244 if ((iNum=pInputContext->dwNumMsgBuf) != 0) { 00245 00246 pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf); 00247 if (pTransMsg != NULL) { 00248 ImmPostMessages(hwnd, hImc, iNum, pTransMsg); 00249 ImmUnlockIMCC(pInputContext->hMsgBuf); 00250 fReturn = TRUE; 00251 } 00252 00253 pInputContext->dwNumMsgBuf = 0; 00254 } 00255 goto ExitITM; 00256 } 00257 00258 pInputContext->fChgMsg = FALSE; 00259 00260 // 00261 // retrieve the keyboard layout and IME entry points 00262 // 00263 hkl = GetKeyboardLayout( GetWindowThreadProcessId(hwnd, NULL) ); 00264 pImeDpi = ImmLockImeDpi(hkl); 00265 if (pImeDpi == NULL) { 00266 RIPMSG1(RIP_WARNING, "ImmTranslateMessage pImeDpi is NULL(hkl=%x)", hkl); 00267 goto ExitITM; 00268 } 00269 00270 pbKeyState = ImmLocalAlloc(0, 256); 00271 if ( pbKeyState == NULL ) { 00272 RIPMSG0(RIP_WARNING, "ImmTranslateMessage out of memory" ); 00273 goto ExitITM; 00274 } 00275 00276 if (!GetKeyboardState(pbKeyState)) { 00277 RIPMSG0(RIP_WARNING, "ImmTranslateMessage GetKeyboardState() failed" ); 00278 ImmLocalFree( pbKeyState ); 00279 goto ExitITM; 00280 } 00281 00282 // 00283 // Translate the saved vkey into character code if needed 00284 // 00285 uVKey = pInputContext->uSavedVKey; 00286 00287 if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST) { 00288 00289 if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) { 00290 WCHAR wcTemp; 00291 00292 iNum = ToUnicode(pInputContext->uSavedVKey, // virtual-key code 00293 HIWORD(lParam), // scan code 00294 pbKeyState, // key-state array 00295 &wcTemp, // buffer for translated key 00296 1, // size of buffer 00297 0); 00298 if (iNum == 1) { 00299 // 00300 // hi word : unicode character code 00301 // hi byte of lo word : zero 00302 // lo byte of lo word : virtual key 00303 // 00304 uVKey = (uVKey & 0x00ff) | ((UINT)wcTemp << 16); 00305 } 00306 00307 } else { 00308 WORD wTemp = 0; 00309 00310 iNum = ToAsciiEx(pInputContext->uSavedVKey, // virtual-key code 00311 HIWORD(lParam), // scan code 00312 pbKeyState, // key-state array 00313 &wTemp, // buffer for translated key 00314 0, // active-menu flag 00315 hkl); 00316 ImmAssert(iNum <= 2); 00317 if (iNum > 0) { 00318 // 00319 // hi word : should be zero 00320 // hi byte of lo word : character code 00321 // lo byte of lo word : virtual key 00322 // 00323 uVKey = (uVKey & 0x00FF) | ((UINT)wTemp << 8); 00324 00325 if ((BYTE)uVKey == VK_PACKET) { 00326 // 00327 // If ANSI IME is wide vkey aware, its ImeToAsciiEx will receive the uVKey 00328 // as follows: 00329 // 00330 // 31 24 23 16 15 8 7 0 00331 // +----------------+-----------------------------+-------------------+---------------+ 00332 // | 24~31:reserved | 16~23:trailing byte(if any) | 8~15:leading byte | 0~7:VK_PACKET | 00333 // +----------------+-----------------------------+-------------------+---------------+ 00334 // 00335 ImmAssert(pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY); 00336 } 00337 else { 00338 uVKey &= 0xffff; 00339 } 00340 } 00341 } 00342 } 00343 00344 dwSize = FIELD_OFFSET(TRANSMSGLIST, TransMsg) 00345 + TRANSMSGCOUNT * sizeof(TRANSMSG); 00346 00347 pTransMsgList = (PTRANSMSGLIST)ImmLocalAlloc(0, dwSize); 00348 00349 if (pTransMsgList == NULL) { 00350 RIPMSG0(RIP_WARNING, "ImmTranslateMessage out of memory" ); 00351 ImmLocalFree(pbKeyState); 00352 goto ExitITM; 00353 } 00354 00355 pTransMsgList->uMsgCount = TRANSMSGCOUNT; 00356 iNum = (*pImeDpi->pfn.ImeToAsciiEx)(uVKey, 00357 HIWORD(lParam), 00358 pbKeyState, 00359 pTransMsgList, 00360 0, 00361 hImc); 00362 00363 if (iNum > TRANSMSGCOUNT) { 00364 00365 // 00366 // The message buffer is not big enough. IME put messages 00367 // into hMsgBuf in the input context. 00368 // 00369 00370 pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf); 00371 if (pTransMsg != NULL) { 00372 ImmPostMessages(hwnd, hImc, iNum, pTransMsg); 00373 ImmUnlockIMCC(pInputContext->hMsgBuf); 00374 } 00375 00376 #ifdef LATER 00377 // Shouldn't we need this ? 00378 fReturn = TRUE; 00379 #endif 00380 00381 } else if (iNum > 0) { 00382 ImmPostMessages(hwnd, hImc, iNum, &pTransMsgList->TransMsg[0]); 00383 fReturn = TRUE; 00384 } 00385 00386 ImmLocalFree(pbKeyState); 00387 ImmLocalFree(pTransMsgList); 00388 00389 ExitITM: 00390 ImmUnlockImeDpi(pImeDpi); 00391 ImmUnlockIMC(hImc); 00392 ImmReleaseContext(hwnd, hImc); 00393 00394 return fReturn; 00395 } 00396 00397 /***************************************************************************\ 00398 * ImmPostMessages(Called from ImmTranslateMessage() ) 00399 * 00400 * Post IME messages to application. If application is 3.x, messages 00401 * are translated to old IME messages. 00402 * 00403 * History: 00404 * 01-Mar-1996 TakaoK Created 00405 \***************************************************************************/ 00406 00407 VOID 00408 ImmPostMessages( 00409 HWND hWnd, 00410 HIMC hImc, 00411 INT iNum, 00412 PTRANSMSG pTransMsg) 00413 { 00414 INT i; 00415 BOOL fAnsiIME; 00416 PCLIENTIMC pClientImc; 00417 PTRANSMSG pTransMsgTemp, pTransMsgBuf = NULL; 00418 00419 // 00420 // Check if the IME is unicode or not. 00421 // The message buffer contains unicode messages 00422 // if the IME is unicode. 00423 // 00424 pClientImc = ImmLockClientImc(hImc); 00425 if (pClientImc == NULL) { 00426 RIPMSG1(RIP_WARNING, 00427 "ImmPostMessages: Invalid hImc %lx.", hImc); 00428 return; 00429 } 00430 00431 fAnsiIME = ! TestICF(pClientImc, IMCF_UNICODE); 00432 ImmUnlockClientImc(pClientImc); 00433 00434 // 00435 // translate messages to 3.x format if the App's version is 3.x. 00436 // 00437 pTransMsgTemp = pTransMsg; 00438 if (GetClientInfo()->dwExpWinVer < VER40) { 00439 DWORD dwLangId = PRIMARYLANGID( 00440 LANGIDFROMLCID( 00441 GetSystemDefaultLCID())); 00442 if ( (dwLangId == LANG_KOREAN && TransGetLevel(hWnd) == 3) || 00443 dwLangId == LANG_JAPANESE ) { 00444 00445 pTransMsgBuf = ImmLocalAlloc(0, iNum * sizeof(TRANSMSG)); 00446 if (pTransMsgBuf != NULL) { 00447 RtlCopyMemory(pTransMsgBuf, pTransMsg, iNum * sizeof(TRANSMSG)); 00448 iNum = WINNLSTranslateMessage(iNum, 00449 pTransMsgBuf, 00450 hImc, 00451 fAnsiIME, 00452 dwLangId ); 00453 pTransMsgTemp = pTransMsgBuf; 00454 } 00455 } 00456 } 00457 00458 for (i = 0; i < iNum; i++) { 00459 if (fAnsiIME) { 00460 PostMessageA(hWnd, 00461 pTransMsgTemp->message, 00462 pTransMsgTemp->wParam, 00463 pTransMsgTemp->lParam); 00464 } else { 00465 PostMessageW(hWnd, 00466 pTransMsgTemp->message, 00467 pTransMsgTemp->wParam, 00468 pTransMsgTemp->lParam); 00469 } 00470 pTransMsgTemp++; 00471 } 00472 00473 if (pTransMsgBuf != NULL) { 00474 ImmLocalFree(pTransMsgBuf); 00475 } 00476 } 00477 00478 UINT WINNLSTranslateMessage( 00479 INT iNum, // number of messages in the source buffer 00480 PTRANSMSG pTransMsg, // source buffer that contains 4.0 style messages 00481 HIMC hImc, // input context handle 00482 BOOL fAnsi, // TRUE if pdwt contains ANSI messages 00483 DWORD dwLangId ) // language ID ( KOREAN or JAPANESE ) 00484 { 00485 LPINPUTCONTEXT pInputContext; 00486 LPCOMPOSITIONSTRING pCompStr; 00487 UINT uiRet = 0; 00488 00489 pInputContext = ImmLockIMC(hImc); 00490 if (pInputContext == NULL) { 00491 return uiRet; 00492 } 00493 00494 pCompStr = (LPCOMPOSITIONSTRING)ImmLockIMCC( pInputContext->hCompStr ); 00495 00496 if (dwLangId == LANG_KOREAN) { 00497 uiRet = WINNLSTranslateMessageK((UINT)iNum, 00498 pTransMsg, 00499 pInputContext, 00500 pCompStr, 00501 fAnsi ); 00502 } else if ( dwLangId == LANG_JAPANESE ) { 00503 uiRet = WINNLSTranslateMessageJ((UINT)iNum, 00504 pTransMsg, 00505 pInputContext, 00506 pCompStr, 00507 fAnsi ); 00508 } 00509 00510 if (pCompStr != NULL) { 00511 ImmUnlockIMCC(pInputContext->hCompStr); 00512 } 00513 ImmUnlockIMC(hImc); 00514 00515 return uiRet; 00516 } 00517

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