| /* | |
| * 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?\n" ); | |
| return 0; | |
| case WM_IME_KEYUP: | |
| ERR( "Why WM_IME_KEYUP is generated?\n" ); | |
| 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; | |
| } |