diff --git a/dll/win32/imm32/ime.c b/dll/win32/imm32/ime.c index b1b31ce9eeb..7ae3325f323 100644 --- a/dll/win32/imm32/ime.c +++ b/dll/win32/imm32/ime.c @@ -168,11 +168,11 @@ BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi) } pImeDpi->hInst = hIME; -#define DEFINE_IME_ENTRY(type, name, params, extended) \ +#define DEFINE_IME_ENTRY(type, name, params, optional) \ do { \ fn = GetProcAddress(hIME, #name); \ if (fn) pImeDpi->name = (FN_##name)fn; \ - else if (!(extended)) goto Failed; \ + else if (!(optional)) goto Failed; \ } while (0); #include "imetable.h" #undef DEFINE_IME_ENTRY @@ -330,6 +330,151 @@ Quit: return ret; } +DWORD APIENTRY +Imm32GetImeMenuItemWCrossProcess(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu, + LPVOID lpImeMenu, DWORD dwSize) +{ + FIXME("We have to do something\n"); + return 0; +} + +DWORD APIENTRY +Imm32GetImeMenuItemsAW(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu, + LPVOID lpImeMenu, DWORD dwSize, BOOL bTargetIsAnsi) +{ + DWORD ret = 0, cbTotal, dwProcessId, dwThreadId, iItem; + LPINPUTCONTEXT pIC; + PIMEDPI pImeDpi = NULL; + IMEMENUITEMINFOA ParentA; + IMEMENUITEMINFOW ParentW; + LPIMEMENUITEMINFOA pItemA; + LPIMEMENUITEMINFOW pItemW; + LPVOID pNewItems = NULL, pNewParent = NULL; + BOOL bImcIsAnsi; + HKL hKL; + + if (!hIMC) + return 0; + + dwProcessId = NtUserQueryInputContext(hIMC, 0); + if (dwProcessId == 0) + return 0; + + if (dwProcessId != GetCurrentProcessId()) + { + if (bTargetIsAnsi) + return 0; + return Imm32GetImeMenuItemWCrossProcess(hIMC, dwFlags, dwType, lpImeParentMenu, + lpImeMenu, dwSize); + } + + pIC = ImmLockIMC(hIMC); + if (pIC == NULL) + return 0; + + dwThreadId = NtUserQueryInputContext(hIMC, 1); + if (dwThreadId == 0) + { + ImmUnlockIMC(hIMC); + return 0; + } + + hKL = GetKeyboardLayout(dwThreadId); + pImeDpi = ImmLockImeDpi(hKL); + if (!pImeDpi) + { + ImmUnlockIMC(hIMC); + return 0; + } + + if (pImeDpi->ImeGetImeMenuItems == NULL) + goto Quit; + + bImcIsAnsi = Imm32IsImcAnsi(hIMC); + + if (bImcIsAnsi != bTargetIsAnsi) + { + if (bTargetIsAnsi) + { + if (lpImeParentMenu) + pNewParent = &ParentW; + + if (lpImeMenu) + { + cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOA)) * sizeof(IMEMENUITEMINFOW)); + pNewItems = Imm32HeapAlloc(0, cbTotal); + if (!pNewItems) + goto Quit; + } + } + else + { + if (lpImeParentMenu) + pNewParent = &ParentA; + + if (lpImeMenu) + { + cbTotal = ((dwSize / sizeof(IMEMENUITEMINFOW)) * sizeof(IMEMENUITEMINFOA)); + pNewItems = Imm32HeapAlloc(0, cbTotal); + if (!pNewItems) + goto Quit; + } + } + } + else + { + pNewItems = lpImeMenu; + pNewParent = lpImeParentMenu; + } + + ret = pImeDpi->ImeGetImeMenuItems(hIMC, dwFlags, dwType, pNewParent, pNewItems, dwSize); + if (!ret || !lpImeMenu) + goto Quit; + + if (bImcIsAnsi != bTargetIsAnsi) + { + if (bTargetIsAnsi) + { + if (pNewParent) + Imm32ImeMenuWideToAnsi(pNewParent, lpImeParentMenu, CP_ACP); + + pItemW = pNewItems; + pItemA = lpImeMenu; + for (iItem = 0; iItem < ret; ++iItem, ++pItemW, ++pItemA) + { + if (!Imm32ImeMenuWideToAnsi(pItemW, pItemA, CP_ACP)) + { + ret = 0; + break; + } + } + } + else + { + if (pNewParent) + Imm32ImeMenuAnsiToWide(pNewParent, lpImeParentMenu, pImeDpi->uCodePage, TRUE); + + pItemA = pNewItems; + pItemW = lpImeMenu; + for (iItem = 0; iItem < dwSize; ++iItem, ++pItemA, ++pItemW) + { + if (!Imm32ImeMenuAnsiToWide(pItemA, pItemW, pImeDpi->uCodePage, TRUE)) + { + ret = 0; + break; + } + } + } + } + +Quit: + if (pNewItems != lpImeMenu) + Imm32HeapFree(pNewItems); + ImmUnlockImeDpi(pImeDpi); + ImmUnlockIMC(hIMC); + return ret; +} + /*********************************************************************** * ImmIsIME (IMM32.@) */ @@ -1505,6 +1650,34 @@ Quit: return ret; } +/*********************************************************************** + * ImmGetImeMenuItemsA (IMM32.@) + */ +DWORD WINAPI +ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType, + LPIMEMENUITEMINFOA lpImeParentMenu, + LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize) +{ + TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", + hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize); + return Imm32GetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, + dwSize, TRUE); +} + +/*********************************************************************** + * ImmGetImeMenuItemsW (IMM32.@) + */ +DWORD WINAPI +ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, + LPIMEMENUITEMINFOW lpImeParentMenu, + LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize) +{ + TRACE("(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", + hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, dwSize); + return Imm32GetImeMenuItemsAW(hIMC, dwFlags, dwType, lpImeParentMenu, lpImeMenu, + dwSize, FALSE); +} + /*********************************************************************** * ImmFreeLayout (IMM32.@) */ diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c index 07eb129bffc..5cb72db884c 100644 --- a/dll/win32/imm32/imm.c +++ b/dll/win32/imm32/imm.c @@ -1425,148 +1425,6 @@ BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, BOOL fFlag) return FALSE; } -/*********************************************************************** - * ImmGetImeMenuItemsA (IMM32.@) - */ -DWORD WINAPI -ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType, - LPIMEMENUITEMINFOA lpImeParentMenu, - LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize) -{ - InputContextData *data = get_imc_data(hIMC); - TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType, - lpImeParentMenu, lpImeMenu, dwSize); - - if (!data) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - - 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; -} - -/*********************************************************************** - * ImmGetImeMenuItemsW (IMM32.@) - */ -DWORD WINAPI -ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType, - LPIMEMENUITEMINFOW lpImeParentMenu, - LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize) -{ - InputContextData *data = get_imc_data(hIMC); - TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType, - lpImeParentMenu, lpImeMenu, dwSize); - - if (!data) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - - 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; -} - BOOL WINAPI User32InitializeImmEntryTable(DWORD); BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) diff --git a/dll/win32/imm32/precomp.h b/dll/win32/imm32/precomp.h index 7bab3b95031..1bcc18bbb30 100644 --- a/dll/win32/imm32/precomp.h +++ b/dll/win32/imm32/precomp.h @@ -95,6 +95,8 @@ static inline BOOL Imm32IsCrossProcessAccess(HWND hWnd) (DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess); } +BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC); + #define ImeDpi_IsUnicode(pImeDpi) ((pImeDpi)->ImeInfo.fdwProperty & IME_PROP_UNICODE) #define Imm32IsImmMode() (g_psi && (g_psi->dwSRVIFlags & SRVINFO_IMM32)) #define Imm32IsCiceroMode() (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED)) @@ -112,3 +114,10 @@ Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD DWORD_PTR dwCommand, DWORD_PTR dwData); DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphList); + +INT APIENTRY +Imm32ImeMenuAnsiToWide(const IMEMENUITEMINFOA *pItemA, LPIMEMENUITEMINFOW pItemW, + UINT uCodePage, BOOL bBitmap); +INT APIENTRY +Imm32ImeMenuWideToAnsi(const IMEMENUITEMINFOW *pItemW, LPIMEMENUITEMINFOA pItemA, + UINT uCodePage); diff --git a/dll/win32/imm32/utils.c b/dll/win32/imm32/utils.c index 64bd3d158be..cda20efc884 100644 --- a/dll/win32/imm32/utils.c +++ b/dll/win32/imm32/utils.c @@ -16,6 +16,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm); HANDLE g_hImm32Heap = NULL; +BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC) +{ + BOOL ret; + PCLIENTIMC pClientImc = ImmLockClientImc(hIMC); + if (!pClientImc) + return -1; + ret = !(pClientImc->dwFlags & CLIENTIMC_WIDE); + ImmUnlockClientImc(pClientImc); + return ret; +} + LPWSTR APIENTRY Imm32WideFromAnsi(LPCSTR pszA) { INT cch = lstrlenA(pszA); @@ -202,6 +213,55 @@ DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphList) #undef MAX_RETRY } +INT APIENTRY +Imm32ImeMenuAnsiToWide(const IMEMENUITEMINFOA *pItemA, LPIMEMENUITEMINFOW pItemW, + UINT uCodePage, BOOL bBitmap) +{ + INT ret; + pItemW->cbSize = pItemA->cbSize; + pItemW->fType = pItemA->fType; + pItemW->fState = pItemA->fState; + pItemW->wID = pItemA->wID; + if (bBitmap) + { + pItemW->hbmpChecked = pItemA->hbmpChecked; + pItemW->hbmpUnchecked = pItemA->hbmpUnchecked; + pItemW->hbmpItem = pItemA->hbmpItem; + } + pItemW->dwItemData = pItemA->dwItemData; + ret = MultiByteToWideChar(uCodePage, 0, pItemA->szString, -1, + pItemW->szString, _countof(pItemW->szString)); + if (ret >= _countof(pItemW->szString)) + { + ret = 0; + pItemW->szString[0] = 0; + } + return ret; +} + +INT APIENTRY +Imm32ImeMenuWideToAnsi(const IMEMENUITEMINFOW *pItemW, LPIMEMENUITEMINFOA pItemA, + UINT uCodePage) +{ + INT ret; + pItemA->cbSize = pItemW->cbSize; + pItemA->fType = pItemW->fType; + pItemA->fState = pItemW->fState; + pItemA->wID = pItemW->wID; + pItemA->hbmpChecked = pItemW->hbmpChecked; + pItemA->hbmpUnchecked = pItemW->hbmpUnchecked; + pItemA->dwItemData = pItemW->dwItemData; + pItemA->hbmpItem = pItemW->hbmpItem; + ret = WideCharToMultiByte(uCodePage, 0, pItemW->szString, -1, + pItemA->szString, _countof(pItemA->szString), NULL, NULL); + if (ret >= _countof(pItemA->szString)) + { + ret = 0; + pItemA->szString[0] = 0; + } + return ret; +} + /*********************************************************************** * ImmCreateIMCC(IMM32.@) */ diff --git a/win32ss/include/imetable.h b/win32ss/include/imetable.h index 09580a4ac95..70bc982a6dc 100644 --- a/win32ss/include/imetable.h +++ b/win32ss/include/imetable.h @@ -1,4 +1,4 @@ -/* DEFINE_IME_ENTRY(type, name, params, extended) */ +/* DEFINE_IME_ENTRY(type, name, params, optional) */ DEFINE_IME_ENTRY(BOOL, ImeInquire, (LPIMEINFO lpIMEInfo, LPVOID lpszWndClass, DWORD dwSystemInfoFlags), FALSE) DEFINE_IME_ENTRY(DWORD, ImeConversionList, (HIMC hIMC, LPCVOID lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen, UINT uFlag), FALSE) DEFINE_IME_ENTRY(BOOL, ImeRegisterWord, (LPCVOID lpszReading, DWORD dwStyle, LPCVOID lpszString), FALSE) @@ -14,7 +14,7 @@ DEFINE_IME_ENTRY(BOOL, ImeSetActiveContext, (HIMC hIMC, BOOL fFlag), FALSE) DEFINE_IME_ENTRY(UINT, ImeToAsciiEx, (UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState, LPTRANSMSGLIST lpTransMsgList, UINT fuState, HIMC hIMC), FALSE) DEFINE_IME_ENTRY(BOOL, NotifyIME, (HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue), FALSE) DEFINE_IME_ENTRY(BOOL, ImeSetCompositionString, (HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen), FALSE) -DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize), FALSE) +DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize), TRUE) DEFINE_IME_ENTRY(BOOL, CtfImeInquireExW, (LPIMEINFO lpIMEInfo, LPVOID lpszWndClass, DWORD dwSystemInfoFlags, HKL hKL), TRUE) DEFINE_IME_ENTRY(BOOL, CtfImeSelectEx, (HIMC hIMC, BOOL fSelect, HKL hKL), TRUE) DEFINE_IME_ENTRY(LRESULT, CtfImeEscapeEx, (HIMC hIMC, UINT uSubFunc, LPVOID lpData, HKL hKL), TRUE)