[MSCTFIME][SDK] Implement CCompartmentEventSink (#6205)

- Modify <cicero/cicbase.h> and
  <cicero/cicarray.h>.
- Add CCompartmentEventSink class.
CORE-19360
This commit is contained in:
Katayama Hirofumi MZ 2023-12-20 22:01:39 +09:00 committed by GitHub
parent 209e9a7c1d
commit 954598037f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 178 additions and 9 deletions

View file

@ -164,6 +164,10 @@ void TFUninitLib_Thread(PLIBTHREAD pLibThread)
}
}
/***********************************************************************
* Compartment
*/
HRESULT
GetCompartment(
IUnknown *pUnknown,
@ -304,6 +308,154 @@ ClearCompartment(
return hr;
}
typedef struct CESMAP
{
ITfCompartment *m_pComp;
DWORD m_dwCookie;
} CESMAP, *PCESMAP;
typedef INT (CALLBACK *FN_EVENTSINK)(LPVOID, REFGUID);
class CCompartmentEventSink : public ITfCompartmentEventSink
{
CicArray m_array;
LONG m_cRefs;
FN_EVENTSINK m_fnEventSink;
LPVOID m_pUserData;
public:
CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData);
virtual ~CCompartmentEventSink();
HRESULT _Advise(IUnknown *pUnknown, REFGUID rguid, ITfCompartment *pComp);
HRESULT _Unadvise();
// IUnknown interface
STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override;
STDMETHODIMP_(ULONG) AddRef() override;
STDMETHODIMP_(ULONG) Release() override;
// ITfCompartmentEventSink interface
STDMETHODIMP OnChange(REFGUID rguid) override;
};
CCompartmentEventSink::CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData)
: m_array(8)
, m_cRefs(1)
, m_fnEventSink(fnEventSink)
, m_pUserData(pUserData)
{
}
CCompartmentEventSink::~CCompartmentEventSink()
{
}
STDMETHODIMP CCompartmentEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCompartmentEventSink))
{
*ppvObj = this;
AddRef();
return S_OK;
}
*ppvObj = NULL;
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CCompartmentEventSink::AddRef()
{
return ::InterlockedIncrement(&m_cRefs);
}
STDMETHODIMP_(ULONG) CCompartmentEventSink::Release()
{
if (::InterlockedDecrement(&m_cRefs) == 0)
{
delete this;
return 0;
}
return m_cRefs;
}
STDMETHODIMP CCompartmentEventSink::OnChange(REFGUID rguid)
{
return m_fnEventSink(m_pUserData, rguid);
}
HRESULT
CCompartmentEventSink::_Advise(IUnknown *pUnknown, REFGUID rguid, ITfCompartment *pComp)
{
CESMAP *pCesMap = (CESMAP *)m_array.Append(1);
if (!pCesMap)
return E_OUTOFMEMORY;
ITfSource *pSource = NULL;
HRESULT hr = GetCompartment(pUnknown, rguid, &pCesMap->m_pComp, !!pComp);
if (FAILED(hr))
{
hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource);
if (FAILED(hr))
{
hr = pSource->AdviseSink(IID_ITfCompartmentEventSink, this, &pCesMap->m_dwCookie);
if (FAILED(hr))
{
if (pCesMap->m_pComp)
{
pCesMap->m_pComp->Release();
pCesMap->m_pComp = NULL;
}
m_array.Remove(m_array.m_cItems - 1, 1);
}
else
{
hr = S_OK;
}
}
}
if (pSource)
pSource->Release();
return hr;
}
HRESULT CCompartmentEventSink::_Unadvise()
{
CESMAP *pCesMap = (CESMAP *)m_array.m_pb;
if (!m_array.m_cItems)
return S_OK;
INT cItems = m_array.m_cItems;
do
{
ITfSource *pSource = NULL;
HRESULT hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource);
if (SUCCEEDED(hr))
pSource->UnadviseSink(pCesMap->m_dwCookie);
if (pCesMap->m_pComp)
{
pCesMap->m_pComp->Release();
pCesMap->m_pComp = NULL;
}
if (pSource)
pSource->Release();
++pCesMap;
--cItems;
} while (cItems);
return S_OK;
}
/***********************************************************************
* CicInputContext
*/
/* FIXME */
class CicInputContext : public ITfContextOwnerCompositionSink
{

View file

@ -23,6 +23,7 @@
#include <strsafe.h>
#include <cicero/cicbase.h>
#include <cicero/cicarray.h>
#include <cicero/osinfo.h>
#include <cicero/CModulePath.h>
#include <cicero/imclock.h>

View file

@ -11,18 +11,17 @@
class CicArray
{
LPVOID lpVtbl;
public:
LPBYTE m_pb;
INT m_cItems;
INT m_cbItem;
INT m_cCapacity;
public:
CicArray(INT cbItem);
virtual CicArray();
virtual ~CicArray();
void Insert(INT iItem, INT cGrow);
void Append(INT cGrow);
BOOL Insert(INT iItem, INT cGrow);
LPVOID Append(INT cGrow);
void Remove(INT iItem, INT cRemove);
};
@ -40,12 +39,14 @@ inline CicArray::~CicArray()
cicMemFree(m_pb);
}
inline void CicArray::Append(INT cGrow)
inline LPVOID CicArray::Append(INT cGrow)
{
Insert(m_cItems, cGrow);
if (!Insert(m_cItems, cGrow))
return NULL;
return &m_pb[(m_cItems - cGrow) * m_cbItem];
}
inline void CicArray::Insert(INT iItem, INT cGrow)
inline BOOL CicArray::Insert(INT iItem, INT cGrow)
{
INT cNewCapacity = m_cItems + cGrow;
if (m_cCapacity < cNewCapacity)
@ -60,7 +61,7 @@ inline void CicArray::Insert(INT iItem, INT cGrow)
pbNew = (BYTE *)cicMemAlloc(cNewCapacity * m_cbItem);
if (!pbNew)
return;
return FALSE;
m_pb = pbNew;
m_cCapacity = cNewCapacity;
@ -74,6 +75,7 @@ inline void CicArray::Insert(INT iItem, INT cGrow)
}
m_cItems += cGrow;
return TRUE;
}
inline void CicArray::Remove(INT iItem, INT cRemove)

View file

@ -5,11 +5,25 @@
* COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#pragma once
static inline LPVOID cicMemAlloc(SIZE_T size)
{
return LocalAlloc(0, size);
}
static inline LPVOID cicMemAllocClear(SIZE_T size)
{
return LocalAlloc(LMEM_ZEROINIT, size);
}
static inline LPVOID cicMemReAlloc(LPVOID ptr, SIZE_T newSize)
{
if (!ptr)
return LocalAlloc(LMEM_ZEROINIT, newSize);
return LocalReAlloc(ptr, newSize, LMEM_ZEROINIT);
}
static inline void cicMemFree(LPVOID ptr)
{
if (ptr)