|  | /* | 
|  | * IMM32 library | 
|  | * | 
|  | * Copyright 1998 Patrik Stridvall | 
|  | * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #include <stdarg.h> | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "wingdi.h" | 
|  | #include "winuser.h" | 
|  | #include "winerror.h" | 
|  | #include "wine/debug.h" | 
|  | #include "imm.h" | 
|  | #include "ddk/imm.h" | 
|  | #include "winnls.h" | 
|  |  | 
|  | WINE_DEFAULT_DEBUG_CHANNEL(imm); | 
|  |  | 
|  | #define FROM_IME 0xcafe1337 | 
|  |  | 
|  | static void (*pX11DRV_ForceXIMReset)(HWND); | 
|  |  | 
|  | typedef struct tagIMCCInternal | 
|  | { | 
|  | DWORD dwLock; | 
|  | DWORD dwSize; | 
|  | } IMCCInternal; | 
|  |  | 
|  | typedef struct tagInputContextData | 
|  | { | 
|  | BOOL            bInternalState; | 
|  | BOOL            bRead; | 
|  | BOOL            bInComposition; | 
|  | HFONT           textfont; | 
|  |  | 
|  | DWORD           dwLock; | 
|  | INPUTCONTEXT    IMC; | 
|  | } InputContextData; | 
|  |  | 
|  | static InputContextData *root_context = NULL; | 
|  | static HWND hwndDefault = NULL; | 
|  | static HANDLE hImeInst; | 
|  | static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0}; | 
|  | static ATOM atIMEClass = 0; | 
|  |  | 
|  | /* MSIME messages */ | 
|  | static UINT WM_MSIME_SERVICE; | 
|  | static UINT WM_MSIME_RECONVERTOPTIONS; | 
|  | static UINT WM_MSIME_MOUSE; | 
|  | static UINT WM_MSIME_RECONVERTREQUEST; | 
|  | static UINT WM_MSIME_RECONVERT; | 
|  | static UINT WM_MSIME_QUERYPOSITION; | 
|  | static UINT WM_MSIME_DOCUMENTFEED; | 
|  |  | 
|  | /* | 
|  | * prototypes | 
|  | */ | 
|  | static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, | 
|  | LPARAM lParam); | 
|  | static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable); | 
|  | static void ImmInternalPostIMEMessage(UINT, WPARAM, LPARAM); | 
|  | static void ImmInternalSetOpenStatus(BOOL fOpen); | 
|  | static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len); | 
|  |  | 
|  | static VOID IMM_PostResult(InputContextData *data) | 
|  | { | 
|  | unsigned int i; | 
|  | LPCOMPOSITIONSTRING compstr; | 
|  | LPBYTE compdata; | 
|  | LPWSTR ResultStr; | 
|  | HIMCC newCompStr; | 
|  |  | 
|  | TRACE("Posting result as IME_CHAR\n"); | 
|  | compdata = ImmLockIMCC(root_context->IMC.hCompStr); | 
|  | compstr = (LPCOMPOSITIONSTRING)compdata; | 
|  | ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset); | 
|  |  | 
|  | for (i = 0; i < compstr->dwResultStrLen; i++) | 
|  | ImmInternalPostIMEMessage (WM_IME_CHAR, ResultStr[i], 1); | 
|  |  | 
|  | ImmUnlockIMCC(root_context->IMC.hCompStr); | 
|  |  | 
|  | /* clear the buffer */ | 
|  | newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0); | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | root_context->IMC.hCompStr = newCompStr; | 
|  | } | 
|  |  | 
|  | static void IMM_Register(void) | 
|  | { | 
|  | WNDCLASSW wndClass; | 
|  | ZeroMemory(&wndClass, sizeof(WNDCLASSW)); | 
|  | wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW; | 
|  | wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc; | 
|  | wndClass.cbClsExtra = 0; | 
|  | wndClass.cbWndExtra = 0; | 
|  | wndClass.hInstance = hImeInst; | 
|  | wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); | 
|  | wndClass.hIcon = NULL; | 
|  | wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1); | 
|  | wndClass.lpszMenuName   = 0; | 
|  | wndClass.lpszClassName = WC_IMECLASSNAME; | 
|  | atIMEClass = RegisterClassW(&wndClass); | 
|  | } | 
|  |  | 
|  | static void IMM_Unregister(void) | 
|  | { | 
|  | if (atIMEClass) { | 
|  | UnregisterClassW(WC_IMECLASSNAME, NULL); | 
|  | } | 
|  | } | 
|  |  | 
|  | static void IMM_RegisterMessages(void) | 
|  | { | 
|  | WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); | 
|  | WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions"); | 
|  | WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); | 
|  | WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); | 
|  | WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); | 
|  | WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); | 
|  | WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); | 
|  | } | 
|  |  | 
|  |  | 
|  | BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) | 
|  | { | 
|  | HMODULE x11drv; | 
|  |  | 
|  | TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved); | 
|  | switch (fdwReason) | 
|  | { | 
|  | case DLL_PROCESS_ATTACH: | 
|  | DisableThreadLibraryCalls(hInstDLL); | 
|  | hImeInst = hInstDLL; | 
|  | IMM_RegisterMessages(); | 
|  | x11drv = GetModuleHandleA("winex11.drv"); | 
|  | if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset"); | 
|  | break; | 
|  | case DLL_PROCESS_DETACH: | 
|  | if (hwndDefault) | 
|  | { | 
|  | DestroyWindow(hwndDefault); | 
|  | hwndDefault = 0; | 
|  | } | 
|  | IMM_Unregister(); | 
|  | break; | 
|  | } | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* for posting messages as the IME */ | 
|  | static void ImmInternalPostIMEMessage(UINT msg, WPARAM wParam, LPARAM lParam) | 
|  | { | 
|  | HWND target = GetFocus(); | 
|  | if (!target) | 
|  | PostMessageW(root_context->IMC.hWnd,msg,wParam,lParam); | 
|  | else | 
|  | PostMessageW(target, msg, wParam, lParam); | 
|  | } | 
|  |  | 
|  | static LRESULT ImmInternalSendIMENotify(WPARAM notify, LPARAM lParam) | 
|  | { | 
|  | HWND target; | 
|  |  | 
|  | target = root_context->IMC.hWnd; | 
|  | if (!target) target = GetFocus(); | 
|  |  | 
|  | if (target) | 
|  | return SendMessageW(target, WM_IME_NOTIFY, notify, lParam); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | static void ImmInternalSetOpenStatus(BOOL fOpen) | 
|  | { | 
|  | TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED"); | 
|  |  | 
|  | root_context->IMC.fOpen = fOpen; | 
|  | root_context->bInternalState = fOpen; | 
|  |  | 
|  | if (fOpen == FALSE) | 
|  | { | 
|  | ShowWindow(hwndDefault,SW_HIDE); | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | root_context->IMC.hCompStr = NULL; | 
|  | } | 
|  | else | 
|  | ShowWindow(hwndDefault, SW_SHOWNOACTIVATE); | 
|  |  | 
|  | ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0); | 
|  | } | 
|  |  | 
|  | static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset, | 
|  | LPBYTE target, LPBYTE source, DWORD* lenParam, | 
|  | DWORD* offsetParam, BOOL wchars ) | 
|  | { | 
|  | if (origLen > 0 && origOffset > 0) | 
|  | { | 
|  | int truelen = origLen; | 
|  | if (wchars) | 
|  | truelen *= sizeof(WCHAR); | 
|  |  | 
|  | memcpy(&target[currentOffset], &source[origOffset], truelen); | 
|  |  | 
|  | *lenParam = origLen; | 
|  | *offsetParam = currentOffset; | 
|  | currentOffset += truelen; | 
|  | } | 
|  | return currentOffset; | 
|  | } | 
|  |  | 
|  | static HIMCC updateCompStr(HIMCC old, LPWSTR compstr, DWORD len) | 
|  | { | 
|  | /* we need to make sure the CompStr, CompClaus and CompAttr fields are all | 
|  | * set and correct */ | 
|  | int needed_size; | 
|  | HIMCC   rc; | 
|  | LPBYTE newdata = NULL; | 
|  | LPBYTE olddata = NULL; | 
|  | LPCOMPOSITIONSTRING new_one; | 
|  | LPCOMPOSITIONSTRING lpcs = NULL; | 
|  | INT current_offset = 0; | 
|  |  | 
|  | TRACE("%s, %i\n",debugstr_wn(compstr,len),len); | 
|  |  | 
|  | if (old != NULL) | 
|  | { | 
|  | olddata = ImmLockIMCC(old); | 
|  | lpcs = (LPCOMPOSITIONSTRING)olddata; | 
|  | } | 
|  |  | 
|  | needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) + | 
|  | len + sizeof(DWORD) * 2; | 
|  |  | 
|  | if (lpcs != NULL) | 
|  | { | 
|  | needed_size += lpcs->dwCompReadAttrLen; | 
|  | needed_size += lpcs->dwCompReadClauseLen; | 
|  | needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD); | 
|  | needed_size += lpcs->dwResultReadClauseLen; | 
|  | needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD); | 
|  | needed_size += lpcs->dwResultClauseLen; | 
|  | needed_size += lpcs->dwResultStrLen * sizeof(DWORD); | 
|  | needed_size += lpcs->dwPrivateSize; | 
|  | } | 
|  | rc = ImmCreateIMCC(needed_size); | 
|  | newdata = ImmLockIMCC(rc); | 
|  | new_one = (LPCOMPOSITIONSTRING)newdata; | 
|  |  | 
|  | new_one->dwSize = needed_size; | 
|  | current_offset = sizeof(COMPOSITIONSTRING); | 
|  | if (lpcs != NULL) | 
|  | { | 
|  | current_offset = updateField(lpcs->dwCompReadAttrLen, | 
|  | lpcs->dwCompReadAttrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompReadAttrLen, | 
|  | &new_one->dwCompReadAttrOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwCompReadClauseLen, | 
|  | lpcs->dwCompReadClauseOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompReadClauseLen, | 
|  | &new_one->dwCompReadClauseOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwCompReadStrLen, | 
|  | lpcs->dwCompReadStrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompReadStrLen, | 
|  | &new_one->dwCompReadStrOffset, TRUE); | 
|  |  | 
|  | /* new CompAttr, CompClause, CompStr, dwCursorPos */ | 
|  | new_one->dwDeltaStart = 0; | 
|  |  | 
|  | current_offset = updateField(lpcs->dwResultReadClauseLen, | 
|  | lpcs->dwResultReadClauseOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwResultReadClauseLen, | 
|  | &new_one->dwResultReadClauseOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwResultReadStrLen, | 
|  | lpcs->dwResultReadStrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwResultReadStrLen, | 
|  | &new_one->dwResultReadStrOffset, TRUE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwResultClauseLen, | 
|  | lpcs->dwResultClauseOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwResultClauseLen, | 
|  | &new_one->dwResultClauseOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwResultStrLen, | 
|  | lpcs->dwResultStrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwResultStrLen, | 
|  | &new_one->dwResultStrOffset, TRUE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwPrivateSize, | 
|  | lpcs->dwPrivateOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwPrivateSize, | 
|  | &new_one->dwPrivateOffset, FALSE); | 
|  | } | 
|  |  | 
|  | /* set new data */ | 
|  | /* CompAttr */ | 
|  | new_one->dwCompAttrLen = len; | 
|  | if (len > 0) | 
|  | { | 
|  | new_one->dwCompAttrOffset = current_offset; | 
|  | memset(&newdata[current_offset],ATTR_INPUT,len); | 
|  | current_offset += len; | 
|  | } | 
|  |  | 
|  | /* CompClause */ | 
|  | if (len > 0) | 
|  | { | 
|  | new_one->dwCompClauseLen = sizeof(DWORD) * 2; | 
|  | new_one->dwCompClauseOffset = current_offset; | 
|  | *(DWORD*)(&newdata[current_offset]) = 0; | 
|  | current_offset += sizeof(DWORD); | 
|  | *(DWORD*)(&newdata[current_offset]) = len; | 
|  | current_offset += sizeof(DWORD); | 
|  | } | 
|  |  | 
|  | /* CompStr */ | 
|  | new_one->dwCompStrLen = len; | 
|  | if (len > 0) | 
|  | { | 
|  | new_one->dwCompStrOffset = current_offset; | 
|  | memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR)); | 
|  | } | 
|  |  | 
|  | /* CursorPos */ | 
|  | new_one->dwCursorPos = len; | 
|  |  | 
|  | ImmUnlockIMCC(rc); | 
|  | if (lpcs) | 
|  | ImmUnlockIMCC(old); | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len) | 
|  | { | 
|  | /* we need to make sure the ResultStr and ResultClause fields are all | 
|  | * set and correct */ | 
|  | int needed_size; | 
|  | HIMCC   rc; | 
|  | LPBYTE newdata = NULL; | 
|  | LPBYTE olddata = NULL; | 
|  | LPCOMPOSITIONSTRING new_one; | 
|  | LPCOMPOSITIONSTRING lpcs = NULL; | 
|  | INT current_offset = 0; | 
|  |  | 
|  | TRACE("%s, %i\n",debugstr_wn(resultstr,len),len); | 
|  |  | 
|  | if (old != NULL) | 
|  | { | 
|  | olddata = ImmLockIMCC(old); | 
|  | lpcs = (LPCOMPOSITIONSTRING)olddata; | 
|  | } | 
|  |  | 
|  | needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) + | 
|  | sizeof(DWORD) * 2; | 
|  |  | 
|  | if (lpcs != NULL) | 
|  | { | 
|  | needed_size += lpcs->dwCompReadAttrLen; | 
|  | needed_size += lpcs->dwCompReadClauseLen; | 
|  | needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD); | 
|  | needed_size += lpcs->dwCompAttrLen; | 
|  | needed_size += lpcs->dwCompClauseLen; | 
|  | needed_size += lpcs->dwCompStrLen * sizeof(DWORD); | 
|  | needed_size += lpcs->dwResultReadClauseLen; | 
|  | needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD); | 
|  | needed_size += lpcs->dwPrivateSize; | 
|  | } | 
|  | rc = ImmCreateIMCC(needed_size); | 
|  | newdata = ImmLockIMCC(rc); | 
|  | new_one = (LPCOMPOSITIONSTRING)newdata; | 
|  |  | 
|  | new_one->dwSize = needed_size; | 
|  | current_offset = sizeof(COMPOSITIONSTRING); | 
|  | if (lpcs != NULL) | 
|  | { | 
|  | current_offset = updateField(lpcs->dwCompReadAttrLen, | 
|  | lpcs->dwCompReadAttrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompReadAttrLen, | 
|  | &new_one->dwCompReadAttrOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwCompReadClauseLen, | 
|  | lpcs->dwCompReadClauseOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompReadClauseLen, | 
|  | &new_one->dwCompReadClauseOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwCompReadStrLen, | 
|  | lpcs->dwCompReadStrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompReadStrLen, | 
|  | &new_one->dwCompReadStrOffset, TRUE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwCompAttrLen, | 
|  | lpcs->dwCompAttrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompAttrLen, | 
|  | &new_one->dwCompAttrOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwCompClauseLen, | 
|  | lpcs->dwCompClauseOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompClauseLen, | 
|  | &new_one->dwCompClauseOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwCompStrLen, | 
|  | lpcs->dwCompStrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwCompStrLen, | 
|  | &new_one->dwCompStrOffset, TRUE); | 
|  |  | 
|  | new_one->dwCursorPos = lpcs->dwCursorPos; | 
|  | new_one->dwDeltaStart = 0; | 
|  |  | 
|  | current_offset = updateField(lpcs->dwResultReadClauseLen, | 
|  | lpcs->dwResultReadClauseOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwResultReadClauseLen, | 
|  | &new_one->dwResultReadClauseOffset, FALSE); | 
|  |  | 
|  | current_offset = updateField(lpcs->dwResultReadStrLen, | 
|  | lpcs->dwResultReadStrOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwResultReadStrLen, | 
|  | &new_one->dwResultReadStrOffset, TRUE); | 
|  |  | 
|  | /* new ResultClause , ResultStr */ | 
|  |  | 
|  | current_offset = updateField(lpcs->dwPrivateSize, | 
|  | lpcs->dwPrivateOffset, | 
|  | current_offset, newdata, olddata, | 
|  | &new_one->dwPrivateSize, | 
|  | &new_one->dwPrivateOffset, FALSE); | 
|  | } | 
|  |  | 
|  | /* set new data */ | 
|  | /* ResultClause */ | 
|  | if (len > 0) | 
|  | { | 
|  | new_one->dwResultClauseLen = sizeof(DWORD) * 2; | 
|  | new_one->dwResultClauseOffset = current_offset; | 
|  | *(DWORD*)(&newdata[current_offset]) = 0; | 
|  | current_offset += sizeof(DWORD); | 
|  | *(DWORD*)(&newdata[current_offset]) = len; | 
|  | current_offset += sizeof(DWORD); | 
|  | } | 
|  |  | 
|  | /* ResultStr */ | 
|  | new_one->dwResultStrLen = len; | 
|  | if (len > 0) | 
|  | { | 
|  | new_one->dwResultStrOffset = current_offset; | 
|  | memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR)); | 
|  | } | 
|  | ImmUnlockIMCC(rc); | 
|  | if (lpcs) | 
|  | ImmUnlockIMCC(old); | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmAssociateContext (IMM32.@) | 
|  | */ | 
|  | HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  |  | 
|  | WARN("(%p, %p): semi-stub\n", hWnd, hIMC); | 
|  |  | 
|  | if (!hIMC) | 
|  | return NULL; | 
|  |  | 
|  | /* | 
|  | * WINE SPECIFIC! MAY CONFLICT | 
|  | * associate the root context we have an XIM created | 
|  | */ | 
|  | if (hWnd == 0x000) | 
|  | { | 
|  | root_context = (InputContextData*)hIMC; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If already associated just return | 
|  | */ | 
|  | if (data->IMC.hWnd == hWnd) | 
|  | return hIMC; | 
|  |  | 
|  | if (IsWindow(data->IMC.hWnd)) | 
|  | { | 
|  | /* | 
|  | * Post a message that your context is switching | 
|  | */ | 
|  | SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL); | 
|  | } | 
|  |  | 
|  | data->IMC.hWnd = hWnd; | 
|  |  | 
|  | if (IsWindow(data->IMC.hWnd)) | 
|  | { | 
|  | /* | 
|  | * Post a message that your context is switching | 
|  | */ | 
|  | SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * TODO: We need to keep track of the old context associated | 
|  | * with a window and return it for now we will return NULL; | 
|  | */ | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *              ImmAssociateContextEx (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) | 
|  | { | 
|  | FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmConfigureIMEA (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmConfigureIMEA( | 
|  | HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) | 
|  | { | 
|  | FIXME("(%p, %p, %d, %p): stub\n", | 
|  | hKL, hWnd, dwMode, lpData | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmConfigureIMEW (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmConfigureIMEW( | 
|  | HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) | 
|  | { | 
|  | FIXME("(%p, %p, %d, %p): stub\n", | 
|  | hKL, hWnd, dwMode, lpData | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmCreateContext (IMM32.@) | 
|  | */ | 
|  | HIMC WINAPI ImmCreateContext(void) | 
|  | { | 
|  | InputContextData *new_context; | 
|  |  | 
|  | new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData)); | 
|  |  | 
|  | return (HIMC)new_context; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmDestroyContext (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmDestroyContext(HIMC hIMC) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  |  | 
|  | TRACE("Destroying %p\n",hIMC); | 
|  |  | 
|  | if (hIMC) | 
|  | { | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | ImmDestroyIMCC(root_context->IMC.hCandInfo); | 
|  | ImmDestroyIMCC(root_context->IMC.hGuideLine); | 
|  | ImmDestroyIMCC(root_context->IMC.hPrivate); | 
|  | ImmDestroyIMCC(root_context->IMC.hMsgBuf); | 
|  |  | 
|  | if (data->textfont) | 
|  | { | 
|  | DeleteObject(data->textfont); | 
|  | data->textfont = NULL; | 
|  | } | 
|  |  | 
|  | HeapFree(GetProcessHeap(),0,data); | 
|  | } | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmDisableIME (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmDisableIME(DWORD idThread) | 
|  | { | 
|  | FIXME("(%d): stub\n", idThread); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmEnumRegisterWordA (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmEnumRegisterWordA( | 
|  | HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc, | 
|  | LPCSTR lpszReading, DWORD dwStyle, | 
|  | LPCSTR lpszRegister, LPVOID lpData) | 
|  | { | 
|  | FIXME("(%p, %p, %s, %d, %s, %p): stub\n", | 
|  | hKL, lpfnEnumProc, | 
|  | debugstr_a(lpszReading), dwStyle, | 
|  | debugstr_a(lpszRegister), lpData | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmEnumRegisterWordW (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmEnumRegisterWordW( | 
|  | HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc, | 
|  | LPCWSTR lpszReading, DWORD dwStyle, | 
|  | LPCWSTR lpszRegister, LPVOID lpData) | 
|  | { | 
|  | FIXME("(%p, %p, %s, %d, %s, %p): stub\n", | 
|  | hKL, lpfnEnumProc, | 
|  | debugstr_w(lpszReading), dwStyle, | 
|  | debugstr_w(lpszRegister), lpData | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmEscapeA (IMM32.@) | 
|  | */ | 
|  | LRESULT WINAPI ImmEscapeA( | 
|  | HKL hKL, HIMC hIMC, | 
|  | UINT uEscape, LPVOID lpData) | 
|  | { | 
|  | FIXME("(%p, %p, %d, %p): stub\n", | 
|  | hKL, hIMC, uEscape, lpData | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmEscapeW (IMM32.@) | 
|  | */ | 
|  | LRESULT WINAPI ImmEscapeW( | 
|  | HKL hKL, HIMC hIMC, | 
|  | UINT uEscape, LPVOID lpData) | 
|  | { | 
|  | FIXME("(%p, %p, %d, %p): stub\n", | 
|  | hKL, hIMC, uEscape, lpData | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCandidateListA (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetCandidateListA( | 
|  | HIMC hIMC, DWORD deIndex, | 
|  | LPCANDIDATELIST lpCandList, DWORD dwBufLen) | 
|  | { | 
|  | FIXME("(%p, %d, %p, %d): stub\n", | 
|  | hIMC, deIndex, | 
|  | lpCandList, dwBufLen | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCandidateListCountA (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetCandidateListCountA( | 
|  | HIMC hIMC, LPDWORD lpdwListCount) | 
|  | { | 
|  | FIXME("(%p, %p): stub\n", hIMC, lpdwListCount); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCandidateListCountW (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetCandidateListCountW( | 
|  | HIMC hIMC, LPDWORD lpdwListCount) | 
|  | { | 
|  | FIXME("(%p, %p): stub\n", hIMC, lpdwListCount); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCandidateListW (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetCandidateListW( | 
|  | HIMC hIMC, DWORD deIndex, | 
|  | LPCANDIDATELIST lpCandList, DWORD dwBufLen) | 
|  | { | 
|  | FIXME("(%p, %d, %p, %d): stub\n", | 
|  | hIMC, deIndex, | 
|  | lpCandList, dwBufLen | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCandidateWindow (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmGetCandidateWindow( | 
|  | HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate) | 
|  | { | 
|  | FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCompositionFontA (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) | 
|  | { | 
|  | FIXME("(%p, %p): stub\n", hIMC, lplf); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCompositionFontW (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) | 
|  | { | 
|  | FIXME("(%p, %p): stub\n", hIMC, lplf); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCompositionStringA (IMM32.@) | 
|  | */ | 
|  | LONG WINAPI ImmGetCompositionStringA( | 
|  | HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) | 
|  | { | 
|  | CHAR *buf; | 
|  | LONG rc = 0; | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  | LPCOMPOSITIONSTRING compstr; | 
|  | LPBYTE compdata; | 
|  |  | 
|  | TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen); | 
|  |  | 
|  | if (!data) | 
|  | return FALSE; | 
|  |  | 
|  | if (!data->IMC.hCompStr) | 
|  | return FALSE; | 
|  |  | 
|  | compdata = ImmLockIMCC(data->IMC.hCompStr); | 
|  | compstr = (LPCOMPOSITIONSTRING)compdata; | 
|  |  | 
|  | if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 && | 
|  | compstr->dwResultStrOffset > 0) | 
|  | { | 
|  | LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset); | 
|  |  | 
|  | TRACE("GSC_RESULTSTR %p %i\n",ResultStr, | 
|  | compstr->dwResultStrLen); | 
|  |  | 
|  | buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 ); | 
|  | rc = WideCharToMultiByte(CP_ACP, 0, ResultStr, | 
|  | compstr->dwResultStrLen , buf, | 
|  | compstr->dwResultStrLen * 3, NULL, NULL); | 
|  | if (dwBufLen >= rc) | 
|  | memcpy(lpBuf,buf,rc); | 
|  |  | 
|  | data->bRead = TRUE; | 
|  | HeapFree( GetProcessHeap(), 0, buf ); | 
|  | } | 
|  | else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 && | 
|  | compstr->dwCompStrOffset > 0) | 
|  | { | 
|  | LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset); | 
|  |  | 
|  | TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen); | 
|  |  | 
|  | buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 ); | 
|  | rc = WideCharToMultiByte(CP_ACP, 0, CompString, | 
|  | compstr->dwCompStrLen, buf, | 
|  | compstr->dwCompStrLen * 3, NULL, NULL); | 
|  | if (dwBufLen >= rc) | 
|  | memcpy(lpBuf,buf,rc); | 
|  | HeapFree( GetProcessHeap(), 0, buf ); | 
|  | } | 
|  | else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 && | 
|  | compstr->dwCompAttrOffset > 0) | 
|  | { | 
|  | LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset); | 
|  | TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen); | 
|  |  | 
|  | rc = compstr->dwCompAttrLen; | 
|  | if (dwBufLen >= rc) | 
|  | memcpy(lpBuf,Compattr,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 && | 
|  | compstr->dwCompClauseOffset > 0) | 
|  | { | 
|  | LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset); | 
|  | TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen); | 
|  |  | 
|  | rc = compstr->dwCompClauseLen; | 
|  | if (dwBufLen >= compstr->dwCompClauseLen) | 
|  | memcpy(lpBuf,Compclause,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 && | 
|  | compstr->dwResultClauseOffset > 0) | 
|  | { | 
|  | LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset); | 
|  | TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen); | 
|  |  | 
|  | rc = compstr->dwResultClauseLen; | 
|  | if (dwBufLen >= compstr->dwResultClauseLen) | 
|  | memcpy(lpBuf,Resultclause,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_CURSORPOS) | 
|  | { | 
|  | TRACE("GSC_CURSORPOS\n"); | 
|  | rc = compstr->dwCursorPos; | 
|  | } | 
|  | else if (dwIndex == GCS_DELTASTART) | 
|  | { | 
|  | TRACE("GCS_DELTASTART\n"); | 
|  | rc = compstr->dwDeltaStart; | 
|  | } | 
|  | else | 
|  | { | 
|  | FIXME("Unhandled index 0x%x\n",dwIndex); | 
|  | } | 
|  |  | 
|  | ImmUnlockIMCC(data->IMC.hCompStr); | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCompositionStringW (IMM32.@) | 
|  | */ | 
|  | LONG WINAPI ImmGetCompositionStringW( | 
|  | HIMC hIMC, DWORD dwIndex, | 
|  | LPVOID lpBuf, DWORD dwBufLen) | 
|  | { | 
|  | LONG rc = 0; | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  | LPCOMPOSITIONSTRING compstr; | 
|  | LPBYTE compdata; | 
|  |  | 
|  | TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen); | 
|  |  | 
|  | if (!data) | 
|  | return FALSE; | 
|  |  | 
|  | if (!data->IMC.hCompStr) | 
|  | return FALSE; | 
|  |  | 
|  | compdata = ImmLockIMCC(data->IMC.hCompStr); | 
|  | compstr = (LPCOMPOSITIONSTRING)compdata; | 
|  |  | 
|  | if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 && | 
|  | compstr->dwResultStrOffset > 0) | 
|  | { | 
|  | LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset); | 
|  | data->bRead = TRUE; | 
|  | rc =  compstr->dwResultStrLen * sizeof(WCHAR); | 
|  |  | 
|  | if (dwBufLen >= rc) | 
|  | memcpy(lpBuf,ResultStr,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 && | 
|  | compstr->dwResultReadStrOffset > 0) | 
|  | { | 
|  | LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset); | 
|  |  | 
|  | rc = compstr->dwResultReadStrLen * sizeof(WCHAR); | 
|  | if (dwBufLen >= rc) | 
|  | memcpy(lpBuf,ResultReadString,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 && | 
|  | compstr->dwCompStrOffset > 0) | 
|  | { | 
|  | LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset); | 
|  | rc = compstr->dwCompStrLen * sizeof(WCHAR); | 
|  | if (dwBufLen >= rc) | 
|  | memcpy(lpBuf,CompString,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 && | 
|  | compstr->dwCompAttrOffset > 0) | 
|  | { | 
|  |  | 
|  | LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset); | 
|  |  | 
|  | rc = compstr->dwCompAttrLen; | 
|  | if (dwBufLen >= rc) | 
|  | memcpy(lpBuf,Compattr,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 && | 
|  | compstr->dwCompClauseOffset > 0) | 
|  | { | 
|  | LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset); | 
|  |  | 
|  | rc = compstr->dwCompClauseLen; | 
|  | if (dwBufLen >= compstr->dwCompClauseLen) | 
|  | memcpy(lpBuf,Compclause,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 && | 
|  | compstr->dwCompReadStrOffset > 0) | 
|  | { | 
|  | LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset); | 
|  |  | 
|  | rc = compstr->dwCompReadStrLen * sizeof(WCHAR); | 
|  |  | 
|  | if (dwBufLen >= rc) | 
|  | memcpy(lpBuf,CompReadString,rc); | 
|  | } | 
|  | else if (dwIndex == GCS_CURSORPOS) | 
|  | { | 
|  | TRACE("GSC_CURSORPOS\n"); | 
|  | rc = compstr->dwCursorPos; | 
|  | } | 
|  | else if (dwIndex == GCS_DELTASTART) | 
|  | { | 
|  | TRACE("GCS_DELTASTART\n"); | 
|  | rc = compstr->dwDeltaStart; | 
|  | } | 
|  | else | 
|  | { | 
|  | FIXME("Unhandled index 0x%x\n",dwIndex); | 
|  | } | 
|  |  | 
|  | ImmUnlockIMCC(data->IMC.hCompStr); | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetCompositionWindow (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  |  | 
|  | TRACE("(%p, %p)\n", hIMC, lpCompForm); | 
|  |  | 
|  | if (!data) | 
|  | return FALSE; | 
|  |  | 
|  | memcpy(lpCompForm,&(data->IMC.cfCompForm),sizeof(COMPOSITIONFORM)); | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetContext (IMM32.@) | 
|  | * | 
|  | */ | 
|  | HIMC WINAPI ImmGetContext(HWND hWnd) | 
|  | { | 
|  | TRACE("%p\n", hWnd); | 
|  |  | 
|  | if (!root_context) | 
|  | return NULL; | 
|  |  | 
|  | root_context->IMC.hWnd = hWnd; | 
|  | return (HIMC)root_context; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetConversionListA (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetConversionListA( | 
|  | HKL hKL, HIMC hIMC, | 
|  | LPCSTR pSrc, LPCANDIDATELIST lpDst, | 
|  | DWORD dwBufLen, UINT uFlag) | 
|  | { | 
|  | FIXME("(%p, %p, %s, %p, %d, %d): stub\n", | 
|  | hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetConversionListW (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetConversionListW( | 
|  | HKL hKL, HIMC hIMC, | 
|  | LPCWSTR pSrc, LPCANDIDATELIST lpDst, | 
|  | DWORD dwBufLen, UINT uFlag) | 
|  | { | 
|  | FIXME("(%p, %p, %s, %p, %d, %d): stub\n", | 
|  | hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetConversionStatus (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmGetConversionStatus( | 
|  | HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence) | 
|  | { | 
|  | TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence); | 
|  | if (lpfdwConversion) | 
|  | *lpfdwConversion = IME_CMODE_NATIVE; | 
|  | if (lpfdwSentence) | 
|  | *lpfdwSentence = IME_SMODE_NONE; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetDefaultIMEWnd (IMM32.@) | 
|  | */ | 
|  | HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) | 
|  | { | 
|  | FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context); | 
|  |  | 
|  | if (hwndDefault == NULL) | 
|  | { | 
|  | static const WCHAR the_name[] = {'I','M','E','\0'}; | 
|  |  | 
|  | IMM_Register(); | 
|  | hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME, | 
|  | the_name, WS_POPUP, 0, 0, 1, 1, 0, 0, | 
|  | hImeInst, 0); | 
|  |  | 
|  | TRACE("Default created (%p)\n",hwndDefault); | 
|  | } | 
|  |  | 
|  | return (HWND)hwndDefault; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetDescriptionA (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmGetDescriptionA( | 
|  | HKL hKL, LPSTR lpszDescription, UINT uBufLen) | 
|  | { | 
|  | WCHAR *buf; | 
|  | DWORD len; | 
|  |  | 
|  | TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen); | 
|  |  | 
|  | /* find out how many characters in the unicode buffer */ | 
|  | len = ImmGetDescriptionW( hKL, NULL, 0 ); | 
|  |  | 
|  | /* allocate a buffer of that size */ | 
|  | buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) ); | 
|  | if( !buf ) | 
|  | return 0; | 
|  |  | 
|  | /* fetch the unicode buffer */ | 
|  | len = ImmGetDescriptionW( hKL, buf, len + 1 ); | 
|  |  | 
|  | /* convert it back to ASCII */ | 
|  | len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1, | 
|  | lpszDescription, uBufLen, NULL, NULL ); | 
|  |  | 
|  | HeapFree( GetProcessHeap(), 0, buf ); | 
|  |  | 
|  | return len; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetDescriptionW (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen) | 
|  | { | 
|  | static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 }; | 
|  |  | 
|  | FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen); | 
|  |  | 
|  | if (!uBufLen) return lstrlenW( name ); | 
|  | lstrcpynW( lpszDescription, name, uBufLen ); | 
|  | return lstrlenW( lpszDescription ); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetGuideLineA (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetGuideLineA( | 
|  | HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen) | 
|  | { | 
|  | FIXME("(%p, %d, %s, %d): stub\n", | 
|  | hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetGuideLineW (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen) | 
|  | { | 
|  | FIXME("(%p, %d, %s, %d): stub\n", | 
|  | hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetIMEFileNameA (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmGetIMEFileNameA( | 
|  | HKL hKL, LPSTR lpszFileName, UINT uBufLen) | 
|  | { | 
|  | FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetIMEFileNameW (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmGetIMEFileNameW( | 
|  | HKL hKL, LPWSTR lpszFileName, UINT uBufLen) | 
|  | { | 
|  | FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetOpenStatus (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  |  | 
|  | if (!data) | 
|  | return FALSE; | 
|  | FIXME("(%p): semi-stub\n", hIMC); | 
|  |  | 
|  | return data->IMC.fOpen; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetProperty (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) | 
|  | { | 
|  | DWORD rc = 0; | 
|  | TRACE("(%p, %d)\n", hKL, fdwIndex); | 
|  |  | 
|  | switch (fdwIndex) | 
|  | { | 
|  | case IGP_PROPERTY: | 
|  | TRACE("(%s)\n", "IGP_PROPERTY"); | 
|  | rc = IME_PROP_UNICODE | IME_PROP_AT_CARET; | 
|  | break; | 
|  | case IGP_CONVERSION: | 
|  | FIXME("(%s)\n", "IGP_CONVERSION"); | 
|  | rc = IME_CMODE_NATIVE; | 
|  | break; | 
|  | case IGP_SENTENCE: | 
|  | FIXME("%s)\n", "IGP_SENTENCE"); | 
|  | rc = IME_SMODE_AUTOMATIC; | 
|  | break; | 
|  | case IGP_SETCOMPSTR: | 
|  | TRACE("(%s)\n", "IGP_SETCOMPSTR"); | 
|  | rc = 0; | 
|  | break; | 
|  | case IGP_SELECT: | 
|  | TRACE("(%s)\n", "IGP_SELECT"); | 
|  | rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE; | 
|  | break; | 
|  | case IGP_GETIMEVERSION: | 
|  | TRACE("(%s)\n", "IGP_GETIMEVERSION"); | 
|  | rc = IMEVER_0400; | 
|  | break; | 
|  | case IGP_UI: | 
|  | TRACE("(%s)\n", "IGP_UI"); | 
|  | rc = 0; | 
|  | break; | 
|  | default: | 
|  | rc = 0; | 
|  | } | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetRegisterWordStyleA (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmGetRegisterWordStyleA( | 
|  | HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf) | 
|  | { | 
|  | FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetRegisterWordStyleW (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmGetRegisterWordStyleW( | 
|  | HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf) | 
|  | { | 
|  | FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetStatusWindowPos (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) | 
|  | { | 
|  | FIXME("(%p, %p): stub\n", hIMC, lpptPos); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetVirtualKey (IMM32.@) | 
|  | */ | 
|  | UINT WINAPI ImmGetVirtualKey(HWND hWnd) | 
|  | { | 
|  | OSVERSIONINFOA version; | 
|  | FIXME("(%p): stub\n", hWnd); | 
|  | GetVersionExA( &version ); | 
|  | switch(version.dwPlatformId) | 
|  | { | 
|  | case VER_PLATFORM_WIN32_WINDOWS: | 
|  | return VK_PROCESSKEY; | 
|  | case VER_PLATFORM_WIN32_NT: | 
|  | return 0; | 
|  | default: | 
|  | FIXME("%d not supported\n",version.dwPlatformId); | 
|  | return VK_PROCESSKEY; | 
|  | } | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmInstallIMEA (IMM32.@) | 
|  | */ | 
|  | HKL WINAPI ImmInstallIMEA( | 
|  | LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText) | 
|  | { | 
|  | FIXME("(%s, %s): stub\n", | 
|  | debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText) | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmInstallIMEW (IMM32.@) | 
|  | */ | 
|  | HKL WINAPI ImmInstallIMEW( | 
|  | LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText) | 
|  | { | 
|  | FIXME("(%s, %s): stub\n", | 
|  | debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText) | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmIsIME (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmIsIME(HKL hKL) | 
|  | { | 
|  | TRACE("(%p): semi-stub\n", hKL); | 
|  | /* | 
|  | * FIXME: Dead key locales will return TRUE here when they should not | 
|  | * There is probably a more proper way to check this. | 
|  | */ | 
|  | return (root_context != NULL); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmIsUIMessageA (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmIsUIMessageA( | 
|  | HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) | 
|  | { | 
|  | BOOL rc = FALSE; | 
|  |  | 
|  | TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam); | 
|  | if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || | 
|  | (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) || | 
|  | (msg == WM_MSIME_SERVICE) || | 
|  | (msg == WM_MSIME_RECONVERTOPTIONS) || | 
|  | (msg == WM_MSIME_MOUSE) || | 
|  | (msg == WM_MSIME_RECONVERTREQUEST) || | 
|  | (msg == WM_MSIME_RECONVERT) || | 
|  | (msg == WM_MSIME_QUERYPOSITION) || | 
|  | (msg == WM_MSIME_DOCUMENTFEED)) | 
|  |  | 
|  | { | 
|  | if (!hwndDefault) | 
|  | ImmGetDefaultIMEWnd(NULL); | 
|  |  | 
|  | if (hWndIME == NULL) | 
|  | PostMessageA(hwndDefault, msg, wParam, lParam); | 
|  |  | 
|  | rc = TRUE; | 
|  | } | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmIsUIMessageW (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmIsUIMessageW( | 
|  | HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) | 
|  | { | 
|  | BOOL rc = FALSE; | 
|  | TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam); | 
|  | if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || | 
|  | (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) || | 
|  | (msg == WM_MSIME_SERVICE) || | 
|  | (msg == WM_MSIME_RECONVERTOPTIONS) || | 
|  | (msg == WM_MSIME_MOUSE) || | 
|  | (msg == WM_MSIME_RECONVERTREQUEST) || | 
|  | (msg == WM_MSIME_RECONVERT) || | 
|  | (msg == WM_MSIME_QUERYPOSITION) || | 
|  | (msg == WM_MSIME_DOCUMENTFEED)) | 
|  | rc = TRUE; | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmNotifyIME (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmNotifyIME( | 
|  | HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) | 
|  | { | 
|  | BOOL rc = FALSE; | 
|  |  | 
|  | TRACE("(%p, %d, %d, %d)\n", | 
|  | hIMC, dwAction, dwIndex, dwValue); | 
|  |  | 
|  | if (!root_context) | 
|  | return rc; | 
|  |  | 
|  | switch(dwAction) | 
|  | { | 
|  | case NI_CHANGECANDIDATELIST: | 
|  | FIXME("%s\n","NI_CHANGECANDIDATELIST"); | 
|  | break; | 
|  | case NI_CLOSECANDIDATE: | 
|  | FIXME("%s\n","NI_CLOSECANDIDATE"); | 
|  | break; | 
|  | case NI_COMPOSITIONSTR: | 
|  | switch (dwIndex) | 
|  | { | 
|  | case CPS_CANCEL: | 
|  | TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL"); | 
|  | { | 
|  | HIMCC newCompStr; | 
|  | if (pX11DRV_ForceXIMReset) | 
|  | pX11DRV_ForceXIMReset(root_context->IMC.hWnd); | 
|  |  | 
|  | newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0); | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | root_context->IMC.hCompStr = newCompStr; | 
|  |  | 
|  | ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0, | 
|  | GCS_COMPSTR); | 
|  | rc = TRUE; | 
|  | } | 
|  | break; | 
|  | case CPS_COMPLETE: | 
|  | TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE"); | 
|  | if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset) | 
|  | pX11DRV_ForceXIMReset(root_context->IMC.hWnd); | 
|  | { | 
|  | HIMCC newCompStr; | 
|  | DWORD cplen; | 
|  | LPWSTR cpstr; | 
|  | LPCOMPOSITIONSTRING cs = NULL; | 
|  | LPBYTE cdata = NULL; | 
|  |  | 
|  | /* clear existing result */ | 
|  | newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0); | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | root_context->IMC.hCompStr = newCompStr; | 
|  |  | 
|  | cdata = ImmLockIMCC(root_context->IMC.hCompStr); | 
|  | cs = (LPCOMPOSITIONSTRING)cdata; | 
|  | cplen = cs->dwCompStrLen; | 
|  | cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]); | 
|  | ImmUnlockIMCC(root_context->IMC.hCompStr); | 
|  | if (cplen > 0) | 
|  | { | 
|  | WCHAR param = cpstr[0]; | 
|  | newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen); | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | root_context->IMC.hCompStr = newCompStr; | 
|  | newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0); | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | root_context->IMC.hCompStr = newCompStr; | 
|  |  | 
|  | root_context->bRead = FALSE; | 
|  |  | 
|  | ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0, | 
|  | GCS_COMPSTR); | 
|  |  | 
|  | ImmInternalPostIMEMessage(WM_IME_COMPOSITION, | 
|  | param, | 
|  | GCS_RESULTSTR|GCS_RESULTCLAUSE); | 
|  | } | 
|  |  | 
|  | ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION, 0, 0); | 
|  | root_context->bInComposition = FALSE; | 
|  | } | 
|  | break; | 
|  | case CPS_CONVERT: | 
|  | FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT"); | 
|  | break; | 
|  | case CPS_REVERT: | 
|  | FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT"); | 
|  | break; | 
|  | default: | 
|  | ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex); | 
|  | break; | 
|  | } | 
|  | break; | 
|  | case NI_IMEMENUSELECTED: | 
|  | FIXME("%s\n", "NI_IMEMENUSELECTED"); | 
|  | break; | 
|  | case NI_OPENCANDIDATE: | 
|  | FIXME("%s\n", "NI_OPENCANDIDATE"); | 
|  | break; | 
|  | case NI_SELECTCANDIDATESTR: | 
|  | FIXME("%s\n", "NI_SELECTCANDIDATESTR"); | 
|  | break; | 
|  | case NI_SETCANDIDATE_PAGESIZE: | 
|  | FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE"); | 
|  | break; | 
|  | case NI_SETCANDIDATE_PAGESTART: | 
|  | FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART"); | 
|  | break; | 
|  | default: | 
|  | ERR("Unknown\n"); | 
|  | } | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmRegisterWordA (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmRegisterWordA( | 
|  | HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister) | 
|  | { | 
|  | FIXME("(%p, %s, %d, %s): stub\n", | 
|  | hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister) | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmRegisterWordW (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmRegisterWordW( | 
|  | HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister) | 
|  | { | 
|  | FIXME("(%p, %s, %d, %s): stub\n", | 
|  | hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister) | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmReleaseContext (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC) | 
|  | { | 
|  | FIXME("(%p, %p): stub\n", hWnd, hIMC); | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetCandidateWindow (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetCandidateWindow( | 
|  | HIMC hIMC, LPCANDIDATEFORM lpCandidate) | 
|  | { | 
|  | FIXME("(%p, %p): stub\n", hIMC, lpCandidate); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetCompositionFontA (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  | TRACE("(%p, %p)\n", hIMC, lplf); | 
|  |  | 
|  | if (!data) | 
|  | return FALSE; | 
|  |  | 
|  | memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA)); | 
|  | MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName, | 
|  | LF_FACESIZE); | 
|  |  | 
|  | ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0); | 
|  |  | 
|  | if (data->textfont) | 
|  | { | 
|  | DeleteObject(data->textfont); | 
|  | data->textfont = NULL; | 
|  | } | 
|  |  | 
|  | data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetCompositionFontW (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  | TRACE("(%p, %p)\n", hIMC, lplf); | 
|  |  | 
|  | if (!data) | 
|  | return FALSE; | 
|  |  | 
|  | memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTW)); | 
|  | ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0); | 
|  |  | 
|  | if (data->textfont) | 
|  | { | 
|  | DeleteObject(data->textfont); | 
|  | data->textfont = NULL; | 
|  | } | 
|  | data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetCompositionStringA (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetCompositionStringA( | 
|  | HIMC hIMC, DWORD dwIndex, | 
|  | LPCVOID lpComp, DWORD dwCompLen, | 
|  | LPCVOID lpRead, DWORD dwReadLen) | 
|  | { | 
|  | DWORD comp_len; | 
|  | DWORD read_len; | 
|  | WCHAR *CompBuffer = NULL; | 
|  | WCHAR *ReadBuffer = NULL; | 
|  | BOOL rc; | 
|  |  | 
|  | TRACE("(%p, %d, %p, %d, %p, %d): stub\n", | 
|  | hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); | 
|  |  | 
|  | comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0); | 
|  | if (comp_len) | 
|  | { | 
|  | CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR)); | 
|  | MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len); | 
|  | } | 
|  |  | 
|  | read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0); | 
|  | if (read_len) | 
|  | { | 
|  | ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR)); | 
|  | MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len); | 
|  | } | 
|  |  | 
|  | rc =  ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len, | 
|  | ReadBuffer, read_len); | 
|  |  | 
|  | HeapFree(GetProcessHeap(), 0, CompBuffer); | 
|  | HeapFree(GetProcessHeap(), 0, ReadBuffer); | 
|  |  | 
|  | return rc; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetCompositionStringW (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetCompositionStringW( | 
|  | HIMC hIMC, DWORD dwIndex, | 
|  | LPCVOID lpComp, DWORD dwCompLen, | 
|  | LPCVOID lpRead, DWORD dwReadLen) | 
|  | { | 
|  | DWORD flags = 0; | 
|  | WCHAR wParam  = 0; | 
|  |  | 
|  | TRACE("(%p, %d, %p, %d, %p, %d): stub\n", | 
|  | hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); | 
|  |  | 
|  |  | 
|  | if (hIMC != (HIMC)FROM_IME) | 
|  | FIXME("PROBLEM: This only sets the wine level string\n"); | 
|  |  | 
|  | /* | 
|  | * Explanation: | 
|  | *  this sets the composition string in the imm32.dll level | 
|  | *  of the composition buffer. we cannot manipulate the xim level | 
|  | *  buffer, which means that once the xim level buffer changes again | 
|  | *  any call to this function from the application will be lost | 
|  | */ | 
|  |  | 
|  | if (lpRead && dwReadLen) | 
|  | FIXME("Reading string unimplemented\n"); | 
|  |  | 
|  | /* | 
|  | * app operating this api to also receive the message from xim | 
|  | */ | 
|  |  | 
|  | if (dwIndex == SCS_SETSTR) | 
|  | { | 
|  | HIMCC newCompStr; | 
|  | if (!root_context->bInComposition) | 
|  | { | 
|  | ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION, 0, 0); | 
|  | root_context->bInComposition = TRUE; | 
|  | } | 
|  |  | 
|  | flags = GCS_COMPSTR; | 
|  |  | 
|  | if (dwCompLen && lpComp) | 
|  | { | 
|  | newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR)); | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | root_context->IMC.hCompStr = newCompStr; | 
|  |  | 
|  | wParam = ((const WCHAR*)lpComp)[0]; | 
|  | flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART; | 
|  | } | 
|  | else | 
|  | { | 
|  | newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0); | 
|  | ImmDestroyIMCC(root_context->IMC.hCompStr); | 
|  | root_context->IMC.hCompStr = newCompStr; | 
|  | } | 
|  | } | 
|  |  | 
|  | UpdateDataInDefaultIMEWindow(hwndDefault,FALSE); | 
|  |  | 
|  | ImmInternalPostIMEMessage(WM_IME_COMPOSITION, wParam, flags); | 
|  |  | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetCompositionWindow (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetCompositionWindow( | 
|  | HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) | 
|  | { | 
|  | BOOL reshow = FALSE; | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  |  | 
|  | TRACE("(%p, %p)\n", hIMC, lpCompForm); | 
|  | TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle, | 
|  | lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top, | 
|  | lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right); | 
|  |  | 
|  | if (!data) | 
|  | return FALSE; | 
|  |  | 
|  | memcpy(&data->IMC.cfCompForm,lpCompForm,sizeof(COMPOSITIONFORM)); | 
|  |  | 
|  | if (IsWindowVisible(hwndDefault)) | 
|  | { | 
|  | reshow = TRUE; | 
|  | ShowWindow(hwndDefault,SW_HIDE); | 
|  | } | 
|  |  | 
|  | /* FIXME: this is a partial stub */ | 
|  |  | 
|  | if (reshow) | 
|  | ShowWindow(hwndDefault,SW_SHOWNOACTIVATE); | 
|  |  | 
|  | ImmInternalSendIMENotify(IMN_SETCOMPOSITIONWINDOW, 0); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetConversionStatus (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetConversionStatus( | 
|  | HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) | 
|  | { | 
|  | FIXME("(%p, %d, %d): stub\n", | 
|  | hIMC, fdwConversion, fdwSentence | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetOpenStatus (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  |  | 
|  | TRACE("%p %d\n", hIMC, fOpen); | 
|  |  | 
|  | if (hIMC == (HIMC)FROM_IME) | 
|  | { | 
|  | ImmInternalSetOpenStatus(fOpen); | 
|  | ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | if (!data) | 
|  | return FALSE; | 
|  |  | 
|  | if (fOpen != data->bInternalState) | 
|  | { | 
|  | if (fOpen == FALSE && pX11DRV_ForceXIMReset) | 
|  | pX11DRV_ForceXIMReset(data->IMC.hWnd); | 
|  |  | 
|  | if (fOpen == FALSE) | 
|  | ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0); | 
|  | else | 
|  | ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0); | 
|  |  | 
|  | ImmInternalSetOpenStatus(fOpen); | 
|  | ImmInternalSetOpenStatus(!fOpen); | 
|  |  | 
|  | if (data->IMC.fOpen == FALSE) | 
|  | ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0); | 
|  | else | 
|  | ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0); | 
|  |  | 
|  | return FALSE; | 
|  | } | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSetStatusWindowPos (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) | 
|  | { | 
|  | FIXME("(%p, %p): stub\n", hIMC, lpptPos); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmSimulateHotKey (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID) | 
|  | { | 
|  | FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmUnregisterWordA (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmUnregisterWordA( | 
|  | HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister) | 
|  | { | 
|  | FIXME("(%p, %s, %d, %s): stub\n", | 
|  | hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister) | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmUnregisterWordW (IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmUnregisterWordW( | 
|  | HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister) | 
|  | { | 
|  | FIXME("(%p, %s, %d, %s): stub\n", | 
|  | hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister) | 
|  | ); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetImeMenuItemsA (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType, | 
|  | LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu, | 
|  | DWORD dwSize) | 
|  | { | 
|  | FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType, | 
|  | lpImeParentMenu, lpImeMenu, dwSize); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetImeMenuItemsW (IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType, | 
|  | LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, | 
|  | DWORD dwSize) | 
|  | { | 
|  | FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType, | 
|  | lpImeParentMenu, lpImeMenu, dwSize); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmLockIMC(IMM32.@) | 
|  | */ | 
|  | LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  |  | 
|  | if (!data) | 
|  | return NULL; | 
|  | data->dwLock++; | 
|  | return &data->IMC; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmUnlockIMC(IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmUnlockIMC(HIMC hIMC) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  | data->dwLock--; | 
|  | return (data->dwLock!=0); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetIMCLockCount(IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC) | 
|  | { | 
|  | InputContextData *data = (InputContextData*)hIMC; | 
|  | return data->dwLock; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmCreateIMCC(IMM32.@) | 
|  | */ | 
|  | HIMCC  WINAPI ImmCreateIMCC(DWORD size) | 
|  | { | 
|  | IMCCInternal *internal; | 
|  | int real_size = size + sizeof(IMCCInternal); | 
|  |  | 
|  | internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size); | 
|  | if (internal == NULL) | 
|  | return NULL; | 
|  |  | 
|  | internal->dwSize = size; | 
|  | return  (HIMCC)internal; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *       ImmDestroyIMCC(IMM32.@) | 
|  | */ | 
|  | HIMCC WINAPI ImmDestroyIMCC(HIMCC block) | 
|  | { | 
|  | HeapFree(GetProcessHeap(),0,block); | 
|  | return NULL; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmLockIMCC(IMM32.@) | 
|  | */ | 
|  | LPVOID WINAPI ImmLockIMCC(HIMCC imcc) | 
|  | { | 
|  | IMCCInternal *internal; | 
|  | internal = (IMCCInternal*) imcc; | 
|  |  | 
|  | internal->dwLock ++; | 
|  | return internal + 1; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmUnlockIMCC(IMM32.@) | 
|  | */ | 
|  | BOOL WINAPI ImmUnlockIMCC(HIMCC imcc) | 
|  | { | 
|  | IMCCInternal *internal; | 
|  | internal = (IMCCInternal*) imcc; | 
|  |  | 
|  | internal->dwLock --; | 
|  | return (internal->dwLock!=0); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetIMCCLockCount(IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc) | 
|  | { | 
|  | IMCCInternal *internal; | 
|  | internal = (IMCCInternal*) imcc; | 
|  |  | 
|  | return internal->dwLock; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmReSizeIMCC(IMM32.@) | 
|  | */ | 
|  | HIMCC  WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size) | 
|  | { | 
|  | IMCCInternal *internal,*newone; | 
|  | int real_size = size + sizeof(IMCCInternal); | 
|  |  | 
|  | internal = (IMCCInternal*) imcc; | 
|  |  | 
|  | newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size); | 
|  | newone->dwSize = size; | 
|  |  | 
|  | return newone; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *		ImmGetIMCCSize(IMM32.@) | 
|  | */ | 
|  | DWORD WINAPI ImmGetIMCCSize(HIMCC imcc) | 
|  | { | 
|  | IMCCInternal *internal; | 
|  | internal = (IMCCInternal*) imcc; | 
|  |  | 
|  | return internal->dwSize; | 
|  | } | 
|  |  | 
|  | /***** | 
|  | * Internal functions to help with IME window management | 
|  | */ | 
|  | static void PaintDefaultIMEWnd(HWND hwnd) | 
|  | { | 
|  | PAINTSTRUCT ps; | 
|  | RECT rect; | 
|  | HDC hdc = BeginPaint(hwnd,&ps); | 
|  | LPCOMPOSITIONSTRING compstr; | 
|  | LPBYTE compdata = NULL; | 
|  | HMONITOR monitor; | 
|  | MONITORINFO mon_info; | 
|  | INT offX=0, offY=0; | 
|  |  | 
|  | GetClientRect(hwnd,&rect); | 
|  | FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1)); | 
|  |  | 
|  | compdata = ImmLockIMCC(root_context->IMC.hCompStr); | 
|  | compstr = (LPCOMPOSITIONSTRING)compdata; | 
|  |  | 
|  | if (compstr->dwCompStrLen && compstr->dwCompStrOffset) | 
|  | { | 
|  | SIZE size; | 
|  | POINT pt; | 
|  | HFONT oldfont = NULL; | 
|  | LPWSTR CompString; | 
|  |  | 
|  | CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset); | 
|  | if (root_context->textfont) | 
|  | oldfont = SelectObject(hdc,root_context->textfont); | 
|  |  | 
|  |  | 
|  | GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size); | 
|  | pt.x = size.cx; | 
|  | pt.y = size.cy; | 
|  | LPtoDP(hdc,&pt,1); | 
|  |  | 
|  | /* | 
|  | * How this works based on tests on windows: | 
|  | * CFS_POINT: then we start our window at the point and grow it as large | 
|  | *    as it needs to be for the string. | 
|  | * CFS_RECT:  we still use the ptCurrentPos as a starting point and our | 
|  | *    window is only as large as we need for the string, but we do not | 
|  | *    grow such that our window exceeds the given rect.  Wrapping if | 
|  | *    needed and possible.   If our ptCurrentPos is outside of our rect | 
|  | *    then no window is displayed. | 
|  | * CFS_FORCE_POSITION: appears to behave just like CFS_POINT | 
|  | *    maybe becase the default MSIME does not do any IME adjusting. | 
|  | */ | 
|  | if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT) | 
|  | { | 
|  | POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos; | 
|  | ClientToScreen(root_context->IMC.hWnd,&cpt); | 
|  | rect.left = cpt.x; | 
|  | rect.top = cpt.y; | 
|  | rect.right = rect.left + pt.x; | 
|  | rect.bottom = rect.top + pt.y; | 
|  | offX=offY=10; | 
|  | monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY); | 
|  | } | 
|  | else /* CFS_DEFAULT */ | 
|  | { | 
|  | /* Windows places the default IME window in the bottom left */ | 
|  | HWND target = root_context->IMC.hWnd; | 
|  | if (!target) target = GetFocus(); | 
|  |  | 
|  | GetWindowRect(target,&rect); | 
|  | rect.top = rect.bottom; | 
|  | rect.right = rect.left + pt.x + 20; | 
|  | rect.bottom = rect.top + pt.y + 20; | 
|  | offX=offY=10; | 
|  | monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY); | 
|  | } | 
|  |  | 
|  | if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT) | 
|  | { | 
|  | RECT client; | 
|  | client =root_context->IMC.cfCompForm.rcArea; | 
|  | MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 ); | 
|  | IntersectRect(&rect,&rect,&client); | 
|  | /* TODO:  Wrap the input if needed */ | 
|  | } | 
|  |  | 
|  | if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT) | 
|  | { | 
|  | /* make sure we are on the desktop */ | 
|  | mon_info.cbSize = sizeof(mon_info); | 
|  | GetMonitorInfoW(monitor, &mon_info); | 
|  |  | 
|  | if (rect.bottom > mon_info.rcWork.bottom) | 
|  | { | 
|  | int shift = rect.bottom - mon_info.rcWork.bottom; | 
|  | rect.top -= shift; | 
|  | rect.bottom -= shift; | 
|  | } | 
|  | if (rect.left < 0) | 
|  | { | 
|  | rect.right -= rect.left; | 
|  | rect.left = 0; | 
|  | } | 
|  | if (rect.right > mon_info.rcWork.right) | 
|  | { | 
|  | int shift = rect.right - mon_info.rcWork.right; | 
|  | rect.left -= shift; | 
|  | rect.right -= shift; | 
|  | } | 
|  | } | 
|  |  | 
|  | SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE); | 
|  |  | 
|  | TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen); | 
|  |  | 
|  | if (oldfont) | 
|  | SelectObject(hdc,oldfont); | 
|  | } | 
|  |  | 
|  | ImmUnlockIMCC(root_context->IMC.hCompStr); | 
|  |  | 
|  | EndPaint(hwnd,&ps); | 
|  | } | 
|  |  | 
|  | static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable) | 
|  | { | 
|  | LPCOMPOSITIONSTRING compstr; | 
|  |  | 
|  | if (root_context->IMC.hCompStr) | 
|  | compstr = ImmLockIMCC(root_context->IMC.hCompStr); | 
|  | else | 
|  | compstr = NULL; | 
|  |  | 
|  | if (compstr == NULL || compstr->dwCompStrLen == 0) | 
|  | ShowWindow(hwndDefault,SW_HIDE); | 
|  | else if (showable) | 
|  | ShowWindow(hwndDefault,SW_SHOWNOACTIVATE); | 
|  |  | 
|  | RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE); | 
|  |  | 
|  | if (compstr != NULL) | 
|  | ImmUnlockIMCC(root_context->IMC.hCompStr); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * The window proc for the default IME window | 
|  | */ | 
|  | static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, | 
|  | LPARAM lParam) | 
|  | { | 
|  | LRESULT rc = 0; | 
|  |  | 
|  | TRACE("Incoming Message 0x%x  (0x%08x, 0x%08x)\n", msg, (UINT)wParam, | 
|  | (UINT)lParam); | 
|  |  | 
|  | switch(msg) | 
|  | { | 
|  | case WM_PAINT: | 
|  | PaintDefaultIMEWnd(hwnd); | 
|  | return FALSE; | 
|  |  | 
|  | case WM_NCCREATE: | 
|  | return TRUE; | 
|  |  | 
|  | case WM_CREATE: | 
|  | SetWindowTextA(hwnd,"Wine Ime Active"); | 
|  | return TRUE; | 
|  |  | 
|  | case WM_SETFOCUS: | 
|  | if (wParam) | 
|  | SetFocus((HWND)wParam); | 
|  | else | 
|  | FIXME("Received focus, should never have focus\n"); | 
|  | break; | 
|  | case WM_IME_COMPOSITION: | 
|  | TRACE("IME message %s, 0x%x, 0x%x (%i)\n", | 
|  | "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam, | 
|  | root_context->bRead); | 
|  | if (lParam & GCS_RESULTSTR) | 
|  | IMM_PostResult(root_context); | 
|  | else | 
|  | UpdateDataInDefaultIMEWindow(hwnd,TRUE); | 
|  | break; | 
|  | case WM_IME_STARTCOMPOSITION: | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n", | 
|  | "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam); | 
|  | root_context->IMC.hWnd = GetFocus(); | 
|  | ShowWindow(hwndDefault,SW_SHOWNOACTIVATE); | 
|  | break; | 
|  | case WM_IME_ENDCOMPOSITION: | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n", | 
|  | "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam); | 
|  | ShowWindow(hwndDefault,SW_HIDE); | 
|  | break; | 
|  | case WM_IME_SELECT: | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | break; | 
|  | case WM_IME_CONTROL: | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | rc = 1; | 
|  | break; | 
|  | case WM_IME_NOTIFY: | 
|  | TRACE("!! IME NOTIFY\n"); | 
|  | break; | 
|  | default: | 
|  | TRACE("Non-standard message 0x%x\n",msg); | 
|  | } | 
|  | /* check the MSIME messages */ | 
|  | if (msg == WM_MSIME_SERVICE) | 
|  | { | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | rc = FALSE; | 
|  | } | 
|  | else if (msg == WM_MSIME_RECONVERTOPTIONS) | 
|  | { | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | } | 
|  | else if (msg == WM_MSIME_MOUSE) | 
|  | { | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | } | 
|  | else if (msg == WM_MSIME_RECONVERTREQUEST) | 
|  | { | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | } | 
|  | else if (msg == WM_MSIME_RECONVERT) | 
|  | { | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | } | 
|  | else if (msg == WM_MSIME_QUERYPOSITION) | 
|  | { | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | } | 
|  | else if (msg == WM_MSIME_DOCUMENTFEED) | 
|  | { | 
|  | TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED", | 
|  | (UINT)wParam, (UINT)lParam); | 
|  | } | 
|  | /* DefWndProc if not an IME message */ | 
|  | else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || | 
|  | (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP))) | 
|  | rc = DefWindowProcW(hwnd,msg,wParam,lParam); | 
|  |  | 
|  | return rc; | 
|  | } |