/* * Implementation of the 'IME window' class * * Copyright 2000 Hidenori Takeshima * * * FIXME: * - handle all messages. * - handle all notifications. */ #include "config.h" #include "winbase.h" #include "windef.h" #include "wingdi.h" #include "winuser.h" #include "winerror.h" #include "immddk.h" #include "debugtools.h" DEFAULT_DEBUG_CHANNEL(imm); #include "imm_private.h" #define IMM32_CONVERSION_BUFSIZE 200 static CHAR IMM32_szIMEClass[] = "IME"; static CHAR IMM32_szIMEWindowName[] = "Default IME"; typedef struct { HWND hwndSelf; HWND hwndActive; DWORD dwBufUsed; union { CHAR A[IMM32_CONVERSION_BUFSIZE]; WCHAR W[IMM32_CONVERSION_BUFSIZE]; } buf; } IMM32_IMEWNDPARAM; static BOOL IMM32_IsUIMessage( UINT nMsg ); static LRESULT IMM32_IMEWnd_WM_KEYDOWN( IMM32_IMEWNDPARAM* pParam, WPARAM wParam, LPARAM lParam ) { BYTE bKeyState[ 256 ]; DWORD dwTransBufSize; UINT nNumOfMsg; LRESULT lr; HIMC hIMC; IMM32_IMC* pIMC; const IMM32_IMEKL* pkl; if ( pParam->hwndActive == (HWND)NULL ) return 0; /* get context -> get pkl. */ hIMC = ImmGetContext( pParam->hwndActive ); if ( hIMC == NULLIMC ) return 0; pIMC = IMM32_LockIMC( hIMC ); if ( pIMC == NULL ) { ImmReleaseContext( pParam->hwndActive, hIMC ); return 0; } pkl = pIMC->pkl; GetKeyboardState( bKeyState ); if ( !pkl->handlers.pImeProcessKey ( hIMC, wParam, lParam, bKeyState ) ) { lr = SendMessageA( pParam->hwndActive, WM_IME_KEYDOWN, wParam, lParam ); goto end; } dwTransBufSize = 0; nNumOfMsg = pkl->handlers.pImeToAsciiEx ( wParam, (lParam>>16)&0xff, bKeyState, &dwTransBufSize, 0, /* FIXME!!! - 1 if a menu is active */ hIMC ); /* FIXME - process generated messages */ /* I cannot use ImmGenerateMessage() since * the IME window must handle generated messages. */ /* NOTE - I must check pkl->fUnicode. */ FIXME( "%d messages generated.\n", nNumOfMsg ); lr = 0; end: IMM32_UnlockIMC( hIMC ); ImmReleaseContext( pParam->hwndActive, hIMC ); return lr; } static LRESULT IMM32_IMEWnd_WM_KEYUP( IMM32_IMEWNDPARAM* pParam, WPARAM wParam, LPARAM lParam ) { BYTE bKeyState[ 256 ]; LRESULT lr; HIMC hIMC; IMM32_IMC* pIMC; const IMM32_IMEKL* pkl; if ( pParam->hwndActive == (HWND)NULL ) return 0; /* get context -> get pkl. */ hIMC = ImmGetContext( pParam->hwndActive ); if ( hIMC == NULLIMC ) return 0; pIMC = IMM32_LockIMC( hIMC ); if ( pIMC == NULL ) { ImmReleaseContext( pParam->hwndActive, hIMC ); return 0; } pkl = pIMC->pkl; GetKeyboardState( bKeyState ); if ( !pkl->handlers.pImeProcessKey ( hIMC, wParam, lParam, bKeyState ) ) { lr = SendMessageA( pParam->hwndActive, WM_IME_KEYUP, wParam, lParam ); goto end; } lr = 0; end: IMM32_UnlockIMC( hIMC ); ImmReleaseContext( pParam->hwndActive, hIMC ); return lr; } static LRESULT CALLBACK IMM32_IMEWndProc( HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam ) { IMM32_IMEWNDPARAM* pParam = (IMM32_IMEWNDPARAM*)GetWindowLongA( hwnd, 0L ); if ( nMsg == WM_CREATE ) { pParam = (IMM32_IMEWNDPARAM*)IMM32_HeapAlloc( HEAP_ZERO_MEMORY, sizeof(IMM32_IMEWNDPARAM) ); if ( pParam == NULL ) return -1L; SetWindowLongA( hwnd, 0L, (LONG)pParam ); /* Initialize pParam. */ pParam->hwndSelf = hwnd; pParam->hwndActive = (HWND)NULL; pParam->dwBufUsed = 0; return 0; } else if ( nMsg == WM_DESTROY ) { /* Uninitialize pParam. */ IMM32_HeapFree( pParam ); SetWindowLongA( hwnd, 0L, (LONG)NULL ); return 0; } if ( pParam == NULL ) { if ( IMM32_IsUIMessage( nMsg ) ) return 0; return DefWindowProcA( hwnd, nMsg, wParam, lParam ); } /* FIXME - handle all messages. */ /* FIXME - handle all notifications. */ switch ( nMsg ) { case WM_KEYDOWN: return IMM32_IMEWnd_WM_KEYDOWN( pParam, wParam, lParam ); case WM_KEYUP: return IMM32_IMEWnd_WM_KEYUP( pParam, wParam, lParam ); case WM_IME_KEYDOWN: ERR( "Why WM_IME_KEYDOWN is generated?" ); return 0; case WM_IME_KEYUP: ERR( "Why WM_IME_KEYUP is generated?" ); return 0; case WM_IME_CHAR: FIXME( "ignore WM_IME_CHAR - wParam %08x, lParam %08lx.\n", wParam, lParam ); return 0; case WM_CHAR: /* TranslateMessage don't support IME HKL. - FIXME? */ FIXME( "ignore WM_CHAR - wParam %08x, lParam %08lx.\n", wParam, lParam ); return 0; case WM_IME_CONTROL: case WM_IME_REQUEST: case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY: case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: case 0x287: /* What is this message? IMM32.DLL returns TRUE. */ FIXME( "handle message %08x\n", nMsg ); return 0; } return DefWindowProcA( hwnd, nMsg, wParam, lParam ); } /*********************************************************************** * IMM32_RegisterClass (internal) */ BOOL IMM32_RegisterIMEWndClass( HINSTANCE hInstDLL ) { WNDCLASSA wc; /* SDK says the "IME" window class is a system global class. */ wc.style = CS_GLOBALCLASS; wc.lpfnWndProc = IMM32_IMEWndProc; wc.cbClsExtra = 0; wc.cbWndExtra = sizeof(LONG); wc.hInstance = hInstDLL; wc.hIcon = (HICON)NULL; wc.hCursor = LoadCursorA((HINSTANCE)NULL,IDC_ARROWA); wc.hbrBackground = (HBRUSH)NULL; wc.lpszMenuName = NULL; wc.lpszClassName = IMM32_szIMEClass; if ( !RegisterClassA( &wc ) ) return FALSE; return TRUE; } /*********************************************************************** * IMM32_UnregisterClass (internal) */ void IMM32_UnregisterIMEWndClass( HINSTANCE hInstDLL ) { (void)UnregisterClassA( IMM32_szIMEClass, hInstDLL ); } /*********************************************************************** * IMM32_CreateDefaultIMEWnd (internal) */ HWND IMM32_CreateDefaultIMEWnd( void ) { return CreateWindowExA( 0L, IMM32_szIMEClass, IMM32_szIMEWindowName, WS_POPUP | WS_CLIPSIBLINGS | WS_OVERLAPPED, 0, 0, 0, 0, (HWND)NULL, (HMENU)NULL, (HINSTANCE)GetModuleHandleA(NULL), NULL ); } static BOOL IMM32_IsUIMessage( UINT nMsg ) { switch ( nMsg ) { case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY: case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: case 0x287: /* What is this message? IMM32.DLL returns TRUE. */ return TRUE; } return FALSE; } /*********************************************************************** * ImmIsUIMessageA (IMM32.@) */ BOOL WINAPI ImmIsUIMessageA( HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam) { TRACE("(0x%08x, %d, %d, %ld)\n", hwndIME, msg, wParam, lParam); if ( !IMM32_IsUIMessage( msg ) ) return FALSE; if ( hwndIME == (HWND)NULL ) return TRUE; switch ( msg ) { case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY: case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: SendMessageA( hwndIME, msg, wParam, lParam ); break; case 0x287: /* What is this message? */ FIXME("(0x%08x, %d, %d, %ld) - unknown message 0x287.\n", hwndIME, msg, wParam, lParam); SendMessageA( hwndIME, msg, wParam, lParam ); break; } return TRUE; } /*********************************************************************** * ImmIsUIMessageW (IMM32.@) */ BOOL WINAPI ImmIsUIMessageW( HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam) { TRACE("(0x%08x, %d, %d, %ld)\n", hwndIME, msg, wParam, lParam); if ( !IMM32_IsUIMessage( msg ) ) return FALSE; if ( hwndIME == (HWND)NULL ) return TRUE; switch ( msg ) { case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION: case WM_IME_COMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY: case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: SendMessageW( hwndIME, msg, wParam, lParam ); break; case 0x287: /* What is this message? */ FIXME("(0x%08x, %d, %d, %ld) - unknown message 0x287.\n", hwndIME, msg, wParam, lParam); SendMessageW( hwndIME, msg, wParam, lParam ); break; } return TRUE; }