https://git.reactos.org/?p=reactos.git;a=commitdiff;h=006bdfa234a834e5b0a24…
commit 006bdfa234a834e5b0a2464bdd79f9eeed878156
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Jan 2 19:45:03 2024 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Jan 2 19:45:03 2024 +0900
[MSCTFIME][SDK] Half-implement CTextEventSink (#6274)
Supporting TIPs...
JIRA issue: CORE-19360
- Add CTextEventSink class.
- Add ITfTextLayoutSink interface
into "msctf.idl".
---
dll/ime/msctfime/msctfime.cpp | 167 +++++++++++++++++++++++++++++++++++++++++-
sdk/include/psdk/msctf.idl | 21 ++++++
2 files changed, 186 insertions(+), 2 deletions(-)
diff --git a/dll/ime/msctfime/msctfime.cpp b/dll/ime/msctfime/msctfime.cpp
index d0feb2008da..c9f235937bc 100644
--- a/dll/ime/msctfime/msctfime.cpp
+++ b/dll/ime/msctfime/msctfime.cpp
@@ -597,9 +597,166 @@ HRESULT CCompartmentEventSink::_Unadvise()
}
class CInputContextOwnerCallBack;
-class CTextEventSink;
class CInputContextOwner;
+typedef INT (CALLBACK *FN_ENDEDIT)(INT, LPVOID, LPVOID);
+typedef INT (CALLBACK *FN_LAYOUTCHANGE)(UINT nType, FN_ENDEDIT fnEndEdit, ITfContextView
*pView);
+
+class CTextEventSink : public ITfTextEditSink, ITfTextLayoutSink
+{
+protected:
+ LONG m_cRefs;
+ IUnknown *m_pUnknown;
+ DWORD m_dwEditSinkCookie;
+ DWORD m_dwLayoutSinkCookie;
+ FN_LAYOUTCHANGE m_fnLayoutChange;
+ FN_ENDEDIT m_fnEndEdit;
+ LPVOID m_pCallbackPV;
+
+public:
+ CTextEventSink(FN_ENDEDIT fnEndEdit, LPVOID pCallbackPV);
+ virtual ~CTextEventSink();
+
+ HRESULT _Advise(IUnknown *pUnknown, UINT uFlags);
+ HRESULT _Unadvise();
+
+ // IUnknown interface
+ STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override;
+ STDMETHODIMP_(ULONG) AddRef() override;
+ STDMETHODIMP_(ULONG) Release() override;
+
+ // ITfTextEditSink interface
+ STDMETHODIMP OnEndEdit(
+ ITfContext *pic,
+ TfEditCookie ecReadOnly,
+ ITfEditRecord *pEditRecord) override;
+
+ // ITfTextLayoutSink interface
+ STDMETHODIMP
+ OnLayoutChange(
+ ITfContext *pContext,
+ TfLayoutCode lcode,
+ ITfContextView *pContextView) override;
+};
+
+/**
+ * @implemented
+ */
+CTextEventSink::CTextEventSink(FN_ENDEDIT fnEndEdit, LPVOID pCallbackPV)
+{
+ m_cRefs = 1;
+ m_pUnknown = NULL;
+ m_dwEditSinkCookie = (DWORD)-1;
+ m_dwLayoutSinkCookie = (DWORD)-1;
+ m_fnLayoutChange = NULL;
+ m_fnEndEdit = fnEndEdit;
+ m_pCallbackPV = pCallbackPV;
+}
+
+/**
+ * @implemented
+ */
+CTextEventSink::~CTextEventSink()
+{
+}
+
+/**
+ * @implemented
+ */
+STDMETHODIMP CTextEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj)
+{
+ if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfTextEditSink))
+ {
+ *ppvObj = this;
+ AddRef();
+ return S_OK;
+ }
+ if (IsEqualIID(riid, IID_ITfTextLayoutSink))
+ {
+ *ppvObj = static_cast<ITfTextLayoutSink*>(this);
+ AddRef();
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+/**
+ * @implemented
+ */
+STDMETHODIMP_(ULONG) CTextEventSink::AddRef()
+{
+ return ::InterlockedIncrement(&m_cRefs);
+}
+
+/**
+ * @implemented
+ */
+STDMETHODIMP_(ULONG) CTextEventSink::Release()
+{
+ if (::InterlockedDecrement(&m_cRefs) == 0)
+ {
+ delete this;
+ return 0;
+ }
+ return m_cRefs;
+}
+
+struct TEXT_EVENT_SINK_END_EDIT
+{
+ TfEditCookie m_ecReadOnly;
+ ITfEditRecord *m_pEditRecord;
+ ITfContext *m_pContext;
+};
+
+/**
+ * @implemented
+ */
+STDMETHODIMP CTextEventSink::OnEndEdit(
+ ITfContext *pic,
+ TfEditCookie ecReadOnly,
+ ITfEditRecord *pEditRecord)
+{
+ TEXT_EVENT_SINK_END_EDIT Data = { ecReadOnly, pEditRecord, pic };
+ return m_fnEndEdit(1, m_pCallbackPV, (LPVOID)&Data);
+}
+
+/**
+ * @implemented
+ */
+STDMETHODIMP CTextEventSink::OnLayoutChange(
+ ITfContext *pContext,
+ TfLayoutCode lcode,
+ ITfContextView *pContextView)
+{
+ switch (lcode)
+ {
+ case TF_LC_CREATE:
+ return m_fnLayoutChange(3, m_fnEndEdit, pContextView);
+ case TF_LC_CHANGE:
+ return m_fnLayoutChange(2, m_fnEndEdit, pContextView);
+ case TF_LC_DESTROY:
+ return m_fnLayoutChange(4, m_fnEndEdit, pContextView);
+ default:
+ return E_INVALIDARG;
+ }
+}
+
+/**
+ * @unimplemented
+ */
+HRESULT CTextEventSink::_Advise(IUnknown *pUnknown, UINT uFlags)
+{
+ return E_NOTIMPL;
+}
+
+/**
+ * @unimplemented
+ */
+HRESULT CTextEventSink::_Unadvise()
+{
+ return E_NOTIMPL;
+}
+
/***********************************************************************
* CicInputContext
*
@@ -821,7 +978,13 @@ CicInputContext::DestroyInputContext()
pSource->UnadviseSingleSink(m_clientId, IID_ITfCleanupContextSink);
//FIXME: m_dwUnknown5
- //FIXME: m_pTextEventSink
+
+ if (m_pTextEventSink)
+ {
+ m_pTextEventSink->_Unadvise();
+ m_pTextEventSink->Release();
+ m_pTextEventSink = NULL;
+ }
if (m_pCompEventSink2)
{
diff --git a/sdk/include/psdk/msctf.idl b/sdk/include/psdk/msctf.idl
index e3d642c651c..60219b328e0 100644
--- a/sdk/include/psdk/msctf.idl
+++ b/sdk/include/psdk/msctf.idl
@@ -109,6 +109,7 @@ interface ITfKeyEventSink;
interface ITfPersistentPropertyLoaderACP;
interface ITfRangeACP;
interface ITfCleanupContextSink;
+interface ITfTextLayoutSink;
cpp_quote("#if 0")
typedef [uuid(4f5d560f-5ab5-4dde-8c4d-404592857ab0)] UINT_PTR HKL;
@@ -1919,3 +1920,23 @@ interface ITfTransitoryExtensionSink : IUnknown
[in] ITfRange *pCompositionRange,
[out] BOOL *pfDeleteResultRange);
}
+
+[
+ object,
+ uuid(2af2d06a-dd5b-4927-a0b4-54f19c91fade),
+ pointer_default(unique)
+]
+interface ITfTextLayoutSink : IUnknown
+{
+ typedef [uuid(603553cf-9edd-4cc1-9ecc-069e4a427734)] enum
+ {
+ TF_LC_CREATE = 0,
+ TF_LC_CHANGE = 1,
+ TF_LC_DESTROY = 2
+ } TfLayoutCode;
+
+ HRESULT OnLayoutChange(
+ [in] ITfContext *pic,
+ [in] TfLayoutCode lcode,
+ [in] ITfContextView *pView);
+}