https://git.reactos.org/?p=reactos.git;a=commitdiff;h=006bdfa234a834e5b0a2464bdd79f9eeed878156
commit 006bdfa234a834e5b0a2464bdd79f9eeed878156 Author: Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com> AuthorDate: Tue Jan 2 19:45:03 2024 +0900 Commit: GitHub <nore...@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); +}