Module: wine Branch: master Commit: 17666004c839a40f1dbc5c98468557091bf3e13c URL: http://source.winehq.org/git/wine.git/?a=commit;h=17666004c839a40f1dbc5c9846...
Author: Aric Stewart aric@codeweavers.com Date: Wed Feb 4 14:48:36 2009 -0600
msctf: Add sink framework and implement ITfTextEditSink in Context.
---
dlls/msctf/context.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++-- include/msctf.idl | 14 +++++++ 2 files changed, 117 insertions(+), 4 deletions(-)
diff --git a/dlls/msctf/context.c b/dlls/msctf/context.c index aa8647c..593f0ad 100644 --- a/dlls/msctf/context.c +++ b/dlls/msctf/context.c @@ -32,14 +32,29 @@ #include "shlwapi.h" #include "winerror.h" #include "objbase.h" +#include "olectl.h"
#include "wine/unicode.h" +#include "wine/list.h"
#include "msctf.h" #include "msctf_internal.h"
WINE_DEFAULT_DEBUG_CHANNEL(msctf);
+typedef struct tagContextSink { + struct list entry; + union { + /* Context Sinks */ + IUnknown *pIUnknown; + /* ITfContextKeyEventSink *pITfContextKeyEventSink; */ + /* ITfEditTransactionSink *pITfEditTransactionSink; */ + /* ITfStatusSink *pITfStatusSink; */ + ITfTextEditSink *pITfTextEditSink; + /* ITfTextLayoutSink *pITfTextLayoutSink; */ + } interfaces; +} ContextSink; + typedef struct tagContext { const ITfContextVtbl *ContextVtbl; const ITfSourceVtbl *SourceVtbl; @@ -47,6 +62,14 @@ typedef struct tagContext {
TfClientId tidOwner; IUnknown *punk; /* possible ITextStoreACP or ITfContextOwnerCompositionSink */ + + /* kept as seperate lists to reduce unnesseccary iterations */ + struct list pContextKeyEventSink; + struct list pEditTransactionSink; + struct list pStatusSink; + struct list pTextEditSink; + struct list pTextLayoutSink; + } Context;
static inline Context *impl_from_ITfSourceVtbl(ITfSource *iface) @@ -54,9 +77,48 @@ static inline Context *impl_from_ITfSourceVtbl(ITfSource *iface) return (Context *)((char *)iface - FIELD_OFFSET(Context,SourceVtbl)); }
+static void free_sink(ContextSink *sink) +{ + IUnknown_Release(sink->interfaces.pIUnknown); + HeapFree(GetProcessHeap(),0,sink); +} + static void Context_Destructor(Context *This) { + struct list *cursor, *cursor2; TRACE("destroying %p\n", This); + + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pContextKeyEventSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pEditTransactionSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pStatusSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextEditSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextLayoutSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + HeapFree(GetProcessHeap(),0,This); }
@@ -275,16 +337,46 @@ static ULONG WINAPI Source_Release(ITfSource *iface) static WINAPI HRESULT ContextSource_AdviseSink(ITfSource *iface, REFIID riid, IUnknown *punk, DWORD *pdwCookie) { + ContextSink *es; Context *This = impl_from_ITfSourceVtbl(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie); + + if (!riid || !punk || !pdwCookie) + return E_INVALIDARG; + + if (IsEqualIID(riid, &IID_ITfTextEditSink)) + { + es = HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink)); + if (!es) + return E_OUTOFMEMORY; + if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&es->interfaces.pITfTextEditSink))) + { + HeapFree(GetProcessHeap(),0,es); + return CONNECT_E_CANNOTCONNECT; + } + list_add_head(&This->pTextEditSink ,&es->entry); + *pdwCookie = (DWORD)es; + } + else + { + FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); + return E_NOTIMPL; + } + + TRACE("cookie %x\n",*pdwCookie); + return S_OK; }
static WINAPI HRESULT ContextSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) { + ContextSink *sink = (ContextSink*)pdwCookie; Context *This = impl_from_ITfSourceVtbl(iface); - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + TRACE("(%p) %x\n",This,pdwCookie); + + list_remove(&sink->entry); + free_sink(sink); + + return S_OK; }
static const ITfSourceVtbl Context_SourceVtbl = @@ -315,5 +407,12 @@ HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **pp *ppOut = (ITfContext*)This; /* FIXME */ *pecTextStore = 0xdeaddead; + + list_init(&This->pContextKeyEventSink); + list_init(&This->pEditTransactionSink); + list_init(&This->pStatusSink); + list_init(&This->pTextEditSink); + list_init(&This->pTextLayoutSink); + return S_OK; } diff --git a/include/msctf.idl b/include/msctf.idl index 2b5d2dd..47bec71 100644 --- a/include/msctf.idl +++ b/include/msctf.idl @@ -48,6 +48,7 @@ interface ITfReadOnlyProperty; interface IEnumTfProperties; interface ITfRangeBackup; interface IEnumTfLanguageProfiles; +interface ITfEditRecord;
[ object, @@ -401,3 +402,16 @@ interface ITfCategoryMgr : IUnknown [in] REFGUID rguid, [out] BOOL *pfEqual); }; + +[ + object, + uuid(8127d409-ccd3-4683-967a-b43d5b482bf7), + pointer_default(unique) +] +interface ITfTextEditSink : IUnknown +{ + HRESULT OnEndEdit( + [in] ITfContext *pic, + [in] TfEditCookie ecReadOnly, + [in] ITfEditRecord *pEditRecord); +};