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