https://git.reactos.org/?p=reactos.git;a=commitdiff;h=73a1c9d4185cb0f183c2df787562d082888ed763

commit 73a1c9d4185cb0f183c2df787562d082888ed763
Author:     Katayama Hirofumi MZ <[email protected]>
AuthorDate: Wed Dec 27 20:29:02 2023 +0900
Commit:     GitHub <[email protected]>
CommitDate: Wed Dec 27 20:29:02 2023 +0900

    [MSCTFIME][SDK] Implement CtfImeSelectEx (#6238)
    
    Supporting TIPs...
    JIRA issue: CORE-19360
    - Add GetCharsetFromLangId and
      InternalSelectEx helper functions.
    - Add CicBridge::GetInputContext
      and CicBridge::SelectEx.
    - Implement CtfImeSelectEx function.
    - CTFIMECONTEXT structure moved
      into <cicero/cicimc.h>.
---
 dll/ime/msctfime/msctfime.cpp       | 193 +++++++++++++++++++++++++++++++++++-
 dll/ime/msctfime/msctfime.h         |   8 --
 sdk/include/reactos/cicero/cicimc.h |  59 +++++++++++
 3 files changed, 250 insertions(+), 10 deletions(-)

diff --git a/dll/ime/msctfime/msctfime.cpp b/dll/ime/msctfime/msctfime.cpp
index 726d1b38a96..769b56e6502 100644
--- a/dll/ime/msctfime/msctfime.cpp
+++ b/dll/ime/msctfime/msctfime.cpp
@@ -81,6 +81,9 @@ BOOL RegisterMSIMEMessage(VOID)
 
 typedef BOOLEAN (WINAPI *FN_DllShutDownInProgress)(VOID);
 
+/**
+ * @implemented
+ */
 EXTERN_C BOOLEAN WINAPI
 DllShutDownInProgress(VOID)
 {
@@ -99,6 +102,9 @@ DllShutDownInProgress(VOID)
     return s_fnDllShutDownInProgress();
 }
 
+/**
+ * @implemented
+ */
 static BOOL
 IsInteractiveUserLogon(VOID)
 {
@@ -136,6 +142,9 @@ HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
     return E_NOTIMPL;
 }
 
+/**
+ * @implemented
+ */
 HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
 {
     if (!pLibThread)
@@ -150,6 +159,86 @@ HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
     return S_OK;
 }
 
+/**
+ * @implemented
+ */
+BYTE GetCharsetFromLangId(DWORD dwValue)
+{
+    CHARSETINFO info;
+    if (!::TranslateCharsetInfo((DWORD*)(DWORD_PTR)dwValue, &info, 
TCI_SRCLOCALE))
+        return 0;
+    return info.ciCharset;
+}
+
+/**
+ * @implemented
+ */
+HRESULT
+InternalSelectEx(HIMC hIMC, BOOL fSelect, LANGID LangID)
+{
+    CicIMCLock imcLock(hIMC);
+    if (!imcLock)
+        imcLock.m_hr = E_FAIL;
+    if (FAILED(imcLock.m_hr))
+        return imcLock.m_hr;
+
+    if (PRIMARYLANGID(LangID) == LANG_CHINESE)
+    {
+        imcLock.get().cfCandForm[0].dwStyle = 0;
+        imcLock.get().cfCandForm[0].dwIndex = (DWORD)-1;
+    }
+
+    if (!fSelect)
+    {
+        imcLock.get().fdwInit &= ~INIT_GUIDMAP;
+        return imcLock.m_hr;
+    }
+
+    if (!imcLock.ClearCand())
+        return imcLock.m_hr;
+
+    // Populate conversion mode
+    if (!(imcLock.get().fdwInit & INIT_CONVERSION))
+    {
+        DWORD dwConv = (imcLock.get().fdwConversion & IME_CMODE_SOFTKBD);
+        if (LangID)
+        {
+            if (PRIMARYLANGID(LangID) == LANG_JAPANESE)
+            {
+                dwConv |= IME_CMODE_ROMAN | IME_CMODE_FULLSHAPE | 
IME_CMODE_NATIVE;
+            }
+            else if (PRIMARYLANGID(LangID) != LANG_KOREAN)
+            {
+                dwConv |= IME_CMODE_NATIVE;
+            }
+        }
+        imcLock.get().fdwConversion |= dwConv;
+        imcLock.get().fdwInit |= INIT_CONVERSION;
+    }
+
+    // Populate sentence mode
+    imcLock.get().fdwSentence |= IME_SMODE_PHRASEPREDICT;
+
+    // Populate LOGFONT
+    if (!(imcLock.get().fdwInit & INIT_LOGFONT))
+    {
+        // Get logical font
+        LOGFONTW lf;
+        HDC hDC = ::GetDC(imcLock.get().hWnd);
+        HGDIOBJ hFont = GetCurrentObject(hDC, OBJ_FONT);
+        ::GetObjectW(hFont, sizeof(LOGFONTW), &lf);
+        ::ReleaseDC(imcLock.get().hWnd, hDC);
+
+        imcLock.get().lfFont.W = lf;
+        imcLock.get().fdwInit |= INIT_LOGFONT;
+    }
+    imcLock.get().lfFont.W.lfCharSet = GetCharsetFromLangId(LangID);
+
+    imcLock.InitContext();
+
+    return imcLock.m_hr;
+}
+
 /***********************************************************************
  *      Compartment
  */
@@ -1037,6 +1126,19 @@ public:
 
     HRESULT CreateInputContext(TLS *pTLS, HIMC hIMC);
     HRESULT DestroyInputContext(TLS *pTLS, HIMC hIMC);
+    ITfContext *GetInputContext(CicIMCCLock<CTFIMECONTEXT>& imeContext);
+
+    HRESULT SelectEx(
+        TLS *pTLS,
+        ITfThreadMgr_P *pThreadMgr,
+        HIMC hIMC,
+        BOOL fSelect,
+        HKL hKL);
+    HRESULT OnSetOpenStatus(
+        TLS *pTLS,
+        ITfThreadMgr_P *pThreadMgr,
+        CicIMCLock& imcLock,
+        CicInputContext *pCicIC);
 
     void PostTransMsg(HWND hWnd, INT cTransMsgs, LPTRANSMSG pTransMsgs);
     void GetDocumentManager(CicIMCCLock<CTFIMECONTEXT>& imeContext);
@@ -1764,12 +1866,81 @@ HRESULT CicBridge::DestroyInputContext(TLS *pTLS, HIMC 
hIMC)
     return hr;
 }
 
+ITfContext *
+CicBridge::GetInputContext(CicIMCCLock<CTFIMECONTEXT>& imeContext)
+{
+    CicInputContext *pCicIC = imeContext.get().m_pCicIC;
+    if (!pCicIC)
+        return NULL;
+    return pCicIC->m_pContext;
+}
+
+/**
+ * @unimplemented
+ */
+HRESULT CicBridge::OnSetOpenStatus(
+    TLS *pTLS,
+    ITfThreadMgr_P *pThreadMgr,
+    CicIMCLock& imcLock,
+    CicInputContext *pCicIC)
+{
+    return E_NOTIMPL;
+}
+
+/**
+ * @implemented
+ */
+HRESULT
+CicBridge::SelectEx(
+    TLS *pTLS,
+    ITfThreadMgr_P *pThreadMgr,
+    HIMC hIMC,
+    BOOL fSelect,
+    HKL hKL)
+{
+    CicIMCLock imcLock(hIMC);
+    if (FAILED(imcLock.m_hr))
+        return imcLock.m_hr;
+
+    CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
+    if (!imeContext)
+        imeContext.m_hr = E_FAIL;
+    if (FAILED(imeContext.m_hr))
+        return imeContext.m_hr;
+
+    CicInputContext *pCicIC = imeContext.get().m_pCicIC;
+    if (pCicIC)
+        pCicIC->m_dw2[11] |= 1;
+
+    if (fSelect)
+    {
+        if (pCicIC)
+            pCicIC->m_dw2[1] &= ~1;
+        if (imcLock.get().fOpen)
+            OnSetOpenStatus(pTLS, pThreadMgr, imcLock, pCicIC);
+    }
+    else
+    {
+        ITfContext *pContext = GetInputContext(imeContext);
+        pThreadMgr->RequestPostponedLock(pContext);
+        if (pCicIC)
+            pCicIC->m_dw2[11] &= ~1;
+        if (pContext)
+            pContext->Release();
+    }
+
+    return imeContext.m_hr;
+}
+
 typedef struct ENUM_CREATE_DESTROY_IC
 {
     TLS *m_pTLS;
     CicBridge *m_pBridge;
 } ENUM_CREATE_DESTROY_IC, *PENUM_CREATE_DESTROY_IC;
 
+/**
+ * @implemented
+ */
 BOOL CALLBACK CicBridge::EnumCreateInputContextCallback(HIMC hIMC, LPARAM 
lParam)
 {
     PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam;
@@ -1777,6 +1948,9 @@ BOOL CALLBACK 
CicBridge::EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam
     return TRUE;
 }
 
+/**
+ * @implemented
+ */
 BOOL CALLBACK CicBridge::EnumDestroyInputContextCallback(HIMC hIMC, LPARAM 
lParam)
 {
     PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam;
@@ -2454,14 +2628,29 @@ CtfImeInquireExW(
     return Inquire(lpIMEInfo, lpszWndClass, dwSystemInfoFlags, hKL);
 }
 
+/***********************************************************************
+ *      CtfImeSelectEx (MSCTFIME.@)
+ *
+ * @implemented
+ */
 EXTERN_C BOOL WINAPI
 CtfImeSelectEx(
     _In_ HIMC hIMC,
     _In_ BOOL fSelect,
     _In_ HKL hKL)
 {
-    FIXME("stub:(%p, %d, %p)\n", hIMC, fSelect, hKL);
-    return FALSE;
+    TRACE("(%p, %d, %p)\n", hIMC, fSelect, hKL);
+
+    TLS *pTLS = TLS::PeekTLS();
+    if (!pTLS)
+        return E_OUTOFMEMORY;
+
+    InternalSelectEx(hIMC, fSelect, LOWORD(hKL));
+
+    if (!pTLS->m_pBridge || !pTLS->m_pThreadMgr)
+        return E_OUTOFMEMORY;
+
+    return pTLS->m_pBridge->SelectEx(pTLS, pTLS->m_pThreadMgr, hIMC, fSelect, 
hKL);
 }
 
 EXTERN_C LRESULT WINAPI
diff --git a/dll/ime/msctfime/msctfime.h b/dll/ime/msctfime/msctfime.h
index 8ab6bf3f5ad..0fe3b49d5d7 100644
--- a/dll/ime/msctfime/msctfime.h
+++ b/dll/ime/msctfime/msctfime.h
@@ -28,14 +28,6 @@
 #include <cicero/cicimc.h>
 #include <cicero/cictf.h>
 
-class CicInputContext;
-
-typedef struct tagCTFIMECONTEXT
-{
-    CicInputContext *m_pCicIC;
-    DWORD m_dwCicFlags;
-} CTFIMECONTEXT, *PCTFIMECONTEXT;
-
 #include <wine/debug.h>
 
 #include "resource.h"
diff --git a/sdk/include/reactos/cicero/cicimc.h 
b/sdk/include/reactos/cicero/cicimc.h
index 18b25bdb191..dcef56ef687 100644
--- a/sdk/include/reactos/cicero/cicimc.h
+++ b/sdk/include/reactos/cicero/cicimc.h
@@ -7,11 +7,20 @@
 
 #pragma once
 
+// struct CTFIMECONTEXT;
 // class CIC_IMCC_LOCK<T_DATA>;
 // class CicIMCCLock<T_DATA>;
 // class CIC_IMC_LOCK;
 // class CicIMCLock;
 
+class CicInputContext;
+
+typedef struct tagCTFIMECONTEXT
+{
+    CicInputContext *m_pCicIC;
+    DWORD m_dwCicFlags;
+} CTFIMECONTEXT, *PCTFIMECONTEXT;
+
 template <typename T_DATA>
 class CIC_IMCC_LOCK
 {
@@ -143,6 +152,8 @@ public:
         return imccLock.get().dwCompStrLen > 0;
     }
 
+    BOOL ClearCand();
+
     BOOL UseVerticalCompWindow() const
     {
         return m_pIC->cfCompForm.dwStyle && ((m_pIC->lfFont.A.lfEscapement / 
900) % 4 == 3);
@@ -172,3 +183,51 @@ protected:
         return ::ImmUnlockIMC(hIMC) ? S_OK : E_FAIL;
     }
 };
+
+inline BOOL CicIMCLock::ClearCand()
+{
+    HIMCC hNewCandInfo, hCandInfo = m_pIC->hCandInfo;
+    if (hCandInfo)
+    {
+        hNewCandInfo = ImmReSizeIMCC(hCandInfo, 1964);
+        if (!hNewCandInfo)
+        {
+            ImmDestroyIMCC(m_pIC->hCandInfo);
+            m_pIC->hCandInfo = ImmCreateIMCC(1964);
+            return FALSE;
+        }
+    }
+    else
+    {
+        hNewCandInfo = ImmCreateIMCC(1964u);
+    }
+
+    m_pIC->hCandInfo = hNewCandInfo;
+    if (!m_pIC->hCandInfo)
+        return FALSE;
+
+    CicIMCCLock<CANDIDATEINFO> candInfo(m_pIC->hCandInfo);
+    if (!candInfo)
+    {
+        ImmDestroyIMCC(m_pIC->hCandInfo);
+        m_pIC->hCandInfo = ImmCreateIMCC(1964);
+        return FALSE;
+    }
+
+    candInfo.get().dwSize = 1964;
+    candInfo.get().dwCount = 0;
+    candInfo.get().dwOffset[0] = sizeof(CANDIDATEINFO);
+
+    LPBYTE pb = (LPBYTE)(&candInfo.get());
+    pb += sizeof(CANDIDATEINFO);
+
+    LPDWORD pdwUnknown = (LPDWORD)pb;
+    pdwUnknown[0] = candInfo.get().dwSize - sizeof(CANDIDATEINFO); // +0x0
+    pdwUnknown[2] = 0;     // +0x08
+    pdwUnknown[3] = 0;     // +0x0c
+    pdwUnknown[4] = 0;     // +0x10
+    pdwUnknown[1] = 1;     // +0x04
+    pdwUnknown[5] = 9;     // +0x14
+    pdwUnknown[6] = 1048;  // +0x18
+    return TRUE;
+}

Reply via email to