* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
* Copyright 2017 James Tabor <james.tabor@reactos.org>
* Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
- * Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
- * Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
+ * Copyright 2020-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include "precomp.h"
+#include <ndk/exfuncs.h>
WINE_DEFAULT_DEBUG_CHANNEL(imm);
-HMODULE g_hImm32Inst = NULL;
-PSERVERINFO g_psi = NULL;
-SHAREDINFO g_SharedInfo = { NULL };
-BYTE g_bClientRegd = FALSE;
+HMODULE ghImm32Inst = NULL; /* The IMM32 instance */
+PSERVERINFO gpsi = NULL;
+SHAREDINFO gSharedInfo = { NULL };
+BYTE gfImmInitialized = FALSE; /* Is IMM32 initialized? */
+ULONG_PTR gHighestUserAddress = 0;
-static BOOL APIENTRY Imm32InitInstance(HMODULE hMod)
+static BOOL APIENTRY ImmInitializeGlobals(HMODULE hMod)
{
NTSTATUS status;
+ SYSTEM_BASIC_INFORMATION SysInfo;
if (hMod)
- g_hImm32Inst = hMod;
+ ghImm32Inst = hMod;
- if (g_bClientRegd)
+ if (gfImmInitialized)
return TRUE;
- status = RtlInitializeCriticalSection(&g_csImeDpi);
+ status = RtlInitializeCriticalSection(&gcsImeDpi);
if (NT_ERROR(status))
+ {
+ ERR("\n");
+ return FALSE;
+ }
+
+ status = NtQuerySystemInformation(SystemBasicInformation, &SysInfo, sizeof(SysInfo), NULL);
+ if (NT_ERROR(status))
+ {
+ ERR("\n");
return FALSE;
+ }
+ gHighestUserAddress = SysInfo.MaximumUserModeAddress;
- g_bClientRegd = TRUE;
+ gfImmInitialized = TRUE;
return TRUE;
}
*/
BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod)
{
- g_SharedInfo = *ptr;
- g_psi = g_SharedInfo.psi;
- return Imm32InitInstance(hMod);
+ gSharedInfo = *ptr;
+ gpsi = gSharedInfo.psi;
+ return ImmInitializeGlobals(hMod);
}
/***********************************************************************
* ImmLoadLayout (IMM32.@)
*/
-HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
+BOOL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
{
- DWORD cbData;
- UNICODE_STRING UnicodeString;
- HKEY hLayoutKey = NULL, hLayoutsKey = NULL;
- LONG error;
- NTSTATUS Status;
+ DWORD cbData, dwType;
+ HKEY hKey;
+ LSTATUS error;
WCHAR szLayout[MAX_PATH];
+ LPCWSTR pszSubKey;
TRACE("(%p, %p)\n", hKL, pImeInfoEx);
- if (IS_IME_HKL(hKL) ||
- !g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) ||
- ((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->W32ClientInfo[0] & 2)
+ /* Choose a key */
+ if (IS_IME_HKL(hKL) || !IS_CICERO_MODE() || IS_16BIT_MODE()) /* Non-Cicero? */
{
- UnicodeString.Buffer = szLayout;
- UnicodeString.MaximumLength = sizeof(szLayout);
- Status = RtlIntegerToUnicodeString((DWORD_PTR)hKL, 16, &UnicodeString);
- if (!NT_SUCCESS(Status))
- return NULL;
-
- error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS, &hLayoutsKey);
- if (error)
- return NULL;
-
- error = RegOpenKeyW(hLayoutsKey, szLayout, &hLayoutKey);
+ StringCchPrintfW(szLayout, _countof(szLayout), L"%s\\%08lX",
+ REGKEY_KEYBOARD_LAYOUTS, HandleToUlong(hKL));
+ pszSubKey = szLayout;
}
- else
+ else /* Cicero */
{
- error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_IMM, &hLayoutKey);
+ pszSubKey = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM";
}
- if (error)
+ /* Open the key */
+ error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pszSubKey, 0, KEY_READ, &hKey);
+ if (IS_ERROR_UNEXPECTEDLY(error))
+ return FALSE;
+
+ /* Load "IME File" value */
+ cbData = sizeof(pImeInfoEx->wszImeFile);
+ error = RegQueryValueExW(hKey, L"IME File", NULL, &dwType,
+ (LPBYTE)pImeInfoEx->wszImeFile, &cbData);
+
+ /* Avoid buffer overrun */
+ pImeInfoEx->wszImeFile[_countof(pImeInfoEx->wszImeFile) - 1] = UNICODE_NULL;
+
+ RegCloseKey(hKey);
+
+ if (error != ERROR_SUCCESS || dwType != REG_SZ)
+ return FALSE; /* Failed */
+
+ pImeInfoEx->hkl = hKL;
+ pImeInfoEx->fLoadFlag = 0;
+ return Imm32LoadImeVerInfo(pImeInfoEx);
+}
+
+/***********************************************************************
+ * ImmFreeLayout (IMM32.@)
+ */
+BOOL WINAPI ImmFreeLayout(DWORD dwUnknown)
+{
+ WCHAR szKBD[KL_NAMELENGTH];
+ UINT iKL, cKLs;
+ HKL hOldKL, hNewKL, *pList;
+ PIMEDPI pImeDpi;
+ LANGID LangID;
+
+ TRACE("(0x%lX)\n", dwUnknown);
+
+ hOldKL = GetKeyboardLayout(0);
+
+ if (dwUnknown == 1)
+ {
+ if (!IS_IME_HKL(hOldKL))
+ return TRUE;
+
+ LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
+
+ cKLs = GetKeyboardLayoutList(0, NULL);
+ if (cKLs)
+ {
+ pList = ImmLocalAlloc(0, cKLs * sizeof(HKL));
+ if (IS_NULL_UNEXPECTEDLY(pList))
+ return FALSE;
+
+ cKLs = GetKeyboardLayoutList(cKLs, pList);
+ for (iKL = 0; iKL < cKLs; ++iKL)
+ {
+ if (!IS_IME_HKL(pList[iKL]))
+ {
+ LangID = LOWORD(pList[iKL]);
+ break;
+ }
+ }
+
+ ImmLocalFree(pList);
+ }
+
+ StringCchPrintfW(szKBD, _countof(szKBD), L"%08X", LangID);
+ if (!LoadKeyboardLayoutW(szKBD, KLF_ACTIVATE))
+ {
+ WARN("Default to English US\n");
+ LoadKeyboardLayoutW(L"00000409", KLF_ACTIVATE | 0x200);
+ }
+ }
+ else if (dwUnknown == 2)
{
- ERR("RegOpenKeyW error: 0x%08lX\n", error);
- hKL = NULL;
+ RtlEnterCriticalSection(&gcsImeDpi);
+Retry:
+ for (pImeDpi = gpImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext)
+ {
+ if (Imm32ReleaseIME(pImeDpi->hKL))
+ goto Retry;
+ }
+ RtlLeaveCriticalSection(&gcsImeDpi);
}
else
{
- cbData = sizeof(pImeInfoEx->wszImeFile);
- error = RegQueryValueExW(hLayoutKey, L"Ime File", 0, 0,
- (LPBYTE)pImeInfoEx->wszImeFile, &cbData);
- if (error)
- hKL = NULL;
+ hNewKL = (HKL)(DWORD_PTR)dwUnknown;
+ if (IS_IME_HKL(hNewKL) && hNewKL != hOldKL)
+ Imm32ReleaseIME(hNewKL);
}
- RegCloseKey(hLayoutKey);
- if (hLayoutsKey)
- RegCloseKey(hLayoutsKey);
- return hKL;
+ return TRUE;
}
-typedef struct _tagImmHkl
+VOID APIENTRY Imm32SelectInputContext(HKL hNewKL, HKL hOldKL, HIMC hIMC)
{
- struct list entry;
- HKL hkl;
- HMODULE hIME;
- IMEINFO imeInfo;
- WCHAR imeClassName[17]; /* 16 character max */
- ULONG uSelected;
- HWND UIWnd;
-
- /* Function Pointers */
- BOOL (WINAPI *pImeInquire)(IMEINFO *, WCHAR *, const WCHAR *);
- BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *);
- BOOL (WINAPI *pImeDestroy)(UINT);
- LRESULT (WINAPI *pImeEscape)(HIMC, UINT, void *);
- BOOL (WINAPI *pImeSelect)(HIMC, BOOL);
- BOOL (WINAPI *pImeSetActiveContext)(HIMC, BOOL);
- UINT (WINAPI *pImeToAsciiEx)(UINT, UINT, const BYTE *, DWORD *, UINT, HIMC);
- BOOL (WINAPI *pNotifyIME)(HIMC, DWORD, DWORD, DWORD);
- BOOL (WINAPI *pImeRegisterWord)(const WCHAR *, DWORD, const WCHAR *);
- BOOL (WINAPI *pImeUnregisterWord)(const WCHAR *, DWORD, const WCHAR *);
- UINT (WINAPI *pImeEnumRegisterWord)(REGISTERWORDENUMPROCW, const WCHAR *, DWORD, const WCHAR *, void *);
- BOOL (WINAPI *pImeSetCompositionString)(HIMC, DWORD, const void *, DWORD, const void *, DWORD);
- DWORD (WINAPI *pImeConversionList)(HIMC, const WCHAR *, CANDIDATELIST *, DWORD, UINT);
- BOOL (WINAPI *pImeProcessKey)(HIMC, UINT, LPARAM, const BYTE *);
- UINT (WINAPI *pImeGetRegisterWordStyle)(UINT, STYLEBUFW *);
- DWORD (WINAPI *pImeGetImeMenuItems)(HIMC, DWORD, DWORD, IMEMENUITEMINFOW *, IMEMENUITEMINFOW *, DWORD);
-} ImmHkl;
-
-typedef struct tagInputContextData
-{
- DWORD dwLock;
- INPUTCONTEXT IMC;
- DWORD threadID;
+ PCLIENTIMC pClientImc;
+ LPINPUTCONTEXTDX pIC;
+ LPGUIDELINE pGL;
+ LPCANDIDATEINFO pCI;
+ LPCOMPOSITIONSTRING pCS;
+ LOGFONTA LogFontA;
+ LOGFONTW LogFontW;
+ BOOL fOldOpen, bIsNewHKLIme = TRUE, bIsOldHKLIme = TRUE, bClientWide, bNewDpiWide;
+ DWORD cbNewPrivate = 0, cbOldPrivate = 0, dwOldConversion, dwOldSentence, dwSize, dwNewSize;
+ PIMEDPI pNewImeDpi = NULL, pOldImeDpi = NULL;
+ HANDLE hPrivate;
+ PIME_STATE pNewState = NULL, pOldState = NULL;
- ImmHkl *immKbd;
- UINT lastVK;
- BOOL threadDefault;
- DWORD magic;
-} InputContextData;
+ pClientImc = ImmLockClientImc(hIMC);
+ if (IS_NULL_UNEXPECTEDLY(pClientImc))
+ return;
-#define WINE_IMC_VALID_MAGIC 0x56434D49
+ pNewImeDpi = ImmLockImeDpi(hNewKL);
-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};
+ if (hNewKL != hOldKL)
+ pOldImeDpi = ImmLockImeDpi(hOldKL);
-static inline BOOL is_himc_ime_unicode(const InputContextData *data)
-{
- return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
-}
+ if (pNewImeDpi)
+ {
+ cbNewPrivate = pNewImeDpi->ImeInfo.dwPrivateDataSize;
+ pClientImc->uCodePage = pNewImeDpi->uCodePage;
+ }
+ else
+ {
+ pClientImc->uCodePage = CP_ACP;
+ }
-static InputContextData* get_imc_data(HIMC hIMC)
-{
- InputContextData *data = (InputContextData *)hIMC;
+ if (pOldImeDpi)
+ cbOldPrivate = pOldImeDpi->ImeInfo.dwPrivateDataSize;
- if (hIMC == NULL)
- return NULL;
+ cbNewPrivate = max(cbNewPrivate, sizeof(DWORD));
+ cbOldPrivate = max(cbOldPrivate, sizeof(DWORD));
- if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
+ if (pClientImc->hKL == hOldKL)
{
- SetLastError(ERROR_INVALID_HANDLE);
- return NULL;
+ if (pOldImeDpi)
+ {
+ if (IS_IME_HKL(hOldKL))
+ pOldImeDpi->ImeSelect(hIMC, FALSE);
+ else if (IS_CICERO_MODE() && !IS_16BIT_MODE())
+ pOldImeDpi->CtfImeSelectEx(hIMC, FALSE, hOldKL);
+ }
+ pClientImc->hKL = NULL;
+ }
+
+ if (CtfImmIsTextFrameServiceDisabled() && IS_CICERO_MODE() && !IS_16BIT_MODE())
+ {
+ bIsNewHKLIme = IS_IME_HKL(hNewKL);
+ bIsOldHKLIme = IS_IME_HKL(hOldKL);
+ }
+
+ pIC = (LPINPUTCONTEXTDX)Imm32InternalLockIMC(hIMC, FALSE);
+ if (!pIC)
+ {
+ if (pNewImeDpi)
+ {
+ if (IS_IME_HKL(hNewKL))
+ pNewImeDpi->ImeSelect(hIMC, TRUE);
+ else if (IS_CICERO_MODE() && !IS_16BIT_MODE())
+ pNewImeDpi->CtfImeSelectEx(hIMC, TRUE, hNewKL);
+
+ pClientImc->hKL = hNewKL;
+ }
+ }
+ else
+ {
+ dwOldConversion = pIC->fdwConversion;
+ dwOldSentence = pIC->fdwSentence;
+ fOldOpen = pIC->fOpen;
+
+ if (pNewImeDpi)
+ {
+ bClientWide = (pClientImc->dwFlags & CLIENTIMC_WIDE);
+ bNewDpiWide = ImeDpi_IsUnicode(pNewImeDpi);
+ if (bClientWide && !bNewDpiWide)
+ {
+ if (pIC->fdwInit & INIT_LOGFONT)
+ {
+ LogFontWideToAnsi(&pIC->lfFont.W, &LogFontA);
+ pIC->lfFont.A = LogFontA;
+ }
+ pClientImc->dwFlags &= ~CLIENTIMC_WIDE;
+ }
+ else if (!bClientWide && bNewDpiWide)
+ {
+ if (pIC->fdwInit & INIT_LOGFONT)
+ {
+ LogFontAnsiToWide(&pIC->lfFont.A, &LogFontW);
+ pIC->lfFont.W = LogFontW;
+ }
+ pClientImc->dwFlags |= CLIENTIMC_WIDE;
+ }
+ }
+
+ if (cbOldPrivate != cbNewPrivate)
+ {
+ hPrivate = ImmReSizeIMCC(pIC->hPrivate, cbNewPrivate);
+ if (!hPrivate)
+ {
+ ImmDestroyIMCC(pIC->hPrivate);
+ hPrivate = ImmCreateIMCC(cbNewPrivate);
+ }
+ pIC->hPrivate = hPrivate;
+ }
+
+#define MAX_IMCC_SIZE 0x1000
+ dwSize = ImmGetIMCCSize(pIC->hMsgBuf);
+ if (ImmGetIMCCLockCount(pIC->hMsgBuf) || dwSize > MAX_IMCC_SIZE)
+ {
+ ImmDestroyIMCC(pIC->hMsgBuf);
+ pIC->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
+ pIC->dwNumMsgBuf = 0;
+ }
+
+ dwSize = ImmGetIMCCSize(pIC->hGuideLine);
+ dwNewSize = sizeof(GUIDELINE);
+ if (ImmGetIMCCLockCount(pIC->hGuideLine) ||
+ dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE)
+ {
+ ImmDestroyIMCC(pIC->hGuideLine);
+ pIC->hGuideLine = ImmCreateIMCC(dwNewSize);
+ pGL = ImmLockIMCC(pIC->hGuideLine);
+ if (pGL)
+ {
+ pGL->dwSize = dwNewSize;
+ ImmUnlockIMCC(pIC->hGuideLine);
+ }
+ }
+
+ dwSize = ImmGetIMCCSize(pIC->hCandInfo);
+ dwNewSize = sizeof(CANDIDATEINFO);
+ if (ImmGetIMCCLockCount(pIC->hCandInfo) ||
+ dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE)
+ {
+ ImmDestroyIMCC(pIC->hCandInfo);
+ pIC->hCandInfo = ImmCreateIMCC(dwNewSize);
+ pCI = ImmLockIMCC(pIC->hCandInfo);
+ if (pCI)
+ {
+ pCI->dwSize = dwNewSize;
+ ImmUnlockIMCC(pIC->hCandInfo);
+ }
+ }
+
+ dwSize = ImmGetIMCCSize(pIC->hCompStr);
+ dwNewSize = sizeof(COMPOSITIONSTRING);
+ if (ImmGetIMCCLockCount(pIC->hCompStr) ||
+ dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE)
+ {
+ ImmDestroyIMCC(pIC->hCompStr);
+ pIC->hCompStr = ImmCreateIMCC(dwNewSize);
+ pCS = ImmLockIMCC(pIC->hCompStr);
+ if (pCS)
+ {
+ pCS->dwSize = dwNewSize;
+ ImmUnlockIMCC(pIC->hCompStr);
+ }
+ }
+#undef MAX_IMCC_SIZE
+
+ if (pOldImeDpi && bIsOldHKLIme)
+ {
+ pOldState = Imm32FetchImeState(pIC, hOldKL);
+ if (pOldState)
+ Imm32SaveImeStateSentence(pIC, pOldState, hOldKL);
+ }
+
+ if (pNewImeDpi && bIsNewHKLIme)
+ pNewState = Imm32FetchImeState(pIC, hNewKL);
+
+ if (pOldState != pNewState)
+ {
+ if (pOldState)
+ {
+ pOldState->fOpen = !!pIC->fOpen;
+ pOldState->dwConversion = pIC->fdwConversion;
+ pOldState->dwConversion &= ~IME_CMODE_EUDC;
+ pOldState->dwSentence = pIC->fdwSentence;
+ pOldState->dwInit = pIC->fdwInit;
+ }
+
+ if (pNewState)
+ {
+ if (pIC->dwChange & INPUTCONTEXTDX_CHANGE_FORCE_OPEN)
+ {
+ pIC->dwChange &= ~INPUTCONTEXTDX_CHANGE_FORCE_OPEN;
+ pIC->fOpen = TRUE;
+ }
+ else
+ {
+ pIC->fOpen = pNewState->fOpen;
+ }
+
+ pIC->fdwConversion = pNewState->dwConversion;
+ pIC->fdwConversion &= ~IME_CMODE_EUDC;
+ pIC->fdwSentence = pNewState->dwSentence;
+ pIC->fdwInit = pNewState->dwInit;
+ }
+ }
+
+ if (pNewState)
+ Imm32LoadImeStateSentence(pIC, pNewState, hNewKL);
+
+ if (pNewImeDpi)
+ {
+ if (IS_IME_HKL(hNewKL))
+ pNewImeDpi->ImeSelect(hIMC, TRUE);
+ else if (IS_CICERO_MODE() && !IS_16BIT_MODE())
+ pNewImeDpi->CtfImeSelectEx(hIMC, TRUE, hNewKL);
+
+ pClientImc->hKL = hNewKL;
+ }
+
+ pIC->dwChange = 0;
+ if (pIC->fOpen != fOldOpen)
+ pIC->dwChange |= INPUTCONTEXTDX_CHANGE_OPEN;
+ if (pIC->fdwConversion != dwOldConversion)
+ pIC->dwChange |= INPUTCONTEXTDX_CHANGE_CONVERSION;
+ if (pIC->fdwSentence != dwOldSentence)
+ pIC->dwChange |= INPUTCONTEXTDX_CHANGE_SENTENCE;
+
+ ImmUnlockIMC(hIMC);
}
- return data;
+
+ ImmUnlockImeDpi(pOldImeDpi);
+ ImmUnlockImeDpi(pNewImeDpi);
+ ImmUnlockClientImc(pClientImc);
}
-static HIMC get_default_context( HWND hwnd )
+typedef struct SELECT_LAYOUT
{
- FIXME("Don't use this function\n");
- return FALSE;
+ HKL hNewKL;
+ HKL hOldKL;
+} SELECT_LAYOUT, *LPSELECT_LAYOUT;
+
+// Win: SelectContextProc
+static BOOL CALLBACK Imm32SelectContextProc(HIMC hIMC, LPARAM lParam)
+{
+ LPSELECT_LAYOUT pSelect = (LPSELECT_LAYOUT)lParam;
+ Imm32SelectInputContext(pSelect->hNewKL, pSelect->hOldKL, hIMC);
+ return TRUE;
+}
+
+// Win: NotifyIMEProc
+static BOOL CALLBACK Imm32NotifyIMEProc(HIMC hIMC, LPARAM lParam)
+{
+ ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, (DWORD)lParam, 0);
+ return TRUE;
}
-static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
+/***********************************************************************
+ * ImmActivateLayout (IMM32.@)
+ */
+BOOL WINAPI ImmActivateLayout(HKL hKL)
{
- InputContextData *data;
+ PIMEDPI pImeDpi;
+ HKL hOldKL;
+ LPARAM lParam;
+ HWND hwndDefIME = NULL;
+ SELECT_LAYOUT SelectLayout;
+
+ hOldKL = GetKeyboardLayout(0);
+
+ if (hOldKL == hKL && !(GetWin32ClientInfo()->CI_flags & CI_IMMACTIVATE))
+ return TRUE;
- if (hWnd)
+ ImmLoadIME(hKL);
+
+ if (hOldKL != hKL)
{
- DWORD thread = GetWindowThreadProcessId(hWnd, NULL);
- if (thread != GetCurrentThreadId()) return TRUE;
+ pImeDpi = ImmLockImeDpi(hOldKL);
+ if (pImeDpi)
+ {
+ if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT)
+ lParam = CPS_COMPLETE;
+ else
+ lParam = CPS_CANCEL;
+ ImmUnlockImeDpi(pImeDpi);
+
+ ImmEnumInputContext(0, Imm32NotifyIMEProc, lParam);
+ }
+
+ hwndDefIME = ImmGetDefaultIMEWnd(NULL);
+ if (IsWindow(hwndDefIME))
+ SendMessageW(hwndDefIME, WM_IME_SELECT, FALSE, (LPARAM)hOldKL);
+
+ NtUserSetThreadLayoutHandles(hKL, hOldKL);
}
- data = get_imc_data(hIMC);
- if (data && data->threadID != GetCurrentThreadId())
- return TRUE;
- return FALSE;
+ SelectLayout.hNewKL = hKL;
+ SelectLayout.hOldKL = hOldKL;
+ ImmEnumInputContext(0, Imm32SelectContextProc, (LPARAM)&SelectLayout);
+
+ if (IsWindow(hwndDefIME))
+ SendMessageW(hwndDefIME, WM_IME_SELECT, TRUE, (LPARAM)hKL);
+
+ return TRUE;
}
/***********************************************************************
*/
HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
{
- HIMC old = NULL;
- InputContextData *data = get_imc_data(hIMC);
+ PWND pWnd;
+ HWND hwndFocus;
+ DWORD dwValue;
+ HIMC hOldIMC;
- TRACE("(%p, %p):\n", hWnd, hIMC);
+ TRACE("(%p, %p)\n", hWnd, hIMC);
- if(hIMC && !data)
+ if (!IS_IMM_MODE())
+ {
+ TRACE("\n");
return NULL;
+ }
- /*
- * If already associated just return
- */
- if (hIMC && data->IMC.hWnd == hWnd)
- return hIMC;
-
- if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
+ pWnd = ValidateHwnd(hWnd);
+ if (IS_NULL_UNEXPECTEDLY(pWnd))
return NULL;
- if (hWnd)
- {
- HIMC defaultContext = get_default_context( hWnd );
- old = RemovePropW(hWnd,szwWineIMCProperty);
-
- if (old == NULL)
- old = defaultContext;
- else if (old == (HIMC)-1)
- old = NULL;
+ if (hIMC && IS_CROSS_THREAD_HIMC(hIMC))
+ return NULL;
- if (hIMC != defaultContext)
- {
- if (hIMC == NULL) /* Meaning disable imm for that window*/
- SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
- else
- SetPropW(hWnd,szwWineIMCProperty,hIMC);
- }
+ hOldIMC = pWnd->hImc;
+ if (hOldIMC == hIMC)
+ return hIMC;
- if (old)
- {
- InputContextData *old_data = (InputContextData *)old;
- if (old_data->IMC.hWnd == hWnd)
- old_data->IMC.hWnd = NULL;
- }
- }
+ dwValue = NtUserAssociateInputContext(hWnd, hIMC, 0);
+ switch (dwValue)
+ {
+ case 0:
+ return hOldIMC;
- if (!hIMC)
- return old;
+ case 1:
+ hwndFocus = (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_FOCUS);
+ if (hwndFocus == hWnd)
+ {
+ ImmSetActiveContext(hWnd, hOldIMC, FALSE);
+ ImmSetActiveContext(hWnd, hIMC, TRUE);
+ }
+ return hOldIMC;
- if(GetActiveWindow() == data->IMC.hWnd)
- {
- SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
- data->IMC.hWnd = hWnd;
- SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
+ default:
+ return NULL;
}
-
- return old;
}
/***********************************************************************
TRACE("(%p, %p, 0x%lX)\n", hWnd, hIMC, dwFlags);
- if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
+ if (!IS_IMM_MODE())
+ {
+ TRACE("\n");
return FALSE;
+ }
- if (hIMC && !(dwFlags & IACE_DEFAULT) && Imm32IsCrossThreadAccess(hIMC))
+ if (hIMC && !(dwFlags & IACE_DEFAULT) && IS_CROSS_THREAD_HIMC(hIMC))
return FALSE;
hwndFocus = (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_FOCUS);
- pFocusWnd = ValidateHwndNoErr(hwndFocus);
+ pFocusWnd = ValidateHwnd(hwndFocus);
if (pFocusWnd)
hOldIMC = pFocusWnd->hImc;
return TRUE;
case 1:
- pFocusWnd = ValidateHwndNoErr(hwndFocus);
+ pFocusWnd = ValidateHwnd(hwndFocus);
if (pFocusWnd)
{
hIMC = pFocusWnd->hImc;
TRACE("()\n");
- if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
+ if (!IS_IMM_MODE())
+ {
+ TRACE("\n");
return NULL;
+ }
- pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
- if (pClientImc == NULL)
+ pClientImc = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
+ if (IS_NULL_UNEXPECTEDLY(pClientImc))
return NULL;
- hIMC = NtUserCreateInputContext(pClientImc);
- if (hIMC == NULL)
+ hIMC = NtUserCreateInputContext((ULONG_PTR)pClientImc);
+ if (IS_NULL_UNEXPECTEDLY(hIMC))
{
- Imm32HeapFree(pClientImc);
+ ImmLocalFree(pClientImc);
return NULL;
}
RtlInitializeCriticalSection(&pClientImc->cs);
- // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
- pClientImc->unknown = NtUserGetThreadState(13);
+ pClientImc->dwCompatFlags = (DWORD)NtUserGetThreadState(THREADSTATE_IMECOMPATFLAGS);
return hIMC;
}
-static VOID APIENTRY Imm32CleanupContextExtra(LPINPUTCONTEXT pIC)
+// Win: DestroyImeModeSaver
+static VOID APIENTRY Imm32DestroyImeModeSaver(LPINPUTCONTEXTDX pIC)
{
- FIXME("We have to do something do here");
-}
+ PIME_STATE pState, pNext;
+ PIME_SUBSTATE pSubState, pSubNext;
-static PCLIENTIMC APIENTRY Imm32FindClientImc(HIMC hIMC)
-{
- // FIXME
- return NULL;
+ for (pState = pIC->pState; pState; pState = pNext)
+ {
+ pNext = pState->pNext;
+
+ for (pSubState = pState->pSubState; pSubState; pSubState = pSubNext)
+ {
+ pSubNext = pSubState->pNext;
+ ImmLocalFree(pSubState);
+ }
+
+ ImmLocalFree(pState);
+ }
+
+ pIC->pState = NULL;
}
-BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
+// Win: DestroyInputContext
+BOOL APIENTRY Imm32DestroyInputContext(HIMC hIMC, HKL hKL, BOOL bKeep)
{
PIMEDPI pImeDpi;
- LPINPUTCONTEXT pIC;
+ LPINPUTCONTEXTDX pIC;
PCLIENTIMC pClientImc;
+ PIMC pIMC;
- if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32) || hIMC == NULL)
+ if (hIMC == NULL)
return FALSE;
- FIXME("We have do something to do here\n");
- pClientImc = Imm32FindClientImc(hIMC);
- if (!pClientImc)
+ if (!IS_IMM_MODE())
+ {
+ TRACE("\n");
+ return FALSE;
+ }
+
+ pIMC = ValidateHandle(hIMC, TYPE_INPUTCONTEXT);
+ if (IS_NULL_UNEXPECTEDLY(pIMC))
return FALSE;
- if (pClientImc->hImc == NULL)
+ if (pIMC->head.pti != Imm32CurrentPti())
{
- pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
- ImmUnlockClientImc(pClientImc);
- if (!bKeep)
- return NtUserDestroyInputContext(hIMC);
- return TRUE;
+ ERR("Thread mismatch\n");
+ return FALSE;
+ }
+
+ pClientImc = (PCLIENTIMC)pIMC->dwClientImcData;
+ if (pClientImc == NULL)
+ {
+ TRACE("pClientImc == NULL\n");
+ goto Finish;
+ }
+
+ if ((pClientImc->dwFlags & CLIENTIMC_UNKNOWN2) && !bKeep)
+ {
+ ERR("Can't destroy for CLIENTIMC_UNKNOWN2\n");
+ return FALSE;
}
- pIC = ImmLockIMC(hIMC);
- if (pIC == NULL)
+ if (pClientImc->dwFlags & CLIENTIMC_DESTROY)
+ return TRUE;
+
+ InterlockedIncrement(&pClientImc->cLockObj);
+
+ if (IS_NULL_UNEXPECTEDLY(pClientImc->hInputContext))
+ goto Quit;
+
+ pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
+ if (IS_NULL_UNEXPECTEDLY(pIC))
{
ImmUnlockClientImc(pClientImc);
return FALSE;
}
- FIXME("We have do something to do here\n");
+ CtfImmTIMDestroyInputContext(hIMC);
if (pClientImc->hKL == hKL)
{
pImeDpi = ImmLockImeDpi(hKL);
- if (pImeDpi != NULL)
+ if (pImeDpi)
{
if (IS_IME_HKL(hKL))
- {
pImeDpi->ImeSelect(hIMC, FALSE);
- }
- else if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
- {
- FIXME("We have do something to do here\n");
- }
+ else if (IS_CICERO_MODE() && !IS_16BIT_MODE())
+ pImeDpi->CtfImeSelectEx(hIMC, FALSE, hKL);
+
ImmUnlockImeDpi(pImeDpi);
}
+
pClientImc->hKL = NULL;
}
ImmDestroyIMCC(pIC->hGuideLine);
ImmDestroyIMCC(pIC->hCandInfo);
ImmDestroyIMCC(pIC->hCompStr);
-
- Imm32CleanupContextExtra(pIC);
-
+ Imm32DestroyImeModeSaver(pIC);
ImmUnlockIMC(hIMC);
- pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
+Quit:
+ pClientImc->dwFlags |= CLIENTIMC_DESTROY;
ImmUnlockClientImc(pClientImc);
- if (!bKeep)
- return NtUserDestroyInputContext(hIMC);
-
- return TRUE;
+Finish:
+ if (bKeep)
+ return TRUE;
+ return NtUserDestroyInputContext(hIMC);
}
-/***********************************************************************
- * ImmDestroyContext (IMM32.@)
- */
-BOOL WINAPI ImmDestroyContext(HIMC hIMC)
+// NOTE: Windows does recursive call ImmLockIMC here but we don't do so.
+// Win: BOOL CreateInputContext(HIMC hIMC, HKL hKL, BOOL fSelect)
+BOOL APIENTRY
+Imm32CreateInputContext(HIMC hIMC, LPINPUTCONTEXT pIC, PCLIENTIMC pClientImc, HKL hKL, BOOL fSelect)
{
- HKL hKL;
+ DWORD dwIndex, cbPrivate;
+ PIMEDPI pImeDpi = NULL;
+ LPCOMPOSITIONSTRING pCS;
+ LPCANDIDATEINFO pCI;
+ LPGUIDELINE pGL;
+
+ /* Create IC components */
+ pIC->hCompStr = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
+ pIC->hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
+ pIC->hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
+ pIC->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
+ if (IS_NULL_UNEXPECTEDLY(pIC->hCompStr) ||
+ IS_NULL_UNEXPECTEDLY(pIC->hCandInfo) ||
+ IS_NULL_UNEXPECTEDLY(pIC->hGuideLine) ||
+ IS_NULL_UNEXPECTEDLY(pIC->hMsgBuf))
+ {
+ goto Fail;
+ }
- TRACE("(%p)\n", hIMC);
+ /* Initialize IC components */
+ pCS = ImmLockIMCC(pIC->hCompStr);
+ if (IS_NULL_UNEXPECTEDLY(pCS))
+ goto Fail;
+ pCS->dwSize = sizeof(COMPOSITIONSTRING);
+ ImmUnlockIMCC(pIC->hCompStr);
+
+ pCI = ImmLockIMCC(pIC->hCandInfo);
+ if (IS_NULL_UNEXPECTEDLY(pCI))
+ goto Fail;
+ pCI->dwSize = sizeof(CANDIDATEINFO);
+ ImmUnlockIMCC(pIC->hCandInfo);
+
+ pGL = ImmLockIMCC(pIC->hGuideLine);
+ if (IS_NULL_UNEXPECTEDLY(pGL))
+ goto Fail;
+ pGL->dwSize = sizeof(GUIDELINE);
+ ImmUnlockIMCC(pIC->hGuideLine);
+
+ pIC->dwNumMsgBuf = 0;
+ pIC->fOpen = FALSE;
+ pIC->fdwConversion = pIC->fdwSentence = 0;
+
+ for (dwIndex = 0; dwIndex < MAX_CANDIDATEFORM; ++dwIndex)
+ pIC->cfCandForm[dwIndex].dwIndex = IMM_INVALID_CANDFORM;
+
+ /* Get private data size */
+ pImeDpi = ImmLockImeDpi(hKL);
+ if (!pImeDpi)
+ {
+ cbPrivate = sizeof(DWORD);
+ }
+ else
+ {
+ /* Update CLIENTIMC */
+ pClientImc->uCodePage = pImeDpi->uCodePage;
+ if (ImeDpi_IsUnicode(pImeDpi))
+ pClientImc->dwFlags |= CLIENTIMC_WIDE;
- if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
- return FALSE;
+ cbPrivate = pImeDpi->ImeInfo.dwPrivateDataSize;
+ }
- if (Imm32IsCrossThreadAccess(hIMC))
- return FALSE;
+ /* Create private data */
+ pIC->hPrivate = ImmCreateIMCC(cbPrivate);
+ if (IS_NULL_UNEXPECTEDLY(pIC->hPrivate))
+ goto Fail;
- hKL = GetKeyboardLayout(0);
- return Imm32CleanupContext(hIMC, hKL, FALSE);
+ CtfImmTIMCreateInputContext(hIMC);
+
+ if (pImeDpi)
+ {
+ /* Select the IME */
+ if (fSelect)
+ {
+ if (IS_IME_HKL(hKL))
+ pImeDpi->ImeSelect(hIMC, TRUE);
+ else if (IS_CICERO_MODE() && !IS_16BIT_MODE())
+ pImeDpi->CtfImeSelectEx(hIMC, TRUE, hKL);
+ }
+
+ /* Set HKL */
+ pClientImc->hKL = hKL;
+
+ ImmUnlockImeDpi(pImeDpi);
+ }
+
+ return TRUE;
+
+Fail:
+ if (pImeDpi)
+ ImmUnlockImeDpi(pImeDpi);
+
+ pIC->hMsgBuf = ImmDestroyIMCC(pIC->hMsgBuf);
+ pIC->hGuideLine = ImmDestroyIMCC(pIC->hGuideLine);
+ pIC->hCandInfo = ImmDestroyIMCC(pIC->hCandInfo);
+ pIC->hCompStr = ImmDestroyIMCC(pIC->hCompStr);
+ return FALSE;
}
-static PCLIENTIMC APIENTRY Imm32GetClientImcCache(void)
+LPINPUTCONTEXT APIENTRY Imm32InternalLockIMC(HIMC hIMC, BOOL fSelect)
{
- // FIXME: Do something properly here
+ HANDLE hIC;
+ LPINPUTCONTEXT pIC = NULL;
+ PCLIENTIMC pClientImc;
+ WORD LangID;
+ DWORD dwThreadId;
+ HKL hOldKL, hNewKL;
+ PIMEDPI pImeDpi = NULL;
+
+ pClientImc = ImmLockClientImc(hIMC);
+ if (!pClientImc)
+ return NULL;
+
+ RtlEnterCriticalSection(&pClientImc->cs);
+
+ if (pClientImc->hInputContext)
+ {
+ pIC = LocalLock(pClientImc->hInputContext);
+ if (IS_NULL_UNEXPECTEDLY(pIC))
+ goto Failure;
+
+ CtfImmTIMCreateInputContext(hIMC);
+ goto Success;
+ }
+
+ dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID);
+ if (dwThreadId == GetCurrentThreadId() && IS_CICERO_MODE() && !IS_16BIT_MODE())
+ {
+ hOldKL = GetKeyboardLayout(0);
+ LangID = LOWORD(hOldKL);
+ hNewKL = (HKL)(DWORD_PTR)MAKELONG(LangID, LangID);
+
+ pImeDpi = Imm32FindOrLoadImeDpi(hNewKL);
+ if (pImeDpi)
+ {
+ CtfImmTIMActivate(hNewKL);
+ }
+ }
+
+ if (!NtUserQueryInputContext(hIMC, QIC_DEFAULTWINDOWIME))
+ {
+ ERR("No default IME window\n");
+ goto Failure;
+ }
+
+ hIC = LocalAlloc(LHND, sizeof(INPUTCONTEXTDX));
+ pIC = LocalLock(hIC);
+ if (IS_NULL_UNEXPECTEDLY(pIC))
+ {
+ LocalFree(hIC);
+ goto Failure;
+ }
+ pClientImc->hInputContext = hIC;
+
+ hNewKL = GetKeyboardLayout(dwThreadId);
+ if (!Imm32CreateInputContext(hIMC, pIC, pClientImc, hNewKL, fSelect))
+ {
+ LocalUnlock(hIC);
+ pClientImc->hInputContext = LocalFree(hIC);
+ goto Failure;
+ }
+
+Success:
+ RtlLeaveCriticalSection(&pClientImc->cs);
+ InterlockedIncrement(&pClientImc->cLockObj);
+ ImmUnlockClientImc(pClientImc);
+ return pIC;
+
+Failure:
+ RtlLeaveCriticalSection(&pClientImc->cs);
+ ImmUnlockClientImc(pClientImc);
return NULL;
}
+/***********************************************************************
+ * ImmDestroyContext (IMM32.@)
+ */
+BOOL WINAPI ImmDestroyContext(HIMC hIMC)
+{
+ HKL hKL;
+
+ TRACE("(%p)\n", hIMC);
+
+ if (!IS_IMM_MODE())
+ {
+ TRACE("\n");
+ return FALSE;
+ }
+
+ if (IS_CROSS_THREAD_HIMC(hIMC))
+ return FALSE;
+
+ hKL = GetKeyboardLayout(0);
+ return Imm32DestroyInputContext(hIMC, hKL, FALSE);
+}
+
/***********************************************************************
* ImmLockClientImc (IMM32.@)
*/
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
{
+ PIMC pIMC;
PCLIENTIMC pClientImc;
TRACE("(%p)\n", hImc);
- if (hImc == NULL)
+ if (IS_NULL_UNEXPECTEDLY(hImc))
return NULL;
- pClientImc = Imm32GetClientImcCache();
- if (!pClientImc)
+ pIMC = ValidateHandle(hImc, TYPE_INPUTCONTEXT);
+ if (!pIMC || !Imm32CheckImcProcess(pIMC))
+ return NULL;
+
+ pClientImc = (PCLIENTIMC)pIMC->dwClientImcData;
+ if (pClientImc)
{
- pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
- if (!pClientImc)
+ if (pClientImc->dwFlags & CLIENTIMC_DESTROY)
return NULL;
+ goto Finish;
+ }
- RtlInitializeCriticalSection(&pClientImc->cs);
-
- // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
- pClientImc->unknown = NtUserGetThreadState(13);
+ pClientImc = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
+ if (IS_NULL_UNEXPECTEDLY(pClientImc))
+ return NULL;
- if (!NtUserUpdateInputContext(hImc, 0, pClientImc))
- {
- Imm32HeapFree(pClientImc);
- return NULL;
- }
+ RtlInitializeCriticalSection(&pClientImc->cs);
+ pClientImc->dwCompatFlags = (DWORD)NtUserGetThreadState(THREADSTATE_IMECOMPATFLAGS);
- pClientImc->dwFlags |= CLIENTIMC_UNKNOWN2;
- }
- else
+ if (!NtUserUpdateInputContext(hImc, UIC_CLIENTIMCDATA, (DWORD_PTR)pClientImc))
{
- if (pClientImc->dwFlags & CLIENTIMC_UNKNOWN1)
- return NULL;
+ ERR("\n");
+ ImmLocalFree(pClientImc);
+ return NULL;
}
+ pClientImc->dwFlags |= CLIENTIMC_UNKNOWN2;
+
+Finish:
InterlockedIncrement(&pClientImc->cLockObj);
return pClientImc;
}
VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc)
{
LONG cLocks;
- HIMC hImc;
+ HANDLE hInputContext;
TRACE("(%p)\n", pClientImc);
cLocks = InterlockedDecrement(&pClientImc->cLockObj);
- if (cLocks != 0 || !(pClientImc->dwFlags & CLIENTIMC_UNKNOWN1))
+ if (cLocks != 0 || !(pClientImc->dwFlags & CLIENTIMC_DESTROY))
return;
- hImc = pClientImc->hImc;
- if (hImc)
- LocalFree(hImc);
+ hInputContext = pClientImc->hInputContext;
+ if (hInputContext)
+ LocalFree(hInputContext);
RtlDeleteCriticalSection(&pClientImc->cs);
- Imm32HeapFree(pClientImc);
+ ImmLocalFree(pClientImc);
}
-static HIMC APIENTRY Imm32GetContextEx(HWND hWnd, DWORD dwContextFlags)
+// Win: ImmGetSaveContext
+static HIMC APIENTRY ImmGetSaveContext(HWND hWnd, DWORD dwContextFlags)
{
HIMC hIMC;
PCLIENTIMC pClientImc;
PWND pWnd;
- if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
+ if (!IS_IMM_MODE())
+ {
+ TRACE("Not IMM mode.\n");
return NULL;
+ }
if (!hWnd)
{
- // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
- hIMC = (HIMC)NtUserGetThreadState(4);
+ hIMC = (HIMC)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT);
goto Quit;
}
- pWnd = ValidateHwndNoErr(hWnd);
- if (!pWnd || Imm32IsCrossProcessAccess(hWnd))
+ pWnd = ValidateHwnd(hWnd);
+ if (IS_NULL_UNEXPECTEDLY(pWnd) || IS_CROSS_PROCESS_HWND(hWnd))
return NULL;
hIMC = pWnd->hImc;
Quit:
pClientImc = ImmLockClientImc(hIMC);
- if (pClientImc == NULL)
+ if (IS_NULL_UNEXPECTEDLY(pClientImc))
return NULL;
- if ((dwContextFlags & 2) && (pClientImc->dwFlags & CLIENTIMC_UNKNOWN3))
+
+ if ((dwContextFlags & 2) && (pClientImc->dwFlags & CLIENTIMC_DISABLEIME))
hIMC = NULL;
+
ImmUnlockClientImc(pClientImc);
return hIMC;
}
-
-/* Helpers for the GetCompositionString functions */
-
-/* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
- length is always in bytes. */
-static INT
-CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT src_len, void *dst,
- INT dst_len, BOOL unicode)
-{
- int char_size = unicode ? sizeof(WCHAR) : sizeof(char);
- INT ret;
-
- if (is_himc_ime_unicode(data) ^ unicode)
- {
- if (unicode)
- ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len / sizeof(WCHAR));
- else
- ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, NULL, NULL);
- ret *= char_size;
- }
- else
- {
- if (dst_len)
- {
- ret = min(src_len * char_size, dst_len);
- memcpy(dst, src, ret);
- }
- else
- ret = src_len * char_size;
- }
-
- return ret;
-}
-
-/* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
- passed mode. String length is in characters, attributes are in byte arrays. */
-static INT
-CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE *src, INT src_len, const void *comp_string,
- INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
-{
- union
- {
- const void *str;
- const WCHAR *strW;
- const char *strA;
- } string;
- INT rc;
-
- string.str = comp_string;
-
- if (is_himc_ime_unicode(data) && !unicode)
- {
- rc = WideCharToMultiByte(CP_ACP, 0, string.strW, str_len, NULL, 0, NULL, NULL);
- if (dst_len)
- {
- int i, j = 0, k = 0;
-
- if (rc < dst_len)
- dst_len = rc;
- for (i = 0; i < str_len; ++i)
- {
- int len;
-
- len = WideCharToMultiByte(CP_ACP, 0, string.strW + i, 1, NULL, 0, NULL, NULL);
- for (; len > 0; --len)
- {
- dst[j++] = src[k];
-
- if (j >= dst_len)
- goto end;
- }
- ++k;
- }
- end:
- rc = j;
- }
- }
- else if (!is_himc_ime_unicode(data) && unicode)
- {
- rc = MultiByteToWideChar(CP_ACP, 0, string.strA, str_len, NULL, 0);
- if (dst_len)
- {
- int i, j = 0;
-
- if (rc < dst_len)
- dst_len = rc;
- for (i = 0; i < str_len; ++i)
- {
- if (IsDBCSLeadByte(string.strA[i]))
- continue;
-
- dst[j++] = src[i];
-
- if (j >= dst_len)
- break;
- }
- rc = j;
- }
- }
- else
- {
- memcpy(dst, src, min(src_len, dst_len));
- rc = src_len;
- }
-
- return rc;
-}
-
-static INT
-CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
- 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 = get_imc_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,
- lpBuf, dwBufLen, unicode);
- break;
- case GCS_RESULTCLAUSE:
- TRACE("GCS_RESULTCLAUSE\n");
- rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
- compdata + compstr->dwResultStrOffset,
- 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,
- 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,
- 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)
-{
- return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
-}
-
-/***********************************************************************
- * ImmGetCompositionStringW (IMM32.@)
- */
-LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
-{
- return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
-}
-
/***********************************************************************
* ImmGetContext (IMM32.@)
*/
HIMC WINAPI ImmGetContext(HWND hWnd)
{
TRACE("(%p)\n", hWnd);
- if (hWnd == NULL)
+ if (IS_NULL_UNEXPECTEDLY(hWnd))
return NULL;
- return Imm32GetContextEx(hWnd, 2);
+ return ImmGetSaveContext(hWnd, 2);
}
/***********************************************************************
- * CtfImmIsCiceroEnabled (IMM32.@)
+ * ImmLockIMC(IMM32.@)
+ *
+ * NOTE: This is not ImmLockIMCC. Don't confuse.
*/
-BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
-{
- return (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED));
-}
-
-/***********************************************************************
- * ImmInstallIMEA (IMM32.@)
- */
-HKL WINAPI ImmInstallIMEA(LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
-{
- HKL hKL = NULL;
- LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL;
-
- TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText));
-
- pszFileNameW = Imm32WideFromAnsi(lpszIMEFileName);
- if (pszFileNameW == NULL)
- goto Quit;
-
- pszLayoutTextW = Imm32WideFromAnsi(lpszLayoutText);
- if (pszLayoutTextW == NULL)
- goto Quit;
-
- hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW);
-
-Quit:
- Imm32HeapFree(pszFileNameW);
- Imm32HeapFree(pszLayoutTextW);
- return hKL;
-}
-
-/***********************************************************************
- * ImmInstallIMEW (IMM32.@)
- */
-HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
-{
- INT lcid = GetUserDefaultLCID();
- INT count;
- HKL hkl;
- DWORD rc;
- HKEY hkey;
- WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+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, (const BYTE*)lpszIMEFileName,
- (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
- if (rc == ERROR_SUCCESS)
- rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
- (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
- RegCloseKey(hkey);
- return hkl;
- }
- else
- {
- WARN("Unable to set IME registry values\n");
- return 0;
- }
-}
-
-/***********************************************************************
-* ImmLockIMC(IMM32.@)
-*/
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
{
- InputContextData *data = get_imc_data(hIMC);
-
- if (!data)
- return NULL;
- data->dwLock++;
- return &data->IMC;
+ TRACE("(%p)\n", hIMC);
+ return Imm32InternalLockIMC(hIMC, TRUE);
}
/***********************************************************************
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
{
PCLIENTIMC pClientImc;
- HIMC hClientImc;
pClientImc = ImmLockClientImc(hIMC);
- if (pClientImc == NULL)
+ if (IS_NULL_UNEXPECTEDLY(pClientImc))
return FALSE;
- hClientImc = pClientImc->hImc;
- if (hClientImc)
- LocalUnlock(hClientImc);
+ if (pClientImc->hInputContext)
+ LocalUnlock(pClientImc->hInputContext);
InterlockedDecrement(&pClientImc->cLockObj);
ImmUnlockClientImc(pClientImc);
return TRUE;
}
-/***********************************************************************
- * ImmRequestMessageA(IMM32.@)
- */
-LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
-{
- InputContextData *data = get_imc_data(hIMC);
-
- TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
-
- if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
-
- SetLastError(ERROR_INVALID_HANDLE);
- return 0;
-}
-
-/***********************************************************************
- * ImmRequestMessageW(IMM32.@)
- */
-LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
-{
- InputContextData *data = get_imc_data(hIMC);
-
- TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
-
- if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
-
- SetLastError(ERROR_INVALID_HANDLE);
- return 0;
-}
-
/***********************************************************************
* ImmReleaseContext (IMM32.@)
*/
}
/***********************************************************************
- * ImmSetCompositionStringA (IMM32.@)
+ * ImmEnumInputContext(IMM32.@)
*/
-BOOL WINAPI
-ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex,
- LPCVOID lpComp, DWORD dwCompLen,
- LPCVOID lpRead, DWORD dwReadLen)
+BOOL WINAPI ImmEnumInputContext(DWORD dwThreadId, IMCENUMPROC lpfn, LPARAM lParam)
{
- DWORD comp_len;
- DWORD read_len;
- WCHAR *CompBuffer = NULL;
- WCHAR *ReadBuffer = NULL;
- BOOL rc;
- InputContextData *data = get_imc_data(hIMC);
-
- TRACE("(%p, %d, %p, %d, %p, %d):\n",
- hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
+ HIMC *phList;
+ DWORD dwIndex, dwCount;
+ BOOL ret = TRUE;
+ HIMC hIMC;
- if (!data)
- return FALSE;
+ TRACE("(%lu, %p, %p)\n", dwThreadId, lpfn, lParam);
- if (!(dwIndex == SCS_SETSTR ||
- dwIndex == SCS_CHANGEATTR ||
- dwIndex == SCS_CHANGECLAUSE ||
- dwIndex == SCS_SETRECONVERTSTRING ||
- dwIndex == SCS_QUERYRECONVERTSTRING))
+ dwCount = Imm32BuildHimcList(dwThreadId, &phList);
+ if (IS_ZERO_UNEXPECTEDLY(dwCount))
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)
- {
- 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)
+ for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
{
- ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
+ hIMC = phList[dwIndex];
+ ret = (*lpfn)(hIMC, lParam);
+ if (!ret)
+ break;
}
- rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
- ReadBuffer, read_len);
-
- HeapFree(GetProcessHeap(), 0, CompBuffer);
- HeapFree(GetProcessHeap(), 0, ReadBuffer);
-
- return rc;
+ ImmLocalFree(phList);
+ return ret;
}
/***********************************************************************
- * ImmSetCompositionStringW (IMM32.@)
+ * ImmSetActiveContext(IMM32.@)
*/
-BOOL WINAPI
-ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex,
- LPCVOID lpComp, DWORD dwCompLen,
- LPCVOID lpRead, DWORD dwReadLen)
+BOOL WINAPI ImmSetActiveContext(HWND hWnd, HIMC hIMC, BOOL fActive)
{
- DWORD comp_len;
- DWORD read_len;
- CHAR *CompBuffer = NULL;
- CHAR *ReadBuffer = NULL;
- BOOL rc;
- InputContextData *data = get_imc_data(hIMC);
-
- TRACE("(%p, %d, %p, %d, %p, %d):\n",
- hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
+ PCLIENTIMC pClientImc;
+ LPINPUTCONTEXTDX pIC;
+ PIMEDPI pImeDpi;
+ HIMC hOldIMC;
+ HKL hKL;
+ BOOL fOpen = FALSE;
+ DWORD dwConversion = 0, dwShowFlags = ISC_SHOWUIALL;
+ HWND hwndDefIME;
- if (!data)
- return FALSE;
+ TRACE("(%p, %p, %d)\n", hWnd, hIMC, fActive);
- if (!(dwIndex == SCS_SETSTR ||
- dwIndex == SCS_CHANGEATTR ||
- dwIndex == SCS_CHANGECLAUSE ||
- dwIndex == SCS_SETRECONVERTSTRING ||
- dwIndex == SCS_QUERYRECONVERTSTRING))
+ if (!IS_IMM_MODE())
+ {
+ TRACE("\n");
return FALSE;
+ }
- if (is_himc_ime_unicode(data))
- return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
- dwCompLen, lpRead, dwReadLen);
+ pClientImc = ImmLockClientImc(hIMC);
- comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
- NULL);
- if (comp_len)
+ if (!fActive)
{
- CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
- WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
- NULL, NULL);
+ if (pClientImc)
+ pClientImc->dwFlags &= ~CLIENTIMC_ACTIVE;
}
-
- read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
- NULL);
- if (read_len)
+ else if (hIMC)
{
- ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
- WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
- NULL, NULL);
- }
-
- rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
- ReadBuffer, read_len);
-
- HeapFree(GetProcessHeap(), 0, CompBuffer);
- HeapFree(GetProcessHeap(), 0, ReadBuffer);
-
- return rc;
-}
+ if (IS_NULL_UNEXPECTEDLY(pClientImc))
+ return FALSE;
-/***********************************************************************
- * 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;
-}
+ pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
+ if (IS_NULL_UNEXPECTEDLY(pIC))
+ {
+ ImmUnlockClientImc(pClientImc);
+ return FALSE;
+ }
-/***********************************************************************
- * ImmDestroySoftKeyboard(IMM32.@)
- */
-BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
-{
- TRACE("(%p)\n", hSoftWnd);
- return DestroyWindow(hSoftWnd);
-}
+ pIC->hWnd = hWnd;
+ pClientImc->dwFlags |= CLIENTIMC_ACTIVE;
-/***********************************************************************
- * ImmShowSoftKeyboard(IMM32.@)
- */
-BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
-{
- TRACE("(%p, %d)\n", hSoftWnd, nCmdShow);
- if (hSoftWnd)
- return ShowWindow(hSoftWnd, nCmdShow);
- return FALSE;
-}
+ if (pIC->dwUIFlags & 2)
+ dwShowFlags = (ISC_SHOWUIGUIDELINE | ISC_SHOWUIALLCANDIDATEWINDOW);
-/***********************************************************************
-* ImmDisableTextFrameService(IMM32.@)
-*/
-BOOL WINAPI ImmDisableTextFrameService(DWORD dwThreadId)
-{
- FIXME("Stub\n");
- return FALSE;
-}
+ fOpen = pIC->fOpen;
+ dwConversion = pIC->fdwConversion;
-/***********************************************************************
- * ImmEnumInputContext(IMM32.@)
- */
-BOOL WINAPI ImmEnumInputContext(DWORD dwThreadId, IMCENUMPROC lpfn, LPARAM lParam)
-{
- HIMC *phList;
- DWORD dwIndex, dwCount;
- BOOL ret = TRUE;
- HIMC hIMC;
+ ImmUnlockIMC(hIMC);
+ }
+ else
+ {
+ hOldIMC = ImmGetSaveContext(hWnd, 1);
+ pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hOldIMC);
+ if (pIC)
+ {
+ pIC->hWnd = hWnd;
+ ImmUnlockIMC(hOldIMC);
+ }
+ }
- TRACE("(%lu, %p, %p)\n", dwThreadId, lpfn, lParam);
+ hKL = GetKeyboardLayout(0);
+ if (IS_CICERO_MODE() && !IS_16BIT_MODE())
+ {
+ CtfImeSetActiveContextAlways(hIMC, fActive, hWnd, hKL);
+ hKL = GetKeyboardLayout(0);
+ }
- dwCount = Imm32AllocAndBuildHimcList(dwThreadId, &phList);
- if (!dwCount)
- return FALSE;
+ pImeDpi = ImmLockImeDpi(hKL);
+ if (pImeDpi)
+ {
+ if (IS_IME_HKL(hKL))
+ pImeDpi->ImeSetActiveContext(hIMC, fActive);
+ ImmUnlockImeDpi(pImeDpi);
+ }
- for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
+ if (IsWindow(hWnd))
{
- hIMC = phList[dwIndex];
- ret = (*lpfn)(hIMC, lParam);
- if (!ret)
- break;
+ SendMessageW(hWnd, WM_IME_SETCONTEXT, fActive, dwShowFlags);
+ if (fActive)
+ NtUserNotifyIMEStatus(hWnd, fOpen, dwConversion);
+ }
+ else if (!fActive)
+ {
+ hwndDefIME = ImmGetDefaultIMEWnd(NULL);
+ if (hwndDefIME)
+ SendMessageW(hwndDefIME, WM_IME_SETCONTEXT, 0, dwShowFlags);
}
- Imm32HeapFree(phList);
- return ret;
+ if (pClientImc)
+ ImmUnlockClientImc(pClientImc);
+
+ return TRUE;
}
/***********************************************************************
- * ImmSetActiveContext(IMM32.@)
+ * ImmWINNLSGetEnableStatus (IMM32.@)
*/
-BOOL WINAPI ImmSetActiveContext(HWND hwnd, HIMC hIMC, BOOL fFlag)
+
+BOOL WINAPI ImmWINNLSGetEnableStatus(HWND hWnd)
{
- FIXME("(%p, %p, %d): stub\n", hwnd, hIMC, fFlag);
- return FALSE;
+ if (!Imm32IsSystemJapaneseOrKorean())
+ {
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+ }
+
+ return !!ImmGetSaveContext(hWnd, 2);
}
/***********************************************************************
TRACE("(%p, %d)\n", hwnd, fFlag);
hIMC = ImmGetContext(hwnd);
- if (hIMC)
- return ImmSetActiveContext(hwnd, hIMC, fFlag);
- return FALSE;
+ if (IS_NULL_UNEXPECTEDLY(hIMC))
+ return FALSE;
+ return ImmSetActiveContext(hwnd, hIMC, fFlag);
}
/***********************************************************************
- * ImmGetImeMenuItemsA (IMM32.@)
+ * GetKeyboardLayoutCP (IMM32.@)
*/
-DWORD WINAPI
-ImmGetImeMenuItemsA(HIMC hIMC, DWORD dwFlags, DWORD dwType,
- LPIMEMENUITEMINFOA lpImeParentMenu,
- LPIMEMENUITEMINFOA lpImeMenu, DWORD dwSize)
+UINT WINAPI GetKeyboardLayoutCP(_In_ LANGID wLangId)
{
- InputContextData *data = get_imc_data(hIMC);
- TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
- lpImeParentMenu, lpImeMenu, dwSize);
+ WCHAR szText[8];
+ static LANGID s_wKeyboardLangIdCache = 0;
+ static UINT s_uKeyboardLayoutCPCache = 0;
- if (!data)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return 0;
- }
+ TRACE("(%u)\n", wLangId);
- 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;
+ if (wLangId == s_wKeyboardLangIdCache)
+ return s_uKeyboardLayoutCPCache;
- 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
+ if (!GetLocaleInfoW(wLangId, LOCALE_IDEFAULTANSICODEPAGE, szText, _countof(szText)))
return 0;
+
+ s_wKeyboardLangIdCache = wLangId;
+ szText[_countof(szText) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
+ s_uKeyboardLayoutCPCache = wcstol(szText, NULL, 10);
+ return s_uKeyboardLayoutCPCache;
}
-/***********************************************************************
- * ImmGetImeMenuItemsW (IMM32.@)
- */
-DWORD WINAPI
-ImmGetImeMenuItemsW(HIMC hIMC, DWORD dwFlags, DWORD dwType,
- LPIMEMENUITEMINFOW lpImeParentMenu,
- LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize)
+#ifndef NDEBUG
+VOID APIENTRY Imm32UnitTest(VOID)
{
- 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 (0)
{
- 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;
- }
+ DWORD dwValue;
+ WCHAR szText[64];
+
+ Imm32StrToUInt(L"123", &dwValue, 10);
+ ASSERT(dwValue == 123);
+ Imm32StrToUInt(L"100", &dwValue, 16);
+ ASSERT(dwValue == 0x100);
+
+ Imm32UIntToStr(123, 10, szText, _countof(szText));
+ ASSERT(lstrcmpW(szText, L"123") == 0);
+ Imm32UIntToStr(0x100, 16, szText, _countof(szText));
+ ASSERT(lstrcmpW(szText, L"100") == 0);
}
- else
- return 0;
}
+#endif
BOOL WINAPI User32InitializeImmEntryTable(DWORD);
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
+BOOL
+WINAPI
+ImmDllInitialize(
+ _In_ HINSTANCE hDll,
+ _In_ ULONG dwReason,
+ _In_opt_ PVOID pReserved)
{
HKL hKL;
HIMC hIMC;
- PTEB pTeb;
- TRACE("(%p, 0x%X, %p)\n", hinstDLL, fdwReason, lpReserved);
+ TRACE("(%p, 0x%X, %p)\n", hDll, dwReason, pReserved);
- switch (fdwReason)
+ switch (dwReason)
{
case DLL_PROCESS_ATTACH:
- //Imm32GenerateRandomSeed(hinstDLL, 1, lpReserved); // Non-sense
- if (!Imm32InitInstance(hinstDLL))
+ if (!ImmInitializeGlobals(hDll))
{
- ERR("Imm32InitInstance failed\n");
+ ERR("ImmInitializeGlobals failed\n");
return FALSE;
}
if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
ERR("User32InitializeImmEntryTable failed\n");
return FALSE;
}
+#ifndef NDEBUG
+ Imm32UnitTest();
+#endif
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
- if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
- return TRUE;
-
- pTeb = NtCurrentTeb();
- if (pTeb->Win32ThreadInfo == NULL)
+ if (!IS_IMM_MODE() || NtCurrentTeb()->Win32ThreadInfo == NULL)
return TRUE;
hKL = GetKeyboardLayout(0);
- // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
- hIMC = (HIMC)NtUserGetThreadState(4);
- Imm32CleanupContext(hIMC, hKL, TRUE);
+ hIMC = (HIMC)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT);
+ Imm32DestroyInputContext(hIMC, hKL, TRUE);
break;
case DLL_PROCESS_DETACH:
- RtlDeleteCriticalSection(&g_csImeDpi);
+ RtlDeleteCriticalSection(&gcsImeDpi);
TRACE("imm32.dll is unloaded\n");
break;
}