[MSCTFIME] Implement CtfImeSetActiveContextAlways (#6522)

Supporting TIPs...
JIRA issue: CORE-19360
- Move code of functions.cpp
  into misc.cpp and delete functions.cpp.
- Add implementation to
  CicBridge::GetDocumentManager,
  CicBridge::CreateInputContext, and
  CicBridge::SetActiveContextAlways
  methods.
- Implement NotifyIME,
  CtfImeSetActiveContextAlways, and
  CtfImeCreateInputContext functions.
This commit is contained in:
Katayama Hirofumi MZ 2024-02-23 17:43:13 +09:00 committed by GitHub
parent 69b08be0e0
commit 980ebf0694
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 727 additions and 592 deletions

View file

@ -1,12 +1,8 @@
include_directories(
${REACTOS_SOURCE_DIR}/win32ss/include)
spec2def(msctfime.ime msctfime.spec)
list(APPEND SOURCE
bridge.cpp
functions.cpp
inputcontext.cpp
misc.cpp
msctfime.cpp

View file

@ -1,7 +1,7 @@
/*
* PROJECT: ReactOS msctfime.ime
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Bridge
* PURPOSE: The bridge of msctfime.ime
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
@ -65,22 +65,19 @@ CicBridge::~CicBridge()
UnInitIMMX(pTLS);
}
void CicBridge::GetDocumentManager(_Inout_ CicIMCCLock<CTFIMECONTEXT>& imeContext)
/// @implemented
ITfDocumentMgr*
CicBridge::GetDocumentManager(_Inout_ CicIMCCLock<CTFIMECONTEXT>& imeContext)
{
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (pCicIC)
{
m_pDocMgr = pCicIC->m_pDocumentMgr;
m_pDocMgr->AddRef();
}
else
{
m_pDocMgr->Release();
m_pDocMgr = NULL;
}
if (!pCicIC)
return NULL;
pCicIC->m_pDocumentMgr->AddRef();
return pCicIC->m_pDocumentMgr;
}
/// @unimplemented
/// @implemented
HRESULT
CicBridge::CreateInputContext(
_Inout_ TLS *pTLS,
@ -100,45 +97,49 @@ CicBridge::CreateInputContext(
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (pCicIC)
return S_OK;
pCicIC = new(cicNoThrow) CicInputContext(m_cliendId, &m_LibThread, hIMC);
if (!pCicIC)
{
pCicIC = new(cicNoThrow) CicInputContext(m_cliendId, &m_LibThread, hIMC);
if (!pCicIC)
{
imeContext.unlock();
imcLock.unlock();
DestroyInputContext(pTLS, hIMC);
return E_OUTOFMEMORY;
}
if (!pTLS->m_pThreadMgr)
{
pCicIC->Release();
imeContext.unlock();
imcLock.unlock();
DestroyInputContext(pTLS, hIMC);
return E_NOINTERFACE;
}
imeContext.get().m_pCicIC = pCicIC;
imeContext.unlock();
imcLock.unlock();
DestroyInputContext(pTLS, hIMC);
return E_OUTOFMEMORY;
}
if (!pTLS->m_pThreadMgr)
{
pCicIC->Release();
imeContext.unlock();
imcLock.unlock();
DestroyInputContext(pTLS, hIMC);
return E_NOINTERFACE;
}
imeContext.get().m_pCicIC = pCicIC;
HRESULT hr = pCicIC->CreateInputContext(pTLS->m_pThreadMgr, imcLock);
if (FAILED(hr))
{
pCicIC->Release();
imeContext.get().m_pCicIC = NULL;
return hr;
}
else
HWND hWnd = imcLock.get().hWnd;
if (hWnd && hWnd == ::GetFocus())
{
if (imcLock.get().hWnd && imcLock.get().hWnd == ::GetFocus())
ITfDocumentMgr *pDocMgr = GetDocumentManager(imeContext);
if (pDocMgr)
{
GetDocumentManager(imeContext);
//FIXME
SetAssociate(pTLS, hWnd, hIMC, pTLS->m_pThreadMgr, pDocMgr);
pDocMgr->Release();
}
}
return E_NOTIMPL;
return hr;
}
/// @implemented
@ -608,3 +609,83 @@ CicBridge::ConfigureRegisterWord(
pFunction->Release();
return hr;
}
/// @unimplemented
void CicBridge::SetAssociate(
TLS *pTLS,
HWND hWnd,
HIMC hIMC,
ITfThreadMgr_P *pThreadMgr,
ITfDocumentMgr *pDocMgr)
{
//FIXME
}
HRESULT
CicBridge::SetActiveContextAlways(TLS *pTLS, HIMC hIMC, BOOL fActive, HWND hWnd, HKL hKL)
{
auto pThreadMgr = pTLS->m_pThreadMgr;
if (!pThreadMgr)
return E_OUTOFMEMORY;
if (fActive)
{
if (!hIMC)
{
SetAssociate(pTLS, hWnd, hIMC, pThreadMgr, m_pDocMgr);
return S_OK;
}
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
if (hIMC == ::ImmGetContext(hWnd))
{
ITfDocumentMgr *pDocMgr = GetDocumentManager(imeContext);
if (pDocMgr)
{
SetAssociate(pTLS, imcLock.get().hWnd, hIMC, pThreadMgr, pDocMgr);
pDocMgr->Release();
}
}
return S_OK;
}
if (hIMC && !IsEALang(LOWORD(hKL)))
{
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC->m_dwUnknown6_5[2] && !pCicIC->m_dwUnknown6_5[3])
::ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
}
if (!hIMC || (::GetFocus() != hWnd) || (hIMC != ::ImmGetContext(hWnd)))
SetAssociate(pTLS, hWnd, hIMC, pThreadMgr, m_pDocMgr);
return S_OK;
}
/// @unimplemented
HRESULT CicBridge::Notify(
TLS *pTLS,
ITfThreadMgr *pThreadMgr,
HIMC hIMC,
DWORD dwAction,
DWORD dwIndex,
DWORD_PTR dwValue)
{
return E_NOTIMPL; // FIXME
}

View file

@ -1,7 +1,7 @@
/*
* PROJECT: ReactOS msctfime.ime
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Bridge
* PURPOSE: The bridge of msctfime.ime
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
@ -64,7 +64,7 @@ public:
CicInputContext *pCicIC);
void PostTransMsg(_In_ HWND hWnd, _In_ INT cTransMsgs, _In_ const TRANSMSG *pTransMsgs);
void GetDocumentManager(_Inout_ CicIMCCLock<CTFIMECONTEXT>& imeContext);
ITfDocumentMgr* GetDocumentManager(_Inout_ CicIMCCLock<CTFIMECONTEXT>& imeContext);
HRESULT
ConfigureGeneral(_Inout_ TLS* pTLS,
@ -77,4 +77,21 @@ public:
_In_ HKL hKL,
_In_ HWND hWnd,
_Inout_opt_ LPVOID lpData);
HRESULT SetActiveContextAlways(TLS *pTLS, HIMC hIMC, BOOL fActive, HWND hWnd, HKL hKL);
void SetAssociate(
TLS *pTLS,
HWND hWnd,
HIMC hIMC,
ITfThreadMgr_P *pThreadMgr,
ITfDocumentMgr *pDocMgr);
HRESULT Notify(
TLS *pTLS,
ITfThreadMgr *pThreadMgr,
HIMC hIMC,
DWORD dwAction,
DWORD dwIndex,
DWORD_PTR dwValue);
};

View file

@ -1,261 +0,0 @@
/*
* PROJECT: ReactOS msctfime.ime
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: The functionalities of msctfime.ime
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include "msctfime.h"
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
/// @implemented
CFunctionProviderBase::CFunctionProviderBase(_In_ TfClientId clientId)
{
m_clientId = clientId;
m_guid = GUID_NULL;
m_bstr = NULL;
m_cRefs = 1;
}
/// @implemented
CFunctionProviderBase::~CFunctionProviderBase()
{
if (!DllShutdownInProgress())
::SysFreeString(m_bstr);
}
/// @implemented
BOOL
CFunctionProviderBase::Init(
_In_ REFGUID rguid,
_In_ LPCWSTR psz)
{
m_bstr = ::SysAllocString(psz);
m_guid = rguid;
return (m_bstr != NULL);
}
/// @implemented
STDMETHODIMP
CFunctionProviderBase::QueryInterface(
_In_ REFIID riid,
_Out_ LPVOID* ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfFunctionProvider))
{
*ppvObj = this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/// @implemented
STDMETHODIMP_(ULONG) CFunctionProviderBase::AddRef()
{
return ::InterlockedIncrement(&m_cRefs);
}
/// @implemented
STDMETHODIMP_(ULONG) CFunctionProviderBase::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
delete this;
return 0;
}
return m_cRefs;
}
/// @implemented
STDMETHODIMP CFunctionProviderBase::GetType(_Out_ GUID *guid)
{
*guid = m_guid;
return S_OK;
}
/// @implemented
STDMETHODIMP CFunctionProviderBase::GetDescription(_Out_ BSTR *desc)
{
*desc = ::SysAllocString(m_bstr);
return (*desc ? S_OK : E_OUTOFMEMORY);
}
/***********************************************************************/
/// @implemented
CFunctionProvider::CFunctionProvider(_In_ TfClientId clientId) : CFunctionProviderBase(clientId)
{
Init(CLSID_CAImmLayer, L"MSCTFIME::Function Provider");
}
/// @implemented
STDMETHODIMP
CFunctionProvider::GetFunction(
_In_ REFGUID guid,
_In_ REFIID riid,
_Out_ IUnknown **func)
{
*func = NULL;
if (IsEqualGUID(guid, GUID_NULL) &&
IsEqualIID(riid, IID_IAImmFnDocFeed))
{
*func = new(cicNoThrow) CFnDocFeed();
if (*func)
return S_OK;
}
return E_NOINTERFACE;
}
/***********************************************************************/
CFnDocFeed::CFnDocFeed()
{
m_cRefs = 1;
}
CFnDocFeed::~CFnDocFeed()
{
}
/// @implemented
STDMETHODIMP CFnDocFeed::QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IAImmFnDocFeed))
{
*ppvObj = this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/// @implemented
STDMETHODIMP_(ULONG) CFnDocFeed::AddRef()
{
return ::InterlockedIncrement(&m_cRefs);
}
/// @implemented
STDMETHODIMP_(ULONG) CFnDocFeed::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
delete this;
return 0;
}
return m_cRefs;
}
/// @implemented
STDMETHODIMP CFnDocFeed::DocFeed()
{
TLS *pTLS = TLS::GetTLS();
if (!pTLS)
return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext();
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC)
return E_FAIL;
UINT uCodePage = CP_ACP;
pTLS->m_pProfile->GetCodePageA(&uCodePage);
pCicIC->SetupDocFeedString(imcLock, uCodePage);
return S_OK;
}
/// @implemented
STDMETHODIMP CFnDocFeed::ClearDocFeedBuffer()
{
if (!TLS::GetTLS())
return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext();
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC)
return E_FAIL;
pCicIC->EscbClearDocFeedBuffer(imcLock, TRUE);
return S_OK;
}
/// @unimplemented
STDMETHODIMP CFnDocFeed::StartReconvert()
{
TLS *pTLS = TLS::GetTLS();
if (!pTLS)
return E_OUTOFMEMORY;
auto *pThreadMgr = pTLS->m_pThreadMgr;
if (!pThreadMgr)
return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext();
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC)
return E_FAIL;
UINT uCodePage = CP_ACP;
pTLS->m_pProfile->GetCodePageA(&uCodePage);
pCicIC->m_bReconverting = TRUE;
pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, 0, 0);
pCicIC->EndReconvertString(imcLock);
pCicIC->m_bReconverting = FALSE;
return S_OK;
}
/// @implemented
STDMETHODIMP CFnDocFeed::StartUndoCompositionString()
{
TLS *pTLS = TLS::GetTLS();
if (!pTLS)
return E_OUTOFMEMORY;
auto *pThreadMgr = pTLS->m_pThreadMgr;
if (!pThreadMgr)
return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext();
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC)
return E_FAIL;
UINT uCodePage = CP_ACP;
pTLS->m_pProfile->GetCodePageA(&uCodePage);
pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, 0, TRUE);
pCicIC->EndReconvertString(imcLock);
return S_OK;
}

View file

@ -1,63 +0,0 @@
/*
* PROJECT: ReactOS msctfime.ime
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: The functionalities of msctfime.ime
* COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
class CFunctionProviderBase : public ITfFunctionProvider
{
protected:
TfClientId m_clientId;
GUID m_guid;
BSTR m_bstr;
LONG m_cRefs;
public:
CFunctionProviderBase(_In_ TfClientId clientId);
virtual ~CFunctionProviderBase();
// IUnknown interface
STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// ITfFunctionProvider interface
STDMETHODIMP GetType(_Out_ GUID *guid) override;
STDMETHODIMP GetDescription(_Out_ BSTR *desc) override;
//STDMETHODIMP GetFunction(_In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func) = 0;
BOOL Init(_In_ REFGUID rguid, _In_ LPCWSTR psz);
};
/***********************************************************************/
class CFunctionProvider : public CFunctionProviderBase
{
public:
CFunctionProvider(_In_ TfClientId clientId);
STDMETHODIMP GetFunction(_In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func) override;
};
/***********************************************************************/
class CFnDocFeed : public IAImmFnDocFeed
{
LONG m_cRefs;
public:
CFnDocFeed();
virtual ~CFnDocFeed();
// IUnknown interface
STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IAImmFnDocFeed interface
STDMETHODIMP DocFeed() override;
STDMETHODIMP ClearDocFeedBuffer() override;
STDMETHODIMP StartReconvert() override;
STDMETHODIMP StartUndoCompositionString() override;
};

View file

@ -9,6 +9,185 @@
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
/// East-Asian language?
/// @implemented
BOOL IsEALang(LANGID LangID)
{
if (LangID == 0)
{
TLS *pTLS = TLS::GetTLS();
if (!pTLS || !pTLS->m_pProfile)
return FALSE;
pTLS->m_pProfile->GetLangId(&LangID);
}
switch (PRIMARYLANGID(LangID))
{
case LANG_CHINESE:
case LANG_JAPANESE:
case LANG_KOREAN:
return TRUE;
default:
return FALSE;
}
}
typedef BOOLEAN (WINAPI *FN_DllShutdownInProgress)(VOID);
/// This function calls ntdll!RtlDllShutdownInProgress.
/// It can detect the system is shutting down or not.
/// @implemented
BOOLEAN DllShutdownInProgress(VOID)
{
HMODULE hNTDLL;
static FN_DllShutdownInProgress s_fnDllShutdownInProgress = NULL;
if (s_fnDllShutdownInProgress)
return s_fnDllShutdownInProgress();
hNTDLL = cicGetSystemModuleHandle(L"ntdll.dll", FALSE);
s_fnDllShutdownInProgress =
(FN_DllShutdownInProgress)GetProcAddress(hNTDLL, "RtlDllShutdownInProgress");
if (!s_fnDllShutdownInProgress)
return FALSE;
return s_fnDllShutdownInProgress();
}
/// This function checks if the current user logon session is interactive.
/// @implemented
BOOL IsInteractiveUserLogon(VOID)
{
BOOL bOK, IsMember = FALSE;
PSID pSid;
SID_IDENTIFIER_AUTHORITY IdentAuth = { SECURITY_NT_AUTHORITY };
if (!AllocateAndInitializeSid(&IdentAuth, 1, SECURITY_INTERACTIVE_RID,
0, 0, 0, 0, 0, 0, 0, &pSid))
{
ERR("Error: %ld\n", GetLastError());
return FALSE;
}
bOK = CheckTokenMembership(NULL, pSid, &IsMember);
if (pSid)
FreeSid(pSid);
return bOK && IsMember;
}
/// Gets the charset from a language ID.
/// @implemented
BYTE GetCharsetFromLangId(_In_ DWORD dwValue)
{
CHARSETINFO info;
if (!::TranslateCharsetInfo((DWORD*)(DWORD_PTR)dwValue, &info, TCI_SRCLOCALE))
return 0;
return info.ciCharset;
}
/// Get the active input context.
/// @implemented
HIMC GetActiveContext(VOID)
{
HWND hwndFocus = ::GetFocus();
if (!hwndFocus)
hwndFocus = ::GetActiveWindow();
return ::ImmGetContext(hwndFocus);
}
/// @implemented
ITfCategoryMgr *GetUIMCat(PCIC_LIBTHREAD pLibThread)
{
if (!pLibThread)
return NULL;
if (pLibThread->m_pCategoryMgr)
return pLibThread->m_pCategoryMgr;
if (FAILED(cicCoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER,
IID_ITfCategoryMgr, (void **)&pLibThread->m_pCategoryMgr)))
{
return NULL;
}
return pLibThread->m_pCategoryMgr;
}
/// @implemented
static HRESULT
LibEnumItemsInCategory(PCIC_LIBTHREAD pLibThread, REFGUID rguid, IEnumGUID **ppEnum)
{
ITfCategoryMgr *pCat = GetUIMCat(pLibThread);
if (!pCat)
return E_FAIL;
return pCat->EnumItemsInCategory(rguid, ppEnum);
}
/// @implemented
HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
{
if (!pLibThread)
return E_FAIL;
if (pLibThread->m_pDisplayAttrMgr)
{
pLibThread->m_pDisplayAttrMgr->Release();
pLibThread->m_pDisplayAttrMgr = NULL;
}
if (FAILED(cicCoCreateInstance(CLSID_TF_DisplayAttributeMgr, NULL, CLSCTX_INPROC_SERVER,
IID_ITfDisplayAttributeMgr,
(void **)&pLibThread->m_pDisplayAttrMgr)))
{
return E_FAIL;
}
IEnumGUID *pEnumGuid;
LibEnumItemsInCategory(pLibThread, GUID_TFCAT_DISPLAYATTRIBUTEPROPERTY, &pEnumGuid);
HRESULT hr = E_OUTOFMEMORY;
::EnterCriticalSection(&g_csLock);
if (pEnumGuid && !g_pPropCache)
{
g_pPropCache = new(cicNoThrow) CDispAttrPropCache();
if (g_pPropCache)
{
g_pPropCache->Add(GUID_PROP_ATTRIBUTE);
GUID guid;
while (pEnumGuid->Next(1, &guid, NULL) == S_OK)
{
if (!IsEqualGUID(guid, GUID_PROP_ATTRIBUTE))
g_pPropCache->Add(guid);
}
hr = S_OK;
}
}
::LeaveCriticalSection(&g_csLock);
return hr;
}
/// @implemented
HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
{
if (!pLibThread)
return E_FAIL;
if (pLibThread->m_pDisplayAttrMgr)
{
pLibThread->m_pDisplayAttrMgr->Release();
pLibThread->m_pDisplayAttrMgr = NULL;
}
return S_OK;
}
/***********************************************************************/
/// @implemented
HRESULT
GetCompartment(
@ -179,11 +358,13 @@ static const MODEBIAS g_ModeBiasMap[] =
{ GUID_MODEBIAS_NONE, 0x00000000 },
};
/// @implemented
void CModeBias::SetModeBias(REFGUID rguid)
{
m_guid = rguid;
}
/// @implemented
GUID CModeBias::ConvertModeBias(LONG bias)
{
const GUID *pguid = &GUID_NULL;
@ -199,6 +380,7 @@ GUID CModeBias::ConvertModeBias(LONG bias)
return *pguid;
}
/// @implemented
LONG CModeBias::ConvertModeBias(REFGUID guid)
{
for (auto& item : g_ModeBiasMap)
@ -211,25 +393,253 @@ LONG CModeBias::ConvertModeBias(REFGUID guid)
/***********************************************************************/
/// East-Asian language?
/// @implemented
BOOL IsEALang(VOID)
CFunctionProviderBase::CFunctionProviderBase(_In_ TfClientId clientId)
{
m_clientId = clientId;
m_guid = GUID_NULL;
m_bstr = NULL;
m_cRefs = 1;
}
/// @implemented
CFunctionProviderBase::~CFunctionProviderBase()
{
if (!DllShutdownInProgress())
::SysFreeString(m_bstr);
}
/// @implemented
BOOL
CFunctionProviderBase::Init(
_In_ REFGUID rguid,
_In_ LPCWSTR psz)
{
m_bstr = ::SysAllocString(psz);
m_guid = rguid;
return (m_bstr != NULL);
}
/// @implemented
STDMETHODIMP
CFunctionProviderBase::QueryInterface(
_In_ REFIID riid,
_Out_ LPVOID* ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfFunctionProvider))
{
*ppvObj = this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/// @implemented
STDMETHODIMP_(ULONG) CFunctionProviderBase::AddRef()
{
return ::InterlockedIncrement(&m_cRefs);
}
/// @implemented
STDMETHODIMP_(ULONG) CFunctionProviderBase::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
delete this;
return 0;
}
return m_cRefs;
}
/// @implemented
STDMETHODIMP CFunctionProviderBase::GetType(_Out_ GUID *guid)
{
*guid = m_guid;
return S_OK;
}
/// @implemented
STDMETHODIMP CFunctionProviderBase::GetDescription(_Out_ BSTR *desc)
{
*desc = ::SysAllocString(m_bstr);
return (*desc ? S_OK : E_OUTOFMEMORY);
}
/***********************************************************************/
/// @implemented
CFunctionProvider::CFunctionProvider(_In_ TfClientId clientId) : CFunctionProviderBase(clientId)
{
Init(CLSID_CAImmLayer, L"MSCTFIME::Function Provider");
}
/// @implemented
STDMETHODIMP
CFunctionProvider::GetFunction(
_In_ REFGUID guid,
_In_ REFIID riid,
_Out_ IUnknown **func)
{
*func = NULL;
if (IsEqualGUID(guid, GUID_NULL) &&
IsEqualIID(riid, IID_IAImmFnDocFeed))
{
*func = new(cicNoThrow) CFnDocFeed();
if (*func)
return S_OK;
}
return E_NOINTERFACE;
}
/***********************************************************************/
CFnDocFeed::CFnDocFeed()
{
m_cRefs = 1;
}
CFnDocFeed::~CFnDocFeed()
{
}
/// @implemented
STDMETHODIMP CFnDocFeed::QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IAImmFnDocFeed))
{
*ppvObj = this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
/// @implemented
STDMETHODIMP_(ULONG) CFnDocFeed::AddRef()
{
return ::InterlockedIncrement(&m_cRefs);
}
/// @implemented
STDMETHODIMP_(ULONG) CFnDocFeed::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
delete this;
return 0;
}
return m_cRefs;
}
/// @implemented
STDMETHODIMP CFnDocFeed::DocFeed()
{
TLS *pTLS = TLS::GetTLS();
if (!pTLS || !pTLS->m_pProfile)
return FALSE;
if (!pTLS)
return E_OUTOFMEMORY;
LANGID LangID;
pTLS->m_pProfile->GetLangId(&LangID);
HIMC hIMC = GetActiveContext();
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
switch (PRIMARYLANGID(LangID))
{
case LANG_CHINESE:
case LANG_JAPANESE:
case LANG_KOREAN:
return TRUE;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC)
return E_FAIL;
default:
return FALSE;
}
UINT uCodePage = CP_ACP;
pTLS->m_pProfile->GetCodePageA(&uCodePage);
pCicIC->SetupDocFeedString(imcLock, uCodePage);
return S_OK;
}
/// @implemented
STDMETHODIMP CFnDocFeed::ClearDocFeedBuffer()
{
if (!TLS::GetTLS())
return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext();
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC)
return E_FAIL;
pCicIC->EscbClearDocFeedBuffer(imcLock, TRUE);
return S_OK;
}
/// @unimplemented
STDMETHODIMP CFnDocFeed::StartReconvert()
{
TLS *pTLS = TLS::GetTLS();
if (!pTLS)
return E_OUTOFMEMORY;
auto *pThreadMgr = pTLS->m_pThreadMgr;
if (!pThreadMgr)
return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext();
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC)
return E_FAIL;
UINT uCodePage = CP_ACP;
pTLS->m_pProfile->GetCodePageA(&uCodePage);
pCicIC->m_bReconverting = TRUE;
pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, 0, 0);
pCicIC->EndReconvertString(imcLock);
pCicIC->m_bReconverting = FALSE;
return S_OK;
}
/// @implemented
STDMETHODIMP CFnDocFeed::StartUndoCompositionString()
{
TLS *pTLS = TLS::GetTLS();
if (!pTLS)
return E_OUTOFMEMORY;
auto *pThreadMgr = pTLS->m_pThreadMgr;
if (!pThreadMgr)
return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext();
CicIMCLock imcLock(hIMC);
if (FAILED(imcLock.m_hr))
return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext);
if (FAILED(imeContext.m_hr))
return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC;
if (!pCicIC)
return E_FAIL;
UINT uCodePage = CP_ACP;
pTLS->m_pProfile->GetCodePageA(&uCodePage);
pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, 0, TRUE);
pCicIC->EndReconvertString(imcLock);
return S_OK;
}

View file

@ -7,6 +7,17 @@
#pragma once
BOOLEAN DllShutdownInProgress(VOID);
BOOL IsEALang(LANGID LangID);
BOOL IsInteractiveUserLogon(VOID);
BYTE GetCharsetFromLangId(_In_ DWORD dwValue);
HIMC GetActiveContext(VOID);
ITfCategoryMgr *GetUIMCat(PCIC_LIBTHREAD pLibThread);
HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread);
HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread);
/***********************************************************************/
HRESULT
GetCompartment(
IUnknown *pUnknown,
@ -59,4 +70,59 @@ public:
/***********************************************************************/
BOOL IsEALang(VOID);
class CFunctionProviderBase : public ITfFunctionProvider
{
protected:
TfClientId m_clientId;
GUID m_guid;
BSTR m_bstr;
LONG m_cRefs;
public:
CFunctionProviderBase(_In_ TfClientId clientId);
virtual ~CFunctionProviderBase();
// IUnknown interface
STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// ITfFunctionProvider interface
STDMETHODIMP GetType(_Out_ GUID *guid) override;
STDMETHODIMP GetDescription(_Out_ BSTR *desc) override;
//STDMETHODIMP GetFunction(_In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func) = 0;
BOOL Init(_In_ REFGUID rguid, _In_ LPCWSTR psz);
};
/***********************************************************************/
class CFunctionProvider : public CFunctionProviderBase
{
public:
CFunctionProvider(_In_ TfClientId clientId);
STDMETHODIMP GetFunction(_In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func) override;
};
/***********************************************************************/
class CFnDocFeed : public IAImmFnDocFeed
{
LONG m_cRefs;
public:
CFnDocFeed();
virtual ~CFnDocFeed();
// IUnknown interface
STDMETHODIMP QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// IAImmFnDocFeed interface
STDMETHODIMP DocFeed() override;
STDMETHODIMP ClearDocFeedBuffer() override;
STDMETHODIMP StartReconvert() override;
STDMETHODIMP StartUndoCompositionString() override;
};

View file

@ -6,12 +6,9 @@
*/
#include "msctfime.h"
#include <ndk/ldrfuncs.h> /* for RtlDllShutdownInProgress */
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
typedef CicArray<GUID> CDispAttrPropCache;
HINSTANCE g_hInst = NULL; /* The instance of this module */
BOOL g_bWinLogon = FALSE;
UINT g_uACP = CP_ACP;
@ -25,148 +22,6 @@ EXTERN_C void __cxa_pure_virtual(void)
ERR("__cxa_pure_virtual\n");
}
typedef BOOLEAN (WINAPI *FN_DllShutdownInProgress)(VOID);
/// This function calls ntdll!RtlDllShutdownInProgress.
/// It can detect the system is shutting down or not.
/// @implemented
EXTERN_C BOOLEAN WINAPI DllShutdownInProgress(VOID)
{
HMODULE hNTDLL;
static FN_DllShutdownInProgress s_fnDllShutdownInProgress = NULL;
if (s_fnDllShutdownInProgress)
return s_fnDllShutdownInProgress();
hNTDLL = cicGetSystemModuleHandle(L"ntdll.dll", FALSE);
s_fnDllShutdownInProgress =
(FN_DllShutdownInProgress)GetProcAddress(hNTDLL, "RtlDllShutdownInProgress");
if (!s_fnDllShutdownInProgress)
return FALSE;
return s_fnDllShutdownInProgress();
}
/// This function checks if the current user logon session is interactive.
/// @implemented
static BOOL
IsInteractiveUserLogon(VOID)
{
BOOL bOK, IsMember = FALSE;
PSID pSid;
SID_IDENTIFIER_AUTHORITY IdentAuth = { SECURITY_NT_AUTHORITY };
if (!AllocateAndInitializeSid(&IdentAuth, 1, SECURITY_INTERACTIVE_RID,
0, 0, 0, 0, 0, 0, 0, &pSid))
{
ERR("Error: %ld\n", GetLastError());
return FALSE;
}
bOK = CheckTokenMembership(NULL, pSid, &IsMember);
if (pSid)
FreeSid(pSid);
return bOK && IsMember;
}
/// @implemented
ITfCategoryMgr *GetUIMCat(PCIC_LIBTHREAD pLibThread)
{
if (!pLibThread)
return NULL;
if (pLibThread->m_pCategoryMgr)
return pLibThread->m_pCategoryMgr;
if (FAILED(cicCoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER,
IID_ITfCategoryMgr, (void **)&pLibThread->m_pCategoryMgr)))
{
return NULL;
}
return pLibThread->m_pCategoryMgr;
}
/// @implemented
HRESULT LibEnumItemsInCategory(PCIC_LIBTHREAD pLibThread, REFGUID rguid, IEnumGUID **ppEnum)
{
ITfCategoryMgr *pCat = GetUIMCat(pLibThread);
if (!pCat)
return E_FAIL;
return pCat->EnumItemsInCategory(rguid, ppEnum);
}
/// @implemented
HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
{
if (!pLibThread)
return E_FAIL;
if (pLibThread->m_pDisplayAttrMgr)
{
pLibThread->m_pDisplayAttrMgr->Release();
pLibThread->m_pDisplayAttrMgr = NULL;
}
if (FAILED(cicCoCreateInstance(CLSID_TF_DisplayAttributeMgr, NULL, CLSCTX_INPROC_SERVER,
IID_ITfDisplayAttributeMgr,
(void **)&pLibThread->m_pDisplayAttrMgr)))
{
return E_FAIL;
}
IEnumGUID *pEnumGuid;
LibEnumItemsInCategory(pLibThread, GUID_TFCAT_DISPLAYATTRIBUTEPROPERTY, &pEnumGuid);
HRESULT hr = E_OUTOFMEMORY;
::EnterCriticalSection(&g_csLock);
if (pEnumGuid && !g_pPropCache)
{
g_pPropCache = new(cicNoThrow) CDispAttrPropCache();
if (g_pPropCache)
{
g_pPropCache->Add(GUID_PROP_ATTRIBUTE);
GUID guid;
while (pEnumGuid->Next(1, &guid, NULL) == S_OK)
{
if (!IsEqualGUID(guid, GUID_PROP_ATTRIBUTE))
g_pPropCache->Add(guid);
}
hr = S_OK;
}
}
::LeaveCriticalSection(&g_csLock);
return hr;
}
/// @implemented
HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
{
if (!pLibThread)
return E_FAIL;
if (pLibThread->m_pDisplayAttrMgr)
{
pLibThread->m_pDisplayAttrMgr->Release();
pLibThread->m_pDisplayAttrMgr = NULL;
}
return S_OK;
}
/// Gets the charset from a language ID.
/// @implemented
BYTE GetCharsetFromLangId(_In_ DWORD dwValue)
{
CHARSETINFO info;
if (!::TranslateCharsetInfo((DWORD*)(DWORD_PTR)dwValue, &info, TCI_SRCLOCALE))
return 0;
return info.ciCharset;
}
/// Selects or unselects the input context.
/// @implemented
HRESULT
@ -236,8 +91,6 @@ InternalSelectEx(
return imcLock.m_hr;
}
class TLS;
/***********************************************************************
* ImeInquire (MSCTFIME.@)
*
@ -245,6 +98,7 @@ class TLS;
*
* @implemented
* @see CtfImeInquireExW
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeInquire.html
*/
EXTERN_C
BOOL WINAPI
@ -264,6 +118,7 @@ ImeInquire(
*
* @implemented
* @see ImmGetConversionListW
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeConversionList.html
*/
EXTERN_C DWORD WINAPI
ImeConversionList(
@ -284,6 +139,7 @@ ImeConversionList(
*
* @implemented
* @see ImeUnregisterWord
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeRegisterWord.html
*/
EXTERN_C BOOL WINAPI
ImeRegisterWord(
@ -302,6 +158,7 @@ ImeRegisterWord(
*
* @implemented
* @see ImeRegisterWord
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeUnregisterWord.html
*/
EXTERN_C BOOL WINAPI
ImeUnregisterWord(
@ -320,6 +177,7 @@ ImeUnregisterWord(
*
* @implemented
* @see ImeRegisterWord
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeGetRegisterWordStyle.html
*/
EXTERN_C UINT WINAPI
ImeGetRegisterWordStyle(
@ -337,6 +195,7 @@ ImeGetRegisterWordStyle(
*
* @implemented
* @see ImeRegisterWord
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeEnumRegisterWord.html
*/
EXTERN_C UINT WINAPI
ImeEnumRegisterWord(
@ -351,6 +210,12 @@ ImeEnumRegisterWord(
return 0;
}
/***********************************************************************
* ImeConfigure (MSCTFIME.@)
*
* @implemented
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeConfigure.html
*/
EXTERN_C BOOL WINAPI
ImeConfigure(
_In_ HKL hKL,
@ -380,6 +245,7 @@ ImeConfigure(
* ImeDestroy (MSCTFIME.@)
*
* @implemented
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeDestroy.html
*/
EXTERN_C BOOL WINAPI
ImeDestroy(
@ -410,6 +276,7 @@ ImeDestroy(
*
* @implemented
* @see CtfImeEscapeEx
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeEscape.html
*/
EXTERN_C LRESULT WINAPI
ImeEscape(
@ -439,6 +306,7 @@ ImeProcessKey(
*
* @implemented
* @see CtfImeSelectEx
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeSelect.html
*/
EXTERN_C BOOL WINAPI
ImeSelect(
@ -456,6 +324,7 @@ ImeSelect(
*
* @implemented
* @see CtfImeSetActiveContextAlways
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeSetActiveContext.html
*/
EXTERN_C BOOL WINAPI
ImeSetActiveContext(
@ -480,6 +349,12 @@ ImeToAsciiEx(
return 0;
}
/***********************************************************************
* NotifyIME (MSCTFIME.@)
*
* @implemented
* @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/NotifyIME.html
*/
EXTERN_C BOOL WINAPI
NotifyIME(
_In_ HIMC hIMC,
@ -487,8 +362,19 @@ NotifyIME(
_In_ DWORD dwIndex,
_In_ DWORD_PTR dwValue)
{
FIXME("stub:(%p, 0x%lX, 0x%lX, %p)\n", hIMC, dwAction, dwIndex, dwValue);
return FALSE;
TRACE("(%p, 0x%lX, 0x%lX, %p)\n", hIMC, dwAction, dwIndex, dwValue);
TLS *pTLS = TLS::GetTLS();
if (!pTLS)
return FALSE;
auto pBridge = pTLS->m_pBridge;
auto pThreadMgr = pTLS->m_pThreadMgr;
if (!pBridge || !pThreadMgr)
return FALSE;
HRESULT hr = pBridge->Notify(pTLS, pThreadMgr, hIMC, dwAction, dwIndex, dwValue);
return (hr == S_OK);
}
EXTERN_C BOOL WINAPI
@ -704,11 +590,22 @@ CtfImeDestroyThreadMgr(VOID)
return hr;
}
/***********************************************************************
* CtfImeCreateInputContext (MSCTFIME.@)
*
* @implemented
*/
EXTERN_C HRESULT WINAPI
CtfImeCreateInputContext(
_In_ HIMC hIMC)
{
return E_NOTIMPL;
TRACE("(%p)\n", hIMC);
TLS *pTLS = TLS::GetTLS();
if (!pTLS || !pTLS->m_pBridge)
return E_OUTOFMEMORY;
return pTLS->m_pBridge->CreateInputContext(pTLS, hIMC);
}
/***********************************************************************
@ -729,6 +626,11 @@ CtfImeDestroyInputContext(
return pTLS->m_pBridge->DestroyInputContext(pTLS, hIMC);
}
/***********************************************************************
* CtfImeSetActiveContextAlways (MSCTFIME.@)
*
* @implemented
*/
EXTERN_C HRESULT WINAPI
CtfImeSetActiveContextAlways(
_In_ HIMC hIMC,
@ -736,10 +638,13 @@ CtfImeSetActiveContextAlways(
_In_ HWND hWnd,
_In_ HKL hKL)
{
FIXME("stub:(%p, %d, %p, %p)\n", hIMC, fActive, hWnd, hKL);
return E_NOTIMPL;
}
TRACE("(%p, %d, %p, %p)\n", hIMC, fActive, hWnd, hKL);
TLS *pTLS = TLS::GetTLS();
if (!pTLS || !pTLS->m_pBridge)
return E_OUTOFMEMORY;
return pTLS->m_pBridge->SetActiveContextAlways(pTLS, hIMC, fActive, hWnd, hKL);
}
/***********************************************************************
* CtfImeProcessCicHotkey (MSCTFIME.@)

View file

@ -35,18 +35,10 @@
#include <wine/debug.h>
EXTERN_C BOOLEAN WINAPI DllShutdownInProgress(VOID);
extern CRITICAL_SECTION g_csLock;
HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread);
HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread);
static inline HIMC GetActiveContext(VOID)
{
HWND hwndFocus = ::GetFocus();
if (!hwndFocus)
hwndFocus = ::GetActiveWindow();
return ::ImmGetContext(hwndFocus);
}
typedef CicArray<GUID> CDispAttrPropCache;
extern CDispAttrPropCache *g_pPropCache;
DEFINE_GUID(GUID_COMPARTMENT_CTFIME_DIMFLAGS, 0xA94C5FD2, 0xC471, 0x4031, 0x95, 0x46, 0x70, 0x9C, 0x17, 0x30, 0x0C, 0xB9);
DEFINE_GUID(GUID_COMPARTMENT_CTFIME_CICINPUTCONTEXT, 0x85A688F7, 0x6DC8, 0x4F17, 0xA8, 0x3A, 0xB1, 0x1C, 0x09, 0xCD, 0xD7, 0xBF);
@ -55,13 +47,11 @@ DEFINE_GUID(GUID_MODEBIAS_NUMERIC, 0x4021766C, 0xE872, 0x48FD,
DEFINE_GUID(GUID_MODEBIAS_URLHISTORY, 0x8B0E54D9, 0x63F2, 0x4C68, 0x84, 0xD4, 0x79, 0xAE, 0xE7, 0xA5, 0x9F, 0x09);
DEFINE_GUID(GUID_MODEBIAS_DEFAULT, 0xF3DA8BD4, 0x0786, 0x49C2, 0x8C, 0x09, 0x68, 0x39, 0xD8, 0xB8, 0x4F, 0x58);
DEFINE_GUID(GUID_PROP_MODEBIAS, 0x372E0716, 0x974F, 0x40AC, 0xA0, 0x88, 0x08, 0xCD, 0xC9, 0x2E, 0xBF, 0xBC);
#define GUID_MODEBIAS_NONE GUID_NULL
#include "resource.h"
#include "bridge.h"
#include "functions.h"
#include "inputcontext.h"
#include "misc.h"
#include "profile.h"

View file

@ -11,6 +11,38 @@ WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
DWORD TLS::s_dwTlsIndex = (DWORD)-1;
/// @implemented
BOOL TLS::Initialize()
{
s_dwTlsIndex = ::TlsAlloc();
return s_dwTlsIndex != (DWORD)-1;
}
/// @implemented
VOID TLS::Uninitialize()
{
if (s_dwTlsIndex != (DWORD)-1)
{
::TlsFree(s_dwTlsIndex);
s_dwTlsIndex = (DWORD)-1;
}
}
/// @implemented
TLS* TLS::GetTLS()
{
if (s_dwTlsIndex == (DWORD)-1)
return NULL;
return InternalAllocateTLS();
}
/// @implemented
TLS* TLS::PeekTLS()
{
return (TLS*)::TlsGetValue(TLS::s_dwTlsIndex);
}
/// @implemented
TLS* TLS::InternalAllocateTLS()
{

View file

@ -7,8 +7,6 @@
#pragma once
class TLS;
class CicBridge;
class CicProfile;
@ -29,45 +27,11 @@ public:
DWORD m_NonEAComposition;
DWORD m_cWnds;
/**
* @implemented
*/
static BOOL Initialize()
{
s_dwTlsIndex = ::TlsAlloc();
return s_dwTlsIndex != (DWORD)-1;
}
static BOOL Initialize();
static VOID Uninitialize();
/**
* @implemented
*/
static VOID Uninitialize()
{
if (s_dwTlsIndex != (DWORD)-1)
{
::TlsFree(s_dwTlsIndex);
s_dwTlsIndex = (DWORD)-1;
}
}
/**
* @implemented
*/
static TLS* GetTLS()
{
if (s_dwTlsIndex == (DWORD)-1)
return NULL;
return InternalAllocateTLS();
}
/**
* @implemented
*/
static TLS* PeekTLS()
{
return (TLS*)::TlsGetValue(TLS::s_dwTlsIndex);
}
static TLS* GetTLS();
static TLS* PeekTLS();
static TLS* InternalAllocateTLS();
static BOOL InternalDestroyTLS();

View file

@ -529,7 +529,7 @@ HRESULT UIComposition::CreateCompButtonWnd(HWND hwndParent, HIMC hIMC)
if (!pTLS || !pTLS->NonEACompositionEnabled())
return S_OK;
if (IsEALang())
if (IsEALang(0))
{
if (m_pCompButtonFrameWindow)
{

View file

@ -44,8 +44,6 @@ public:
/***********************************************************************/
class CCompFrameWindow;
class CCompFinalizeButton : public CUIFToolbarButton
{
public: