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
21 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
31 #include <wine/debug.h>
35 //#include "winuser.h"
36 //#include "shlwapi.h"
37 //#include "winerror.h"
40 //#include "wine/unicode.h"
43 #include "msctf_internal.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(msctf
);
47 typedef struct tagDocumentMgr
{
48 ITfDocumentMgr ITfDocumentMgr_iface
;
49 ITfSource ITfSource_iface
;
53 ITfCompartmentMgr
*CompartmentMgr
;
55 ITfContext
* contextStack
[2]; /* limit of 2 contexts */
56 ITfThreadMgrEventSink
* ThreadMgrSink
;
59 typedef struct tagEnumTfContext
{
60 IEnumTfContexts IEnumTfContexts_iface
;
67 static HRESULT
EnumTfContext_Constructor(DocumentMgr
* mgr
, IEnumTfContexts
**ppOut
);
69 static inline DocumentMgr
*impl_from_ITfDocumentMgr(ITfDocumentMgr
*iface
)
71 return CONTAINING_RECORD(iface
, DocumentMgr
, ITfDocumentMgr_iface
);
74 static inline DocumentMgr
*impl_from_ITfSource(ITfSource
*iface
)
76 return CONTAINING_RECORD(iface
, DocumentMgr
, ITfSource_iface
);
79 static inline EnumTfContext
*impl_from_IEnumTfContexts(IEnumTfContexts
*iface
)\
81 return CONTAINING_RECORD(iface
, EnumTfContext
, IEnumTfContexts_iface
);
84 static void DocumentMgr_Destructor(DocumentMgr
*This
)
87 TRACE("destroying %p\n", This
);
90 ThreadMgr_OnDocumentMgrDestruction(tm
, &This
->ITfDocumentMgr_iface
);
92 if (This
->contextStack
[0])
93 ITfContext_Release(This
->contextStack
[0]);
94 if (This
->contextStack
[1])
95 ITfContext_Release(This
->contextStack
[1]);
96 CompartmentMgr_Destructor(This
->CompartmentMgr
);
97 HeapFree(GetProcessHeap(),0,This
);
100 static HRESULT WINAPI
DocumentMgr_QueryInterface(ITfDocumentMgr
*iface
, REFIID iid
, LPVOID
*ppvOut
)
102 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
105 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfDocumentMgr
))
109 else if (IsEqualIID(iid
, &IID_ITfSource
))
111 *ppvOut
= &This
->ITfSource_iface
;
113 else if (IsEqualIID(iid
, &IID_ITfCompartmentMgr
))
115 *ppvOut
= This
->CompartmentMgr
;
120 IUnknown_AddRef(iface
);
124 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
125 return E_NOINTERFACE
;
128 static ULONG WINAPI
DocumentMgr_AddRef(ITfDocumentMgr
*iface
)
130 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
131 return InterlockedIncrement(&This
->refCount
);
134 static ULONG WINAPI
DocumentMgr_Release(ITfDocumentMgr
*iface
)
136 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
139 ret
= InterlockedDecrement(&This
->refCount
);
141 DocumentMgr_Destructor(This
);
145 /*****************************************************
146 * ITfDocumentMgr functions
147 *****************************************************/
148 static HRESULT WINAPI
DocumentMgr_CreateContext(ITfDocumentMgr
*iface
,
150 DWORD dwFlags
, IUnknown
*punk
, ITfContext
**ppic
,
151 TfEditCookie
*pecTextStore
)
153 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
154 TRACE("(%p) 0x%x 0x%x %p %p %p\n",This
,tidOwner
,dwFlags
,punk
,ppic
,pecTextStore
);
155 return Context_Constructor(tidOwner
, punk
, iface
, ppic
, pecTextStore
);
158 static HRESULT WINAPI
DocumentMgr_Push(ITfDocumentMgr
*iface
, ITfContext
*pic
)
160 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
163 TRACE("(%p) %p\n",This
,pic
);
165 if (This
->contextStack
[1]) /* FUll */
166 return TF_E_STACKFULL
;
168 if (!pic
|| FAILED(IUnknown_QueryInterface(pic
,&IID_ITfContext
,(LPVOID
*) &check
)))
171 if (This
->contextStack
[0] == NULL
)
172 ITfThreadMgrEventSink_OnInitDocumentMgr(This
->ThreadMgrSink
,iface
);
174 This
->contextStack
[1] = This
->contextStack
[0];
175 This
->contextStack
[0] = check
;
177 Context_Initialize(check
, iface
);
178 ITfThreadMgrEventSink_OnPushContext(This
->ThreadMgrSink
,check
);
183 static HRESULT WINAPI
DocumentMgr_Pop(ITfDocumentMgr
*iface
, DWORD dwFlags
)
185 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
186 TRACE("(%p) 0x%x\n",This
,dwFlags
);
188 if (dwFlags
== TF_POPF_ALL
)
190 if (This
->contextStack
[0])
192 ITfThreadMgrEventSink_OnPopContext(This
->ThreadMgrSink
,This
->contextStack
[0]);
193 ITfContext_Release(This
->contextStack
[0]);
194 Context_Uninitialize(This
->contextStack
[0]);
196 if (This
->contextStack
[1])
198 ITfThreadMgrEventSink_OnPopContext(This
->ThreadMgrSink
,This
->contextStack
[1]);
199 ITfContext_Release(This
->contextStack
[1]);
200 Context_Uninitialize(This
->contextStack
[1]);
202 This
->contextStack
[0] = This
->contextStack
[1] = NULL
;
203 ITfThreadMgrEventSink_OnUninitDocumentMgr(This
->ThreadMgrSink
, iface
);
210 if (This
->contextStack
[1] == NULL
) /* Cannot pop last context */
213 ITfThreadMgrEventSink_OnPopContext(This
->ThreadMgrSink
,This
->contextStack
[0]);
214 ITfContext_Release(This
->contextStack
[0]);
215 Context_Uninitialize(This
->contextStack
[0]);
216 This
->contextStack
[0] = This
->contextStack
[1];
217 This
->contextStack
[1] = NULL
;
219 if (This
->contextStack
[0] == NULL
)
220 ITfThreadMgrEventSink_OnUninitDocumentMgr(This
->ThreadMgrSink
, iface
);
225 static HRESULT WINAPI
DocumentMgr_GetTop(ITfDocumentMgr
*iface
, ITfContext
**ppic
)
227 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
228 TRACE("(%p)\n",This
);
232 if (This
->contextStack
[0])
233 ITfContext_AddRef(This
->contextStack
[0]);
235 *ppic
= This
->contextStack
[0];
240 static HRESULT WINAPI
DocumentMgr_GetBase(ITfDocumentMgr
*iface
, ITfContext
**ppic
)
242 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
245 TRACE("(%p)\n",This
);
249 if (This
->contextStack
[1])
250 tgt
= This
->contextStack
[1];
252 tgt
= This
->contextStack
[0];
255 ITfContext_AddRef(tgt
);
262 static HRESULT WINAPI
DocumentMgr_EnumContexts(ITfDocumentMgr
*iface
, IEnumTfContexts
**ppEnum
)
264 DocumentMgr
*This
= impl_from_ITfDocumentMgr(iface
);
265 TRACE("(%p) %p\n",This
,ppEnum
);
266 return EnumTfContext_Constructor(This
, ppEnum
);
269 static const ITfDocumentMgrVtbl DocumentMgr_DocumentMgrVtbl
=
271 DocumentMgr_QueryInterface
,
275 DocumentMgr_CreateContext
,
280 DocumentMgr_EnumContexts
284 static HRESULT WINAPI
Source_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
286 DocumentMgr
*This
= impl_from_ITfSource(iface
);
287 return DocumentMgr_QueryInterface(&This
->ITfDocumentMgr_iface
, iid
, *ppvOut
);
290 static ULONG WINAPI
Source_AddRef(ITfSource
*iface
)
292 DocumentMgr
*This
= impl_from_ITfSource(iface
);
293 return DocumentMgr_AddRef(&This
->ITfDocumentMgr_iface
);
296 static ULONG WINAPI
Source_Release(ITfSource
*iface
)
298 DocumentMgr
*This
= impl_from_ITfSource(iface
);
299 return DocumentMgr_Release(&This
->ITfDocumentMgr_iface
);
302 /*****************************************************
303 * ITfSource functions
304 *****************************************************/
305 static HRESULT WINAPI
DocumentMgrSource_AdviseSink(ITfSource
*iface
,
306 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
308 DocumentMgr
*This
= impl_from_ITfSource(iface
);
309 FIXME("STUB:(%p)\n",This
);
313 static HRESULT WINAPI
DocumentMgrSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
315 DocumentMgr
*This
= impl_from_ITfSource(iface
);
316 FIXME("STUB:(%p)\n",This
);
320 static const ITfSourceVtbl DocumentMgr_SourceVtbl
=
322 Source_QueryInterface
,
326 DocumentMgrSource_AdviseSink
,
327 DocumentMgrSource_UnadviseSink
,
330 HRESULT
DocumentMgr_Constructor(ITfThreadMgrEventSink
*ThreadMgrSink
, ITfDocumentMgr
**ppOut
)
334 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DocumentMgr
));
336 return E_OUTOFMEMORY
;
338 This
->ITfDocumentMgr_iface
.lpVtbl
= &DocumentMgr_DocumentMgrVtbl
;
339 This
->ITfSource_iface
.lpVtbl
= &DocumentMgr_SourceVtbl
;
341 This
->ThreadMgrSink
= ThreadMgrSink
;
343 CompartmentMgr_Constructor((IUnknown
*)This
, &IID_IUnknown
, (IUnknown
**)&This
->CompartmentMgr
);
345 TRACE("returning %p\n", This
);
346 *ppOut
= &This
->ITfDocumentMgr_iface
;
350 /**************************************************
351 * IEnumTfContexts implementation
352 **************************************************/
353 static void EnumTfContext_Destructor(EnumTfContext
*This
)
355 TRACE("destroying %p\n", This
);
356 HeapFree(GetProcessHeap(),0,This
);
359 static HRESULT WINAPI
EnumTfContext_QueryInterface(IEnumTfContexts
*iface
, REFIID iid
, LPVOID
*ppvOut
)
361 EnumTfContext
*This
= impl_from_IEnumTfContexts(iface
);
364 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumTfContexts
))
371 IUnknown_AddRef(iface
);
375 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
376 return E_NOINTERFACE
;
379 static ULONG WINAPI
EnumTfContext_AddRef(IEnumTfContexts
*iface
)
381 EnumTfContext
*This
= impl_from_IEnumTfContexts(iface
);
382 return InterlockedIncrement(&This
->refCount
);
385 static ULONG WINAPI
EnumTfContext_Release(IEnumTfContexts
*iface
)
387 EnumTfContext
*This
= impl_from_IEnumTfContexts(iface
);
390 ret
= InterlockedDecrement(&This
->refCount
);
392 EnumTfContext_Destructor(This
);
396 static HRESULT WINAPI
EnumTfContext_Next(IEnumTfContexts
*iface
,
397 ULONG ulCount
, ITfContext
**rgContext
, ULONG
*pcFetched
)
399 EnumTfContext
*This
= impl_from_IEnumTfContexts(iface
);
402 TRACE("(%p)\n",This
);
404 if (rgContext
== NULL
) return E_POINTER
;
406 while (fetched
< ulCount
)
411 if (!This
->docmgr
->contextStack
[This
->index
])
414 *rgContext
= This
->docmgr
->contextStack
[This
->index
];
415 ITfContext_AddRef(*rgContext
);
422 if (pcFetched
) *pcFetched
= fetched
;
423 return fetched
== ulCount
? S_OK
: S_FALSE
;
426 static HRESULT WINAPI
EnumTfContext_Skip( IEnumTfContexts
* iface
, ULONG celt
)
428 EnumTfContext
*This
= impl_from_IEnumTfContexts(iface
);
429 TRACE("(%p)\n",This
);
434 static HRESULT WINAPI
EnumTfContext_Reset( IEnumTfContexts
* iface
)
436 EnumTfContext
*This
= impl_from_IEnumTfContexts(iface
);
437 TRACE("(%p)\n",This
);
442 static HRESULT WINAPI
EnumTfContext_Clone( IEnumTfContexts
*iface
,
443 IEnumTfContexts
**ppenum
)
445 EnumTfContext
*This
= impl_from_IEnumTfContexts(iface
);
448 TRACE("(%p)\n",This
);
450 if (ppenum
== NULL
) return E_POINTER
;
452 res
= EnumTfContext_Constructor(This
->docmgr
, ppenum
);
455 EnumTfContext
*new_This
= impl_from_IEnumTfContexts(*ppenum
);
456 new_This
->index
= This
->index
;
461 static const IEnumTfContextsVtbl IEnumTfContexts_Vtbl
={
462 EnumTfContext_QueryInterface
,
463 EnumTfContext_AddRef
,
464 EnumTfContext_Release
,
472 static HRESULT
EnumTfContext_Constructor(DocumentMgr
*mgr
, IEnumTfContexts
**ppOut
)
476 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(EnumTfContext
));
478 return E_OUTOFMEMORY
;
480 This
->IEnumTfContexts_iface
.lpVtbl
= &IEnumTfContexts_Vtbl
;
484 TRACE("returning %p\n", This
);
485 *ppOut
= &This
->IEnumTfContexts_iface
;