Aric Stewart : msctf: Implement ITfDocumentMgr::EnumContexts.

Alexandre Julliard julliard at winehq.org
Wed Jul 1 09:28:09 CDT 2009


Module: wine
Branch: master
Commit: 7de0b8299db9ebe839919cb90885a89ff46eeadd
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=7de0b8299db9ebe839919cb90885a89ff46eeadd

Author: Aric Stewart <aric at codeweavers.com>
Date:   Tue Jun 30 14:47:12 2009 -0500

msctf: Implement ITfDocumentMgr::EnumContexts.

---

 dlls/msctf/documentmgr.c          |  153 ++++++++++++++++++++++++++++++++++++-
 dlls/msctf/tests/inputprocessor.c |   33 ++++++++
 include/msctf.idl                 |   21 +++++
 3 files changed, 205 insertions(+), 2 deletions(-)

diff --git a/dlls/msctf/documentmgr.c b/dlls/msctf/documentmgr.c
index f5ea71f..66f0f50 100644
--- a/dlls/msctf/documentmgr.c
+++ b/dlls/msctf/documentmgr.c
@@ -52,6 +52,16 @@ typedef struct tagDocumentMgr {
     ITfThreadMgrEventSink* ThreadMgrSink;
 } DocumentMgr;
 
+typedef struct tagEnumTfContext {
+    const IEnumTfContextsVtbl *Vtbl;
+    LONG refCount;
+
+    DWORD   index;
+    DocumentMgr *docmgr;
+} EnumTfContext;
+
+static HRESULT EnumTfContext_Constructor(DocumentMgr* mgr, IEnumTfContexts **ppOut);
+
 static inline DocumentMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
 {
     return (DocumentMgr *)((char *)iface - FIELD_OFFSET(DocumentMgr,SourceVtbl));
@@ -233,8 +243,8 @@ static HRESULT WINAPI DocumentMgr_GetBase(ITfDocumentMgr *iface, ITfContext **pp
 static HRESULT WINAPI DocumentMgr_EnumContexts(ITfDocumentMgr *iface, IEnumTfContexts **ppEnum)
 {
     DocumentMgr *This = (DocumentMgr *)iface;
-    FIXME("STUB:(%p)\n",This);
-    return E_NOTIMPL;
+    TRACE("(%p) %p\n",This,ppEnum);
+    return EnumTfContext_Constructor(This, ppEnum);
 }
 
 static const ITfDocumentMgrVtbl DocumentMgr_DocumentMgrVtbl =
@@ -317,3 +327,142 @@ HRESULT DocumentMgr_Constructor(ITfThreadMgrEventSink *ThreadMgrSink, ITfDocumen
     *ppOut = (ITfDocumentMgr*)This;
     return S_OK;
 }
+
+/**************************************************
+ * IEnumTfContexts implementaion
+ **************************************************/
+static void EnumTfContext_Destructor(EnumTfContext *This)
+{
+    TRACE("destroying %p\n", This);
+    HeapFree(GetProcessHeap(),0,This);
+}
+
+static HRESULT WINAPI EnumTfContext_QueryInterface(IEnumTfContexts *iface, REFIID iid, LPVOID *ppvOut)
+{
+    EnumTfContext *This = (EnumTfContext *)iface;
+    *ppvOut = NULL;
+
+    if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfContexts))
+    {
+        *ppvOut = This;
+    }
+
+    if (*ppvOut)
+    {
+        IUnknown_AddRef(iface);
+        return S_OK;
+    }
+
+    WARN("unsupported interface: %s\n", debugstr_guid(iid));
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI EnumTfContext_AddRef(IEnumTfContexts *iface)
+{
+    EnumTfContext *This = (EnumTfContext*)iface;
+    return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI EnumTfContext_Release(IEnumTfContexts *iface)
+{
+    EnumTfContext *This = (EnumTfContext *)iface;
+    ULONG ret;
+
+    ret = InterlockedDecrement(&This->refCount);
+    if (ret == 0)
+        EnumTfContext_Destructor(This);
+    return ret;
+}
+
+static HRESULT WINAPI EnumTfContext_Next(IEnumTfContexts *iface,
+    ULONG ulCount, ITfContext **rgContext, ULONG *pcFetched)
+{
+    EnumTfContext *This = (EnumTfContext *)iface;
+    ULONG fetched = 0;
+
+    TRACE("(%p)\n",This);
+
+    if (rgContext == NULL) return E_POINTER;
+
+    while (fetched < ulCount)
+    {
+        if (This->index > 1)
+            break;
+
+        if (!This->docmgr->contextStack[This->index])
+            break;
+
+        *rgContext = This->docmgr->contextStack[This->index];
+        ITfContext_AddRef(*rgContext);
+
+        ++This->index;
+        ++fetched;
+        ++rgContext;
+    }
+
+    if (pcFetched) *pcFetched = fetched;
+    return fetched == ulCount ? S_OK : S_FALSE;
+}
+
+static HRESULT WINAPI EnumTfContext_Skip( IEnumTfContexts* iface, ULONG celt)
+{
+    EnumTfContext *This = (EnumTfContext *)iface;
+    TRACE("(%p)\n",This);
+    This->index += celt;
+    return S_OK;
+}
+
+static HRESULT WINAPI EnumTfContext_Reset( IEnumTfContexts* iface)
+{
+    EnumTfContext *This = (EnumTfContext *)iface;
+    TRACE("(%p)\n",This);
+    This->index = 0;
+    return S_OK;
+}
+
+static HRESULT WINAPI EnumTfContext_Clone( IEnumTfContexts *iface,
+    IEnumTfContexts **ppenum)
+{
+    EnumTfContext *This = (EnumTfContext *)iface;
+    HRESULT res;
+
+    TRACE("(%p)\n",This);
+
+    if (ppenum == NULL) return E_POINTER;
+
+    res = EnumTfContext_Constructor(This->docmgr, ppenum);
+    if (SUCCEEDED(res))
+    {
+        EnumTfContext *new_This = (EnumTfContext *)*ppenum;
+        new_This->index = This->index;
+    }
+    return res;
+}
+
+static const IEnumTfContextsVtbl IEnumTfContexts_Vtbl ={
+    EnumTfContext_QueryInterface,
+    EnumTfContext_AddRef,
+    EnumTfContext_Release,
+
+    EnumTfContext_Clone,
+    EnumTfContext_Next,
+    EnumTfContext_Reset,
+    EnumTfContext_Skip
+};
+
+static HRESULT EnumTfContext_Constructor(DocumentMgr *mgr, IEnumTfContexts **ppOut)
+{
+    EnumTfContext *This;
+
+    This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfContext));
+    if (This == NULL)
+        return E_OUTOFMEMORY;
+
+    This->Vtbl= &IEnumTfContexts_Vtbl;
+    This->refCount = 1;
+    This->docmgr = mgr;
+
+    TRACE("returning %p\n", This);
+    *ppOut = (IEnumTfContexts*)This;
+    return S_OK;
+}
diff --git a/dlls/msctf/tests/inputprocessor.c b/dlls/msctf/tests/inputprocessor.c
index ba43570..9b266ba 100644
--- a/dlls/msctf/tests/inputprocessor.c
+++ b/dlls/msctf/tests/inputprocessor.c
@@ -1113,6 +1113,35 @@ static void test_Activate(void)
     ok(SUCCEEDED(hr),"Failed to Activate text service\n");
 }
 
+
+static void test_EnumContexts(ITfDocumentMgr *dm, ITfContext *search)
+{
+    HRESULT hr;
+    IEnumTfContexts* pEnum;
+    BOOL found = FALSE;
+
+    hr = ITfDocumentMgr_EnumContexts(dm,&pEnum);
+    ok(SUCCEEDED(hr),"EnumContexts failed\n");
+    if (SUCCEEDED(hr))
+    {
+        ULONG fetched;
+        ITfContext *cxt;
+        while (IEnumTfContexts_Next(pEnum, 1, &cxt, &fetched) == S_OK)
+        {
+            if (!search)
+                found = TRUE;
+            else if (search == cxt)
+                found = TRUE;
+            ITfContext_Release(cxt);
+        }
+        IEnumTfContexts_Release(pEnum);
+    }
+    if (search)
+        ok(found,"Did not find proper ITfContext\n");
+    else
+        ok(!found,"Found an ITfContext we should should not have\n");
+}
+
 static inline int check_context_refcount(ITfContext *iface)
 {
     IUnknown_AddRef(iface);
@@ -1183,6 +1212,8 @@ static void test_startSession(void)
     hr = ITfDocumentMgr_CreateContext(g_dm, cid, 0, NULL, &cxt3, &editCookie);
     ok(SUCCEEDED(hr),"CreateContext Failed\n");
 
+    test_EnumContexts(g_dm, NULL);
+
     hr = ITfContext_GetDocumentMgr(cxt,&dmtest);
     ok(hr == S_OK, "ITfContext_GetDocumentMgr failed with %x\n",hr);
     ok(dmtest == g_dm, "Wrong documentmgr\n");
@@ -1199,6 +1230,8 @@ static void test_startSession(void)
     ok(test_OnInitDocumentMgr == SINK_FIRED, "OnInitDocumentMgr sink not fired\n");
     ok(test_ACP_AdviseSink == SINK_FIRED,"TextStoreACP_AdviseSink not fired\n");
 
+    test_EnumContexts(g_dm, cxt);
+
     hr = ITfDocumentMgr_GetTop(g_dm, &cxtTest);
     ok(SUCCEEDED(hr),"GetTop Failed\n");
     ok(cxtTest == cxt, "Wrong context on top\n");
diff --git a/include/msctf.idl b/include/msctf.idl
index ef362e0..6b341d2 100644
--- a/include/msctf.idl
+++ b/include/msctf.idl
@@ -953,3 +953,24 @@ interface ITfCompartmentEventSink : IUnknown
     HRESULT OnChange(
         [in] REFGUID rguid);
 }
+
+[
+  object,
+  uuid(8f1a7ea6-1654-4502-a86e-b2902344d507),
+  pointer_default(unique)
+]
+interface IEnumTfContexts : IUnknown
+{
+    HRESULT Clone(
+        [out] IEnumTfContexts **ppEnum);
+
+    HRESULT Next(
+        [in] ULONG ulCount,
+        [out, size_is(ulCount), length_is(*pcFetched)] ITfContext **rgContext,
+        [out] ULONG *pcFetched);
+
+    HRESULT Reset();
+
+    HRESULT Skip(
+        [in] ULONG ulCount);
+};




More information about the wine-cvs mailing list