diff --git a/dlls/msctf/context.c b/dlls/msctf/context.c index 941245c10db..a649c3832b3 100644 --- a/dlls/msctf/context.c +++ b/dlls/msctf/context.c @@ -65,6 +65,7 @@ typedef struct tagContext { /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */ /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */ ITfSourceSingle ITfSourceSingle_iface; + ITextStoreACPSink ITextStoreACPSink_iface; LONG refCount; BOOL connected; @@ -79,7 +80,6 @@ typedef struct tagContext { ITextStoreACP *pITextStoreACP; ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink; - ITextStoreACPSink *pITextStoreACPSink; ITfEditSession* currentEditSession; /* kept as separate lists to reduce unnecessary iterations */ @@ -96,17 +96,6 @@ typedef struct tagEditCookie { Context *pOwningContext; } EditCookie; -typedef struct tagTextStoreACPSink { - ITextStoreACPSink ITextStoreACPSink_iface; - /* const ITextStoreACPServicesVtbl *TextStoreACPServicesVtbl; */ - LONG refCount; - - Context *pContext; -} TextStoreACPSink; - - -static HRESULT TextStoreACPSink_Constructor(ITextStoreACPSink **ppOut, Context *pContext); - static inline Context *impl_from_ITfContext(ITfContext *iface) { return CONTAINING_RECORD(iface, Context, ITfContext_iface); @@ -127,9 +116,9 @@ static inline Context *impl_from_ITfSourceSingle(ITfSourceSingle* iface) return CONTAINING_RECORD(iface, Context, ITfSourceSingle_iface); } -static inline TextStoreACPSink *impl_from_ITextStoreACPSink(ITextStoreACPSink *iface) +static inline Context *impl_from_ITextStoreACPSink(ITextStoreACPSink *iface) { - return CONTAINING_RECORD(iface, TextStoreACPSink, ITextStoreACPSink_iface); + return CONTAINING_RECORD(iface, Context, ITextStoreACPSink_iface); } static void free_sink(ContextSink *sink) @@ -144,14 +133,11 @@ static void Context_Destructor(Context *This) EditCookie *cookie; TRACE("destroying %p\n", This); - if (This->pITextStoreACPSink) - { - ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)This->pITextStoreACPSink); - ITextStoreACPSink_Release(This->pITextStoreACPSink); - } - if (This->pITextStoreACP) + { + ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)&This->ITextStoreACPSink_iface); ITextStoreACP_Release(This->pITextStoreACP); + } if (This->pITfContextOwnerCompositionSink) ITfContextOwnerCompositionSink_Release(This->pITfContextOwnerCompositionSink); @@ -791,6 +777,192 @@ static const ITfSourceSingleVtbl ContextSourceSingleVtbl = SourceSingle_UnadviseSingleSink, }; +/************************************************************************** + * ITextStoreACPSink + **************************************************************************/ + +static HRESULT WINAPI TextStoreACPSink_QueryInterface(ITextStoreACPSink *iface, REFIID iid, LPVOID *ppvOut) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACPSink)) + { + *ppvOut = &This->ITextStoreACPSink_iface; + } + + if (*ppvOut) + { + ITextStoreACPSink_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI TextStoreACPSink_AddRef(ITextStoreACPSink *iface) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + return ITfContext_AddRef(&This->ITfContext_iface); +} + +static ULONG WINAPI TextStoreACPSink_Release(ITextStoreACPSink *iface) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + return ITfContext_Release(&This->ITfContext_iface); +} + +/***************************************************** + * ITextStoreACPSink functions + *****************************************************/ + +static HRESULT WINAPI TextStoreACPSink_OnTextChange(ITextStoreACPSink *iface, + DWORD dwFlags, const TS_TEXTCHANGE *pChange) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnLayoutChange(ITextStoreACPSink *iface, + TsLayoutCode lcode, TsViewCookie vcView) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface, + DWORD dwFlags) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + HRESULT hr, hrSession; + + TRACE("(%p) %x\n",This, dwFlags); + + if (!This->pITextStoreACP) + { + FIXME("Context does not have a ITextStoreACP\n"); + return E_NOTIMPL; + } + + hr = ITextStoreACP_RequestLock(This->pITextStoreACP, TS_LF_READ, &hrSession); + + if(SUCCEEDED(hr) && SUCCEEDED(hrSession)) + This->documentStatus.dwDynamicFlags = dwFlags; + + return S_OK; +} + +static HRESULT WINAPI TextStoreACPSink_OnAttrsChange(ITextStoreACPSink *iface, + LONG acpStart, LONG acpEnd, ULONG cAttrs, const TS_ATTRID *paAttrs) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface, + DWORD dwLockFlags) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + HRESULT hr; + EditCookie *cookie,*sinkcookie; + TfEditCookie ec; + struct list *cursor; + + TRACE("(%p) %x\n",This, dwLockFlags); + + if (!This->currentEditSession) + { + FIXME("OnLockGranted called for something other than an EditSession\n"); + return S_OK; + } + + cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); + if (!cookie) + return E_OUTOFMEMORY; + + sinkcookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); + if (!sinkcookie) + { + HeapFree(GetProcessHeap(), 0, cookie); + return E_OUTOFMEMORY; + } + + cookie->lockType = dwLockFlags; + cookie->pOwningContext = This; + ec = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, cookie); + + hr = ITfEditSession_DoEditSession(This->currentEditSession, ec); + + if ((dwLockFlags&TS_LF_READWRITE) == TS_LF_READWRITE) + { + TfEditCookie sc; + + sinkcookie->lockType = TS_LF_READ; + sinkcookie->pOwningContext = This; + sc = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, sinkcookie); + + /*TODO: implement ITfEditRecord */ + LIST_FOR_EACH(cursor, &This->pTextEditSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + ITfTextEditSink_OnEndEdit(sink->interfaces.pITfTextEditSink, + (ITfContext*) &This->ITfContext_iface, sc, NULL); + } + sinkcookie = remove_Cookie(sc); + } + HeapFree(GetProcessHeap(),0,sinkcookie); + + ITfEditSession_Release(This->currentEditSession); + This->currentEditSession = NULL; + + /* Edit Cookie is only valid during the edit session */ + cookie = remove_Cookie(ec); + HeapFree(GetProcessHeap(),0,cookie); + + return hr; +} + +static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface) +{ + Context *This = impl_from_ITextStoreACPSink(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static const ITextStoreACPSinkVtbl TextStoreACPSinkVtbl = +{ + TextStoreACPSink_QueryInterface, + TextStoreACPSink_AddRef, + TextStoreACPSink_Release, + TextStoreACPSink_OnTextChange, + TextStoreACPSink_OnSelectionChange, + TextStoreACPSink_OnLayoutChange, + TextStoreACPSink_OnStatusChange, + TextStoreACPSink_OnAttrsChange, + TextStoreACPSink_OnLockGranted, + TextStoreACPSink_OnStartEditTransaction, + TextStoreACPSink_OnEndEditTransaction +}; + HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore) { Context *This; @@ -813,6 +985,7 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr This->ITfSource_iface.lpVtbl = &ContextSourceVtbl; This->ITfInsertAtSelection_iface.lpVtbl = &InsertAtSelectionVtbl; This->ITfSourceSingle_iface.lpVtbl = &ContextSourceSingleVtbl; + This->ITextStoreACPSink_iface.lpVtbl = &TextStoreACPSinkVtbl; This->refCount = 1; This->tidOwner = tidOwner; This->connected = FALSE; @@ -855,11 +1028,8 @@ HRESULT Context_Initialize(ITfContext *iface, ITfDocumentMgr *manager) Context *This = impl_from_ITfContext(iface); if (This->pITextStoreACP) - { - if (SUCCEEDED(TextStoreACPSink_Constructor(&This->pITextStoreACPSink, This))) - ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink, - (IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS); - } + ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink, + (IUnknown*)&This->ITextStoreACPSink_iface, TS_AS_ALL_SINKS); This->connected = TRUE; This->manager = manager; return S_OK; @@ -869,239 +1039,9 @@ HRESULT Context_Uninitialize(ITfContext *iface) { Context *This = impl_from_ITfContext(iface); - if (This->pITextStoreACPSink) - { - ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)This->pITextStoreACPSink); - if (ITextStoreACPSink_Release(This->pITextStoreACPSink) == 0) - This->pITextStoreACPSink = NULL; - } + if (This->pITextStoreACP) + ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)&This->ITextStoreACPSink_iface); This->connected = FALSE; This->manager = NULL; return S_OK; } - -/************************************************************************** - * ITextStoreACPSink - **************************************************************************/ - -static void TextStoreACPSink_Destructor(TextStoreACPSink *This) -{ - TRACE("destroying %p\n", This); - HeapFree(GetProcessHeap(),0,This); -} - -static HRESULT WINAPI TextStoreACPSink_QueryInterface(ITextStoreACPSink *iface, REFIID iid, LPVOID *ppvOut) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - *ppvOut = NULL; - - if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACPSink)) - { - *ppvOut = &This->ITextStoreACPSink_iface; - } - - if (*ppvOut) - { - ITextStoreACPSink_AddRef(iface); - return S_OK; - } - - WARN("unsupported interface: %s\n", debugstr_guid(iid)); - return E_NOINTERFACE; -} - -static ULONG WINAPI TextStoreACPSink_AddRef(ITextStoreACPSink *iface) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - return InterlockedIncrement(&This->refCount); -} - -static ULONG WINAPI TextStoreACPSink_Release(ITextStoreACPSink *iface) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - ULONG ret; - - ret = InterlockedDecrement(&This->refCount); - if (ret == 0) - TextStoreACPSink_Destructor(This); - return ret; -} - -/***************************************************** - * ITextStoreACPSink functions - *****************************************************/ - -static HRESULT WINAPI TextStoreACPSink_OnTextChange(ITextStoreACPSink *iface, - DWORD dwFlags, const TS_TEXTCHANGE *pChange) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; -} - -static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; -} - -static HRESULT WINAPI TextStoreACPSink_OnLayoutChange(ITextStoreACPSink *iface, - TsLayoutCode lcode, TsViewCookie vcView) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; -} - -static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface, - DWORD dwFlags) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - HRESULT hr, hrSession; - - TRACE("(%p) %x\n",This, dwFlags); - - if (!This->pContext) - { - ERR("No context?\n"); - return E_FAIL; - } - - if (!This->pContext->pITextStoreACP) - { - FIXME("Context does not have a ITextStoreACP\n"); - return E_NOTIMPL; - } - - hr = ITextStoreACP_RequestLock(This->pContext->pITextStoreACP, TS_LF_READ, &hrSession); - - if(SUCCEEDED(hr) && SUCCEEDED(hrSession)) - This->pContext->documentStatus.dwDynamicFlags = dwFlags; - - return S_OK; -} - -static HRESULT WINAPI TextStoreACPSink_OnAttrsChange(ITextStoreACPSink *iface, - LONG acpStart, LONG acpEnd, ULONG cAttrs, const TS_ATTRID *paAttrs) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; -} - -static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface, - DWORD dwLockFlags) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - HRESULT hr; - EditCookie *cookie,*sinkcookie; - TfEditCookie ec; - struct list *cursor; - - TRACE("(%p) %x\n",This, dwLockFlags); - - if (!This->pContext) - { - ERR("OnLockGranted called without a context\n"); - return E_FAIL; - } - - if (!This->pContext->currentEditSession) - { - FIXME("OnLockGranted called for something other than an EditSession\n"); - return S_OK; - } - - cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); - if (!cookie) - return E_OUTOFMEMORY; - - sinkcookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie)); - if (!sinkcookie) - { - HeapFree(GetProcessHeap(), 0, cookie); - return E_OUTOFMEMORY; - } - - cookie->lockType = dwLockFlags; - cookie->pOwningContext = This->pContext; - ec = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, cookie); - - hr = ITfEditSession_DoEditSession(This->pContext->currentEditSession, ec); - - if ((dwLockFlags&TS_LF_READWRITE) == TS_LF_READWRITE) - { - TfEditCookie sc; - - sinkcookie->lockType = TS_LF_READ; - sinkcookie->pOwningContext = This->pContext; - sc = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, sinkcookie); - - /*TODO: implement ITfEditRecord */ - LIST_FOR_EACH(cursor, &This->pContext->pTextEditSink) - { - ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); - ITfTextEditSink_OnEndEdit(sink->interfaces.pITfTextEditSink, - (ITfContext*) &This->pContext, sc, NULL); - } - sinkcookie = remove_Cookie(sc); - } - HeapFree(GetProcessHeap(),0,sinkcookie); - - ITfEditSession_Release(This->pContext->currentEditSession); - This->pContext->currentEditSession = NULL; - - /* Edit Cookie is only valid during the edit session */ - cookie = remove_Cookie(ec); - HeapFree(GetProcessHeap(),0,cookie); - - return hr; -} - -static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; -} - -static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface) -{ - TextStoreACPSink *This = impl_from_ITextStoreACPSink(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; -} - -static const ITextStoreACPSinkVtbl TextStoreACPSinkVtbl = -{ - TextStoreACPSink_QueryInterface, - TextStoreACPSink_AddRef, - TextStoreACPSink_Release, - TextStoreACPSink_OnTextChange, - TextStoreACPSink_OnSelectionChange, - TextStoreACPSink_OnLayoutChange, - TextStoreACPSink_OnStatusChange, - TextStoreACPSink_OnAttrsChange, - TextStoreACPSink_OnLockGranted, - TextStoreACPSink_OnStartEditTransaction, - TextStoreACPSink_OnEndEditTransaction -}; - -static HRESULT TextStoreACPSink_Constructor(ITextStoreACPSink **ppOut, Context *pContext) -{ - TextStoreACPSink *This; - - This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TextStoreACPSink)); - if (This == NULL) - return E_OUTOFMEMORY; - - This->ITextStoreACPSink_iface.lpVtbl= &TextStoreACPSinkVtbl; - This->refCount = 1; - - This->pContext = pContext; - - *ppOut = &This->ITextStoreACPSink_iface; - TRACE("returning %p\n", *ppOut); - return S_OK; -}