/* * IMM32 library * * Copyright 1998 Patrik Stridvall * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include "windef.h" #include "winbase.h" #include "wingdi.h" #include "winuser.h" #include "winerror.h" #include "wine/debug.h" #include "imm.h" #include "ddk/imm.h" #include "winnls.h" #include "winreg.h" #include "wine/list.h" WINE_DEFAULT_DEBUG_CHANNEL(imm); typedef struct tagIMCCInternal { DWORD dwLock; DWORD dwSize; } IMCCInternal; #define MAKE_FUNCPTR(f) typeof(f) * p##f typedef struct _tagImmHkl{ struct list entry; HKL hkl; HMODULE hIME; IMEINFO imeInfo; WCHAR imeClassName[17]; /* 16 character max */ ULONG uSelected; /* Function Pointers */ MAKE_FUNCPTR(ImeInquire); MAKE_FUNCPTR(ImeConfigure); MAKE_FUNCPTR(ImeDestroy); MAKE_FUNCPTR(ImeEscape); MAKE_FUNCPTR(ImeSelect); MAKE_FUNCPTR(ImeSetActiveContext); MAKE_FUNCPTR(ImeToAsciiEx); MAKE_FUNCPTR(NotifyIME); MAKE_FUNCPTR(ImeRegisterWord); MAKE_FUNCPTR(ImeUnregisterWord); MAKE_FUNCPTR(ImeEnumRegisterWord); MAKE_FUNCPTR(ImeSetCompositionString); MAKE_FUNCPTR(ImeConversionList); MAKE_FUNCPTR(ImeProcessKey); MAKE_FUNCPTR(ImeGetRegisterWordStyle); MAKE_FUNCPTR(ImeGetImeMenuItems); } ImmHkl; #undef MAKE_FUNCPTR typedef struct tagInputContextData { DWORD dwLock; INPUTCONTEXT IMC; ImmHkl *immKbd; HWND imeWnd; } InputContextData; typedef struct _tagTRANSMSG { UINT message; WPARAM wParam; LPARAM lParam; } TRANSMSG, *LPTRANSMSG; static InputContextData *root_context = NULL; static HWND hwndDefault = NULL; static HANDLE hImeInst; static struct list ImmHklList = LIST_INIT(ImmHklList); /* MSIME messages */ static UINT WM_MSIME_SERVICE; static UINT WM_MSIME_RECONVERTOPTIONS; static UINT WM_MSIME_MOUSE; static UINT WM_MSIME_RECONVERTREQUEST; static UINT WM_MSIME_RECONVERT; static UINT WM_MSIME_QUERYPOSITION; static UINT WM_MSIME_DOCUMENTFEED; static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',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 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 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);} static ImmHkl *IMM_GetImmHkl(HKL hkl) { ImmHkl *ptr; WCHAR filename[MAX_PATH]; TRACE("Seeking ime for keyboard 0x%x\n",(unsigned)hkl); LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry) { if (ptr->hkl == hkl) return ptr; } /* not found... create it */ ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl)); 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); if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL)) { FreeLibrary(ptr->hIME); ptr->hIME = NULL; } else { 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); return ptr; } #undef LOAD_FUNCPTR static void IMM_FreeAllImmHkl(void) { ImmHkl *ptr,*cursor2; LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry) { list_remove(&ptr->entry); if (ptr->hIME) { ptr->pImeDestroy(1); FreeLibrary(ptr->hIME); } HeapFree(GetProcessHeap(),0,ptr); } } static void IMM_RegisterMessages(void) { WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions"); WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); } BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) { TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved); switch (fdwReason) { case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hInstDLL); hImeInst = hInstDLL; IMM_RegisterMessages(); break; case DLL_PROCESS_DETACH: IMM_FreeAllImmHkl(); break; } return TRUE; } /* for posting messages as the IME */ static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam) { HWND target = GetFocus(); if (!target) PostMessageW(data->IMC.hWnd,msg,wParam,lParam); else PostMessageW(target, msg, wParam, lParam); } static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam) { HWND target; target = data->IMC.hWnd; if (!target) target = GetFocus(); if (target) return SendMessageW(target, WM_IME_NOTIFY, notify, lParam); return 0; } static HIMCC ImmCreateBlankCompStr(void) { HIMCC rc; LPCOMPOSITIONSTRING ptr; rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING)); ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc); memset(ptr,0,sizeof(COMPOSITIONSTRING)); ptr->dwSize = sizeof(COMPOSITIONSTRING); ImmUnlockIMCC(rc); return rc; } /*********************************************************************** * ImmAssociateContext (IMM32.@) */ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC) { HIMC old = NULL; InputContextData *data = (InputContextData*)hIMC; TRACE("(%p, %p):\n", hWnd, hIMC); if (!root_context) root_context = ImmCreateContext(); /* * If already associated just return */ if (hIMC && data->IMC.hWnd == hWnd) return hIMC; if (hWnd) { old = (HIMC)RemovePropW(hWnd,szwWineIMCProperty); if (old == NULL) old = (HIMC)root_context; else if (old == (HIMC)-1) old = NULL; if (hIMC != (HIMC)root_context) { if (hIMC == NULL) /* Meaning disable imm for that window*/ SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1); else SetPropW(hWnd,szwWineIMCProperty,(HANDLE)hIMC); } } if (!hIMC) return old; if (IsWindow(data->IMC.hWnd)) { /* * Post a message that your context is switching */ SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL); } data->IMC.hWnd = hWnd; if (IsWindow(data->IMC.hWnd)) { /* * Post a message that your context is switching */ SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL); } return old; } /*********************************************************************** * ImmAssociateContextEx (IMM32.@) */ BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) { FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmConfigureIMEA (IMM32.@) */ BOOL WINAPI ImmConfigureIMEA( HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) { ImmHkl *immHkl = IMM_GetImmHkl(hKL); TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData); 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 = (REGISTERWORDA*)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; } /*********************************************************************** * ImmConfigureIMEW (IMM32.@) */ BOOL WINAPI ImmConfigureIMEW( HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) { ImmHkl *immHkl = IMM_GetImmHkl(hKL); TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData); 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 = (REGISTERWORDW*)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; } /*********************************************************************** * ImmCreateContext (IMM32.@) */ HIMC WINAPI ImmCreateContext(void) { InputContextData *new_context; new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData)); /* Load the IME */ new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0)); if (!new_context->immKbd->hIME) { TRACE("IME dll could not be loaded\n"); HeapFree(GetProcessHeap(),0,new_context); return 0; } /* hCompStr is never NULL */ new_context->IMC.hCompStr = ImmCreateBlankCompStr(); new_context->IMC.hMsgBuf = ImmCreateIMCC(1); /* Initialize the IME Private */ new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize); if (!new_context->immKbd->pImeSelect(new_context, TRUE)) { TRACE("Selection of IME failed\n"); ImmDestroyContext(new_context); return 0; } new_context->immKbd->uSelected++; TRACE("Created context 0x%x\n",(UINT)new_context); return (HIMC)new_context; } /*********************************************************************** * ImmDestroyContext (IMM32.@) */ BOOL WINAPI ImmDestroyContext(HIMC hIMC) { InputContextData *data = (InputContextData*)hIMC; TRACE("Destroying %p\n",hIMC); if (hIMC) { data->immKbd->uSelected --; data->immKbd->pImeSelect(hIMC, FALSE); if (hwndDefault == data->imeWnd) hwndDefault = NULL; DestroyWindow(data->imeWnd); ImmDestroyIMCC(data->IMC.hCompStr); ImmDestroyIMCC(data->IMC.hCandInfo); ImmDestroyIMCC(data->IMC.hGuideLine); ImmDestroyIMCC(data->IMC.hPrivate); ImmDestroyIMCC(data->IMC.hMsgBuf); HeapFree(GetProcessHeap(),0,data); } return TRUE; } /*********************************************************************** * ImmDisableIME (IMM32.@) */ BOOL WINAPI ImmDisableIME(DWORD idThread) { FIXME("(%d): stub\n", idThread); return TRUE; } /*********************************************************************** * ImmEnumRegisterWordA (IMM32.@) */ UINT WINAPI ImmEnumRegisterWordA( HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister, LPVOID lpData) { FIXME("(%p, %p, %s, %d, %s, %p): stub\n", hKL, lpfnEnumProc, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmEnumRegisterWordW (IMM32.@) */ UINT WINAPI ImmEnumRegisterWordW( HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister, LPVOID lpData) { FIXME("(%p, %p, %s, %d, %s, %p): stub\n", hKL, lpfnEnumProc, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmEscapeA (IMM32.@) */ LRESULT WINAPI ImmEscapeA( HKL hKL, HIMC hIMC, UINT uEscape, LPVOID lpData) { FIXME("(%p, %p, %d, %p): stub\n", hKL, hIMC, uEscape, lpData ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmEscapeW (IMM32.@) */ LRESULT WINAPI ImmEscapeW( HKL hKL, HIMC hIMC, UINT uEscape, LPVOID lpData) { FIXME("(%p, %p, %d, %p): stub\n", hKL, hIMC, uEscape, lpData ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetCandidateListA (IMM32.@) */ DWORD WINAPI ImmGetCandidateListA( HIMC hIMC, DWORD deIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen) { FIXME("(%p, %d, %p, %d): stub\n", hIMC, deIndex, lpCandList, dwBufLen ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetCandidateListCountA (IMM32.@) */ DWORD WINAPI ImmGetCandidateListCountA( HIMC hIMC, LPDWORD lpdwListCount) { FIXME("(%p, %p): stub\n", hIMC, lpdwListCount); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetCandidateListCountW (IMM32.@) */ DWORD WINAPI ImmGetCandidateListCountW( HIMC hIMC, LPDWORD lpdwListCount) { FIXME("(%p, %p): stub\n", hIMC, lpdwListCount); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetCandidateListW (IMM32.@) */ DWORD WINAPI ImmGetCandidateListW( HIMC hIMC, DWORD deIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen) { FIXME("(%p, %d, %p, %d): stub\n", hIMC, deIndex, lpCandList, dwBufLen ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetCandidateWindow (IMM32.@) */ BOOL WINAPI ImmGetCandidateWindow( HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate) { FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmGetCompositionFontA (IMM32.@) */ BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) { LOGFONTW lfW; BOOL rc; 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, LF_FACESIZE, NULL, NULL); } return rc; } /*********************************************************************** * ImmGetCompositionFontW (IMM32.@) */ BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) { InputContextData *data = (InputContextData*)hIMC; TRACE("(%p, %p):\n", hIMC, lplf); if (!data) return FALSE; *lplf = data->IMC.lfFont.W; return TRUE; } /*********************************************************************** * 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); HeapFree( GetProcessHeap(), 0, buf ); } else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 && compstr->dwCompStrOffset > 0) { LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset); TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen); buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 ); rc = WideCharToMultiByte(CP_ACP, 0, CompString, compstr->dwCompStrLen, buf, compstr->dwCompStrLen * 3, NULL, NULL); if (dwBufLen >= rc) memcpy(lpBuf,buf,rc); HeapFree( GetProcessHeap(), 0, buf ); } else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 && compstr->dwCompAttrOffset > 0) { LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset); TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen); rc = compstr->dwCompAttrLen; if (dwBufLen >= rc) memcpy(lpBuf,Compattr,rc); } else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 && compstr->dwCompClauseOffset > 0) { LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset); TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen); rc = compstr->dwCompClauseLen; if (dwBufLen >= compstr->dwCompClauseLen) memcpy(lpBuf,Compclause,rc); } else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 && compstr->dwResultClauseOffset > 0) { LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset); TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen); rc = compstr->dwResultClauseLen; if (dwBufLen >= compstr->dwResultClauseLen) memcpy(lpBuf,Resultclause,rc); } else if (dwIndex == GCS_CURSORPOS) { TRACE("GSC_CURSORPOS\n"); rc = compstr->dwCursorPos; } else if (dwIndex == GCS_DELTASTART) { TRACE("GCS_DELTASTART\n"); rc = compstr->dwDeltaStart; } else { FIXME("Unhandled index 0x%x\n",dwIndex); } ImmUnlockIMCC(data->IMC.hCompStr); return rc; } /*********************************************************************** * ImmGetCompositionStringW (IMM32.@) */ LONG WINAPI ImmGetCompositionStringW( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) { LONG rc = 0; InputContextData *data = (InputContextData*)hIMC; LPCOMPOSITIONSTRING compstr; LPBYTE compdata; TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen); if (!data) return FALSE; if (!data->IMC.hCompStr) return FALSE; compdata = ImmLockIMCC(data->IMC.hCompStr); compstr = (LPCOMPOSITIONSTRING)compdata; if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 && compstr->dwResultStrOffset > 0) { LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset); rc = compstr->dwResultStrLen * sizeof(WCHAR); if (dwBufLen >= rc) memcpy(lpBuf,ResultStr,rc); } else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 && compstr->dwResultReadStrOffset > 0) { LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset); rc = compstr->dwResultReadStrLen * sizeof(WCHAR); if (dwBufLen >= rc) memcpy(lpBuf,ResultReadString,rc); } else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 && compstr->dwCompStrOffset > 0) { LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset); rc = compstr->dwCompStrLen * sizeof(WCHAR); if (dwBufLen >= rc) memcpy(lpBuf,CompString,rc); } else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 && compstr->dwCompAttrOffset > 0) { LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset); rc = compstr->dwCompAttrLen; if (dwBufLen >= rc) memcpy(lpBuf,Compattr,rc); } else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 && compstr->dwCompClauseOffset > 0) { LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset); rc = compstr->dwCompClauseLen; if (dwBufLen >= compstr->dwCompClauseLen) memcpy(lpBuf,Compclause,rc); } else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 && compstr->dwCompReadStrOffset > 0) { LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset); rc = compstr->dwCompReadStrLen * sizeof(WCHAR); if (dwBufLen >= rc) memcpy(lpBuf,CompReadString,rc); } else if (dwIndex == GCS_CURSORPOS) { TRACE("GSC_CURSORPOS\n"); rc = compstr->dwCursorPos; } else if (dwIndex == GCS_DELTASTART) { TRACE("GCS_DELTASTART\n"); rc = compstr->dwDeltaStart; } else { FIXME("Unhandled index 0x%x\n",dwIndex); } ImmUnlockIMCC(data->IMC.hCompStr); return rc; } /*********************************************************************** * ImmGetCompositionWindow (IMM32.@) */ BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) { InputContextData *data = (InputContextData*)hIMC; TRACE("(%p, %p)\n", hIMC, lpCompForm); if (!data) return FALSE; *lpCompForm = data->IMC.cfCompForm; return 1; } /*********************************************************************** * ImmGetContext (IMM32.@) * */ HIMC WINAPI ImmGetContext(HWND hWnd) { HIMC rc = NULL; TRACE("%p\n", hWnd); if (!root_context) root_context = ImmCreateContext(); rc = (HIMC)GetPropW(hWnd,szwWineIMCProperty); if (rc == (HIMC)-1) rc = NULL; else if (rc == NULL) rc = (HIMC)root_context; if (rc) { InputContextData *data = (InputContextData*)rc; data->IMC.hWnd = hWnd; } TRACE("returning %p\n", rc); return rc; } /*********************************************************************** * ImmGetConversionListA (IMM32.@) */ DWORD WINAPI ImmGetConversionListA( HKL hKL, HIMC hIMC, LPCSTR pSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen, UINT uFlag) { FIXME("(%p, %p, %s, %p, %d, %d): stub\n", hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetConversionListW (IMM32.@) */ DWORD WINAPI ImmGetConversionListW( HKL hKL, HIMC hIMC, LPCWSTR pSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen, UINT uFlag) { FIXME("(%p, %p, %s, %p, %d, %d): stub\n", hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetConversionStatus (IMM32.@) */ BOOL WINAPI ImmGetConversionStatus( HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence) { TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence); if (lpfdwConversion) *lpfdwConversion = IME_CMODE_NATIVE; if (lpfdwSentence) *lpfdwSentence = IME_SMODE_NONE; return TRUE; } /*********************************************************************** * ImmGetDefaultIMEWnd (IMM32.@) */ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) { TRACE("Default is %x\n",(unsigned)hwndDefault); return hwndDefault; } /*********************************************************************** * ImmGetDescriptionA (IMM32.@) */ UINT WINAPI ImmGetDescriptionA( HKL hKL, LPSTR lpszDescription, UINT uBufLen) { WCHAR *buf; DWORD len; TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen); /* find out how many characters in the unicode buffer */ len = ImmGetDescriptionW( hKL, NULL, 0 ); /* allocate a buffer of that size */ buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) ); if( !buf ) return 0; /* fetch the unicode buffer */ len = ImmGetDescriptionW( hKL, buf, len + 1 ); /* convert it back to ASCII */ len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1, lpszDescription, uBufLen, NULL, NULL ); HeapFree( GetProcessHeap(), 0, buf ); return len; } /*********************************************************************** * ImmGetDescriptionW (IMM32.@) */ UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen) { static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 }; FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen); if (!uBufLen) return lstrlenW( name ); lstrcpynW( lpszDescription, name, uBufLen ); return lstrlenW( lpszDescription ); } /*********************************************************************** * ImmGetGuideLineA (IMM32.@) */ DWORD WINAPI ImmGetGuideLineA( HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen) { FIXME("(%p, %d, %s, %d): stub\n", hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetGuideLineW (IMM32.@) */ DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen) { FIXME("(%p, %d, %s, %d): stub\n", hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetIMEFileNameA (IMM32.@) */ UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen) { LPWSTR bufW = NULL; UINT wBufLen = uBufLen; UINT rc; if (uBufLen && lpszFileName) bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR)); else /* We need this to get the number of byte required */ { bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR)); wBufLen = MAX_PATH; } rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen); if (rc > 0) { if (uBufLen && lpszFileName) rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName, uBufLen, NULL, NULL); else /* get the length */ rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL, NULL); } HeapFree(GetProcessHeap(),0,bufW); return rc; } /*********************************************************************** * ImmGetIMEFileNameW (IMM32.@) */ 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]; wsprintfW( regKey, fmt, (unsigned)hKL ); rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey); if (rc != ERROR_SUCCESS) { SetLastError(rc); return 0; } length = 0; rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length); if (rc != ERROR_SUCCESS) { RegCloseKey(hkey); SetLastError(rc); return 0; } if (length > uBufLen * sizeof(WCHAR) || !lpszFileName) { RegCloseKey(hkey); if (lpszFileName) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return 0; } else return length / sizeof(WCHAR); } RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length); RegCloseKey(hkey); return length / sizeof(WCHAR); } /*********************************************************************** * ImmGetOpenStatus (IMM32.@) */ BOOL WINAPI ImmGetOpenStatus(HIMC hIMC) { InputContextData *data = (InputContextData*)hIMC; if (!data) return FALSE; FIXME("(%p): semi-stub\n", hIMC); return data->IMC.fOpen; } /*********************************************************************** * ImmGetProperty (IMM32.@) */ DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) { DWORD rc = 0; ImmHkl *kbd; TRACE("(%p, %d)\n", hKL, fdwIndex); kbd = IMM_GetImmHkl(hKL); if (kbd && kbd->hIME) { 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; } /*********************************************************************** * ImmGetRegisterWordStyleA (IMM32.@) */ UINT WINAPI ImmGetRegisterWordStyleA( HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf) { FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetRegisterWordStyleW (IMM32.@) */ UINT WINAPI ImmGetRegisterWordStyleW( HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf) { FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } /*********************************************************************** * ImmGetStatusWindowPos (IMM32.@) */ BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) { FIXME("(%p, %p): stub\n", hIMC, lpptPos); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmGetVirtualKey (IMM32.@) */ UINT WINAPI ImmGetVirtualKey(HWND hWnd) { OSVERSIONINFOA version; FIXME("(%p): stub\n", hWnd); GetVersionExA( &version ); switch(version.dwPlatformId) { case VER_PLATFORM_WIN32_WINDOWS: return VK_PROCESSKEY; case VER_PLATFORM_WIN32_NT: return 0; default: FIXME("%d not supported\n",version.dwPlatformId); return VK_PROCESSKEY; } } /*********************************************************************** * ImmInstallIMEA (IMM32.@) */ HKL WINAPI ImmInstallIMEA( LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText) { FIXME("(%s, %s): stub\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText) ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return NULL; } /*********************************************************************** * ImmInstallIMEW (IMM32.@) */ HKL WINAPI ImmInstallIMEW( LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText) { FIXME("(%s, %s): stub\n", debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText) ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return NULL; } /*********************************************************************** * ImmIsIME (IMM32.@) */ BOOL WINAPI ImmIsIME(HKL hKL) { ImmHkl *ptr; TRACE("(%p):\n", hKL); ptr = IMM_GetImmHkl(hKL); return (ptr && ptr->hIME); } /*********************************************************************** * ImmIsUIMessageA (IMM32.@) */ BOOL WINAPI ImmIsUIMessageA( HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) { BOOL rc = FALSE; TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam); if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) || (msg == WM_MSIME_SERVICE) || (msg == WM_MSIME_RECONVERTOPTIONS) || (msg == WM_MSIME_MOUSE) || (msg == WM_MSIME_RECONVERTREQUEST) || (msg == WM_MSIME_RECONVERT) || (msg == WM_MSIME_QUERYPOSITION) || (msg == WM_MSIME_DOCUMENTFEED)) { if (!hwndDefault) ImmGetDefaultIMEWnd(NULL); if (hWndIME == NULL) PostMessageA(hwndDefault, msg, wParam, lParam); rc = TRUE; } return rc; } /*********************************************************************** * ImmIsUIMessageW (IMM32.@) */ BOOL WINAPI ImmIsUIMessageW( HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam) { BOOL rc = FALSE; TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam); if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) || (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) || (msg == WM_MSIME_SERVICE) || (msg == WM_MSIME_RECONVERTOPTIONS) || (msg == WM_MSIME_MOUSE) || (msg == WM_MSIME_RECONVERTREQUEST) || (msg == WM_MSIME_RECONVERT) || (msg == WM_MSIME_QUERYPOSITION) || (msg == WM_MSIME_DOCUMENTFEED)) rc = TRUE; return rc; } /*********************************************************************** * ImmNotifyIME (IMM32.@) */ BOOL WINAPI ImmNotifyIME( HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) { InputContextData *data = (InputContextData*)hIMC; TRACE("(%p, %d, %d, %d)\n", hIMC, dwAction, dwIndex, dwValue); if (!data || ! data->immKbd->pNotifyIME) return FALSE; return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue); } /*********************************************************************** * ImmRegisterWordA (IMM32.@) */ BOOL WINAPI ImmRegisterWordA( HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister) { FIXME("(%p, %s, %d, %s): stub\n", hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister) ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmRegisterWordW (IMM32.@) */ BOOL WINAPI ImmRegisterWordW( HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister) { FIXME("(%p, %s, %d, %s): stub\n", hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister) ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmReleaseContext (IMM32.@) */ BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC) { static int shown = 0; if (!shown) { FIXME("(%p, %p): stub\n", hWnd, hIMC); shown = 1; } return TRUE; } /*********************************************************************** * ImmSetCandidateWindow (IMM32.@) */ BOOL WINAPI ImmSetCandidateWindow( HIMC hIMC, LPCANDIDATEFORM lpCandidate) { FIXME("(%p, %p): stub\n", hIMC, lpCandidate); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmSetCompositionFontA (IMM32.@) */ BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf) { InputContextData *data = (InputContextData*)hIMC; TRACE("(%p, %p)\n", hIMC, lplf); if (!data) return FALSE; memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA)); MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName, LF_FACESIZE); ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0); return TRUE; } /*********************************************************************** * ImmSetCompositionFontW (IMM32.@) */ BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf) { InputContextData *data = (InputContextData*)hIMC; TRACE("(%p, %p)\n", hIMC, lplf); if (!data) return FALSE; data->IMC.lfFont.W = *lplf; ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0); return TRUE; } /*********************************************************************** * ImmSetCompositionStringA (IMM32.@) */ BOOL WINAPI ImmSetCompositionStringA( HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen) { DWORD comp_len; DWORD read_len; WCHAR *CompBuffer = NULL; WCHAR *ReadBuffer = NULL; BOOL rc; TRACE("(%p, %d, %p, %d, %p, %d):\n", hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0); if (comp_len) { CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len); } read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0); if (read_len) { ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len); } rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len, ReadBuffer, read_len); HeapFree(GetProcessHeap(), 0, CompBuffer); HeapFree(GetProcessHeap(), 0, ReadBuffer); return rc; } /*********************************************************************** * ImmSetCompositionStringW (IMM32.@) */ BOOL WINAPI ImmSetCompositionStringW( HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen) { InputContextData *data = (InputContextData*)hIMC; TRACE("(%p, %d, %p, %d, %p, %d):\n", hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); if (!data) return FALSE; if (is_himc_ime_unicode(data)) return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); else return FALSE; } /*********************************************************************** * ImmSetCompositionWindow (IMM32.@) */ BOOL WINAPI ImmSetCompositionWindow( HIMC hIMC, LPCOMPOSITIONFORM lpCompForm) { BOOL reshow = FALSE; InputContextData *data = (InputContextData*)hIMC; TRACE("(%p, %p)\n", hIMC, lpCompForm); TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle, lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top, lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right); if (!data) return FALSE; data->IMC.cfCompForm = *lpCompForm; if (IsWindowVisible(hwndDefault)) { reshow = TRUE; ShowWindow(hwndDefault,SW_HIDE); } /* FIXME: this is a partial stub */ if (reshow) ShowWindow(hwndDefault,SW_SHOWNOACTIVATE); ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0); return TRUE; } /*********************************************************************** * ImmSetConversionStatus (IMM32.@) */ BOOL WINAPI ImmSetConversionStatus( HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence) { static int shown = 0; if (!shown) { FIXME("(%p, %d, %d): stub\n", hIMC, fdwConversion, fdwSentence ); shown = 1; } SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmSetOpenStatus (IMM32.@) */ BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) { InputContextData *data = (InputContextData*)hIMC; TRACE("%p %d\n", hIMC, fOpen); if (!data) return FALSE; if (data->imeWnd == NULL) { /* create the ime window */ data->imeWnd = CreateWindowExW( WS_EX_TOOLWINDOW, data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, hImeInst, 0); SetWindowLongW(data->imeWnd, IMMGWL_IMC, (LONG)data); hwndDefault = data->imeWnd; } data->IMC.fOpen = fOpen; return ImmNotifyIME(hIMC,NI_CONTEXTUPDATED,0,IMC_SETOPENSTATUS); } /*********************************************************************** * ImmSetStatusWindowPos (IMM32.@) */ BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos) { FIXME("(%p, %p): stub\n", hIMC, lpptPos); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmSimulateHotKey (IMM32.@) */ BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID) { FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmUnregisterWordA (IMM32.@) */ BOOL WINAPI ImmUnregisterWordA( HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister) { FIXME("(%p, %s, %d, %s): stub\n", hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister) ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmUnregisterWordW (IMM32.@) */ BOOL WINAPI ImmUnregisterWordW( HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister) { FIXME("(%p, %s, %d, %s): stub\n", hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister) ); SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; } /*********************************************************************** * ImmGetImeMenuItemsA (IMM32.@) */ DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize) { InputContextData *data = (InputContextData*)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) { 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; } /*********************************************************************** * ImmGetImeMenuItemsW (IMM32.@) */ DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize) { InputContextData *data = (InputContextData*)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) { 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; } /*********************************************************************** * ImmLockIMC(IMM32.@) */ LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) { InputContextData *data = (InputContextData*)hIMC; if (!data) return NULL; data->dwLock++; return &data->IMC; } /*********************************************************************** * ImmUnlockIMC(IMM32.@) */ BOOL WINAPI ImmUnlockIMC(HIMC hIMC) { InputContextData *data = (InputContextData*)hIMC; data->dwLock--; return (data->dwLock!=0); } /*********************************************************************** * ImmGetIMCLockCount(IMM32.@) */ DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC) { InputContextData *data = (InputContextData*)hIMC; return data->dwLock; } /*********************************************************************** * ImmCreateIMCC(IMM32.@) */ HIMCC WINAPI ImmCreateIMCC(DWORD size) { IMCCInternal *internal; int real_size = size + sizeof(IMCCInternal); internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size); if (internal == NULL) return NULL; internal->dwSize = size; return (HIMCC)internal; } /*********************************************************************** * ImmDestroyIMCC(IMM32.@) */ HIMCC WINAPI ImmDestroyIMCC(HIMCC block) { HeapFree(GetProcessHeap(),0,block); return NULL; } /*********************************************************************** * ImmLockIMCC(IMM32.@) */ LPVOID WINAPI ImmLockIMCC(HIMCC imcc) { IMCCInternal *internal; internal = (IMCCInternal*) imcc; internal->dwLock ++; return internal + 1; } /*********************************************************************** * ImmUnlockIMCC(IMM32.@) */ BOOL WINAPI ImmUnlockIMCC(HIMCC imcc) { IMCCInternal *internal; internal = (IMCCInternal*) imcc; internal->dwLock --; return (internal->dwLock!=0); } /*********************************************************************** * ImmGetIMCCLockCount(IMM32.@) */ DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc) { IMCCInternal *internal; internal = (IMCCInternal*) imcc; return internal->dwLock; } /*********************************************************************** * ImmReSizeIMCC(IMM32.@) */ HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size) { IMCCInternal *internal,*newone; int real_size = size + sizeof(IMCCInternal); internal = (IMCCInternal*) imcc; newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size); newone->dwSize = size; return newone; } /*********************************************************************** * ImmGetIMCCSize(IMM32.@) */ DWORD WINAPI ImmGetIMCCSize(HIMCC imcc) { IMCCInternal *internal; internal = (IMCCInternal*) imcc; return internal->dwSize; } /*********************************************************************** * ImmGenerateMessage(IMM32.@) */ BOOL WINAPI ImmGenerateMessage(HIMC hIMC) { InputContextData *data = (InputContextData*)hIMC; TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf); if (data->IMC.dwNumMsgBuf > 0) { LPTRANSMSG lpTransMsg; INT i; lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf); for (i = 0; i < data->IMC.dwNumMsgBuf; i++) ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam); ImmUnlockIMCC(data->IMC.hMsgBuf); data->IMC.dwNumMsgBuf = 0; } return TRUE; }