[IMM32] Implement ImmFreeLayout (#3978)
authorKatayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
Tue, 28 Sep 2021 13:02:30 +0000 (22:02 +0900)
committerGitHub <noreply@github.com>
Tue, 28 Sep 2021 13:02:30 +0000 (22:02 +0900)
- Implement ImmFreeLayout function.
- Add Imm32ReleaseIME helper function.
CORE-11700

dll/win32/imm32/ime.c
dll/win32/imm32/imm32.spec

index 99c675d..3eeb716 100644 (file)
@@ -283,6 +283,53 @@ ImeDpi_Escape(PIMEDPI pImeDpi, HIMC hIMC, UINT uSubFunc, LPVOID lpData, HKL hKL)
     return 0;
 }
 
+BOOL APIENTRY Imm32ReleaseIME(HKL hKL)
+{
+    BOOL ret = TRUE;
+    PIMEDPI pImeDpi0, pImeDpi1;
+
+    RtlEnterCriticalSection(&g_csImeDpi);
+
+    for (pImeDpi0 = g_pImeDpiList; pImeDpi0; pImeDpi0 = pImeDpi0->pNext)
+    {
+        if (pImeDpi0->hKL == hKL)
+            break;
+    }
+
+    if (!pImeDpi0)
+        goto Quit;
+
+    if (pImeDpi0->cLockObj)
+    {
+        pImeDpi0->dwFlags |= IMEDPI_FLAG_UNKNOWN;
+        ret = FALSE;
+        goto Quit;
+    }
+
+    if (g_pImeDpiList == pImeDpi0)
+    {
+        g_pImeDpiList = pImeDpi0->pNext;
+    }
+    else if (g_pImeDpiList)
+    {
+        for (pImeDpi1 = g_pImeDpiList; pImeDpi1; pImeDpi1 = pImeDpi1->pNext)
+        {
+            if (pImeDpi1->pNext == pImeDpi0)
+            {
+                pImeDpi1->pNext = pImeDpi0->pNext;
+                break;
+            }
+        }
+    }
+
+    Imm32FreeImeDpi(pImeDpi0, TRUE);
+    Imm32HeapFree(pImeDpi0);
+
+Quit:
+    RtlLeaveCriticalSection(&g_csImeDpi);
+    return ret;
+}
+
 /***********************************************************************
  *             ImmIsIME (IMM32.@)
  */
@@ -1456,3 +1503,70 @@ Quit:
     ImmUnlockImeDpi(pImeDpi);
     return ret;
 }
+
+/***********************************************************************
+ *             ImmFreeLayout (IMM32.@)
+ */
+BOOL WINAPI ImmFreeLayout(DWORD dwUnknown)
+{
+    WCHAR szKBD[9];
+    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 = Imm32HeapAlloc(0, cKLs * sizeof(HKL));
+            if (pList == NULL)
+                return FALSE;
+
+            cKLs = GetKeyboardLayoutList(cKLs, pList);
+            for (iKL = 0; iKL < cKLs; ++iKL)
+            {
+                if (!IS_IME_HKL(pList[iKL]))
+                {
+                    LangID = LOWORD(pList[iKL]);
+                    break;
+                }
+            }
+
+            Imm32HeapFree(pList);
+        }
+
+        StringCchPrintfW(szKBD, _countof(szKBD), L"%08X", LangID);
+        if (!LoadKeyboardLayoutW(szKBD, KLF_ACTIVATE))
+            LoadKeyboardLayoutW(L"00000409", KLF_ACTIVATE | 0x200);
+    }
+    else if (dwUnknown == 2)
+    {
+        RtlEnterCriticalSection(&g_csImeDpi);
+Retry:
+        for (pImeDpi = g_pImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext)
+        {
+            if (Imm32ReleaseIME(pImeDpi->hKL))
+                goto Retry;
+        }
+        RtlLeaveCriticalSection(&g_csImeDpi);
+    }
+    else
+    {
+        hNewKL = (HKL)(DWORD_PTR)dwUnknown;
+        if (IS_IME_HKL(hNewKL) && hNewKL != hOldKL)
+            Imm32ReleaseIME(hNewKL);
+    }
+
+    return TRUE;
+}
index ba038cb..221c8a8 100644 (file)
@@ -24,7 +24,7 @@
 @ stdcall ImmEnumRegisterWordW(long ptr wstr long wstr ptr)
 @ stdcall ImmEscapeA(long ptr long ptr)
 @ stdcall ImmEscapeW(long ptr long ptr)
-@ stdcall -stub ImmFreeLayout(long)
+@ stdcall ImmFreeLayout(long)
 @ stdcall ImmGenerateMessage(ptr)
 @ stdcall ImmGetCandidateListA(long long ptr long)
 @ stdcall ImmGetCandidateListCountA(long ptr)