diff --git a/dll/win32/imm32/ime.c b/dll/win32/imm32/ime.c index 3edb95b08ef..80a2c50f33c 100644 --- a/dll/win32/imm32/ime.c +++ b/dll/win32/imm32/ime.c @@ -276,6 +276,20 @@ PIMEDPI APIENTRY ImmLockOrLoadImeDpi(HKL hKL) return pImeDpi; } +static LRESULT APIENTRY +ImeDpi_Escape(PIMEDPI pImeDpi, HIMC hIMC, UINT uSubFunc, LPVOID lpData, HKL hKL) +{ + if (IS_IME_HKL(hKL)) + return pImeDpi->ImeEscape(hIMC, uSubFunc, lpData); + + if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED)) + { + if (pImeDpi->CtfImeEscapeEx) + return pImeDpi->CtfImeEscapeEx(hIMC, uSubFunc, lpData, hKL); + } + return 0; +} + /*********************************************************************** * ImmIsIME (IMM32.@) */ @@ -650,6 +664,170 @@ DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex) return dwValue; } +/*********************************************************************** + * ImmEscapeA (IMM32.@) + */ +LRESULT WINAPI ImmEscapeA(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData) +{ + LRESULT ret; + PIMEDPI pImeDpi; + INT cch; + CHAR szA[MAX_IMM_FILENAME]; + WCHAR szW[MAX_IMM_FILENAME]; + + TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData); + + pImeDpi = ImmLockOrLoadImeDpi(hKL); + if (!pImeDpi) + return 0; + + if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || !lpData) + { + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); + ImmUnlockImeDpi(pImeDpi); + return ret; + } + + switch (uSubFunc) + { + case IME_ESC_SEQUENCE_TO_INTERNAL: + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); + + cch = 0; + if (HIWORD(ret)) + szW[cch++] = HIWORD(ret); + if (LOWORD(ret)) + szW[cch++] = LOWORD(ret); + + cch = WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, cch, szA, _countof(szA), + NULL, NULL); + switch (cch) + { + case 1: + ret = MAKEWORD(szA[0], 0); + break; + case 2: + ret = MAKEWORD(szA[1], szA[0]); + break; + case 3: + ret = MAKELONG(MAKEWORD(szA[2], szA[1]), MAKEWORD(szA[0], 0)); + break; + case 4: + ret = MAKELONG(MAKEWORD(szA[3], szA[2]), MAKEWORD(szA[1], szA[0])); + break; + default: + ret = 0; + break; + } + break; + + case IME_ESC_GET_EUDC_DICTIONARY: + case IME_ESC_IME_NAME: + case IME_ESC_GETHELPFILENAME: + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL); + if (ret) + { + szW[_countof(szW) - 1] = 0; + WideCharToMultiByte(pImeDpi->uCodePage, 0, szW, -1, + lpData, MAX_IMM_FILENAME, NULL, NULL); + ((LPSTR)lpData)[MAX_IMM_FILENAME - 1] = 0; + } + break; + + case IME_ESC_SET_EUDC_DICTIONARY: + case IME_ESC_HANJA_MODE: + MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, + lpData, -1, szW, _countof(szW)); + szW[_countof(szW) - 1] = 0; + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szW, hKL); + break; + + default: + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); + break; + } + + ImmUnlockImeDpi(pImeDpi); + return ret; +} + +/*********************************************************************** + * ImmEscapeW (IMM32.@) + */ +LRESULT WINAPI ImmEscapeW(HKL hKL, HIMC hIMC, UINT uSubFunc, LPVOID lpData) +{ + LRESULT ret; + PIMEDPI pImeDpi; + INT cch; + CHAR szA[MAX_IMM_FILENAME]; + WCHAR szW[MAX_IMM_FILENAME]; + WORD word; + + TRACE("(%p, %p, %u, %p)\n", hKL, hIMC, uSubFunc, lpData); + + pImeDpi = ImmLockOrLoadImeDpi(hKL); + if (!pImeDpi) + return 0; + + if ((pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) || !lpData) + { + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); + ImmUnlockImeDpi(pImeDpi); + return ret; + } + + switch (uSubFunc) + { + case IME_ESC_SEQUENCE_TO_INTERNAL: + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); + + word = LOWORD(ret); + cch = 0; + if (HIBYTE(word)) + szA[cch++] = HIBYTE(word); + if (LOBYTE(word)) + szA[cch++] = LOBYTE(word); + + cch = MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, + szA, cch, szW, _countof(szW)); + switch (cch) + { + case 1: ret = szW[0]; break; + case 2: ret = MAKELONG(szW[1], szW[0]); break; + default: ret = 0; break; + } + break; + + case IME_ESC_GET_EUDC_DICTIONARY: + case IME_ESC_IME_NAME: + case IME_ESC_GETHELPFILENAME: + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL); + if (ret) + { + szA[_countof(szA) - 1] = 0; + MultiByteToWideChar(pImeDpi->uCodePage, MB_PRECOMPOSED, + szA, -1, lpData, MAX_IMM_FILENAME); + ((LPWSTR)lpData)[MAX_IMM_FILENAME - 1] = 0; + } + break; + + case IME_ESC_SET_EUDC_DICTIONARY: + case IME_ESC_HANJA_MODE: + WideCharToMultiByte(pImeDpi->uCodePage, 0, + lpData, -1, szA, _countof(szA), NULL, NULL); + szA[_countof(szA) - 1] = 0; + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, szA, hKL); + break; + + default: + ret = ImeDpi_Escape(pImeDpi, hIMC, uSubFunc, lpData, hKL); + break; + } + + ImmUnlockImeDpi(pImeDpi); + return ret; +} + /*********************************************************************** * ImmGetOpenStatus (IMM32.@) */ diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c index a07a6c6965a..21832a5a3bc 100644 --- a/dll/win32/imm32/imm.c +++ b/dll/win32/imm32/imm.c @@ -146,21 +146,7 @@ typedef struct tagInputContextData #define WINE_IMC_VALID_MAGIC 0x56434D49 -typedef struct _tagIMMThreadData -{ - struct list entry; - DWORD threadID; - HIMC defaultContext; - HWND hwndDefault; - BOOL disableIME; - DWORD windowRefs; -} IMMThreadData; - -static struct list ImmHklList = LIST_INIT(ImmHklList); -static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList); - static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0}; - 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}; @@ -170,115 +156,6 @@ static inline BOOL is_himc_ime_unicode(const InputContextData *data) return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE); } -static inline BOOL is_kbd_ime_unicode(const ImmHkl *hkl) -{ - return !!(hkl->imeInfo.fdwProperty & IME_PROP_UNICODE); -} - -static InputContextData* get_imc_data(HIMC hIMC); - -static HMODULE load_graphics_driver(void) -{ - static const WCHAR display_device_guid_propW[] = { - '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_', - 'd','e','v','i','c','e','_','g','u','i','d',0 }; - static const WCHAR key_pathW[] = { - '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','\\', - 'V','i','d','e','o','\\','{',0}; - static const WCHAR displayW[] = {'}','\\','0','0','0','0',0}; - static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0}; - - HMODULE ret = 0; - HKEY hkey; - DWORD size; - WCHAR path[MAX_PATH]; - WCHAR key[ARRAY_SIZE( key_pathW ) + ARRAY_SIZE( displayW ) + 40]; - UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW )); - - if (!guid_atom) return 0; - memcpy( key, key_pathW, sizeof(key_pathW) ); - if (!GlobalGetAtomNameW( guid_atom, key + lstrlenW(key), 40 )) return 0; - lstrcatW( key, displayW ); - if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0; - size = sizeof(path); - if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path ); - RegCloseKey( hkey ); - TRACE( "%s %p\n", debugstr_w(path), ret ); - return ret; -} - -/* 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 %p\n",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 = load_graphics_driver(); - 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 InputContextData* get_imc_data(HIMC hIMC) { InputContextData *data = (InputContextData *)hIMC; @@ -553,82 +430,6 @@ BOOL WINAPI ImmDestroyContext(HIMC hIMC) return Imm32CleanupContext(hIMC, hKL, FALSE); } -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; -} - -/*********************************************************************** - * ImmEscapeA (IMM32.@) - */ -LRESULT WINAPI ImmEscapeA(HKL hKL, HIMC hIMC, UINT uEscape, LPVOID lpData) -{ - 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; -} - -/*********************************************************************** - * ImmEscapeW (IMM32.@) - */ -LRESULT WINAPI ImmEscapeW(HKL hKL, HIMC hIMC, UINT uEscape, LPVOID lpData) -{ - 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; -} - static PCLIENTIMC APIENTRY Imm32GetClientImcCache(void) { // FIXME: Do something properly here diff --git a/dll/win32/imm32/precomp.h b/dll/win32/imm32/precomp.h index 6efcbf70fe1..b96a9afa695 100644 --- a/dll/win32/imm32/precomp.h +++ b/dll/win32/imm32/precomp.h @@ -49,6 +49,7 @@ #define IMM_INVALID_CANDFORM ULONG_MAX #define INVALID_HOTKEY_ID 0xFFFFFFFF #define MAX_CANDIDATEFORM 4 +#define MAX_IMM_FILENAME 80 #define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) #define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) diff --git a/win32ss/include/imetable.h b/win32ss/include/imetable.h index 96d18de18b4..d9d0929757d 100644 --- a/win32ss/include/imetable.h +++ b/win32ss/include/imetable.h @@ -17,6 +17,6 @@ DEFINE_IME_ENTRY(BOOL, ImeSetCompositionString, (HIMC hIMC, DWORD dwIndex, LPCVO DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize), FALSE) DEFINE_IME_ENTRY(DWORD, CtfImeInquireExW, (VOID /* FIXME: unknown */), TRUE) DEFINE_IME_ENTRY(DWORD, CtfImeSelectEx, (VOID /* FIXME: unknown */), TRUE) -DEFINE_IME_ENTRY(DWORD, CtfImeEscapeEx, (VOID /* FIXME: unknown */), TRUE) +DEFINE_IME_ENTRY(LRESULT, CtfImeEscapeEx, (HIMC hIMC, UINT uSubFunc, LPVOID lpData, HKL hKL), TRUE) DEFINE_IME_ENTRY(DWORD, CtfImeGetGuidAtom, (VOID /* FIXME: unknown */), TRUE) DEFINE_IME_ENTRY(DWORD, CtfImeIsGuidMapEnable, (VOID /* FIXME: unknown */), TRUE)