msctf: Implement ITfDocumentMgr::EnumContexts.
This commit is contained in:
parent
fac0d945e4
commit
7de0b8299d
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue