/**************************************************************************\ * Module Name: input.c * * Copyright (c) Microsoft Corp. 1996 All Rights Reserved * * IME key input management routines for imm32 dll * * History: * 01-Apr-1996 takaok split from hotkey.c \**************************************************************************/ #include "precomp.h" #pragma hdrstop /***************************************************************************\ * ImmProcessKey (Callback from Win32K.SYS) * * Call ImeProcessKey and IME hotkey handler * * History: * 01-Mar-1996 TakaoK Created \***************************************************************************/ DWORD WINAPI ImmProcessKey( HWND hWnd, HIMC hIMC, HKL hkl, UINT uVKey, LONG lParam, DWORD dwHotKeyID) { PIMEDPI pImeDpi; PINPUTCONTEXT pInputContext; DWORD dwReturn = 0; // // call ImeProcessKey // pImeDpi = ImmLockImeDpi(hkl); if ( pImeDpi != NULL ) { pInputContext = ImmLockIMC( hIMC ); if ( pInputContext != NULL ) { PBYTE pbKeyState; pbKeyState = (PBYTE)LocalAlloc( LMEM_FIXED, 256); if ( pbKeyState != NULL ) { if ( GetKeyboardState( pbKeyState ) ) { if ( (*pImeDpi->pfn.ImeProcessKey)(hIMC, uVKey, 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; } } LocalFree( pbKeyState ); } ImmUnlockIMC( hIMC ); } ImmUnlockImeDpi(pImeDpi); } // // call hotkey handler // if ( dwHotKeyID != IME_INVALID_HOTKEY && HotKeyIDDispatcher( hWnd, hIMC, hkl, dwHotKeyID) ) { dwReturn |= IPHK_HOTKEY; } return dwReturn; } #define TRANSMSGCOUNT 256 /***************************************************************************\ * 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; PBYTE pbKeyState; PDWORD pdwTransBuf; IMEINFOEX iiex; PIMEINFOEX piiex; UINT uVKey; INT iNum; INT MessageCount = TRANSMSGCOUNT; // // 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 ) { PDWORD pdwt; PDWORD pdwt2; pdwt = (PDWORD)ImmLockIMCC(pInputContext->hMsgBuf); if ( pdwt != NULL ) { INT cbBuf = (iNum * 3 ) * sizeof(DWORD); // // LATER : allocating a temporary buffer // is not needed for 4.x application // pdwt2 = LocalAlloc( LMEM_FIXED, cbBuf ); if ( pdwt2 != NULL ) { RtlCopyMemory( pdwt2, pdwt, cbBuf ); ImmPostMessages( hwnd, hImc, iNum, pdwt2); LocalFree( pdwt2 ); fReturn = TRUE; } ImmUnlockIMCC(pInputContext->hMsgBuf); } 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; } // // get IME info // piiex = &iiex; if ( ! ImmGetImeInfoEx(piiex, ImeInfoExKeyboardLayout, (PVOID)&hkl) ) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage ImmGetImeInfoEx failed" ); goto ExitITM; } // // allocate buffers // pbKeyState = LocalAlloc( LMEM_FIXED, 256 ); if ( pbKeyState == NULL ) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage out of memory" ); goto ExitITM; } if ( ! GetKeyboardState( pbKeyState ) ) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage GetKeyboardState() failed" ); LocalFree( pbKeyState ); goto ExitITM; } pdwTransBuf = (PDWORD)LocalAlloc( LMEM_FIXED, (MessageCount*3+1)*sizeof(DWORD)); if ( pdwTransBuf == NULL ) { RIPMSG0(RIP_WARNING, "ImmTranslateMessage out of memory" ); LocalFree( pbKeyState ); goto ExitITM; } // // Translate the saved vkey into character code if needed // uVKey = pInputContext->uSavedVKey; if ( piiex->ImeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST ) { if ( piiex->ImeInfo.fdwProperty & IME_PROP_UNICODE ) { iNum = ToUnicode( pInputContext->uSavedVKey, // virtual-key code HIWORD(lParam), // scan code pbKeyState, // key-state array (LPWSTR)pdwTransBuf, // 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) | ( ((DWORD)(*(PWCHAR)pdwTransBuf)) << 16 ); } } else { iNum = ToAsciiEx( pInputContext->uSavedVKey, // virtual-key code HIWORD(lParam), // scan code pbKeyState, // key-state array (LPWORD)pdwTransBuf, // buffer for translated key 0, // active-menu flag hkl); 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) | ( ((DWORD)(*(PBYTE)pdwTransBuf)) << 8); uVKey &= 0x0000ffff; } } } // // Call IME // *pdwTransBuf = MessageCount; iNum = (*pImeDpi->pfn.ImeToAsciiEx)( uVKey, HIWORD(lParam), pbKeyState, pdwTransBuf, 0, hImc); if ( iNum > MessageCount ) { // // The message buffer is not big enough. IME put messages // into hMsgBuf in the input context. // PDWORD pdwt; pdwt = (PDWORD)ImmLockIMCC(pInputContext->hMsgBuf); if ( pdwt != NULL ) { LocalFree( pdwTransBuf ); pdwTransBuf = LocalAlloc( LMEM_FIXED, iNum * 3 * sizeof(DWORD) ); if ( pdwTransBuf != NULL ) { RtlCopyMemory( pdwTransBuf, pdwt, iNum * 3 * sizeof(DWORD) ); ImmPostMessages( hwnd, hImc, iNum, pdwTransBuf ); } ImmUnlockIMCC(pInputContext->hMsgBuf); } } if ( iNum > 0 ) { ImmPostMessages( hwnd, hImc, iNum, pdwTransBuf+1 ); fReturn = TRUE; } LocalFree( pbKeyState ); LocalFree( pdwTransBuf ); ExitITM: ImmUnlockIMC( hImc ); ImmReleaseContext( hwnd, hImc ); return fReturn; } /***************************************************************************\ * ImmPostMessages(Called from ImmTranslateMessage() ) * * Post IME messages to application. If application is 3.x, messages * are translated to old IME messages. * * History: * 01-Mar-1996 TakaoK Created \***************************************************************************/ VOID ImmPostMessages( HWND hWnd, HIMC hImc, INT iNum, PDWORD pdwt) { INT i; BOOL fAnsi; PCLIENTIMC pClientImc; pClientImc = ImmLockClientImc(hImc); if (pClientImc == NULL) { RIPMSG1(RIP_WARNING, "ImmPostMessages: Invalid hImc %lx.", hImc); return; } fAnsi = !TestICF(pClientImc, IMCF_UNICODE); ImmUnlockClientImc(pClientImc); #ifdef LATER // // translate messages to 3.x format if the App's version is 3.x. // #endif for ( i = 0; i < iNum; i++ ) { if (fAnsi) { PostMessageA( hWnd, (UINT)*pdwt, (WPARAM)*(pdwt+1), (LPARAM)*(pdwt+2) ); } else { PostMessageW( hWnd, (UINT)*pdwt, (WPARAM)*(pdwt+1), (LPARAM)*(pdwt+2) ); } pdwt += 3; } }