[MSCTFIME][CICERO] Implement CicProfile::GetActiveLanguageProfile (#8869)

Supporting CTF IMEs.
JIRA issue: CORE-19360
- Add base/ctf/cicero/ciciface.h to
  add CicInterface_RefCnt template
  class.
- Add CicProfile::
  LanguageProfilesCallback callback
  function.
- Implement CicProfile::
  GetActiveLanguageProfile and
  CicProfile::IsIME functions.
This commit is contained in:
Katayama Hirofumi MZ
2026-04-20 21:51:45 +09:00
committed by GitHub
parent 01a0906924
commit ffa1c541aa
5 changed files with 162 additions and 14 deletions

View File

@@ -2,11 +2,14 @@
* PROJECT: ReactOS Cicero
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Cicero base
* COPYRIGHT: Copyright 2023-2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
* COPYRIGHT: Copyright 2023-2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#pragma once
#include <assert.h>
#define cicAssert assert
static inline LPVOID cicMemAlloc(SIZE_T size)
{
return LocalAlloc(0, size);

View File

@@ -0,0 +1,59 @@
/*
* PROJECT: ReactOS Cicero
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Cicero COM interface
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#pragma once
#include "cicbase.h"
template <typename T_IFACE>
class CicInterface_RefCnt
{
protected:
T_IFACE* m_ptr;
public:
CicInterface_RefCnt() : m_ptr(NULL) { }
CicInterface_RefCnt(T_IFACE* ptr) : m_ptr(ptr)
{
if (m_ptr)
m_ptr->AddRef();
}
~CicInterface_RefCnt()
{
if (m_ptr)
m_ptr->Release();
}
void Attach(T_IFACE* ptr)
{
if (m_ptr)
m_ptr->Release();
m_ptr = ptr;
}
T_IFACE* Detach()
{
T_IFACE* old_ptr = m_ptr;
m_ptr = NULL;
return old_ptr;
}
operator T_IFACE*() { return m_ptr; }
T_IFACE* operator->() { return m_ptr; }
T_IFACE** operator&()
{
cicAssert(!m_ptr);
return &m_ptr;
}
private:
CicInterface_RefCnt(const CicInterface_RefCnt<T_IFACE>&) = delete;
CicInterface_RefCnt<T_IFACE>& operator=(const CicInterface_RefCnt<T_IFACE>&) = delete;
};

View File

@@ -28,6 +28,7 @@
#include <cicbase.h>
#include <cicarray.h>
#include <ciciface.h>
#include <cicimc.h>
#include <cictf.h>
#include <cicreg.h>

View File

@@ -2,13 +2,67 @@
* PROJECT: ReactOS msctfime.ime
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Profile of msctfime.ime
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
* COPYRIGHT: Copyright 2024-2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include "msctfime.h"
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
// The callback function type
typedef HRESULT (CALLBACK *FN_LanguageProfilesCallback)(TF_LANGUAGEPROFILE profile, LPARAM lParam);
/// @implemented
HRESULT
CicProfile::LanguageProfilesCallback(
_In_ TF_LANGUAGEPROFILE profile,
_Inout_opt_ LPARAM lParam)
{
if (!profile.fActive || !memcmp(&profile.clsid, &GUID_NULL, sizeof(GUID_NULL)))
return S_FALSE;
PLANG_PROF_ENUM_ARG pArg = (PLANG_PROF_ENUM_ARG)lParam;
if (!pArg)
return S_OK;
if (memcmp(&profile.catid, &pArg->catid, sizeof(profile.catid)) != 0)
return S_FALSE;
pArg->profile = profile;
return S_OK;
}
template <typename T_IFACE, typename T_DATA>
class CicEnumValue
{
T_IFACE* m_iface;
FN_LanguageProfilesCallback m_callback;
LPARAM m_lParam;
public:
CicEnumValue(T_IFACE* iface, FN_LanguageProfilesCallback callback, LPARAM lParam = 0)
: m_iface(iface)
, m_callback(callback)
, m_lParam(lParam)
{ }
DWORD DoEnum()
{
HRESULT hr;
T_DATA data;
for (;;)
{
hr = m_iface->Next(1, &data, NULL);
if (hr != S_OK)
break;
hr = m_callback(data, m_lParam);
if (hr == S_OK)
return ERROR_SUCCESS;
}
return ERROR_FILE_NOT_FOUND;
}
};
/// @implemented
CicProfile::CicProfile()
{
@@ -162,19 +216,40 @@ CicProfile::InitProfileInstance(_Inout_ TLS *pTLS)
return hr;
}
/// @unimplemented
/// @implemented
HRESULT
CicProfile::GetActiveLanguageProfile(
_In_ HKL hKL,
_In_ REFGUID rguid,
_Out_ TF_LANGUAGEPROFILE *pProfile)
_In_ REFGUID catid,
_Out_ TF_LANGUAGEPROFILE* pProfile)
{
return E_NOTIMPL;
CicInterface_RefCnt<IEnumTfLanguageProfiles> pEnum;
HRESULT hr = m_pIPProfiles->EnumLanguageProfiles(LOWORD(hKL), &pEnum);
if (FAILED(hr))
return S_FALSE;
LANG_PROF_ENUM_ARG arg;
arg.catid = catid;
CicEnumValue<IEnumTfLanguageProfiles, TF_LANGUAGEPROFILE>
enumValue(pEnum, LanguageProfilesCallback, (LPARAM)&arg);
DWORD ret = enumValue.DoEnum();
if (ret != ERROR_SUCCESS || !pProfile)
return S_FALSE;
*pProfile = arg.profile;
return S_OK;
}
/// The return value of CicProfile::IsIME is brain-damaged.
/// @unimplemented
BOOL CicProfile::IsIME(HKL hKL)
/// @implemented
HRESULT CicProfile::IsIME(HKL hKL)
{
return TRUE;
CicInterface_RefCnt<IEnumTfLanguageProfiles> pEnum;
HRESULT hr = m_pIPProfiles->EnumLanguageProfiles(LOWORD(hKL), &pEnum);
if (FAILED(hr))
return S_FALSE;
CicEnumValue<IEnumTfLanguageProfiles, TF_LANGUAGEPROFILE>
enumValue(pEnum, LanguageProfilesCallback);
DWORD ret = enumValue.DoEnum();
return (ret == ERROR_SUCCESS) ? S_OK : S_FALSE;
}

View File

@@ -2,7 +2,7 @@
* PROJECT: ReactOS msctfime.ime
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Profile of msctfime.ime
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
* COPYRIGHT: Copyright 2024-2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#pragma once
@@ -12,6 +12,12 @@
class CicProfile : public IUnknown
{
protected:
typedef struct tagLANG_PROF_ENUM_ARG
{
GUID catid;
TF_LANGUAGEPROFILE profile;
} LANG_PROF_ENUM_ARG, *PLANG_PROF_ENUM_ARG;
ITfInputProcessorProfiles *m_pIPProfiles;
CActiveLanguageProfileNotifySink *m_pActiveLanguageProfileNotifySink;
LANGID m_LangID1;
@@ -42,12 +48,16 @@ public:
HRESULT
GetActiveLanguageProfile(
_In_ HKL hKL,
_In_ REFGUID rguid,
_Out_ TF_LANGUAGEPROFILE *pProfile);
_In_ REFGUID catid,
_Out_ TF_LANGUAGEPROFILE* pProfile);
HRESULT GetLangId(_Out_ LANGID *pLangID);
HRESULT GetCodePageA(_Out_ UINT *puCodePage);
HRESULT InitProfileInstance(_Inout_ TLS *pTLS);
HRESULT IsIME(HKL hKL);
BOOL IsIME(HKL hKL);
static HRESULT CALLBACK
LanguageProfilesCallback(
_In_ TF_LANGUAGEPROFILE profile,
_Inout_opt_ LPARAM lParam);
};