https://git.reactos.org/?p=reactos.git;a=commitdiff;h=0bce79a50b52bce96b54ab334bb0bf7fe742feb8

commit 0bce79a50b52bce96b54ab334bb0bf7fe742feb8
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Tue Feb 6 21:39:32 2024 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Tue Feb 6 21:39:32 2024 +0900

    [MSCTF][MSUTB][SDK] Add CLBarInatItem (#6447)
    
    Supporting Language Bar...
    JIRA issue: CORE-19363
    - Modify msctf.spec.
    - Add some helper functions.
    - Half-implement CLBarInatItem class.
    - Add some TF_... function prototypes
      to "msctf.idl".
---
 dll/win32/msctf/msctf.spec          |   8 +-
 dll/win32/msutb/lang/en-US.rc       |   3 +
 dll/win32/msutb/msutb.cpp           | 208 ++++++++++++++++++++++++++++++++++++
 dll/win32/msutb/resource.h          |   3 +
 sdk/include/psdk/msctf.idl          |   5 +
 sdk/include/reactos/cicero/cicutb.h |   1 +
 6 files changed, 224 insertions(+), 4 deletions(-)

diff --git a/dll/win32/msctf/msctf.spec b/dll/win32/msctf/msctf.spec
index 52288129e1c..975acdb2118 100644
--- a/dll/win32/msctf/msctf.spec
+++ b/dll/win32/msctf/msctf.spec
@@ -19,11 +19,11 @@
 @ stdcall -stub TF_GetGlobalCompartment(ptr)
 @ stub TF_GetInputScope
 @ stdcall -stub TF_GetLangIcon(long ptr long)
-@ stub TF_GetMlngHKL
-@ stub TF_GetMlngIconIndex
+@ stdcall -stub TF_GetMlngHKL(long ptr ptr long)
+@ stdcall -stub TF_GetMlngIconIndex(long)
 @ stub TF_GetThreadFlags
 @ stdcall TF_GetThreadMgr(ptr)
-@ stub TF_InatExtractIcon
+@ stdcall -stub TF_InatExtractIcon(long)
 @ stdcall TF_InitMlngInfo()
 @ stdcall -stub TF_InitSystem()
 @ stdcall -stub TF_UninitSystem()
@@ -31,7 +31,7 @@
 @ stdcall TF_InvalidAssemblyListCacheIfExist()
 @ stdcall TF_IsCtfmonRunning()
 @ stub TF_IsInMarshaling
-@ stub TF_MlngInfoCount
+@ stdcall -stub TF_MlngInfoCount()
 @ stdcall TF_RunInputCPL()
 @ stdcall -stub TF_PostAllThreadMsg(long long)
 @ stdcall TF_RegisterLangBarAddIn(ptr wstr long)
diff --git a/dll/win32/msutb/lang/en-US.rc b/dll/win32/msutb/lang/en-US.rc
index 3c3a7a579dd..8b09fb014c3 100644
--- a/dll/win32/msutb/lang/en-US.rc
+++ b/dll/win32/msutb/lang/en-US.rc
@@ -18,6 +18,9 @@ BEGIN
     IDS_NO               "&No"
 
     IDS_RESTORELANGBAR   "Restore Language Bar"
+    IDS_LANGUAGE         "Language"
+    IDS_RESTORELANGBAR2  "&Restore Language Bar"
+    IDS_LANGUAGEBUTTON   "Language Button"
     IDS_MENUWND          "Menu Window"
     IDS_LEFTCLICK        "Left Click"
 END
diff --git a/dll/win32/msutb/msutb.cpp b/dll/win32/msutb/msutb.cpp
index 21a68f70b54..37b5176bb1e 100644
--- a/dll/win32/msutb/msutb.cpp
+++ b/dll/win32/msutb/msutb.cpp
@@ -111,6 +111,22 @@ BOOL IsBiDiLocalizedSystem(void)
     return (Sig.lsUsb[3] & 0x8000000) != 0;
 }
 
+BOOL GetFontSig(HWND hWnd, HKL hKL)
+{
+    LOCALESIGNATURE Sig;
+    INT size = sizeof(Sig) / sizeof(WCHAR);
+    if (!::GetLocaleInfoW(LOWORD(hKL), LOCALE_FONTSIGNATURE, (LPWSTR)&Sig, 
size))
+        return FALSE;
+
+    HDC hDC = ::GetDC(hWnd);
+    DWORD CharSet = ::GetTextCharsetInfo(hDC, NULL, 0);
+    CHARSETINFO CharSetInfo;
+    ::TranslateCharsetInfo((DWORD*)(DWORD_PTR)CharSet, &CharSetInfo, 
TCI_SRCCHARSET);
+    ::ReleaseDC(hWnd, hDC);
+
+    return !!(CharSetInfo.fs.fsCsb[0] & Sig.lsCsbSupported[0]);
+}
+
 void InitSkipRedrawHKLArray(void)
 {
     g_prghklSkipRedrawing = new(cicNoThrow) CicArray<HKL>();
@@ -228,6 +244,69 @@ void DoCloseLangbar(void)
         ::RegDeleteValue(regKey, TEXT("ctfmon.exe"));
 }
 
+INT GetIconIndexFromhKL(_In_ HKL hKL)
+{
+    HKL hGotKL;
+
+    INT iKL, cKLs = TF_MlngInfoCount();
+    for (iKL = 0; iKL < cKLs; ++iKL)
+    {
+        if (TF_GetMlngHKL(iKL, &hGotKL, NULL, 0) && hKL == hGotKL)
+            return TF_GetMlngIconIndex(iKL);
+    }
+
+    if (!TF_GetMlngHKL(0, &hGotKL, NULL, 0))
+        return -1;
+
+    return TF_GetMlngIconIndex(0);
+}
+
+BOOL GethKLDesc(_In_ HKL hKL, _Out_ LPWSTR pszDesc, _In_ UINT cchDesc)
+{
+    HKL hGotKL;
+
+    INT iKL, cKLs = TF_MlngInfoCount();
+    for (iKL = 0; iKL < cKLs; ++iKL)
+    {
+        if (TF_GetMlngHKL(iKL, &hGotKL, pszDesc, cchDesc) && hKL == hGotKL)
+            return TRUE;
+    }
+
+    return TF_GetMlngHKL(0, &hGotKL, pszDesc, cchDesc);
+}
+
+HRESULT
+LangBarInsertMenu(
+    _In_ ITfMenu *pMenu,
+    _In_ UINT uId,
+    _In_ LPCWSTR pszText,
+    _In_ BOOL bChecked,
+    _Inout_opt_ HICON hIcon)
+{
+    HBITMAP hbmp = NULL, hbmpMask = NULL;
+    if (hIcon)
+    {
+        HICON hIconNew = (HICON)::CopyImage(hIcon, IMAGE_ICON, 16, 16, 
LR_COPYFROMRESOURCE);
+        SIZE iconSize = { 16, 16 };
+        if (!hIconNew)
+            hIconNew = hIcon;
+        if (!cicGetIconBitmaps(hIconNew, &hbmp, &hbmpMask, &iconSize))
+            return E_FAIL;
+        if (hIconNew)
+            ::DestroyIcon(hIconNew);
+        ::DestroyIcon(hIcon);
+    }
+
+    INT cchText = lstrlenW(pszText);
+    DWORD dwFlags = (bChecked ? TF_LBMENUF_CHECKED : 0);
+    return pMenu->AddMenuItem(uId, dwFlags, hbmp, hbmpMask, pszText, cchText, 
NULL);
+}
+
+HRESULT LangBarInsertSeparator(_In_ ITfMenu *pMenu)
+{
+    return pMenu->AddMenuItem(-1, TF_LBMENUF_SEPARATOR, NULL, NULL, NULL, 0, 
NULL);
+}
+
 BOOL InitFromReg(void)
 {
     DWORD dwValue;
@@ -934,6 +1013,24 @@ public:
     STDMETHOD(UnadviseSink)(DWORD dwCookie) override;
 };
 
+/***********************************************************************/
+
+/// Language Bar international item
+class CLBarInatItem : public CLBarItemButtonBase
+{
+protected:
+    HKL m_hKL;
+    DWORD m_dwThreadId;
+
+public:
+    CLBarInatItem(DWORD dwThreadId);
+
+    STDMETHOD(InitMenu)(ITfMenu *pMenu) override;
+    STDMETHOD(OnMenuSelect)(INT nCommandId);
+    STDMETHOD(GetIcon)(HICON *phIcon) override;
+    STDMETHOD(GetText)(BSTR *pbstr) override;
+};
+
 /***********************************************************************
  * CUTBLangBarDlg
  */
@@ -2779,6 +2876,117 @@ STDMETHODIMP CLBarItemButtonBase::UnadviseSink(DWORD 
dwCookie)
     return CLBarItemBase::UnadviseSink(dwCookie);
 }
 
+/***********************************************************************
+ * CLBarInatItem
+ */
+
+CLBarInatItem::CLBarInatItem(DWORD dwThreadId)
+{
+    WCHAR szText[256];
+    ::LoadStringW(g_hInst, IDS_LANGUAGE, szText, _countof(szText));
+    InitNuiInfo(CLSID_SYSTEMLANGBARITEM, GUID_LBI_INATITEM, 0x20001, 0, 
szText);
+
+    ::LoadStringW(g_hInst, IDS_LANGUAGEBUTTON, szText, _countof(szText));
+    StringCchCopyW(m_szToolTipText, _countof(m_szToolTipText), szText);
+    m_dwThreadId = dwThreadId;
+    m_hKL = ::GetKeyboardLayout(m_dwThreadId);
+
+    TF_InitMlngInfo();
+    ShowInternal(TF_MlngInfoCount() > 1, 0);
+}
+
+STDMETHODIMP CLBarInatItem::GetIcon(HICON *phIcon)
+{
+    HICON hIcon = NULL;
+    INT iIndex = GetIconIndexFromhKL(m_hKL);
+    if (iIndex != -1)
+        hIcon = TF_InatExtractIcon(iIndex);
+    *phIcon = hIcon;
+    return S_OK;
+}
+
+STDMETHODIMP CLBarInatItem::GetText(BSTR *pbstr)
+{
+    if (!pbstr)
+        return E_INVALIDARG;
+
+    WCHAR szText[256];
+    if (!GethKLDesc(m_hKL, szText, _countof(szText)))
+        return GetText(pbstr);
+
+    *pbstr = ::SysAllocString(szText);
+    return S_OK;
+}
+
+STDMETHODIMP CLBarInatItem::InitMenu(ITfMenu *pMenu)
+{
+    TF_InitMlngInfo();
+
+    INT iKL, cKLs = TF_MlngInfoCount();
+    for (iKL = 0; iKL < cKLs; ++iKL)
+    {
+        HKL hKL;
+        WCHAR szDesc[128];
+        if (TF_GetMlngHKL(iKL, &hKL, szDesc, _countof(szDesc)))
+        {
+            HICON hIcon = NULL;
+            INT iIndex = GetIconIndexFromhKL(hKL);
+            if (iIndex != -1)
+                hIcon = TF_InatExtractIcon(iIndex);
+
+            LangBarInsertMenu(pMenu, iKL, szDesc, (hKL == m_hKL), hIcon);
+        }
+    }
+
+#if 0 // FIXME: g_pTipbarWnd
+    DWORD dwStatus;
+    if (g_pTipbarWnd &&
+        g_pTipbarWnd->m_pLangBarMgr &&
+        
SUCCEEDED(g_pTipbarWnd->m_pLangBarMgr->GetShowFloatingStatus(&dwStatus)) &&
+        (dwStatus & (TF_SFT_DESKBAND | TF_SFT_MINIMIZED)))
+    {
+        LangBarInsertSeparator(pMenu);
+
+        WCHAR szText[256];
+        ::LoadStringW(g_hInst, IDS_RESTORELANGBAR2, szText, _countof(szText));
+        LangBarInsertMenu(pMenu, 2000, szText, FALSE, NULL);
+    }
+#endif
+
+    return S_OK;
+}
+
+STDMETHODIMP CLBarInatItem::OnMenuSelect(INT nCommandId)
+{
+    HKL hKL;
+
+    if (nCommandId == 2000)
+    {
+        if (g_pTipbarWnd)
+        {
+#if 0 // FIXME: g_pTipbarWnd
+            ITfLangBarMgr *pLangBarMgr = g_pTipbarWnd->m_pLangBarMgr;
+            if (pLangBarMgr)
+                pLangBarMgr->ShowFloating(TF_SFT_SHOWNORMAL);
+#endif
+        }
+    }
+    else if (TF_GetMlngHKL(nCommandId, &hKL, NULL, 0))
+    {
+#if 0 // FIXME: g_pTipbarWnd
+        g_pTipbarWnd->RestoreLastFocus(0, (g_pTipbarWnd->m_dwTipbarWndFlags & 
2) != 0);
+#endif
+        HWND hwndFore = GetForegroundWindow();
+        if (m_dwThreadId == ::GetWindowThreadProcessId(hwndFore, NULL))
+        {
+            BOOL FontSig = GetFontSig(hwndFore, hKL);
+            ::PostMessage(hwndFore, WM_INPUTLANGCHANGEREQUEST, FontSig, 
(LPARAM)hKL);
+        }
+    }
+
+    return S_OK;
+}
+
 /***********************************************************************
  *              GetLibTls (MSUTB.@)
  *
diff --git a/dll/win32/msutb/resource.h b/dll/win32/msutb/resource.h
index c3abc6b696c..ee02ba159b2 100644
--- a/dll/win32/msutb/resource.h
+++ b/dll/win32/msutb/resource.h
@@ -11,6 +11,9 @@
 #define IDI_MAINICON        100
 
 #define IDS_RESTORELANGBAR  308
+#define IDS_LANGUAGE        309
+#define IDS_LANGUAGEBUTTON  310
+#define IDS_RESTORELANGBAR2 321
 #define IDS_MENUWND         322
 #define IDS_LEFTCLICK       323
 
diff --git a/sdk/include/psdk/msctf.idl b/sdk/include/psdk/msctf.idl
index 748787fb795..f9f6e6fe17d 100644
--- a/sdk/include/psdk/msctf.idl
+++ b/sdk/include/psdk/msctf.idl
@@ -62,6 +62,11 @@ cpp_quote("EXTERN_C HRESULT WINAPI 
TF_DllDetachInOther(VOID);")
 cpp_quote("EXTERN_C HRESULT WINAPI TF_CreateCategoryMgr(ITfCategoryMgr 
**ppcat);")
 cpp_quote("EXTERN_C HRESULT WINAPI 
TF_CreateDisplayAttributeMgr(ITfDisplayAttributeMgr **ppdam);")
 cpp_quote("EXTERN_C HICON WINAPI TF_GetLangIcon(LANGID LangID, LPWSTR pszText, 
INT cchText);")
+cpp_quote("EXTERN_C HRESULT WINAPI TF_InitMlngInfo(VOID);")
+cpp_quote("EXTERN_C INT WINAPI TF_MlngInfoCount(VOID);")
+cpp_quote("EXTERN_C BOOL WINAPI TF_GetMlngHKL(INT iKL, HKL *phKL, LPWSTR 
pszText, INT cchText);")
+cpp_quote("EXTERN_C INT WINAPI TF_GetMlngIconIndex(INT iKL);")
+cpp_quote("EXTERN_C HICON WINAPI TF_InatExtractIcon(INT iKL);")
 
 cpp_quote("EXTERN_C const GUID GUID_PROP_TEXTOWNER;")
 cpp_quote("EXTERN_C const GUID GUID_PROP_ATTRIBUTE;")
diff --git a/sdk/include/reactos/cicero/cicutb.h 
b/sdk/include/reactos/cicero/cicutb.h
index 916b0c4befb..6df17b7c0f2 100644
--- a/sdk/include/reactos/cicero/cicutb.h
+++ b/sdk/include/reactos/cicero/cicutb.h
@@ -12,6 +12,7 @@ DEFINE_GUID(GUID_LBI_TRAYMAIN,                 0xE0B724E9, 
0x6F76, 0x45F7, 0xB4,
 DEFINE_GUID(GUID_LBI_INATITEM,                 0xCDBC683A, 0x55CE, 0x4717, 
0xBA, 0xC0, 0x50, 0xBF, 0x44, 0xA3, 0x27, 0x0C);
 DEFINE_GUID(GUID_LBI_CTRL,                     0x58C99D96, 0x2F9B, 0x42CE, 
0x91, 0xBE, 0x37, 0xEF, 0x18, 0x60, 0xF8, 0x82);
 DEFINE_GUID(GUID_TFCAT_TIP_KEYBOARD,           0x34745C63, 0xB2F0, 0x4784, 
0x8B, 0x67, 0x5E, 0x12, 0xC8, 0x70, 0x1A, 0x31);
+DEFINE_GUID(CLSID_SYSTEMLANGBARITEM,           0xBEBACC94, 0x5CD3, 0x4662, 
0xA1, 0xE0, 0xF3, 0x31, 0x99, 0x49, 0x36, 0x69);
 
 EXTERN_C LPVOID WINAPI GetLibTls(VOID);
 EXTERN_C BOOL WINAPI GetPopupTipbar(HWND hWnd, BOOL fWinLogon);

Reply via email to