From aeda2ffa1013f868db944fedd79466adc4081932 Mon Sep 17 00:00:00 2001 From: Christoph von Wittich Date: Sun, 7 Mar 2010 11:27:14 +0000 Subject: [PATCH] [IMM32] sync imm32 to wine 1.1.40 svn path=/trunk/; revision=45987 --- reactos/dll/win32/imm32/imm.c | 2895 +++++++++++++++------------- reactos/dll/win32/imm32/imm32.spec | 15 +- 2 files changed, 1598 insertions(+), 1312 deletions(-) diff --git a/reactos/dll/win32/imm32/imm.c b/reactos/dll/win32/imm32/imm.c index 4ba1d631313..6f9744872b6 100644 --- a/reactos/dll/win32/imm32/imm.c +++ b/reactos/dll/win32/imm32/imm.c @@ -20,6 +20,7 @@ */ #include +#include #include "windef.h" #include "winbase.h" @@ -35,10 +36,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm); -#define FROM_IME 0xcafe1337 - -static void (*pX11DRV_ForceXIMReset)(HWND); - typedef struct tagIMCCInternal { DWORD dwLock; @@ -76,15 +73,12 @@ typedef struct _tagImmHkl{ typedef struct tagInputContextData { - BOOL bInternalState; - BOOL bRead; - BOOL bInComposition; - HFONT textfont; - DWORD dwLock; INPUTCONTEXT IMC; ImmHkl *immKbd; + HWND imeWnd; + UINT lastVK; } InputContextData; typedef struct _tagTRANSMSG { @@ -93,12 +87,12 @@ typedef struct _tagTRANSMSG { LPARAM lParam; } TRANSMSG, *LPTRANSMSG; -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; +typedef struct _tagIMMThreadData { + HIMC defaultContext; + HWND hwndDefault; +} IMMThreadData; +static DWORD tlsIndex = 0; static struct list ImmHklList = LIST_INIT(ImmHklList); /* MSIME messages */ @@ -111,15 +105,174 @@ static UINT WM_MSIME_QUERYPOSITION; static UINT WM_MSIME_DOCUMENTFEED; static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0}; -/* - * prototypes - */ -static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, - LPARAM lParam); -static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable); -static void ImmInternalPostIMEMessage(InputContextData*, UINT, WPARAM, LPARAM); -static void ImmInternalSetOpenStatus(BOOL fOpen); -static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len); + +static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0}; +static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0}; +static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0}; + + +#define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE) +#define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE) + +static BOOL IMM_DestroyContext(HIMC hIMC); + +static inline WCHAR *strdupAtoW( const char *str ) +{ + WCHAR *ret = NULL; + if (str) + { + DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 ); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) + MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len ); + } + return ret; +} + +static inline CHAR *strdupWtoA( const WCHAR *str ) +{ + CHAR *ret = NULL; + if (str) + { + DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL ); + if ((ret = HeapAlloc( GetProcessHeap(), 0, len ))) + WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL ); + } + return ret; +} + +static DWORD convert_candidatelist_WtoA( + LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen) +{ + DWORD ret, i, len; + + ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] ); + if ( lpDst && dwBufLen > 0 ) + { + *lpDst = *lpSrc; + lpDst->dwOffset[0] = ret; + } + + for ( i = 0; i < lpSrc->dwCount; i++) + { + LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i]; + + if ( lpDst && dwBufLen > 0 ) + { + LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i]; + + len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, + (LPSTR)dest, dwBufLen, NULL, NULL); + + if ( i + 1 < lpSrc->dwCount ) + lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char); + dwBufLen -= len * sizeof(char); + } + else + len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL); + + ret += len * sizeof(char); + } + + if ( lpDst ) + lpDst->dwSize = ret; + + return ret; +} + +static DWORD convert_candidatelist_AtoW( + LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen) +{ + DWORD ret, i, len; + + ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] ); + if ( lpDst && dwBufLen > 0 ) + { + *lpDst = *lpSrc; + lpDst->dwOffset[0] = ret; + } + + for ( i = 0; i < lpSrc->dwCount; i++) + { + LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i]; + + if ( lpDst && dwBufLen > 0 ) + { + LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i]; + + len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, + (LPWSTR)dest, dwBufLen); + + if ( i + 1 < lpSrc->dwCount ) + lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR); + dwBufLen -= len * sizeof(WCHAR); + } + else + len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0); + + ret += len * sizeof(WCHAR); + } + + if ( lpDst ) + lpDst->dwSize = ret; + + return ret; +} + +static IMMThreadData* IMM_GetThreadData(void) +{ + IMMThreadData* data = TlsGetValue(tlsIndex); + if (!data) + { + data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(IMMThreadData)); + TlsSetValue(tlsIndex,data); + TRACE("Thread Data Created\n"); + } + return data; +} + +static void IMM_FreeThreadData(void) +{ + IMMThreadData* data = TlsGetValue(tlsIndex); + if (data) + { + IMM_DestroyContext(data->defaultContext); + DestroyWindow(data->hwndDefault); + HeapFree(GetProcessHeap(),0,data); + TRACE("Thread Data Destroyed\n"); + } +} + +static HMODULE LoadDefaultWineIME(void) +{ + char buffer[MAX_PATH], libname[32], *name, *next; + HMODULE module = 0; + HKEY hkey; + + TRACE("Attempting to fall back to wine default IME\n"); + + strcpy( buffer, "x11" ); /* default value */ + /* @@ Wine registry key: HKCU\Software\Wine\Drivers */ + if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey )) + { + DWORD type, count = sizeof(buffer); + RegQueryValueExA( hkey, "Ime", 0, &type, (LPBYTE) buffer, &count ); + RegCloseKey( hkey ); + } + + name = buffer; + while (name) + { + next = strchr( name, ',' ); + if (next) *next++ = 0; + + snprintf( libname, sizeof(libname), "wine%s.drv", name ); + if ((module = LoadLibraryA( libname )) != 0) break; + name = next; + } + + return module; +} /* ImmHkl loading and freeing */ #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);} @@ -128,7 +281,7 @@ static ImmHkl *IMM_GetImmHkl(HKL hkl) ImmHkl *ptr; WCHAR filename[MAX_PATH]; - TRACE("Seeking ime for keyboard 0x%x\n",(unsigned)hkl); + TRACE("Seeking ime for keyboard %p\n",hkl); LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry) { @@ -141,32 +294,49 @@ static ImmHkl *IMM_GetImmHkl(HKL hkl) ptr->hkl = hkl; if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename); + if (!ptr->hIME) + ptr->hIME = LoadDefaultWineIME(); if (ptr->hIME) { LOAD_FUNCPTR(ImeInquire); - LOAD_FUNCPTR(ImeDestroy); - LOAD_FUNCPTR(ImeSelect); - if (!ptr->pImeInquire || !ptr->pImeDestroy || !ptr->pImeSelect) + if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL)) { FreeLibrary(ptr->hIME); ptr->hIME = NULL; } else { - ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL); - LOAD_FUNCPTR(ImeConfigure); - LOAD_FUNCPTR(ImeEscape); - LOAD_FUNCPTR(ImeSetActiveContext); - LOAD_FUNCPTR(ImeToAsciiEx); - LOAD_FUNCPTR(NotifyIME); - LOAD_FUNCPTR(ImeRegisterWord); - LOAD_FUNCPTR(ImeUnregisterWord); - LOAD_FUNCPTR(ImeEnumRegisterWord); - LOAD_FUNCPTR(ImeSetCompositionString); - LOAD_FUNCPTR(ImeConversionList); - LOAD_FUNCPTR(ImeProcessKey); - LOAD_FUNCPTR(ImeGetRegisterWordStyle); - LOAD_FUNCPTR(ImeGetImeMenuItems); + LOAD_FUNCPTR(ImeDestroy); + LOAD_FUNCPTR(ImeSelect); + if (!ptr->pImeSelect || !ptr->pImeDestroy) + { + FreeLibrary(ptr->hIME); + ptr->hIME = NULL; + } + else + { + LOAD_FUNCPTR(ImeConfigure); + LOAD_FUNCPTR(ImeEscape); + LOAD_FUNCPTR(ImeSetActiveContext); + LOAD_FUNCPTR(ImeToAsciiEx); + LOAD_FUNCPTR(NotifyIME); + LOAD_FUNCPTR(ImeRegisterWord); + LOAD_FUNCPTR(ImeUnregisterWord); + LOAD_FUNCPTR(ImeEnumRegisterWord); + LOAD_FUNCPTR(ImeSetCompositionString); + LOAD_FUNCPTR(ImeConversionList); + LOAD_FUNCPTR(ImeProcessKey); + LOAD_FUNCPTR(ImeGetRegisterWordStyle); + LOAD_FUNCPTR(ImeGetImeMenuItems); + /* make sure our classname is WCHAR */ + if (!is_kbd_ime_unicode(ptr)) + { + WCHAR bufW[17]; + MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName, + -1, bufW, 17); + lstrcpyW(ptr->imeClassName, bufW); + } + } } } list_add_head(&ImmHklList,&ptr->entry); @@ -191,54 +361,6 @@ static void IMM_FreeAllImmHkl(void) } } -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 (root_context, 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"); @@ -250,29 +372,26 @@ static void IMM_RegisterMessages(void) 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"); + tlsIndex = TlsAlloc(); + if (tlsIndex == TLS_OUT_OF_INDEXES) + return FALSE; + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + IMM_FreeThreadData(); break; case DLL_PROCESS_DETACH: - if (hwndDefault) - { - DestroyWindow(hwndDefault); - hwndDefault = 0; - } - IMM_Unregister(); + IMM_FreeThreadData(); IMM_FreeAllImmHkl(); + TlsFree(tlsIndex); break; } return TRUE; @@ -306,337 +425,25 @@ static HIMCC ImmCreateBlankCompStr(void) HIMCC rc; LPCOMPOSITIONSTRING ptr; rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING)); - ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc); + ptr = ImmLockIMCC(rc); memset(ptr,0,sizeof(COMPOSITIONSTRING)); ptr->dwSize = sizeof(COMPOSITIONSTRING); ImmUnlockIMCC(rc); return rc; } -static void ImmInternalSetOpenStatus(BOOL fOpen) -{ - TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED"); - - if (root_context->IMC.fOpen && fOpen == FALSE) - { - ShowWindow(hwndDefault,SW_HIDE); - ImmDestroyIMCC(root_context->IMC.hCompStr); - root_context->IMC.hCompStr = ImmCreateBlankCompStr(); - } - - root_context->IMC.fOpen = fOpen; - root_context->bInternalState = fOpen; - - ImmInternalSendIMENotify(root_context, 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 && compstr == NULL && len == 0) - return NULL; - - 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 && resultstr == NULL && len == 0) - return NULL; - - 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) { HIMC old = NULL; - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("(%p, %p):\n", hWnd, hIMC); - /* - * WINE SPECIFIC! MAY CONFLICT - * associate the root context we have an XIM created - */ - if (hWnd == 0x000) - { - root_context = (InputContextData*)hIMC; - } + if (!IMM_GetThreadData()->defaultContext) + IMM_GetThreadData()->defaultContext = ImmCreateContext(); /* * If already associated just return @@ -646,19 +453,26 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC) if (hWnd) { - old = (HIMC)RemovePropW(hWnd,szwWineIMCProperty); + old = RemovePropW(hWnd,szwWineIMCProperty); if (old == NULL) - old = (HIMC)root_context; + old = IMM_GetThreadData()->defaultContext; else if (old == (HIMC)-1) old = NULL; - if (hIMC != (HIMC)root_context) + if (hIMC != IMM_GetThreadData()->defaultContext) { if (hIMC == NULL) /* Meaning disable imm for that window*/ SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1); else - SetPropW(hWnd,szwWineIMCProperty,(HANDLE)hIMC); + SetPropW(hWnd,szwWineIMCProperty,hIMC); + } + + if (old) + { + InputContextData *old_data = old; + if (old_data->IMC.hWnd == hWnd) + old_data->IMC.hWnd = NULL; } } @@ -686,14 +500,48 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC) return old; } + +/* + * Helper function for ImmAssociateContextEx + */ +static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam) +{ + HIMC hImc = (HIMC)lParam; + ImmAssociateContext(hwnd,hImc); + return TRUE; +} + /*********************************************************************** * 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; + TRACE("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags); + + if (!IMM_GetThreadData()->defaultContext) + IMM_GetThreadData()->defaultContext = ImmCreateContext(); + + if (dwFlags == IACE_DEFAULT) + { + ImmAssociateContext(hWnd,IMM_GetThreadData()->defaultContext); + return TRUE; + } + else if (dwFlags == IACE_IGNORENOCONTEXT) + { + if (GetPropW(hWnd,szwWineIMCProperty)) + ImmAssociateContext(hWnd,hIMC); + return TRUE; + } + else if (dwFlags == IACE_CHILDREN) + { + EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC); + return TRUE; + } + else + { + ERR("Unknown dwFlags 0x%x\n",dwFlags); + return FALSE; + } } /*********************************************************************** @@ -702,11 +550,33 @@ BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + + TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData); + + if (dwMode == IME_CONFIG_REGISTERWORD && !lpData) + return FALSE; + + if (immHkl->hIME && immHkl->pImeConfigure) + { + if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl)) + return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData); + else + { + REGISTERWORDW rww; + REGISTERWORDA *rwa = lpData; + BOOL rc; + + rww.lpReading = strdupAtoW(rwa->lpReading); + rww.lpWord = strdupAtoW(rwa->lpWord); + rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww); + HeapFree(GetProcessHeap(),0,rww.lpReading); + HeapFree(GetProcessHeap(),0,rww.lpWord); + return rc; + } + } + else + return FALSE; } /*********************************************************************** @@ -715,11 +585,33 @@ BOOL WINAPI ImmConfigureIMEA( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + + TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData); + + if (dwMode == IME_CONFIG_REGISTERWORD && !lpData) + return FALSE; + + if (immHkl->hIME && immHkl->pImeConfigure) + { + if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl)) + return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData); + else + { + REGISTERWORDW *rww = lpData; + REGISTERWORDA rwa; + BOOL rc; + + rwa.lpReading = strdupWtoA(rww->lpReading); + rwa.lpWord = strdupWtoA(rww->lpWord); + rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa); + HeapFree(GetProcessHeap(),0,rwa.lpReading); + HeapFree(GetProcessHeap(),0,rwa.lpWord); + return rc; + } + } + else + return FALSE; } /*********************************************************************** @@ -728,54 +620,67 @@ BOOL WINAPI ImmConfigureIMEW( HIMC WINAPI ImmCreateContext(void) { InputContextData *new_context; + LPGUIDELINE gl; + LPCANDIDATEINFO ci; new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData)); /* Load the IME */ new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0)); - /* - * Once we depend on the IME for all the processing like we should - * these will become hard errors and result in creation failures - */ if (!new_context->immKbd->hIME) + { TRACE("IME dll could not be loaded\n"); + HeapFree(GetProcessHeap(),0,new_context); + return 0; + } - /* hCompStr is never NULL */ + /* the HIMCCs are never NULL */ new_context->IMC.hCompStr = ImmCreateBlankCompStr(); - new_context->IMC.hMsgBuf = ImmCreateIMCC(1); + new_context->IMC.hMsgBuf = ImmCreateIMCC(0); + new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO)); + ci = ImmLockIMCC(new_context->IMC.hCandInfo); + memset(ci,0,sizeof(CANDIDATEINFO)); + ci->dwSize = sizeof(CANDIDATEINFO); + ImmUnlockIMCC(new_context->IMC.hCandInfo); + new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE)); + gl = ImmLockIMCC(new_context->IMC.hGuideLine); + memset(gl,0,sizeof(GUIDELINE)); + gl->dwSize = sizeof(GUIDELINE); + ImmUnlockIMCC(new_context->IMC.hGuideLine); /* Initialize the IME Private */ new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize); - if (new_context->immKbd->hIME && - !new_context->immKbd->pImeSelect(new_context, TRUE)) + if (!new_context->immKbd->pImeSelect(new_context, TRUE)) { TRACE("Selection of IME failed\n"); - ImmDestroyContext(new_context); + IMM_DestroyContext(new_context); return 0; } + SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)GetKeyboardLayout(0)); new_context->immKbd->uSelected++; - TRACE("Created context 0x%x\n",(UINT)new_context); + TRACE("Created context %p\n",new_context); - return (HIMC)new_context; + return new_context; } -/*********************************************************************** - * ImmDestroyContext (IMM32.@) - */ -BOOL WINAPI ImmDestroyContext(HIMC hIMC) +static BOOL IMM_DestroyContext(HIMC hIMC) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("Destroying %p\n",hIMC); if (hIMC) { data->immKbd->uSelected --; - if (data->immKbd->hIME) - data->immKbd->pImeSelect(hIMC, FALSE); + data->immKbd->pImeSelect(hIMC, FALSE); + SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0)); + + if (IMM_GetThreadData()->hwndDefault == data->imeWnd) + IMM_GetThreadData()->hwndDefault = NULL; + DestroyWindow(data->imeWnd); ImmDestroyIMCC(data->IMC.hCompStr); ImmDestroyIMCC(data->IMC.hCandInfo); @@ -783,17 +688,22 @@ BOOL WINAPI ImmDestroyContext(HIMC hIMC) ImmDestroyIMCC(data->IMC.hPrivate); ImmDestroyIMCC(data->IMC.hMsgBuf); - if (data->textfont) - { - DeleteObject(data->textfont); - data->textfont = NULL; - } - HeapFree(GetProcessHeap(),0,data); } return TRUE; } +/*********************************************************************** + * ImmDestroyContext (IMM32.@) + */ +BOOL WINAPI ImmDestroyContext(HIMC hIMC) +{ + if (hIMC != IMM_GetThreadData()->defaultContext) + return IMM_DestroyContext(hIMC); + else + return FALSE; +} + /*********************************************************************** * ImmDisableIME (IMM32.@) */ @@ -811,13 +721,31 @@ UINT WINAPI ImmEnumRegisterWordA( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc, + debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData); + if (immHkl->hIME && immHkl->pImeEnumRegisterWord) + { + if (!is_kbd_ime_unicode(immHkl)) + return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc, + (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData); + else + { + LPWSTR lpszwReading = strdupAtoW(lpszReading); + LPWSTR lpszwRegister = strdupAtoW(lpszRegister); + BOOL rc; + + rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc, + lpszwReading, dwStyle, lpszwRegister, + lpData); + + HeapFree(GetProcessHeap(),0,lpszwReading); + HeapFree(GetProcessHeap(),0,lpszwRegister); + return rc; + } + } + else + return 0; } /*********************************************************************** @@ -828,13 +756,40 @@ UINT WINAPI ImmEnumRegisterWordW( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc, + debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData); + if (immHkl->hIME && immHkl->pImeEnumRegisterWord) + { + if (is_kbd_ime_unicode(immHkl)) + return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle, + lpszRegister, lpData); + else + { + LPSTR lpszaReading = strdupWtoA(lpszReading); + LPSTR lpszaRegister = strdupWtoA(lpszRegister); + BOOL rc; + + rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading, + dwStyle, (LPCWSTR)lpszaRegister, lpData); + + HeapFree(GetProcessHeap(),0,lpszaReading); + HeapFree(GetProcessHeap(),0,lpszaRegister); + return rc; + } + } + else + return 0; +} + +static inline BOOL EscapeRequiresWA(UINT uEscape) +{ + if (uEscape == IME_ESC_GET_EUDC_DICTIONARY || + uEscape == IME_ESC_SET_EUDC_DICTIONARY || + uEscape == IME_ESC_IME_NAME || + uEscape == IME_ESC_GETHELPFILENAME) + return TRUE; + return FALSE; } /*********************************************************************** @@ -844,11 +799,32 @@ 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData); + + if (immHkl->hIME && immHkl->pImeEscape) + { + if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl)) + return immHkl->pImeEscape(hIMC,uEscape,lpData); + else + { + WCHAR buffer[81]; /* largest required buffer should be 80 */ + LRESULT rc; + if (uEscape == IME_ESC_SET_EUDC_DICTIONARY) + { + MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81); + rc = immHkl->pImeEscape(hIMC,uEscape,buffer); + } + else + { + rc = immHkl->pImeEscape(hIMC,uEscape,buffer); + WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL); + } + return rc; + } + } + else + return 0; } /*********************************************************************** @@ -858,26 +834,72 @@ 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData); + + if (immHkl->hIME && immHkl->pImeEscape) + { + if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl)) + return immHkl->pImeEscape(hIMC,uEscape,lpData); + else + { + CHAR buffer[81]; /* largest required buffer should be 80 */ + LRESULT rc; + if (uEscape == IME_ESC_SET_EUDC_DICTIONARY) + { + WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL); + rc = immHkl->pImeEscape(hIMC,uEscape,buffer); + } + else + { + rc = immHkl->pImeEscape(hIMC,uEscape,buffer); + MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80); + } + return rc; + } + } + else + return 0; } /*********************************************************************** * ImmGetCandidateListA (IMM32.@) */ DWORD WINAPI ImmGetCandidateListA( - HIMC hIMC, DWORD deIndex, + HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen) { - FIXME("(%p, %d, %p, %d): stub\n", - hIMC, deIndex, - lpCandList, dwBufLen - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + InputContextData *data = hIMC; + LPCANDIDATEINFO candinfo; + LPCANDIDATELIST candlist; + DWORD ret = 0; + + TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen); + + if (!data || !data->IMC.hCandInfo) + return 0; + + candinfo = ImmLockIMCC(data->IMC.hCandInfo); + if ( dwIndex >= candinfo->dwCount || + dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) ) + goto done; + + candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]); + if ( !candlist->dwSize || !candlist->dwCount ) + goto done; + + if ( !is_himc_ime_unicode(data) ) + { + ret = candlist->dwSize; + if ( lpCandList && dwBufLen >= ret ) + memcpy(lpCandList, candlist, ret); + } + else + ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen); + +done: + ImmUnlockIMCC(data->IMC.hCandInfo); + return ret; } /*********************************************************************** @@ -886,9 +908,30 @@ DWORD WINAPI ImmGetCandidateListA( DWORD WINAPI ImmGetCandidateListCountA( HIMC hIMC, LPDWORD lpdwListCount) { - FIXME("(%p, %p): stub\n", hIMC, lpdwListCount); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + InputContextData *data = hIMC; + LPCANDIDATEINFO candinfo; + DWORD ret, count; + + TRACE("%p, %p\n", hIMC, lpdwListCount); + + if (!data || !lpdwListCount || !data->IMC.hCandInfo) + return 0; + + candinfo = ImmLockIMCC(data->IMC.hCandInfo); + + *lpdwListCount = count = candinfo->dwCount; + + if ( !is_himc_ime_unicode(data) ) + ret = candinfo->dwSize; + else + { + ret = sizeof(CANDIDATEINFO); + while ( count-- ) + ret += ImmGetCandidateListA(hIMC, count, NULL, 0); + } + + ImmUnlockIMCC(data->IMC.hCandInfo); + return ret; } /*********************************************************************** @@ -897,35 +940,91 @@ DWORD WINAPI ImmGetCandidateListCountA( DWORD WINAPI ImmGetCandidateListCountW( HIMC hIMC, LPDWORD lpdwListCount) { - FIXME("(%p, %p): stub\n", hIMC, lpdwListCount); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + InputContextData *data = hIMC; + LPCANDIDATEINFO candinfo; + DWORD ret, count; + + TRACE("%p, %p\n", hIMC, lpdwListCount); + + if (!data || !lpdwListCount || !data->IMC.hCandInfo) + return 0; + + candinfo = ImmLockIMCC(data->IMC.hCandInfo); + + *lpdwListCount = count = candinfo->dwCount; + + if ( is_himc_ime_unicode(data) ) + ret = candinfo->dwSize; + else + { + ret = sizeof(CANDIDATEINFO); + while ( count-- ) + ret += ImmGetCandidateListW(hIMC, count, NULL, 0); + } + + ImmUnlockIMCC(data->IMC.hCandInfo); + return ret; } /*********************************************************************** * ImmGetCandidateListW (IMM32.@) */ DWORD WINAPI ImmGetCandidateListW( - HIMC hIMC, DWORD deIndex, + HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen) { - FIXME("(%p, %d, %p, %d): stub\n", - hIMC, deIndex, - lpCandList, dwBufLen - ); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; + InputContextData *data = hIMC; + LPCANDIDATEINFO candinfo; + LPCANDIDATELIST candlist; + DWORD ret = 0; + + TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen); + + if (!data || !data->IMC.hCandInfo) + return 0; + + candinfo = ImmLockIMCC(data->IMC.hCandInfo); + if ( dwIndex >= candinfo->dwCount || + dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) ) + goto done; + + candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]); + if ( !candlist->dwSize || !candlist->dwCount ) + goto done; + + if ( is_himc_ime_unicode(data) ) + { + ret = candlist->dwSize; + if ( lpCandList && dwBufLen >= ret ) + memcpy(lpCandList, candlist, ret); + } + else + ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen); + +done: + ImmUnlockIMCC(data->IMC.hCandInfo); + return ret; } /*********************************************************************** * ImmGetCandidateWindow (IMM32.@) */ BOOL WINAPI ImmGetCandidateWindow( - HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate) + HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate) { - FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + InputContextData *data = hIMC; + + TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate); + + if (!data || !lpCandidate) + return FALSE; + + if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) ) + return FALSE; + + *lpCandidate = data->IMC.cfCandForm[dwIndex]; + + return TRUE; } /*********************************************************************** @@ -939,13 +1038,13 @@ BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) TRACE("(%p, %p):\n", hIMC, lplf); rc = ImmGetCompositionFontW(hIMC,&lfW); - if (rc) - { - memcpy(lplf,&lfW,sizeof(LOGFONTA)); - WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName, + if (!rc || !lplf) + return FALSE; + + memcpy(lplf,&lfW,sizeof(LOGFONTA)); + WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName, LF_FACESIZE, NULL, NULL); - } - return rc; + return TRUE; } /*********************************************************************** @@ -953,11 +1052,11 @@ BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) */ BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("(%p, %p):\n", hIMC, lplf); - if (!data) + if (!data || !lplf) return FALSE; *lplf = data->IMC.lfFont.W; @@ -965,112 +1064,270 @@ BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) return TRUE; } + +/* Helpers for the GetCompositionString functions */ + +static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen, + BOOL unicode ) +{ + INT rc; + + if (is_himc_ime_unicode(data) && !unicode) + rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL); + else if (!is_himc_ime_unicode(data) && unicode) + rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR); + else + { + int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR); + memcpy( target, source, min(slen,tlen)*dlen); + rc = slen*dlen; + } + + return rc; +} + +static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen, + LPBYTE target, INT tlen, BOOL unicode ) +{ + INT rc; + + if (is_himc_ime_unicode(data) && !unicode) + { + rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL); + if (tlen) + { + const BYTE *src = source; + LPBYTE dst = target; + int i, j = 0, k = 0; + + if (rc < tlen) + tlen = rc; + for (i = 0; i < sslen; ++i) + { + int len; + + len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1, + NULL, 0, NULL, NULL); + for (; len > 0; --len) + { + dst[j++] = src[k]; + + if (j >= tlen) + goto end; + } + ++k; + } + end: + rc = j; + } + } + else if (!is_himc_ime_unicode(data) && unicode) + { + rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0); + if (tlen) + { + const BYTE *src = source; + LPBYTE dst = target; + int i, j = 0; + + if (rc < tlen) + tlen = rc; + for (i = 0; i < sslen; ++i) + { + if (IsDBCSLeadByte(((LPSTR)ssource)[i])) + continue; + + dst[j++] = src[i]; + + if (j >= tlen) + break; + } + rc = j; + } + } + else + { + memcpy( target, source, min(slen,tlen)); + rc = slen; + } + + return rc; +} + +static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen, + LPBYTE target, INT tlen, BOOL unicode ) +{ + INT rc; + + if (is_himc_ime_unicode(data) && !unicode) + { + if (tlen) + { + int i; + + if (slen < tlen) + tlen = slen; + tlen /= sizeof (DWORD); + for (i = 0; i < tlen; ++i) + { + ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, + ((DWORD *)source)[i], + NULL, 0, + NULL, NULL); + } + rc = sizeof (DWORD) * i; + } + else + rc = slen; + } + else if (!is_himc_ime_unicode(data) && unicode) + { + if (tlen) + { + int i; + + if (slen < tlen) + tlen = slen; + tlen /= sizeof (DWORD); + for (i = 0; i < tlen; ++i) + { + ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, + ((DWORD *)source)[i], + NULL, 0); + } + rc = sizeof (DWORD) * i; + } + else + rc = slen; + } + else + { + memcpy( target, source, min(slen,tlen)); + rc = slen; + } + + return rc; +} + +static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode) +{ + int rc; + + if (is_himc_ime_unicode(data) && !unicode) + { + rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL); + } + else if (!is_himc_ime_unicode(data) && unicode) + { + rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0); + } + else + rc = offset; + + return rc; +} + +static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, + DWORD dwBufLen, BOOL unicode) +{ + LONG rc = 0; + InputContextData *data = 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; + + switch (dwIndex) + { + case GCS_RESULTSTR: + TRACE("GCS_RESULTSTR\n"); + rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode); + break; + case GCS_COMPSTR: + TRACE("GCS_COMPSTR\n"); + rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode); + break; + case GCS_COMPATTR: + TRACE("GCS_COMPATTR\n"); + rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen, + compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, + lpBuf, dwBufLen, unicode); + break; + case GCS_COMPCLAUSE: + TRACE("GCS_COMPCLAUSE\n"); + rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen, + compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, + lpBuf, dwBufLen, unicode); + break; + case GCS_RESULTCLAUSE: + TRACE("GCS_RESULTCLAUSE\n"); + rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen, + compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, + lpBuf, dwBufLen, unicode); + break; + case GCS_RESULTREADSTR: + TRACE("GCS_RESULTREADSTR\n"); + rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode); + break; + case GCS_RESULTREADCLAUSE: + TRACE("GCS_RESULTREADCLAUSE\n"); + rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen, + compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, + lpBuf, dwBufLen, unicode); + break; + case GCS_COMPREADSTR: + TRACE("GCS_COMPREADSTR\n"); + rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode); + break; + case GCS_COMPREADATTR: + TRACE("GCS_COMPREADATTR\n"); + rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen, + compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, + lpBuf, dwBufLen, unicode); + break; + case GCS_COMPREADCLAUSE: + TRACE("GCS_COMPREADCLAUSE\n"); + rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen, + compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, + lpBuf, dwBufLen, unicode); + break; + case GCS_CURSORPOS: + TRACE("GCS_CURSORPOS\n"); + rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode); + break; + case GCS_DELTASTART: + TRACE("GCS_DELTASTART\n"); + rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode); + break; + default: + FIXME("Unhandled index 0x%x\n",dwIndex); + break; + } + + ImmUnlockIMCC(data->IMC.hCompStr); + + return rc; +} + /*********************************************************************** * 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; + return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE); } + /*********************************************************************** * ImmGetCompositionStringW (IMM32.@) */ @@ -1078,96 +1335,7 @@ 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; + return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE); } /*********************************************************************** @@ -1175,7 +1343,7 @@ LONG WINAPI ImmGetCompositionStringW( */ BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("(%p, %p)\n", hIMC, lpCompForm); @@ -1195,16 +1363,18 @@ HIMC WINAPI ImmGetContext(HWND hWnd) HIMC rc = NULL; TRACE("%p\n", hWnd); + if (!IMM_GetThreadData()->defaultContext) + IMM_GetThreadData()->defaultContext = ImmCreateContext(); - rc = (HIMC)GetPropW(hWnd,szwWineIMCProperty); + rc = GetPropW(hWnd,szwWineIMCProperty); if (rc == (HIMC)-1) rc = NULL; else if (rc == NULL) - rc = (HIMC)root_context; + rc = IMM_GetThreadData()->defaultContext; if (rc) { - InputContextData *data = (InputContextData*)rc; + InputContextData *data = rc; data->IMC.hWnd = hWnd; } TRACE("returning %p\n", rc); @@ -1220,11 +1390,34 @@ DWORD WINAPI ImmGetConversionListA( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst, + dwBufLen, uFlag); + if (immHkl->hIME && immHkl->pImeConversionList) + { + if (!is_kbd_ime_unicode(immHkl)) + return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag); + else + { + LPCANDIDATELIST lpwDst; + DWORD ret = 0, len; + LPWSTR pwSrc = strdupAtoW(pSrc); + + len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag); + lpwDst = HeapAlloc(GetProcessHeap(), 0, len); + if ( lpwDst ) + { + immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag); + ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen); + HeapFree(GetProcessHeap(), 0, lpwDst); + } + HeapFree(GetProcessHeap(), 0, pwSrc); + + return ret; + } + } + else + return 0; } /*********************************************************************** @@ -1235,11 +1428,34 @@ DWORD WINAPI ImmGetConversionListW( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst, + dwBufLen, uFlag); + if (immHkl->hIME && immHkl->pImeConversionList) + { + if (is_kbd_ime_unicode(immHkl)) + return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag); + else + { + LPCANDIDATELIST lpaDst; + DWORD ret = 0, len; + LPSTR paSrc = strdupWtoA(pSrc); + + len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag); + lpaDst = HeapAlloc(GetProcessHeap(), 0, len); + if ( lpaDst ) + { + immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag); + ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen); + HeapFree(GetProcessHeap(), 0, lpaDst); + } + HeapFree(GetProcessHeap(), 0, paSrc); + + return ret; + } + } + else + return 0; } /*********************************************************************** @@ -1248,11 +1464,18 @@ DWORD WINAPI ImmGetConversionListW( BOOL WINAPI ImmGetConversionStatus( HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence) { - TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence); + InputContextData *data = hIMC; + + TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence); + + if (!data) + return FALSE; + if (lpfdwConversion) - *lpfdwConversion = IME_CMODE_NATIVE; + *lpfdwConversion = data->IMC.fdwConversion; if (lpfdwSentence) - *lpfdwSentence = IME_SMODE_NONE; + *lpfdwSentence = data->IMC.fdwSentence; + return TRUE; } @@ -1261,26 +1484,8 @@ BOOL WINAPI ImmGetConversionStatus( */ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) { - static int shown = 0; - - if (!shown) { - FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context); - shown = 1; - } - - 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 hwndDefault; + TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault); + return IMM_GetThreadData()->hwndDefault; } /*********************************************************************** @@ -1391,15 +1596,12 @@ UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen) */ UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen) { - static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0}; - static const WCHAR fmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','x',0}; - HKEY hkey; DWORD length; DWORD rc; - WCHAR regKey[sizeof(fmt)/sizeof(WCHAR)+8]; + WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8]; - wsprintfW( regKey, fmt, (unsigned)hKL ); + wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL ); rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey); if (rc != ERROR_SUCCESS) { @@ -1440,7 +1642,7 @@ UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen) */ BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; if (!data) return FALSE; @@ -1455,40 +1657,24 @@ BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) { DWORD rc = 0; - TRACE("(%p, %d)\n", hKL, fdwIndex); + ImmHkl *kbd; - switch (fdwIndex) + TRACE("(%p, %d)\n", hKL, fdwIndex); + kbd = IMM_GetImmHkl(hKL); + + if (kbd && kbd->hIME) { - 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; + switch (fdwIndex) + { + case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break; + case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break; + case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break; + case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break; + case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break; + case IGP_GETIMEVERSION: rc = IMEVER_0400; break; + case IGP_UI: rc = 0; break; + default: rc = 0; + } } return rc; } @@ -1499,9 +1685,26 @@ DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf); + if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle) + { + if (!is_kbd_ime_unicode(immHkl)) + return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf); + else + { + STYLEBUFW sbw; + UINT rc; + + rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw); + WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1, + lpStyleBuf->szDescription, 32, NULL, NULL); + lpStyleBuf->dwStyle = sbw.dwStyle; + return rc; + } + } + else + return 0; } /*********************************************************************** @@ -1510,9 +1713,26 @@ UINT WINAPI ImmGetRegisterWordStyleA( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf); + if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle) + { + if (is_kbd_ime_unicode(immHkl)) + return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf); + else + { + STYLEBUFA sba; + UINT rc; + + rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba); + MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1, + lpStyleBuf->szDescription, 32); + lpStyleBuf->dwStyle = sba.dwStyle; + return rc; + } + } + else + return 0; } /*********************************************************************** @@ -1520,9 +1740,16 @@ UINT WINAPI ImmGetRegisterWordStyleW( */ BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) { - FIXME("(%p, %p): stub\n", hIMC, lpptPos); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + InputContextData *data = hIMC; + + TRACE("(%p, %p)\n", hIMC, lpptPos); + + if (!data || !lpptPos) + return FALSE; + + *lpptPos = data->IMC.ptStatusWndPos; + + return TRUE; } /*********************************************************************** @@ -1531,7 +1758,12 @@ BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) UINT WINAPI ImmGetVirtualKey(HWND hWnd) { OSVERSIONINFOA version; - FIXME("(%p): stub\n", hWnd); + InputContextData *data = ImmGetContext( hWnd ); + TRACE("%p\n", hWnd); + + if ( data ) + return data->lastVK; + GetVersionExA( &version ); switch(version.dwPlatformId) { @@ -1551,11 +1783,21 @@ UINT WINAPI ImmGetVirtualKey(HWND hWnd) 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; + LPWSTR lpszwIMEFileName; + LPWSTR lpszwLayoutText; + HKL hkl; + + TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName), + debugstr_a(lpszLayoutText)); + + lpszwIMEFileName = strdupAtoW(lpszIMEFileName); + lpszwLayoutText = strdupAtoW(lpszLayoutText); + + hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText); + + HeapFree(GetProcessHeap(),0,lpszwIMEFileName); + HeapFree(GetProcessHeap(),0,lpszwLayoutText); + return hkl; } /*********************************************************************** @@ -1564,11 +1806,56 @@ HKL WINAPI ImmInstallIMEA( 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; + INT lcid = GetUserDefaultLCID(); + INT count; + HKL hkl; + DWORD rc; + HKEY hkey; + WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8]; + + TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName), + debugstr_w(lpszLayoutText)); + + /* Start with 2. e001 will be blank and so default to the wine internal IME */ + count = 2; + + while (count < 0xfff) + { + DWORD disposition = 0; + + hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count ); + wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl); + + rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition); + if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY) + break; + else if (rc == ERROR_SUCCESS) + RegCloseKey(hkey); + + count++; + } + + if (count == 0xfff) + { + WARN("Unable to find slot to install IME\n"); + return 0; + } + + if (rc == ERROR_SUCCESS) + { + rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (LPBYTE)lpszIMEFileName, + (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR)); + if (rc == ERROR_SUCCESS) + rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (LPBYTE)lpszLayoutText, + (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR)); + RegCloseKey(hkey); + return hkl; + } + else + { + WARN("Unable to set IME registry values\n"); + return 0; + } } /*********************************************************************** @@ -1576,12 +1863,10 @@ HKL WINAPI ImmInstallIMEW( */ 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); + ImmHkl *ptr; + TRACE("(%p):\n", hKL); + ptr = IMM_GetImmHkl(hKL); + return (ptr && ptr->hIME); } /*********************************************************************** @@ -1604,11 +1889,11 @@ BOOL WINAPI ImmIsUIMessageA( (msg == WM_MSIME_DOCUMENTFEED)) { - if (!hwndDefault) + if (!IMM_GetThreadData()->hwndDefault) ImmGetDefaultIMEWnd(NULL); if (hWndIME == NULL) - PostMessageA(hwndDefault, msg, wParam, lParam); + PostMessageA(IMM_GetThreadData()->hwndDefault, msg, wParam, lParam); rc = TRUE; } @@ -1622,7 +1907,7 @@ 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); + TRACE("(%p, %d, %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) || @@ -1642,126 +1927,15 @@ BOOL WINAPI ImmIsUIMessageW( BOOL WINAPI ImmNotifyIME( HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) { - BOOL rc = FALSE; + InputContextData *data = hIMC; TRACE("(%p, %d, %d, %d)\n", hIMC, dwAction, dwIndex, dwValue); - if (!root_context) - return rc; + if (!data || ! data->immKbd->pNotifyIME) + return FALSE; - 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"); - { - BOOL send; - LPCOMPOSITIONSTRING lpCompStr; - - if (pX11DRV_ForceXIMReset) - pX11DRV_ForceXIMReset(root_context->IMC.hWnd); - - lpCompStr = ImmLockIMCC(root_context->IMC.hCompStr); - send = (lpCompStr->dwCompStrLen != 0); - ImmUnlockIMCC(root_context->IMC.hCompStr); - - ImmDestroyIMCC(root_context->IMC.hCompStr); - root_context->IMC.hCompStr = ImmCreateBlankCompStr(); - - if (send) - ImmInternalPostIMEMessage(root_context, 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 = 0; - 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; - - if (root_context->IMC.hCompStr) - { - 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(root_context, WM_IME_COMPOSITION, 0, - GCS_COMPSTR); - - ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, - param, - GCS_RESULTSTR|GCS_RESULTCLAUSE); - } - - ImmInternalPostIMEMessage(root_context, 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; + return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue); } /*********************************************************************** @@ -1770,11 +1944,28 @@ BOOL WINAPI ImmNotifyIME( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle, + debugstr_a(lpszRegister)); + if (immHkl->hIME && immHkl->pImeRegisterWord) + { + if (!is_kbd_ime_unicode(immHkl)) + return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle, + (LPCWSTR)lpszRegister); + else + { + LPWSTR lpszwReading = strdupAtoW(lpszReading); + LPWSTR lpszwRegister = strdupAtoW(lpszRegister); + BOOL rc; + + rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister); + HeapFree(GetProcessHeap(),0,lpszwReading); + HeapFree(GetProcessHeap(),0,lpszwRegister); + return rc; + } + } + else + return FALSE; } /*********************************************************************** @@ -1783,11 +1974,28 @@ BOOL WINAPI ImmRegisterWordA( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle, + debugstr_w(lpszRegister)); + if (immHkl->hIME && immHkl->pImeRegisterWord) + { + if (is_kbd_ime_unicode(immHkl)) + return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister); + else + { + LPSTR lpszaReading = strdupWtoA(lpszReading); + LPSTR lpszaRegister = strdupWtoA(lpszRegister); + BOOL rc; + + rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle, + (LPCWSTR)lpszaRegister); + HeapFree(GetProcessHeap(),0,lpszaReading); + HeapFree(GetProcessHeap(),0,lpszaRegister); + return rc; + } + } + else + return FALSE; } /*********************************************************************** @@ -1804,15 +2012,63 @@ BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC) return TRUE; } +/*********************************************************************** +* ImmRequestMessageA(IMM32.@) +*/ +LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam) +{ + InputContextData *data = hIMC; + + TRACE("%p %ld %ld\n", hIMC, wParam, wParam); + + if (data && IsWindow(data->IMC.hWnd)) + return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam); + + return 0; +} + +/*********************************************************************** +* ImmRequestMessageW(IMM32.@) +*/ +LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam) +{ + InputContextData *data = hIMC; + + TRACE("%p %ld %ld\n", hIMC, wParam, wParam); + + if (data && IsWindow(data->IMC.hWnd)) + return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam); + + return 0; +} + /*********************************************************************** * ImmSetCandidateWindow (IMM32.@) */ BOOL WINAPI ImmSetCandidateWindow( HIMC hIMC, LPCANDIDATEFORM lpCandidate) { - FIXME("(%p, %p): stub\n", hIMC, lpCandidate); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + InputContextData *data = hIMC; + + TRACE("(%p, %p)\n", hIMC, lpCandidate); + + if (!data || !lpCandidate) + return FALSE; + + TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n", + lpCandidate->dwIndex, lpCandidate->dwStyle, + lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y, + lpCandidate->rcArea.top, lpCandidate->rcArea.left, + lpCandidate->rcArea.bottom, lpCandidate->rcArea.right); + + if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) ) + return FALSE; + + data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate; + ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS); + ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex); + + return TRUE; } /*********************************************************************** @@ -1820,25 +2076,18 @@ BOOL WINAPI ImmSetCandidateWindow( */ BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("(%p, %p)\n", hIMC, lplf); - if (!data) + if (!data || !lplf) return FALSE; memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA)); MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName, LF_FACESIZE); - + ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT); ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0); - if (data->textfont) - { - DeleteObject(data->textfont); - data->textfont = NULL; - } - - data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W); return TRUE; } @@ -1847,21 +2096,16 @@ BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) */ BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("(%p, %p)\n", hIMC, lplf); - if (!data) + if (!data || !lplf) return FALSE; data->IMC.lfFont.W = *lplf; + ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT); ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0); - if (data->textfont) - { - DeleteObject(data->textfont); - data->textfont = NULL; - } - data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W); return TRUE; } @@ -1878,10 +2122,25 @@ BOOL WINAPI ImmSetCompositionStringA( WCHAR *CompBuffer = NULL; WCHAR *ReadBuffer = NULL; BOOL rc; + InputContextData *data = hIMC; - TRACE("(%p, %d, %p, %d, %p, %d): stub\n", + TRACE("(%p, %d, %p, %d, %p, %d):\n", hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); + if (!data) + return FALSE; + + if (!(dwIndex == SCS_SETSTR || + dwIndex == SCS_CHANGEATTR || + dwIndex == SCS_CHANGECLAUSE || + dwIndex == SCS_SETRECONVERTSTRING || + dwIndex == SCS_QUERYRECONVERTSTRING)) + return FALSE; + + if (!is_himc_ime_unicode(data)) + return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp, + dwCompLen, lpRead, dwReadLen); + comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0); if (comp_len) { @@ -1913,64 +2172,55 @@ BOOL WINAPI ImmSetCompositionStringW( LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen) { - DWORD flags = 0; - WCHAR wParam = 0; + DWORD comp_len; + DWORD read_len; + CHAR *CompBuffer = NULL; + CHAR *ReadBuffer = NULL; + BOOL rc; + InputContextData *data = hIMC; - TRACE("(%p, %d, %p, %d, %p, %d): stub\n", - hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); + TRACE("(%p, %d, %p, %d, %p, %d):\n", + hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); + if (!data) + return FALSE; - if (hIMC != (HIMC)FROM_IME) - FIXME("PROBLEM: This only sets the wine level string\n"); + if (!(dwIndex == SCS_SETSTR || + dwIndex == SCS_CHANGEATTR || + dwIndex == SCS_CHANGECLAUSE || + dwIndex == SCS_SETRECONVERTSTRING || + dwIndex == SCS_QUERYRECONVERTSTRING)) + return FALSE; - /* - * 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 (is_himc_ime_unicode(data)) + return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp, + dwCompLen, lpRead, dwReadLen); - if (lpRead && dwReadLen) - FIXME("Reading string unimplemented\n"); - - /* - * app operating this api to also receive the message from xim - */ - - if (dwIndex == SCS_SETSTR) + comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL, + NULL); + if (comp_len) { - HIMCC newCompStr; - if (!root_context->bInComposition) - { - ImmInternalPostIMEMessage(root_context, 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; - } + CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len); + WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len, + NULL, NULL); } - UpdateDataInDefaultIMEWindow(hwndDefault,FALSE); + read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL, + NULL); + if (read_len) + { + ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len); + WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len, + NULL, NULL); + } - ImmInternalPostIMEMessage(root_context, WM_IME_COMPOSITION, wParam, flags); + rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len, + ReadBuffer, read_len); - return TRUE; + HeapFree(GetProcessHeap(), 0, CompBuffer); + HeapFree(GetProcessHeap(), 0, ReadBuffer); + + return rc; } /*********************************************************************** @@ -1980,7 +2230,7 @@ BOOL WINAPI ImmSetCompositionWindow( HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) { BOOL reshow = FALSE; - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("(%p, %p)\n", hIMC, lpCompForm); TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle, @@ -1992,16 +2242,16 @@ BOOL WINAPI ImmSetCompositionWindow( data->IMC.cfCompForm = *lpCompForm; - if (IsWindowVisible(hwndDefault)) + if (IsWindowVisible(IMM_GetThreadData()->hwndDefault)) { reshow = TRUE; - ShowWindow(hwndDefault,SW_HIDE); + ShowWindow(IMM_GetThreadData()->hwndDefault,SW_HIDE); } /* FIXME: this is a partial stub */ if (reshow) - ShowWindow(hwndDefault,SW_SHOWNOACTIVATE); + ShowWindow(IMM_GetThreadData()->hwndDefault,SW_SHOWNOACTIVATE); ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0); return TRUE; @@ -2013,16 +2263,30 @@ BOOL WINAPI ImmSetCompositionWindow( BOOL WINAPI ImmSetConversionStatus( HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) { - static int shown = 0; + DWORD oldConversion, oldSentence; + InputContextData *data = hIMC; - if (!shown) { - FIXME("(%p, %d, %d): stub\n", - hIMC, fdwConversion, fdwSentence - ); - shown = 1; - } - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence); + + if (!data) + return FALSE; + + if ( fdwConversion != data->IMC.fdwConversion ) + { + oldConversion = data->IMC.fdwConversion; + data->IMC.fdwConversion = fdwConversion; + ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE); + ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0); + } + if ( fdwSentence != data->IMC.fdwSentence ) + { + oldSentence = data->IMC.fdwSentence; + data->IMC.fdwSentence = fdwSentence; + ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE); + ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0); + } + + return TRUE; } /*********************************************************************** @@ -2030,40 +2294,30 @@ BOOL WINAPI ImmSetConversionStatus( */ BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("%p %d\n", hIMC, fOpen); - if (hIMC == (HIMC)FROM_IME) - { - ImmInternalSetOpenStatus(fOpen); - ImmInternalSendIMENotify(root_context, IMN_SETOPENSTATUS, 0); - return TRUE; - } - if (!data) return FALSE; - if (fOpen != data->bInternalState) + if (data->imeWnd == NULL) { - if (fOpen == FALSE && pX11DRV_ForceXIMReset) - pX11DRV_ForceXIMReset(data->IMC.hWnd); - - if (fOpen == FALSE) - ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0); - else - ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0); - - ImmInternalSetOpenStatus(fOpen); - ImmInternalSetOpenStatus(!fOpen); - - if (data->IMC.fOpen == FALSE) - ImmInternalPostIMEMessage(data, WM_IME_ENDCOMPOSITION,0,0); - else - ImmInternalPostIMEMessage(data, WM_IME_STARTCOMPOSITION,0,0); - - return FALSE; + /* create the ime window */ + data->imeWnd = CreateWindowExW( WS_EX_TOOLWINDOW, + data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0, + 0, data->immKbd->hIME, 0); + SetWindowLongPtrW(data->imeWnd, IMMGWL_IMC, (LONG_PTR)data); + IMM_GetThreadData()->hwndDefault = data->imeWnd; } + + if (!fOpen != !data->IMC.fOpen) + { + data->IMC.fOpen = fOpen; + ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS); + ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0); + } + return TRUE; } @@ -2072,9 +2326,50 @@ BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) */ BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) { - FIXME("(%p, %p): stub\n", hIMC, lpptPos); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; + InputContextData *data = hIMC; + + TRACE("(%p, %p)\n", hIMC, lpptPos); + + if (!data || !lpptPos) + return FALSE; + + TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y); + + data->IMC.ptStatusWndPos = *lpptPos; + ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS); + ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0); + + return TRUE; +} + +/*********************************************************************** + * ImmCreateSoftKeyboard(IMM32.@) + */ +HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y) +{ + FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return 0; +} + +/*********************************************************************** + * ImmDestroySoftKeyboard(IMM32.@) + */ +BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd) +{ + FIXME("(%p): stub\n", hSoftWnd); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; +} + +/*********************************************************************** + * ImmShowSoftKeyboard(IMM32.@) + */ +BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow) +{ + FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; } /*********************************************************************** @@ -2093,11 +2388,28 @@ BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID) 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle, + debugstr_a(lpszUnregister)); + if (immHkl->hIME && immHkl->pImeUnregisterWord) + { + if (!is_kbd_ime_unicode(immHkl)) + return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle, + (LPCWSTR)lpszUnregister); + else + { + LPWSTR lpszwReading = strdupAtoW(lpszReading); + LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister); + BOOL rc; + + rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister); + HeapFree(GetProcessHeap(),0,lpszwReading); + HeapFree(GetProcessHeap(),0,lpszwUnregister); + return rc; + } + } + else + return FALSE; } /*********************************************************************** @@ -2106,11 +2418,28 @@ BOOL WINAPI ImmUnregisterWordA( 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; + ImmHkl *immHkl = IMM_GetImmHkl(hKL); + TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle, + debugstr_w(lpszUnregister)); + if (immHkl->hIME && immHkl->pImeUnregisterWord) + { + if (is_kbd_ime_unicode(immHkl)) + return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister); + else + { + LPSTR lpszaReading = strdupWtoA(lpszReading); + LPSTR lpszaUnregister = strdupWtoA(lpszUnregister); + BOOL rc; + + rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle, + (LPCWSTR)lpszaUnregister); + HeapFree(GetProcessHeap(),0,lpszaReading); + HeapFree(GetProcessHeap(),0,lpszaUnregister); + return rc; + } + } + else + return FALSE; } /*********************************************************************** @@ -2120,9 +2449,61 @@ 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; + InputContextData *data = hIMC; + TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType, + lpImeParentMenu, lpImeMenu, dwSize); + if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems) + { + if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu)) + return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, + (IMEMENUITEMINFOW*)lpImeParentMenu, + (IMEMENUITEMINFOW*)lpImeMenu, dwSize); + else + { + IMEMENUITEMINFOW lpImeParentMenuW; + IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL; + DWORD rc; + + if (lpImeParentMenu) + parent = &lpImeParentMenuW; + if (lpImeMenu) + { + int count = dwSize / sizeof(LPIMEMENUITEMINFOA); + dwSize = count * sizeof(IMEMENUITEMINFOW); + lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize); + } + else + lpImeMenuW = NULL; + + rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, + parent, lpImeMenuW, dwSize); + + if (lpImeParentMenu) + { + memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA)); + lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem; + WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString, + -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE, + NULL, NULL); + } + if (lpImeMenu && rc) + { + unsigned int i; + for (i = 0; i < rc; i++) + { + memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA)); + lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem; + WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString, + -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE, + NULL, NULL); + } + } + HeapFree(GetProcessHeap(),0,lpImeMenuW); + return rc; + } + } + else + return 0; } /*********************************************************************** @@ -2132,9 +2513,59 @@ 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; + InputContextData *data = hIMC; + TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType, + lpImeParentMenu, lpImeMenu, dwSize); + if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems) + { + if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu)) + return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, + lpImeParentMenu, lpImeMenu, dwSize); + else + { + IMEMENUITEMINFOA lpImeParentMenuA; + IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL; + DWORD rc; + + if (lpImeParentMenu) + parent = &lpImeParentMenuA; + if (lpImeMenu) + { + int count = dwSize / sizeof(LPIMEMENUITEMINFOW); + dwSize = count * sizeof(IMEMENUITEMINFOA); + lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize); + } + else + lpImeMenuA = NULL; + + rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType, + (IMEMENUITEMINFOW*)parent, + (IMEMENUITEMINFOW*)lpImeMenuA, dwSize); + + if (lpImeParentMenu) + { + memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA)); + lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem; + MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString, + -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE); + } + if (lpImeMenu && rc) + { + unsigned int i; + for (i = 0; i < rc; i++) + { + memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA)); + lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem; + MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString, + -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE); + } + } + HeapFree(GetProcessHeap(),0,lpImeMenuA); + return rc; + } + } + else + return 0; } /*********************************************************************** @@ -2142,7 +2573,7 @@ DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType, */ LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; if (!data) return NULL; @@ -2155,7 +2586,7 @@ LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) */ BOOL WINAPI ImmUnlockIMC(HIMC hIMC) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; data->dwLock--; return (data->dwLock!=0); } @@ -2165,7 +2596,7 @@ BOOL WINAPI ImmUnlockIMC(HIMC hIMC) */ DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; return data->dwLock; } @@ -2182,7 +2613,7 @@ HIMCC WINAPI ImmCreateIMCC(DWORD size) return NULL; internal->dwSize = size; - return (HIMCC)internal; + return internal; } /*********************************************************************** @@ -2200,7 +2631,7 @@ HIMCC WINAPI ImmDestroyIMCC(HIMCC block) LPVOID WINAPI ImmLockIMCC(HIMCC imcc) { IMCCInternal *internal; - internal = (IMCCInternal*) imcc; + internal = imcc; internal->dwLock ++; return internal + 1; @@ -2212,7 +2643,7 @@ LPVOID WINAPI ImmLockIMCC(HIMCC imcc) BOOL WINAPI ImmUnlockIMCC(HIMCC imcc) { IMCCInternal *internal; - internal = (IMCCInternal*) imcc; + internal = imcc; internal->dwLock --; return (internal->dwLock!=0); @@ -2224,7 +2655,7 @@ BOOL WINAPI ImmUnlockIMCC(HIMCC imcc) DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc) { IMCCInternal *internal; - internal = (IMCCInternal*) imcc; + internal = imcc; return internal->dwLock; } @@ -2237,7 +2668,7 @@ HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size) IMCCInternal *internal,*newone; int real_size = size + sizeof(IMCCInternal); - internal = (IMCCInternal*) imcc; + internal = imcc; newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size); newone->dwSize = size; @@ -2251,7 +2682,7 @@ HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size) DWORD WINAPI ImmGetIMCCSize(HIMCC imcc) { IMCCInternal *internal; - internal = (IMCCInternal*) imcc; + internal = imcc; return internal->dwSize; } @@ -2261,15 +2692,15 @@ DWORD WINAPI ImmGetIMCCSize(HIMCC imcc) */ BOOL WINAPI ImmGenerateMessage(HIMC hIMC) { - InputContextData *data = (InputContextData*)hIMC; + InputContextData *data = hIMC; TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf); if (data->IMC.dwNumMsgBuf > 0) { LPTRANSMSG lpTransMsg; - INT i; + DWORD i; - lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf); + lpTransMsg = ImmLockIMCC(data->IMC.hMsgBuf); for (i = 0; i < data->IMC.dwNumMsgBuf; i++) ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam); @@ -2281,252 +2712,106 @@ BOOL WINAPI ImmGenerateMessage(HIMC hIMC) return TRUE; } -/***** - * Internal functions to help with IME window management - */ -static void PaintDefaultIMEWnd(HWND hwnd) +/*********************************************************************** +* ImmTranslateMessage(IMM32.@) +* ( Undocumented, call internally and from user32.dll ) +*/ +BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData) { - PAINTSTRUCT ps; - RECT rect; - HDC hdc = BeginPaint(hwnd,&ps); - LPCOMPOSITIONSTRING compstr; - LPBYTE compdata = NULL; - HMONITOR monitor; - MONITORINFO mon_info; - INT offX=0, offY=0; + InputContextData *data; + HIMC imc = ImmGetContext(hwnd); + BYTE state[256]; + UINT scancode; + LPVOID list = 0; + UINT msg_count; + UINT uVirtKey; + static const DWORD list_count = 10; - GetClientRect(hwnd,&rect); - FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1)); + TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData); - 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; - 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); + if (imc) + data = imc; else - compstr = NULL; + return FALSE; - if (compstr == NULL || compstr->dwCompStrLen == 0) - ShowWindow(hwndDefault,SW_HIDE); - else if (showable) - ShowWindow(hwndDefault,SW_SHOWNOACTIVATE); + if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx) + return FALSE; - RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE); + GetKeyboardState(state); + scancode = lKeyData >> 0x10 & 0xff; - if (compstr != NULL) - ImmUnlockIMCC(root_context->IMC.hCompStr); + list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD)); + ((DWORD*)list)[0] = list_count; + + if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST) + { + WCHAR chr; + + if (!is_himc_ime_unicode(data)) + ToAscii(data->lastVK, scancode, state, &chr, 0); + else + ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0)); + uVirtKey = MAKELONG(data->lastVK,chr); + } + else + uVirtKey = data->lastVK; + + msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc); + TRACE("%i messages generated\n",msg_count); + if (msg_count && msg_count <= list_count) + { + UINT i; + LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD)); + + for (i = 0; i < msg_count; i++) + ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam); + } + else if (msg_count > list_count) + ImmGenerateMessage(imc); + + HeapFree(GetProcessHeap(),0,list); + + data->lastVK = VK_PROCESSKEY; + + return (msg_count > 0); } -/* - * The window proc for the default IME window - */ -static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, - LPARAM lParam) +/*********************************************************************** +* ImmProcessKey(IMM32.@) +* ( Undocumented, called from user32.dll ) +*/ +BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown) { - LRESULT rc = 0; + InputContextData *data; + HIMC imc = ImmGetContext(hwnd); + BYTE state[256]; - TRACE("Incoming Message 0x%x (0x%08x, 0x%08x)\n", msg, (UINT)wParam, - (UINT)lParam); + TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown); - switch(msg) - { - case WM_PAINT: - PaintDefaultIMEWnd(hwnd); - return FALSE; + if (imc) + data = imc; + else + return FALSE; - case WM_NCCREATE: - return TRUE; + if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey) + return FALSE; - case WM_CREATE: - SetWindowTextA(hwnd,"Wine Ime Active"); - return TRUE; + GetKeyboardState(state); + if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state)) + { + data->lastVK = vKey; + 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; + data->lastVK = VK_PROCESSKEY; + return FALSE; +} + +/*********************************************************************** +* ImmDisableTextFrameService(IMM32.@) +*/ +BOOL WINAPI ImmDisableTextFrameService(DWORD idThread) +{ + FIXME("Stub\n"); + return FALSE; } diff --git a/reactos/dll/win32/imm32/imm32.spec b/reactos/dll/win32/imm32/imm32.spec index 0ecd1f93fa8..0d053627d50 100644 --- a/reactos/dll/win32/imm32/imm32.spec +++ b/reactos/dll/win32/imm32/imm32.spec @@ -5,12 +5,13 @@ @ stdcall ImmConfigureIMEW(long long long ptr) @ stdcall ImmCreateContext() @ stdcall ImmCreateIMCC(long) -@ stub ImmCreateSoftKeyboard +@ stdcall ImmCreateSoftKeyboard(long long long long) @ stdcall ImmDestroyContext(long) @ stdcall ImmDestroyIMCC(long) -@ stub ImmDestroySoftKeyboard +@ stdcall ImmDestroySoftKeyboard(long) @ stdcall ImmDisableIME(long) @ stdcall ImmDisableIme(long) ImmDisableIME +@ stdcall ImmDisableTextFrameService(long) @ stub ImmEnumInputContext @ stdcall ImmEnumRegisterWordA(long ptr str long str ptr) @ stdcall ImmEnumRegisterWordW(long ptr wstr long wstr ptr) @@ -72,15 +73,15 @@ @ stub ImmLockImeDpi @ stdcall ImmNotifyIME(long long long long) @ stub ImmPenAuxInput -@ stub ImmProcessKey +@ stdcall ImmProcessKey(long long long long long) @ stub ImmPutImeMenuItemsIntoMappedFile @ stdcall ImmReSizeIMCC(long long) @ stub ImmRegisterClient @ stdcall ImmRegisterWordA(long str long str) @ stdcall ImmRegisterWordW(long wstr long wstr) @ stdcall ImmReleaseContext(long long) -@ stub ImmRequestMessageA -@ stub ImmRequestMessageW +@ stdcall ImmRequestMessageA(ptr long long) +@ stdcall ImmRequestMessageW(ptr long long) @ stub ImmSendIMEMessageExA @ stub ImmSendIMEMessageExW @ stub ImmSendMessageToActiveDefImeWndW @@ -96,10 +97,10 @@ #@ stdcall ImmSetHotKey(long long long ptr) user32.CliImmSetHotKey @ stdcall ImmSetOpenStatus(long long) @ stdcall ImmSetStatusWindowPos(long ptr) -@ stub ImmShowSoftKeyboard +@ stdcall ImmShowSoftKeyboard(long long) @ stdcall ImmSimulateHotKey(long long) @ stub ImmSystemHandler -@ stub ImmTranslateMessage +@ stdcall ImmTranslateMessage(long long long long) @ stub ImmUnlockClientImc @ stdcall ImmUnlockIMC(long) @ stdcall ImmUnlockIMCC(long)