2 * ITfDocumentMgr implementation
4 * Copyright 2009 Aric Stewart, CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
36 #include "wine/unicode.h"
39 #include "msctf_internal.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msctf
);
43 typedef struct tagDocumentMgr
{
44 const ITfDocumentMgrVtbl
*DocumentMgrVtbl
;
45 const ITfSourceVtbl
*SourceVtbl
;
49 ITfCompartmentMgr
*CompartmentMgr
;
51 ITfContext
* contextStack
[2]; /* limit of 2 contexts */
52 ITfThreadMgrEventSink
* ThreadMgrSink
;
55 typedef struct tagEnumTfContext
{
56 const IEnumTfContextsVtbl
*Vtbl
;
63 static HRESULT
EnumTfContext_Constructor(DocumentMgr
* mgr
, IEnumTfContexts
**ppOut
);
65 static inline DocumentMgr
*impl_from_ITfSourceVtbl(ITfSource
*iface
)
67 return (DocumentMgr
*)((char *)iface
- FIELD_OFFSET(DocumentMgr
,SourceVtbl
));
70 static void DocumentMgr_Destructor(DocumentMgr
*This
)
72 TRACE("destroying %p\n", This
);
73 if (This
->contextStack
[0])
74 ITfContext_Release(This
->contextStack
[0]);
75 if (This
->contextStack
[1])
76 ITfContext_Release(This
->contextStack
[1]);
77 CompartmentMgr_Destructor(This
->CompartmentMgr
);
78 HeapFree(GetProcessHeap(),0,This
);
81 static HRESULT WINAPI
DocumentMgr_QueryInterface(ITfDocumentMgr
*iface
, REFIID iid
, LPVOID
*ppvOut
)
83 DocumentMgr
*This
= (DocumentMgr
*)iface
;
86 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfDocumentMgr
))
90 else if (IsEqualIID(iid
, &IID_ITfSource
))
92 *ppvOut
= &This
->SourceVtbl
;
94 else if (IsEqualIID(iid
, &IID_ITfCompartmentMgr
))
96 *ppvOut
= This
->CompartmentMgr
;
101 IUnknown_AddRef(iface
);
105 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
106 return E_NOINTERFACE
;
109 static ULONG WINAPI
DocumentMgr_AddRef(ITfDocumentMgr
*iface
)
111 DocumentMgr
*This
= (DocumentMgr
*)iface
;
112 return InterlockedIncrement(&This
->refCount
);
115 static ULONG WINAPI
DocumentMgr_Release(ITfDocumentMgr
*iface
)
117 DocumentMgr
*This
= (DocumentMgr
*)iface
;
120 ret
= InterlockedDecrement(&This
->refCount
);
122 DocumentMgr_Destructor(This
);
126 /*****************************************************
127 * ITfDocumentMgr functions
128 *****************************************************/
129 static HRESULT WINAPI
DocumentMgr_CreateContext(ITfDocumentMgr
*iface
,
131 DWORD dwFlags
, IUnknown
*punk
, ITfContext
**ppic
,
132 TfEditCookie
*pecTextStore
)
134 DocumentMgr
*This
= (DocumentMgr
*)iface
;
135 TRACE("(%p) 0x%x 0x%x %p %p %p\n",This
,tidOwner
,dwFlags
,punk
,ppic
,pecTextStore
);
136 return Context_Constructor(tidOwner
, punk
, iface
, ppic
, pecTextStore
);
139 static HRESULT WINAPI
DocumentMgr_Push(ITfDocumentMgr
*iface
, ITfContext
*pic
)
141 DocumentMgr
*This
= (DocumentMgr
*)iface
;
144 TRACE("(%p) %p\n",This
,pic
);
146 if (This
->contextStack
[1]) /* FUll */
147 return TF_E_STACKFULL
;
149 if (!pic
|| FAILED(IUnknown_QueryInterface(pic
,&IID_ITfContext
,(LPVOID
*) &check
)))
152 if (This
->contextStack
[0] == NULL
)
153 ITfThreadMgrEventSink_OnInitDocumentMgr(This
->ThreadMgrSink
,iface
);
155 This
->contextStack
[1] = This
->contextStack
[0];
156 This
->contextStack
[0] = check
;
158 Context_Initialize(check
, iface
);
159 ITfThreadMgrEventSink_OnPushContext(This
->ThreadMgrSink
,check
);
164 static HRESULT WINAPI
DocumentMgr_Pop(ITfDocumentMgr
*iface
, DWORD dwFlags
)
166 DocumentMgr
*This
= (DocumentMgr
*)iface
;
167 TRACE("(%p) 0x%x\n",This
,dwFlags
);
169 if (dwFlags
== TF_POPF_ALL
)
171 if (This
->contextStack
[0])
173 ITfThreadMgrEventSink_OnPopContext(This
->ThreadMgrSink
,This
->contextStack
[0]);
174 ITfContext_Release(This
->contextStack
[0]);
175 Context_Uninitialize(This
->contextStack
[0]);
177 if (This
->contextStack
[1])
179 ITfThreadMgrEventSink_OnPopContext(This
->ThreadMgrSink
,This
->contextStack
[1]);
180 ITfContext_Release(This
->contextStack
[1]);
181 Context_Uninitialize(This
->contextStack
[1]);
183 This
->contextStack
[0] = This
->contextStack
[1] = NULL
;
184 ITfThreadMgrEventSink_OnUninitDocumentMgr(This
->ThreadMgrSink
, iface
);
191 if (This
->contextStack
[1] == NULL
) /* Cannot pop last context */
194 ITfThreadMgrEventSink_OnPopContext(This
->ThreadMgrSink
,This
->contextStack
[0]);
195 ITfContext_Release(This
->contextStack
[0]);
196 Context_Uninitialize(This
->contextStack
[0]);
197 This
->contextStack
[0] = This
->contextStack
[1];
198 This
->contextStack
[1] = NULL
;
200 if (This
->contextStack
[0] == NULL
)
201 ITfThreadMgrEventSink_OnUninitDocumentMgr(This
->ThreadMgrSink
, iface
);
206 static HRESULT WINAPI
DocumentMgr_GetTop(ITfDocumentMgr
*iface
, ITfContext
**ppic
)
208 DocumentMgr
*This
= (DocumentMgr
*)iface
;
209 TRACE("(%p)\n",This
);
213 if (This
->contextStack
[0])
214 ITfContext_AddRef(This
->contextStack
[0]);
216 *ppic
= This
->contextStack
[0];
221 static HRESULT WINAPI
DocumentMgr_GetBase(ITfDocumentMgr
*iface
, ITfContext
**ppic
)
223 DocumentMgr
*This
= (DocumentMgr
*)iface
;
226 TRACE("(%p)\n",This
);
230 if (This
->contextStack
[1])
231 tgt
= This
->contextStack
[1];
233 tgt
= This
->contextStack
[0];
236 ITfContext_AddRef(tgt
);
243 static HRESULT WINAPI
DocumentMgr_EnumContexts(ITfDocumentMgr
*iface
, IEnumTfContexts
**ppEnum
)
245 DocumentMgr
*This
= (DocumentMgr
*)iface
;
246 TRACE("(%p) %p\n",This
,ppEnum
);
247 return EnumTfContext_Constructor(This
, ppEnum
);
250 static const ITfDocumentMgrVtbl DocumentMgr_DocumentMgrVtbl
=
252 DocumentMgr_QueryInterface
,
256 DocumentMgr_CreateContext
,
261 DocumentMgr_EnumContexts
265 static HRESULT WINAPI
Source_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
267 DocumentMgr
*This
= impl_from_ITfSourceVtbl(iface
);
268 return DocumentMgr_QueryInterface((ITfDocumentMgr
*)This
, iid
, *ppvOut
);
271 static ULONG WINAPI
Source_AddRef(ITfSource
*iface
)
273 DocumentMgr
*This
= impl_from_ITfSourceVtbl(iface
);
274 return DocumentMgr_AddRef((ITfDocumentMgr
*)This
);
277 static ULONG WINAPI
Source_Release(ITfSource
*iface
)
279 DocumentMgr
*This
= impl_from_ITfSourceVtbl(iface
);
280 return DocumentMgr_Release((ITfDocumentMgr
*)This
);
283 /*****************************************************
284 * ITfSource functions
285 *****************************************************/
286 static WINAPI HRESULT
DocumentMgrSource_AdviseSink(ITfSource
*iface
,
287 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
289 DocumentMgr
*This
= impl_from_ITfSourceVtbl(iface
);
290 FIXME("STUB:(%p)\n",This
);
294 static WINAPI HRESULT
DocumentMgrSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
296 DocumentMgr
*This
= impl_from_ITfSourceVtbl(iface
);
297 FIXME("STUB:(%p)\n",This
);
301 static const ITfSourceVtbl DocumentMgr_SourceVtbl
=
303 Source_QueryInterface
,
307 DocumentMgrSource_AdviseSink
,
308 DocumentMgrSource_UnadviseSink
,
311 HRESULT
DocumentMgr_Constructor(ITfThreadMgrEventSink
*ThreadMgrSink
, ITfDocumentMgr
**ppOut
)
315 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DocumentMgr
));
317 return E_OUTOFMEMORY
;
319 This
->DocumentMgrVtbl
= &DocumentMgr_DocumentMgrVtbl
;
320 This
->SourceVtbl
= &DocumentMgr_SourceVtbl
;
322 This
->ThreadMgrSink
= ThreadMgrSink
;
324 CompartmentMgr_Constructor((IUnknown
*)This
, &IID_IUnknown
, (IUnknown
**)&This
->CompartmentMgr
);
326 TRACE("returning %p\n", This
);
327 *ppOut
= (ITfDocumentMgr
*)This
;
331 /**************************************************
332 * IEnumTfContexts implementaion
333 **************************************************/
334 static void EnumTfContext_Destructor(EnumTfContext
*This
)
336 TRACE("destroying %p\n", This
);
337 HeapFree(GetProcessHeap(),0,This
);
340 static HRESULT WINAPI
EnumTfContext_QueryInterface(IEnumTfContexts
*iface
, REFIID iid
, LPVOID
*ppvOut
)
342 EnumTfContext
*This
= (EnumTfContext
*)iface
;
345 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumTfContexts
))
352 IUnknown_AddRef(iface
);
356 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
357 return E_NOINTERFACE
;
360 static ULONG WINAPI
EnumTfContext_AddRef(IEnumTfContexts
*iface
)
362 EnumTfContext
*This
= (EnumTfContext
*)iface
;
363 return InterlockedIncrement(&This
->refCount
);
366 static ULONG WINAPI
EnumTfContext_Release(IEnumTfContexts
*iface
)
368 EnumTfContext
*This
= (EnumTfContext
*)iface
;
371 ret
= InterlockedDecrement(&This
->refCount
);
373 EnumTfContext_Destructor(This
);
377 static HRESULT WINAPI
EnumTfContext_Next(IEnumTfContexts
*iface
,
378 ULONG ulCount
, ITfContext
**rgContext
, ULONG
*pcFetched
)
380 EnumTfContext
*This
= (EnumTfContext
*)iface
;
383 TRACE("(%p)\n",This
);
385 if (rgContext
== NULL
) return E_POINTER
;
387 while (fetched
< ulCount
)
392 if (!This
->docmgr
->contextStack
[This
->index
])
395 *rgContext
= This
->docmgr
->contextStack
[This
->index
];
396 ITfContext_AddRef(*rgContext
);
403 if (pcFetched
) *pcFetched
= fetched
;
404 return fetched
== ulCount
? S_OK
: S_FALSE
;
407 static HRESULT WINAPI
EnumTfContext_Skip( IEnumTfContexts
* iface
, ULONG celt
)
409 EnumTfContext
*This
= (EnumTfContext
*)iface
;
410 TRACE("(%p)\n",This
);
415 static HRESULT WINAPI
EnumTfContext_Reset( IEnumTfContexts
* iface
)
417 EnumTfContext
*This
= (EnumTfContext
*)iface
;
418 TRACE("(%p)\n",This
);
423 static HRESULT WINAPI
EnumTfContext_Clone( IEnumTfContexts
*iface
,
424 IEnumTfContexts
**ppenum
)
426 EnumTfContext
*This
= (EnumTfContext
*)iface
;
429 TRACE("(%p)\n",This
);
431 if (ppenum
== NULL
) return E_POINTER
;
433 res
= EnumTfContext_Constructor(This
->docmgr
, ppenum
);
436 EnumTfContext
*new_This
= (EnumTfContext
*)*ppenum
;
437 new_This
->index
= This
->index
;
442 static const IEnumTfContextsVtbl IEnumTfContexts_Vtbl
={
443 EnumTfContext_QueryInterface
,
444 EnumTfContext_AddRef
,
445 EnumTfContext_Release
,
453 static HRESULT
EnumTfContext_Constructor(DocumentMgr
*mgr
, IEnumTfContexts
**ppOut
)
457 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(EnumTfContext
));
459 return E_OUTOFMEMORY
;
461 This
->Vtbl
= &IEnumTfContexts_Vtbl
;
465 TRACE("returning %p\n", This
);
466 *ppOut
= (IEnumTfContexts
*)This
;