BOOL WINAPI ImmLoadIME( HKL hKL) { PIMEDPI pImeDpi; pImeDpi = FindOrLoadImeDpi(hKL); ImmUnlockImeDpi(pImeDpi); return (pImeDpi) ? TRUE : FALSE; }
BOOL WINAPI ImmNotifyIME( HIMC hImc, DWORD dwAction, DWORD dwIndex, DWORD dwValue) { PIMEDPI pImeDpi; BOOL bRet; pImeDpi = ImmLockImeDpi(GetKeyboardLayout(0)); if (pImeDpi == NULL) return FALSE; bRet = (*pImeDpi->pfn.NotifyIME)(hImc, dwAction, dwIndex, dwValue); ImmUnlockImeDpi(pImeDpi); return bRet; }
DWORD WINAPI ImmProcessKey( HWND hWnd, HKL hkl, UINT uVKey, LPARAM lParam, DWORD dwHotKeyID) { HIMC hIMC = ImmGetContext(hWnd); PIMEDPI pImeDpi = ImmLockImeDpi(hkl); DWORD dwReturn = 0; #if DBG if (dwHotKeyID >= IME_KHOTKEY_FIRST && dwHotKeyID <= IME_KHOTKEY_LAST) { TAGMSG2(DBGTAG_IMM, "ImmProcessKey: Kor IME Hotkeys should not come here: dwHotKeyID=%x, uVKey=%x", dwHotKeyID, uVKey); } #endif ImmAssert(dwHotKeyID != IME_KHOTKEY_ENGLISH && dwHotKeyID != IME_KHOTKEY_SHAPE_TOGGLE && dwHotKeyID != IME_KHOTKEY_HANJACONVERT); // // call ImeProcessKey // if (pImeDpi != NULL) { PINPUTCONTEXT pInputContext = ImmLockIMC(hIMC); if (pInputContext != NULL) { BOOLEAN fTruncateWideVK = FALSE; BOOLEAN fCallIme = TRUE; BOOLEAN fSkipThisKey = FALSE; #ifdef LATER // // if the current imc is not open and IME doesn't need // keys when being closed, we don't pass any keyboard // input to ime except hotkey and keys that change // the keyboard status. // if ((pImeDpi->fdwProperty & IME_PROP_NO_KEYS_ON_CLOSE) && !pInputContext->fOpen && uVKey != VK_SHIFT && uVKey != VK_CONTROL && uVKey != VK_CAPITAL && uVKey != VK_KANA && uVKey != VK_NUMLOCK && uVKey != VK_SCROLL) { // Check if Korea Hanja conversion mode if(!(pimc->fdwConvMode & IME_CMODE_HANJACONVERT)) { fCallIme = FALSE; } } else #endif // // Protect IMEs which are unaware of wide virtual keys. // if ((BYTE)uVKey == VK_PACKET && (pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY) == 0) { if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) { // // Since this IME is not ready to accept wide VKey, we should // truncate it. // fTruncateWideVK = TRUE; } else { // // Hmm, this guy is ANSI IME, and does not declare Wide Vkey awareness. // Let's guess this one is not ready to accept Wide Vkey, so let's not // pass it to this guy. // And if it is opened, we'd better skip this key for safety. // fCallIme = FALSE; if (pInputContext->fOpen) { fSkipThisKey = TRUE; } } } if (fCallIme) { PBYTE pbKeyState = (PBYTE)ImmLocalAlloc(0, 256); ImmAssert(fSkipThisKey == FALSE); if (pbKeyState != NULL) { if (GetKeyboardState(pbKeyState)) { UINT uVKeyIme = uVKey; if (fTruncateWideVK) { uVKeyIme &= 0xffff; } if ( (*pImeDpi->pfn.ImeProcessKey)(hIMC, uVKeyIme, lParam, pbKeyState) ) { // // if the return value of ImeProcessKey is TRUE, // it means the key is the one that the ime is // waiting for. // pInputContext->fChgMsg = TRUE; pInputContext->uSavedVKey = uVKey; dwReturn |= IPHK_PROCESSBYIME; } } ImmLocalFree(pbKeyState); } } else if (fSkipThisKey) { dwReturn |= IPHK_SKIPTHISKEY; ImmAssert((dwReturn & (IPHK_PROCESSBYIME | IPHK_HOTKEY)) == 0); } ImmUnlockIMC(hIMC); } ImmUnlockImeDpi(pImeDpi); } // // call hotkey handler // if (dwHotKeyID != IME_INVALID_HOTKEY && HotKeyIDDispatcher(hWnd, hIMC, hkl, dwHotKeyID)) { // Backward compat: // On Japanese system, some applications may want VK_KANJI. if ((uVKey != VK_KANJI) || (dwHotKeyID != IME_JHOTKEY_CLOSE_OPEN)) { dwReturn |= IPHK_HOTKEY; } } // // some 3.x application doesn't like to see // VK_PROCESSKEY. // if (dwReturn & IPHK_PROCESSBYIME) { DWORD dwImeCompat = ImmGetAppCompatFlags(hIMC); if (dwImeCompat & IMECOMPAT_NOVKPROCESSKEY) { // Korea 3.x application doesn't like to see dummy finalize VK_PROCESSKEY // and IME hot key. if ( PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_KOREAN && ( (uVKey == VK_PROCESSKEY) || (dwReturn & IPHK_HOTKEY) ) ) { ImmReleaseContext(hWnd, hIMC); return dwReturn; } ImmTranslateMessage(hWnd, WM_KEYDOWN, VK_PROCESSKEY, lParam); dwReturn &= ~IPHK_PROCESSBYIME; dwReturn |= IPHK_SKIPTHISKEY; } } ImmReleaseContext(hWnd, hIMC); return dwReturn; }
/***************************************************************************\ * ImmTranslateMessage (Called from user\client\ntstubs.c\TranslateMessage()) * * Call ImeToAsciiEx() * * History: * 01-Mar-1996 TakaoK Created \***************************************************************************/ BOOL ImmTranslateMessage( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HIMC hImc; PINPUTCONTEXT pInputContext; BOOL fReturn = FALSE; HKL hkl; PIMEDPI pImeDpi = NULL; PBYTE pbKeyState; PTRANSMSG pTransMsg; PTRANSMSGLIST pTransMsgList; DWORD dwSize; UINT uVKey; INT iNum; UNREFERENCED_PARAMETER(wParam); // // we're interested in only those keyboard messages. // switch (message) { case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: break; default: return FALSE; } // // input context is necessary for further handling // hImc = ImmGetContext(hwnd); pInputContext = ImmLockIMC(hImc); if (pInputContext == NULL) { ImmReleaseContext(hwnd, hImc); return FALSE; } // // At first, handle VK_PROCESSKEY generated by IME. // if (!pInputContext->fChgMsg) { if ((iNum=pInputContext->dwNumMsgBuf) != 0) { pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf); if (pTransMsg != NULL) { ImmPostMessages(hwnd, hImc, iNum, pTransMsg); ImmUnlockIMCC(pInputContext->hMsgBuf); fReturn = TRUE; } pInputContext->dwNumMsgBuf = 0; } goto ExitITM; } pInputContext->fChgMsg = FALSE; // // retrieve the keyboard layout and IME entry points // hkl = GetKeyboardLayout( GetWindowThreadProcessId(hwnd, NULL) ); pImeDpi = ImmLockImeDpi(hkl); if (pImeDpi == NULL) { RIPMSG1(RIP_WARNING, "ImmTranslateMessage pImeDpi is NULL(hkl=%x)", hkl); goto ExitITM; } pbKeyState = ImmLocalAlloc(0, 256); if ( pbKeyState == NULL ) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage out of memory" ); goto ExitITM; } if (!GetKeyboardState(pbKeyState)) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage GetKeyboardState() failed" ); ImmLocalFree( pbKeyState ); goto ExitITM; } // // Translate the saved vkey into character code if needed // uVKey = pInputContext->uSavedVKey; if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST) { if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) { WCHAR wcTemp; iNum = ToUnicode(pInputContext->uSavedVKey, // virtual-key code HIWORD(lParam), // scan code pbKeyState, // key-state array &wcTemp, // buffer for translated key 1, // size of buffer 0); if (iNum == 1) { // // hi word : unicode character code // hi byte of lo word : zero // lo byte of lo word : virtual key // uVKey = (uVKey & 0x00ff) | ((UINT)wcTemp << 16); } } else { WORD wTemp = 0; iNum = ToAsciiEx(pInputContext->uSavedVKey, // virtual-key code HIWORD(lParam), // scan code pbKeyState, // key-state array &wTemp, // buffer for translated key 0, // active-menu flag hkl); ImmAssert(iNum <= 2); if (iNum > 0) { // // hi word : should be zero // hi byte of lo word : character code // lo byte of lo word : virtual key // uVKey = (uVKey & 0x00FF) | ((UINT)wTemp << 8); if ((BYTE)uVKey == VK_PACKET) { // // If ANSI IME is wide vkey aware, its ImeToAsciiEx will receive the uVKey // as follows: // // 31 24 23 16 15 8 7 0 // +----------------+-----------------------------+-------------------+---------------+ // | 24~31:reserved | 16~23:trailing byte(if any) | 8~15:leading byte | 0~7:VK_PACKET | // +----------------+-----------------------------+-------------------+---------------+ // ImmAssert(pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY); } else { uVKey &= 0xffff; } } } } dwSize = FIELD_OFFSET(TRANSMSGLIST, TransMsg) + TRANSMSGCOUNT * sizeof(TRANSMSG); pTransMsgList = (PTRANSMSGLIST)ImmLocalAlloc(0, dwSize); if (pTransMsgList == NULL) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage out of memory" ); ImmLocalFree(pbKeyState); goto ExitITM; } pTransMsgList->uMsgCount = TRANSMSGCOUNT; iNum = (*pImeDpi->pfn.ImeToAsciiEx)(uVKey, HIWORD(lParam), pbKeyState, pTransMsgList, 0, hImc); if (iNum > TRANSMSGCOUNT) { // // The message buffer is not big enough. IME put messages // into hMsgBuf in the input context. // pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf); if (pTransMsg != NULL) { ImmPostMessages(hwnd, hImc, iNum, pTransMsg); ImmUnlockIMCC(pInputContext->hMsgBuf); } #ifdef LATER // Shouldn't we need this ? fReturn = TRUE; #endif } else if (iNum > 0) { ImmPostMessages(hwnd, hImc, iNum, &pTransMsgList->TransMsg[0]); fReturn = TRUE; } ImmLocalFree(pbKeyState); ImmLocalFree(pTransMsgList); ExitITM: ImmUnlockImeDpi(pImeDpi); ImmUnlockIMC(hImc); ImmReleaseContext(hwnd, hImc); return fReturn; }
LRESULT WINAPI ImmEscapeW( HKL hKL, HIMC hImc, UINT uSubFunc, LPVOID lpData) { PIMEDPI pImeDpi; LRESULT lRet = 0; pImeDpi = FindOrLoadImeDpi(hKL); if (pImeDpi == NULL) { RIPMSG0(RIP_WARNING, "ImmEscapeW: no pImeDpi entry."); return lRet; } if ((pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || lpData == NULL) { /* * Doesn't need W/A conversion. Calls directly to IME to * bring up the configuration dialogbox. */ lRet = (*pImeDpi->pfn.ImeEscape)(hImc, uSubFunc, lpData); ImmUnlockImeDpi(pImeDpi); return lRet; } /* * Unicode caller, ANSI IME. Needs W/A conversion depending on * uSubFunc. */ switch (uSubFunc) { case IME_ESC_GET_EUDC_DICTIONARY: case IME_ESC_IME_NAME: { CHAR szData[IME_T_EUDC_DIC_SIZE]; INT i; lRet = ImmEscapeA(hKL, hImc, uSubFunc, (LPVOID)szData); if (lRet != 0) { try { i = MultiByteToWideChar(CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)szData, // src (INT)strlen(szData), (LPWSTR)lpData, // dest (INT)IME_T_EUDC_DIC_SIZE); ((LPWSTR)lpData)[i] = L'\0'; } except (EXCEPTION_EXECUTE_HANDLER) { lRet = 0; } } break; } case IME_ESC_SET_EUDC_DICTIONARY: case IME_ESC_HANJA_MODE: { CHAR szData[IME_T_EUDC_DIC_SIZE]; BOOL bUDC; INT i; i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)lpData, // src (INT)wcslen(lpData), (LPSTR)szData, // dest (INT)sizeof(szData), (LPSTR)NULL, (LPBOOL)&bUDC); szData[i] = '\0'; lRet = ImmEscapeA(hKL, hImc, uSubFunc, (LPVOID)szData); break; } case IME_ESC_SEQUENCE_TO_INTERNAL: { CHAR szData[4]; WCHAR wszData[4]; INT i = 0; lRet = ImmEscapeA(hKL, hImc, uSubFunc, lpData); if (HIBYTE(LOWORD(lRet))) szData[i++] = HIBYTE(LOWORD(lRet)); if (LOBYTE(LOWORD(lRet))) szData[i++] = LOBYTE(LOWORD(lRet)); i = MultiByteToWideChar(CP_ACP, (DWORD)MB_PRECOMPOSED, (LPSTR)szData, // src i, (LPWSTR)wszData, // dest (INT)sizeof(wszData)/sizeof(WCHAR)); switch (i) { case 1: lRet = MAKELONG(wszData[0], 0); break; case 2: lRet = MAKELONG(wszData[1], wszData[0]); break; default: lRet = 0; break; } break; } default: lRet = ImmEscapeA(hKL, hImc, uSubFunc, lpData); break; } ImmUnlockImeDpi(pImeDpi); return lRet; }
BOOL WINAPI ImmConfigureIMEW( HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) { PWND pWnd; PIMEDPI pImeDpi; BOOL fRet = FALSE; if ((pWnd = ValidateHwnd(hWnd)) == (PWND)NULL) { RIPMSG1(RIP_WARNING, "ImmConfigureIMEA: invalid window handle %x", hWnd); return FALSE; } if (!TestWindowProcess(pWnd)) { RIPMSG1(RIP_WARNING, "ImmConfigureIMEA: hWnd=%lx belongs to different process!", hWnd); return FALSE; } pImeDpi = FindOrLoadImeDpi(hKL); if (pImeDpi == NULL) { RIPMSG0(RIP_WARNING, "ImmConfigureIMEA: no pImeDpi entry."); return FALSE; } if ((pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || lpData == NULL) { /* * Doesn't need A/W conversion. Calls directly to IME to * bring up the configuration dialogbox. */ fRet = (*pImeDpi->pfn.ImeConfigure)(hKL, hWnd, dwMode, lpData); ImmUnlockImeDpi(pImeDpi); return fRet; } /* * Unicode caller, ANSI IME. Needs A/W conversion on lpData when * dwMode == IME_CONFIG_REGISTERWORD. In this case, lpData points * to a structure of REGISTERWORDW. */ switch (dwMode) { case IME_CONFIG_REGISTERWORD: { LPREGISTERWORDW lpRegisterWordW; REGISTERWORDA RegisterWordA; LPVOID lpBuffer; ULONG cbBuffer; BOOL bUDC; INT i; lpRegisterWordW = (LPREGISTERWORDW)lpData; cbBuffer = 0; lpBuffer = NULL; if (lpRegisterWordW->lpReading != NULL) cbBuffer += wcslen(lpRegisterWordW->lpReading) + 1; if (lpRegisterWordW->lpWord != NULL) cbBuffer += wcslen(lpRegisterWordW->lpWord) + 1; if (cbBuffer != 0) { cbBuffer *= sizeof(WCHAR); if ((lpBuffer = ImmLocalAlloc(0, cbBuffer)) == NULL) { RIPMSG0(RIP_WARNING, "ImmConfigureIMEW: memory failure."); break; } } if (lpRegisterWordW->lpReading != NULL) { RegisterWordA.lpReading = lpBuffer; i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)lpRegisterWordW->lpReading, (INT)wcslen(lpRegisterWordW->lpReading), (LPSTR)RegisterWordA.lpReading, (INT)cbBuffer, (LPSTR)NULL, (LPBOOL)&bUDC); RegisterWordA.lpReading[i] = '\0'; cbBuffer -= (i * sizeof(CHAR)); } else { RegisterWordA.lpReading = NULL; } if (lpRegisterWordW->lpWord != NULL) { if (RegisterWordA.lpReading != NULL) RegisterWordA.lpWord = &RegisterWordA.lpReading[i+1]; else RegisterWordA.lpWord = lpBuffer; i = WideCharToMultiByte( CP_ACP, (DWORD)0, (LPWSTR)lpRegisterWordW->lpWord, (INT)wcslen(lpRegisterWordW->lpWord), (LPSTR)RegisterWordA.lpWord, (INT)cbBuffer, (LPSTR)NULL, (LPBOOL)&bUDC); RegisterWordA.lpWord[i] = '\0'; } else RegisterWordA.lpWord = NULL; fRet = ImmConfigureIMEA(hKL, hWnd, dwMode, &RegisterWordA); if (lpBuffer != NULL) ImmLocalFree(lpBuffer); break; } default: fRet = ImmConfigureIMEA(hKL, hWnd, dwMode, lpData); break; } ImmUnlockImeDpi(pImeDpi); return fRet; }
HWND WINAPI ImmCreateSoftKeyboard( UINT uType, HWND hOwner, int x, int y) { static BOOL fFirstSoftKeyboard = TRUE; PIMEDPI pImeDpi; DWORD fdwUICaps; int nWidth, nHeight; HKL hCurrentKL; UINT i; HWND hSKWnd; RECT rcWork; SIZE szWork; if (!uType) { return (HWND)NULL; } if (uType >= sizeof(SoftKeyboardClassName) / sizeof(LPWSTR)) { return (HWND)NULL; } hCurrentKL = GetKeyboardLayout(0); pImeDpi = ImmLockImeDpi(hCurrentKL); if (pImeDpi == NULL) { RIPMSG1(RIP_WARNING, "ImmCreateSoftKeyboard, pImeDpi = NULL (hkl = 0x%x).\n", hCurrentKL); return (HWND)NULL; } fdwUICaps = pImeDpi->ImeInfo.fdwUICaps; ImmUnlockImeDpi(pImeDpi); if (!(fdwUICaps & UI_CAP_SOFTKBD)) { return (HWND)NULL; } if (fFirstSoftKeyboard) { if (!GetNearestMonitorSize(hOwner, &rcWork)) { // failed return NULL; } for (i = 0; i < sizeof(guScanCode) / sizeof(UINT); i++) { guScanCode[i] = MapVirtualKey(i, 0); } // LATER: have to consider the dynamic resolution change szWork.cx = rcWork.right - rcWork.left; UserAssert(szWork.cx > UI_MARGIN * 2); szWork.cy = rcWork.bottom - rcWork.top; UserAssert(szWork.cy > UI_MARGIN * 2); gptRaiseEdge.x = GetSystemMetrics(SM_CXEDGE) + GetSystemMetrics(SM_CXBORDER); gptRaiseEdge.y = GetSystemMetrics(SM_CYEDGE) + GetSystemMetrics(SM_CYBORDER); fFirstSoftKeyboard = FALSE; } if (!RegisterSoftKeyboard(uType)) { return (HWND)NULL; } GetSoftKeyboardDimension(uType, &nWidth, &nHeight); // boundry check if (x < 0) { x = 0; } else if (x + nWidth > szWork.cx) { x = szWork.cx - nWidth; } if (y < 0) { y = 0; } else if (y + nHeight > szWork.cy) { y = szWork.cy - nHeight; } switch (uType) { case SOFTKEYBOARD_TYPE_T1: hSKWnd = CreateWindowEx(0, SoftKeyboardClassName[uType], (LPCWSTR)NULL, WS_POPUP|WS_DISABLED, x, y, nWidth, nHeight, (HWND)hOwner, (HMENU)NULL, ghInst, NULL); break; case SOFTKEYBOARD_TYPE_C1: hSKWnd = CreateWindowEx(WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME, SoftKeyboardClassName[uType], (LPCWSTR)NULL, WS_POPUP|WS_DISABLED|WS_BORDER, x, y, nWidth, nHeight, (HWND)hOwner, (HMENU)NULL, ghInst, NULL); break; default: return (HWND)NULL; } ShowWindow(hSKWnd, SW_HIDE); UpdateWindow(hSKWnd); return (hSKWnd); }