mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
327 lines
9.7 KiB
327 lines
9.7 KiB
/**************************************************************************\
|
|
* 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;
|
|
}
|
|
}
|