xref: /reactos/dll/win32/msctf/context.c (revision ac50127e)
1 /*
2  *  ITfContext implementation
3  *
4  *  Copyright 2009 Aric Stewart, CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include <stdarg.h>
22 
23 #define COBJMACROS
24 
25 #include "wine/debug.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winuser.h"
30 #include "shlwapi.h"
31 #include "winerror.h"
32 #include "objbase.h"
33 #include "olectl.h"
34 
35 #include "msctf.h"
36 #include "msctf_internal.h"
37 
38 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
39 
40 typedef struct tagContext {
41     ITfContext ITfContext_iface;
42     ITfSource ITfSource_iface;
43     /* const ITfContextCompositionVtbl *ContextCompositionVtbl; */
44     ITfContextOwnerCompositionServices ITfContextOwnerCompositionServices_iface;
45     /* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */
46     ITfInsertAtSelection ITfInsertAtSelection_iface;
47     /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */
48     /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */
49     ITfSourceSingle ITfSourceSingle_iface;
50     ITextStoreACPSink ITextStoreACPSink_iface;
51     ITextStoreACPServices ITextStoreACPServices_iface;
52     LONG refCount;
53     BOOL connected;
54 
55     /* Aggregation */
56     ITfCompartmentMgr  *CompartmentMgr;
57 
58     TfClientId tidOwner;
59     TfEditCookie defaultCookie;
60     TS_STATUS documentStatus;
61     ITfDocumentMgr *manager;
62 
63     ITextStoreACP   *pITextStoreACP;
64     ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink;
65 
66     ITfEditSession* currentEditSession;
67 
68     /* kept as separate lists to reduce unnecessary iterations */
69     struct list     pContextKeyEventSink;
70     struct list     pEditTransactionSink;
71     struct list     pStatusSink;
72     struct list     pTextEditSink;
73     struct list     pTextLayoutSink;
74 
75 } Context;
76 
77 typedef struct tagEditCookie {
78     DWORD lockType;
79     Context *pOwningContext;
80 } EditCookie;
81 
impl_from_ITfContext(ITfContext * iface)82 static inline Context *impl_from_ITfContext(ITfContext *iface)
83 {
84     return CONTAINING_RECORD(iface, Context, ITfContext_iface);
85 }
86 
impl_from_ITfSource(ITfSource * iface)87 static inline Context *impl_from_ITfSource(ITfSource *iface)
88 {
89     return CONTAINING_RECORD(iface, Context, ITfSource_iface);
90 }
91 
impl_from_ITfContextOwnerCompositionServices(ITfContextOwnerCompositionServices * iface)92 static inline Context *impl_from_ITfContextOwnerCompositionServices(ITfContextOwnerCompositionServices *iface)
93 {
94     return CONTAINING_RECORD(iface, Context, ITfContextOwnerCompositionServices_iface);
95 }
96 
impl_from_ITfInsertAtSelection(ITfInsertAtSelection * iface)97 static inline Context *impl_from_ITfInsertAtSelection(ITfInsertAtSelection *iface)
98 {
99     return CONTAINING_RECORD(iface, Context, ITfInsertAtSelection_iface);
100 }
101 
impl_from_ITfSourceSingle(ITfSourceSingle * iface)102 static inline Context *impl_from_ITfSourceSingle(ITfSourceSingle* iface)
103 {
104     return CONTAINING_RECORD(iface, Context, ITfSourceSingle_iface);
105 }
106 
impl_from_ITextStoreACPSink(ITextStoreACPSink * iface)107 static inline Context *impl_from_ITextStoreACPSink(ITextStoreACPSink *iface)
108 {
109     return CONTAINING_RECORD(iface, Context, ITextStoreACPSink_iface);
110 }
111 
impl_from_ITextStoreACPServices(ITextStoreACPServices * iface)112 static inline Context *impl_from_ITextStoreACPServices(ITextStoreACPServices *iface)
113 {
114     return CONTAINING_RECORD(iface, Context, ITextStoreACPServices_iface);
115 }
116 
Context_Destructor(Context * This)117 static void Context_Destructor(Context *This)
118 {
119     EditCookie *cookie;
120     TRACE("destroying %p\n", This);
121 
122     if (This->pITextStoreACP)
123         ITextStoreACP_Release(This->pITextStoreACP);
124 
125     if (This->pITfContextOwnerCompositionSink)
126         ITfContextOwnerCompositionSink_Release(This->pITfContextOwnerCompositionSink);
127 
128     if (This->defaultCookie)
129     {
130         cookie = remove_Cookie(This->defaultCookie);
131         HeapFree(GetProcessHeap(),0,cookie);
132         This->defaultCookie = 0;
133     }
134 
135     free_sinks(&This->pContextKeyEventSink);
136     free_sinks(&This->pEditTransactionSink);
137     free_sinks(&This->pStatusSink);
138     free_sinks(&This->pTextEditSink);
139     free_sinks(&This->pTextLayoutSink);
140 
141     CompartmentMgr_Destructor(This->CompartmentMgr);
142     HeapFree(GetProcessHeap(),0,This);
143 }
144 
Context_QueryInterface(ITfContext * iface,REFIID iid,LPVOID * ppvOut)145 static HRESULT WINAPI Context_QueryInterface(ITfContext *iface, REFIID iid, LPVOID *ppvOut)
146 {
147     Context *This = impl_from_ITfContext(iface);
148     *ppvOut = NULL;
149 
150     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfContext))
151     {
152         *ppvOut = &This->ITfContext_iface;
153     }
154     else if (IsEqualIID(iid, &IID_ITfSource))
155     {
156         *ppvOut = &This->ITfSource_iface;
157     }
158     else if (IsEqualIID(iid, &IID_ITfContextOwnerCompositionServices))
159     {
160         *ppvOut = &This->ITfContextOwnerCompositionServices_iface;
161     }
162     else if (IsEqualIID(iid, &IID_ITfInsertAtSelection))
163     {
164         *ppvOut = &This->ITfInsertAtSelection_iface;
165     }
166     else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
167     {
168         *ppvOut = This->CompartmentMgr;
169     }
170     else if (IsEqualIID(iid, &IID_ITfSourceSingle))
171     {
172         *ppvOut = &This->ITfSourceSingle_iface;
173     }
174 
175     if (*ppvOut)
176     {
177         ITfContext_AddRef(iface);
178         return S_OK;
179     }
180 
181     WARN("unsupported interface: %s\n", debugstr_guid(iid));
182     return E_NOINTERFACE;
183 }
184 
Context_AddRef(ITfContext * iface)185 static ULONG WINAPI Context_AddRef(ITfContext *iface)
186 {
187     Context *This = impl_from_ITfContext(iface);
188     return InterlockedIncrement(&This->refCount);
189 }
190 
Context_Release(ITfContext * iface)191 static ULONG WINAPI Context_Release(ITfContext *iface)
192 {
193     Context *This = impl_from_ITfContext(iface);
194     ULONG ret;
195 
196     ret = InterlockedDecrement(&This->refCount);
197     if (ret == 0)
198         Context_Destructor(This);
199     return ret;
200 }
201 
202 /*****************************************************
203  * ITfContext functions
204  *****************************************************/
Context_RequestEditSession(ITfContext * iface,TfClientId tid,ITfEditSession * pes,DWORD dwFlags,HRESULT * phrSession)205 static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface,
206         TfClientId tid, ITfEditSession *pes, DWORD dwFlags,
207         HRESULT *phrSession)
208 {
209     Context *This = impl_from_ITfContext(iface);
210     HRESULT hr;
211     DWORD  dwLockFlags = 0x0;
212 
213     TRACE("(%p) %i %p %x %p\n",This, tid, pes, dwFlags, phrSession);
214 
215     if (!(dwFlags & TF_ES_READ) && !(dwFlags & TF_ES_READWRITE))
216     {
217         *phrSession = E_FAIL;
218         return E_INVALIDARG;
219     }
220 
221     if (!This->pITextStoreACP)
222     {
223         FIXME("No ITextStoreACP available\n");
224         *phrSession = E_FAIL;
225         return E_FAIL;
226     }
227 
228     if (!(dwFlags & TF_ES_ASYNC))
229         dwLockFlags |= TS_LF_SYNC;
230 
231     if ((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE)
232         dwLockFlags |= TS_LF_READWRITE;
233     else if (dwFlags & TF_ES_READ)
234         dwLockFlags |= TS_LF_READ;
235 
236     if (!This->documentStatus.dwDynamicFlags)
237         ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
238 
239     if (((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) && (This->documentStatus.dwDynamicFlags & TS_SD_READONLY))
240     {
241         *phrSession = TS_E_READONLY;
242         return S_OK;
243     }
244 
245     if (FAILED (ITfEditSession_QueryInterface(pes, &IID_ITfEditSession, (LPVOID*)&This->currentEditSession)))
246     {
247         *phrSession = E_FAIL;
248         return E_INVALIDARG;
249     }
250 
251     hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession);
252 
253     return hr;
254 }
255 
Context_InWriteSession(ITfContext * iface,TfClientId tid,BOOL * pfWriteSession)256 static HRESULT WINAPI Context_InWriteSession (ITfContext *iface,
257          TfClientId tid,
258          BOOL *pfWriteSession)
259 {
260     Context *This = impl_from_ITfContext(iface);
261     FIXME("STUB:(%p)\n",This);
262     return E_NOTIMPL;
263 }
264 
Context_GetSelection(ITfContext * iface,TfEditCookie ec,ULONG ulIndex,ULONG ulCount,TF_SELECTION * pSelection,ULONG * pcFetched)265 static HRESULT WINAPI Context_GetSelection (ITfContext *iface,
266         TfEditCookie ec, ULONG ulIndex, ULONG ulCount,
267         TF_SELECTION *pSelection, ULONG *pcFetched)
268 {
269     Context *This = impl_from_ITfContext(iface);
270     EditCookie *cookie;
271     ULONG count, i;
272     ULONG totalFetched = 0;
273     HRESULT hr = S_OK;
274 
275     if (!pSelection || !pcFetched)
276         return E_INVALIDARG;
277 
278     *pcFetched = 0;
279 
280     if (!This->connected)
281         return TF_E_DISCONNECTED;
282 
283     if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
284         return TF_E_NOLOCK;
285 
286     if (!This->pITextStoreACP)
287     {
288         FIXME("Context does not have a ITextStoreACP\n");
289         return E_NOTIMPL;
290     }
291 
292     cookie = get_Cookie_data(ec);
293 
294     if (ulIndex == TF_DEFAULT_SELECTION)
295         count = 1;
296     else
297         count = ulCount;
298 
299     for (i = 0; i < count; i++)
300     {
301         DWORD fetched;
302         TS_SELECTION_ACP acps;
303 
304         hr = ITextStoreACP_GetSelection(This->pITextStoreACP, ulIndex + i,
305                 1, &acps, &fetched);
306 
307         if (hr == TS_E_NOLOCK)
308             return TF_E_NOLOCK;
309         else if (SUCCEEDED(hr))
310         {
311             pSelection[totalFetched].style.ase = acps.style.ase;
312             pSelection[totalFetched].style.fInterimChar = acps.style.fInterimChar;
313             Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, acps.acpStart, acps.acpEnd, &pSelection[totalFetched].range);
314             totalFetched ++;
315         }
316         else
317             break;
318     }
319 
320     *pcFetched = totalFetched;
321 
322     return hr;
323 }
324 
Context_SetSelection(ITfContext * iface,TfEditCookie ec,ULONG ulCount,const TF_SELECTION * pSelection)325 static HRESULT WINAPI Context_SetSelection (ITfContext *iface,
326         TfEditCookie ec, ULONG ulCount, const TF_SELECTION *pSelection)
327 {
328     Context *This = impl_from_ITfContext(iface);
329     TS_SELECTION_ACP *acp;
330     ULONG i;
331     HRESULT hr;
332 
333     TRACE("(%p) %i %i %p\n",This,ec,ulCount,pSelection);
334 
335     if (!This->pITextStoreACP)
336     {
337         FIXME("Context does not have a ITextStoreACP\n");
338         return E_NOTIMPL;
339     }
340 
341     if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
342         return TF_E_NOLOCK;
343 
344     acp = HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP) * ulCount);
345     if (!acp)
346         return E_OUTOFMEMORY;
347 
348     for (i = 0; i < ulCount; i++)
349         if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection[i], &acp[i])))
350         {
351             TRACE("Selection Conversion Failed\n");
352             HeapFree(GetProcessHeap(), 0 , acp);
353             return E_FAIL;
354         }
355 
356     hr = ITextStoreACP_SetSelection(This->pITextStoreACP, ulCount, acp);
357 
358     HeapFree(GetProcessHeap(), 0, acp);
359 
360     return hr;
361 }
362 
Context_GetStart(ITfContext * iface,TfEditCookie ec,ITfRange ** ppStart)363 static HRESULT WINAPI Context_GetStart (ITfContext *iface,
364         TfEditCookie ec, ITfRange **ppStart)
365 {
366     Context *This = impl_from_ITfContext(iface);
367     EditCookie *cookie;
368     TRACE("(%p) %i %p\n",This,ec,ppStart);
369 
370     if (!ppStart)
371         return E_INVALIDARG;
372 
373     *ppStart = NULL;
374 
375     if (!This->connected)
376         return TF_E_DISCONNECTED;
377 
378     if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
379         return TF_E_NOLOCK;
380 
381     cookie = get_Cookie_data(ec);
382     return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, 0, 0, ppStart);
383 }
384 
Context_GetEnd(ITfContext * iface,TfEditCookie ec,ITfRange ** ppEnd)385 static HRESULT WINAPI Context_GetEnd (ITfContext *iface,
386         TfEditCookie ec, ITfRange **ppEnd)
387 {
388     Context *This = impl_from_ITfContext(iface);
389     EditCookie *cookie;
390     LONG end;
391     TRACE("(%p) %i %p\n",This,ec,ppEnd);
392 
393     if (!ppEnd)
394         return E_INVALIDARG;
395 
396     *ppEnd = NULL;
397 
398     if (!This->connected)
399         return TF_E_DISCONNECTED;
400 
401     if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
402         return TF_E_NOLOCK;
403 
404     if (!This->pITextStoreACP)
405     {
406         FIXME("Context does not have a ITextStoreACP\n");
407         return E_NOTIMPL;
408     }
409 
410     cookie = get_Cookie_data(ec);
411     ITextStoreACP_GetEndACP(This->pITextStoreACP,&end);
412 
413     return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, end, end, ppEnd);
414 }
415 
Context_GetActiveView(ITfContext * iface,ITfContextView ** ppView)416 static HRESULT WINAPI Context_GetActiveView (ITfContext *iface,
417   ITfContextView **ppView)
418 {
419     Context *This = impl_from_ITfContext(iface);
420     FIXME("STUB:(%p)\n",This);
421     return E_NOTIMPL;
422 }
423 
Context_EnumViews(ITfContext * iface,IEnumTfContextViews ** ppEnum)424 static HRESULT WINAPI Context_EnumViews (ITfContext *iface,
425         IEnumTfContextViews **ppEnum)
426 {
427     Context *This = impl_from_ITfContext(iface);
428     FIXME("STUB:(%p)\n",This);
429     return E_NOTIMPL;
430 }
431 
Context_GetStatus(ITfContext * iface,TF_STATUS * pdcs)432 static HRESULT WINAPI Context_GetStatus (ITfContext *iface,
433         TF_STATUS *pdcs)
434 {
435     Context *This = impl_from_ITfContext(iface);
436     TRACE("(%p) %p\n",This,pdcs);
437 
438     if (!This->connected)
439         return TF_E_DISCONNECTED;
440 
441     if (!pdcs)
442         return E_INVALIDARG;
443 
444     if (!This->pITextStoreACP)
445     {
446         FIXME("Context does not have a ITextStoreACP\n");
447         return E_NOTIMPL;
448     }
449 
450     ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
451 
452     *pdcs = This->documentStatus;
453 
454     return S_OK;
455 }
456 
Context_GetProperty(ITfContext * iface,REFGUID guidProp,ITfProperty ** ppProp)457 static HRESULT WINAPI Context_GetProperty (ITfContext *iface,
458         REFGUID guidProp, ITfProperty **ppProp)
459 {
460     Context *This = impl_from_ITfContext(iface);
461     FIXME("STUB:(%p)\n",This);
462     return E_NOTIMPL;
463 }
464 
Context_GetAppProperty(ITfContext * iface,REFGUID guidProp,ITfReadOnlyProperty ** ppProp)465 static HRESULT WINAPI Context_GetAppProperty (ITfContext *iface,
466         REFGUID guidProp, ITfReadOnlyProperty **ppProp)
467 {
468     Context *This = impl_from_ITfContext(iface);
469     FIXME("STUB:(%p)\n",This);
470     return E_NOTIMPL;
471 }
472 
Context_TrackProperties(ITfContext * iface,const GUID ** prgProp,ULONG cProp,const GUID ** prgAppProp,ULONG cAppProp,ITfReadOnlyProperty ** ppProperty)473 static HRESULT WINAPI Context_TrackProperties (ITfContext *iface,
474         const GUID **prgProp, ULONG cProp, const GUID **prgAppProp,
475         ULONG cAppProp, ITfReadOnlyProperty **ppProperty)
476 {
477     Context *This = impl_from_ITfContext(iface);
478     FIXME("STUB:(%p)\n",This);
479     return E_NOTIMPL;
480 }
481 
Context_EnumProperties(ITfContext * iface,IEnumTfProperties ** ppEnum)482 static HRESULT WINAPI Context_EnumProperties (ITfContext *iface,
483         IEnumTfProperties **ppEnum)
484 {
485     Context *This = impl_from_ITfContext(iface);
486     FIXME("STUB:(%p)\n",This);
487     return E_NOTIMPL;
488 }
489 
Context_GetDocumentMgr(ITfContext * iface,ITfDocumentMgr ** ppDm)490 static HRESULT WINAPI Context_GetDocumentMgr (ITfContext *iface,
491         ITfDocumentMgr **ppDm)
492 {
493     Context *This = impl_from_ITfContext(iface);
494     TRACE("(%p) %p\n",This,ppDm);
495 
496     if (!ppDm)
497         return E_INVALIDARG;
498 
499     *ppDm = This->manager;
500     if (!This->manager)
501         return S_FALSE;
502 
503     ITfDocumentMgr_AddRef(This->manager);
504 
505     return S_OK;
506 }
507 
Context_CreateRangeBackup(ITfContext * iface,TfEditCookie ec,ITfRange * pRange,ITfRangeBackup ** ppBackup)508 static HRESULT WINAPI Context_CreateRangeBackup (ITfContext *iface,
509         TfEditCookie ec, ITfRange *pRange, ITfRangeBackup **ppBackup)
510 {
511     Context *This = impl_from_ITfContext(iface);
512     FIXME("STUB:(%p)\n",This);
513     return E_NOTIMPL;
514 }
515 
516 static const ITfContextVtbl ContextVtbl =
517 {
518     Context_QueryInterface,
519     Context_AddRef,
520     Context_Release,
521     Context_RequestEditSession,
522     Context_InWriteSession,
523     Context_GetSelection,
524     Context_SetSelection,
525     Context_GetStart,
526     Context_GetEnd,
527     Context_GetActiveView,
528     Context_EnumViews,
529     Context_GetStatus,
530     Context_GetProperty,
531     Context_GetAppProperty,
532     Context_TrackProperties,
533     Context_EnumProperties,
534     Context_GetDocumentMgr,
535     Context_CreateRangeBackup
536 };
537 
538 /*****************************************************
539  * ITfSource functions
540  *****************************************************/
ContextSource_QueryInterface(ITfSource * iface,REFIID iid,LPVOID * ppvOut)541 static HRESULT WINAPI ContextSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
542 {
543     Context *This = impl_from_ITfSource(iface);
544     return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
545 }
546 
ContextSource_AddRef(ITfSource * iface)547 static ULONG WINAPI ContextSource_AddRef(ITfSource *iface)
548 {
549     Context *This = impl_from_ITfSource(iface);
550     return ITfContext_AddRef(&This->ITfContext_iface);
551 }
552 
ContextSource_Release(ITfSource * iface)553 static ULONG WINAPI ContextSource_Release(ITfSource *iface)
554 {
555     Context *This = impl_from_ITfSource(iface);
556     return ITfContext_Release(&This->ITfContext_iface);
557 }
558 
ContextSource_AdviseSink(ITfSource * iface,REFIID riid,IUnknown * punk,DWORD * pdwCookie)559 static HRESULT WINAPI ContextSource_AdviseSink(ITfSource *iface,
560         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
561 {
562     Context *This = impl_from_ITfSource(iface);
563 
564     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
565 
566     if (!riid || !punk || !pdwCookie)
567         return E_INVALIDARG;
568 
569     if (IsEqualIID(riid, &IID_ITfTextEditSink))
570         return advise_sink(&This->pTextEditSink, &IID_ITfTextEditSink, COOKIE_MAGIC_CONTEXTSINK, punk, pdwCookie);
571 
572     FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
573     return E_NOTIMPL;
574 }
575 
ContextSource_UnadviseSink(ITfSource * iface,DWORD pdwCookie)576 static HRESULT WINAPI ContextSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
577 {
578     Context *This = impl_from_ITfSource(iface);
579 
580     TRACE("(%p) %x\n",This,pdwCookie);
581 
582     if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_CONTEXTSINK)
583         return E_INVALIDARG;
584 
585     return unadvise_sink(pdwCookie);
586 }
587 
588 static const ITfSourceVtbl ContextSourceVtbl =
589 {
590     ContextSource_QueryInterface,
591     ContextSource_AddRef,
592     ContextSource_Release,
593     ContextSource_AdviseSink,
594     ContextSource_UnadviseSink
595 };
596 
597 /*****************************************************
598  * ITfContextOwnerCompositionServices functions
599  *****************************************************/
ContextOwnerCompositionServices_QueryInterface(ITfContextOwnerCompositionServices * iface,REFIID iid,LPVOID * ppvOut)600 static HRESULT WINAPI ContextOwnerCompositionServices_QueryInterface(ITfContextOwnerCompositionServices *iface,
601         REFIID iid, LPVOID *ppvOut)
602 {
603     Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
604     return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
605 }
606 
ContextOwnerCompositionServices_AddRef(ITfContextOwnerCompositionServices * iface)607 static ULONG WINAPI ContextOwnerCompositionServices_AddRef(ITfContextOwnerCompositionServices *iface)
608 {
609     Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
610     return ITfContext_AddRef(&This->ITfContext_iface);
611 }
612 
ContextOwnerCompositionServices_Release(ITfContextOwnerCompositionServices * iface)613 static ULONG WINAPI ContextOwnerCompositionServices_Release(ITfContextOwnerCompositionServices *iface)
614 {
615     Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
616     return ITfContext_Release(&This->ITfContext_iface);
617 }
618 
ContextOwnerCompositionServices_StartComposition(ITfContextOwnerCompositionServices * iface,TfEditCookie ecWrite,ITfRange * pCompositionRange,ITfCompositionSink * pSink,ITfComposition ** ppComposition)619 static HRESULT WINAPI ContextOwnerCompositionServices_StartComposition(ITfContextOwnerCompositionServices *iface,
620         TfEditCookie ecWrite, ITfRange *pCompositionRange, ITfCompositionSink *pSink, ITfComposition **ppComposition)
621 {
622     Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
623     FIXME("STUB:(%p) %#x %p %p %p\n", This, ecWrite, pCompositionRange, pSink, ppComposition);
624     return E_NOTIMPL;
625 }
626 
ContextOwnerCompositionServices_EnumCompositions(ITfContextOwnerCompositionServices * iface,IEnumITfCompositionView ** ppEnum)627 static HRESULT WINAPI ContextOwnerCompositionServices_EnumCompositions(ITfContextOwnerCompositionServices *iface,
628         IEnumITfCompositionView **ppEnum)
629 {
630     Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
631     FIXME("STUB:(%p) %p\n", This, ppEnum);
632     return E_NOTIMPL;
633 }
634 
ContextOwnerCompositionServices_FindComposition(ITfContextOwnerCompositionServices * iface,TfEditCookie ecRead,ITfRange * pTestRange,IEnumITfCompositionView ** ppEnum)635 static HRESULT WINAPI ContextOwnerCompositionServices_FindComposition(ITfContextOwnerCompositionServices *iface,
636         TfEditCookie ecRead, ITfRange *pTestRange, IEnumITfCompositionView **ppEnum)
637 {
638     Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
639     FIXME("STUB:(%p) %#x %p %p\n", This, ecRead, pTestRange, ppEnum);
640     return E_NOTIMPL;
641 }
642 
ContextOwnerCompositionServices_TakeOwnership(ITfContextOwnerCompositionServices * iface,TfEditCookie ecWrite,ITfCompositionView * pComposition,ITfCompositionSink * pSink,ITfComposition ** ppComposition)643 static HRESULT WINAPI ContextOwnerCompositionServices_TakeOwnership(ITfContextOwnerCompositionServices *iface,
644         TfEditCookie ecWrite, ITfCompositionView *pComposition, ITfCompositionSink *pSink, ITfComposition **ppComposition)
645 {
646     Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
647     FIXME("STUB:(%p) %#x %p %p %p\n", This, ecWrite, pComposition, pSink, ppComposition);
648     return E_NOTIMPL;
649 }
650 
ContextOwnerCompositionServices_TerminateComposition(ITfContextOwnerCompositionServices * iface,ITfCompositionView * pComposition)651 static HRESULT WINAPI ContextOwnerCompositionServices_TerminateComposition(ITfContextOwnerCompositionServices *iface,
652         ITfCompositionView *pComposition)
653 {
654     Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
655     FIXME("STUB:(%p) %p\n", This, pComposition);
656     return E_NOTIMPL;
657 }
658 
659 static const ITfContextOwnerCompositionServicesVtbl ContextOwnerCompositionServicesVtbl =
660 {
661     ContextOwnerCompositionServices_QueryInterface,
662     ContextOwnerCompositionServices_AddRef,
663     ContextOwnerCompositionServices_Release,
664     ContextOwnerCompositionServices_StartComposition,
665     ContextOwnerCompositionServices_EnumCompositions,
666     ContextOwnerCompositionServices_FindComposition,
667     ContextOwnerCompositionServices_TakeOwnership,
668     ContextOwnerCompositionServices_TerminateComposition
669 };
670 
671 /*****************************************************
672  * ITfInsertAtSelection functions
673  *****************************************************/
InsertAtSelection_QueryInterface(ITfInsertAtSelection * iface,REFIID iid,LPVOID * ppvOut)674 static HRESULT WINAPI InsertAtSelection_QueryInterface(ITfInsertAtSelection *iface, REFIID iid, LPVOID *ppvOut)
675 {
676     Context *This = impl_from_ITfInsertAtSelection(iface);
677     return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
678 }
679 
InsertAtSelection_AddRef(ITfInsertAtSelection * iface)680 static ULONG WINAPI InsertAtSelection_AddRef(ITfInsertAtSelection *iface)
681 {
682     Context *This = impl_from_ITfInsertAtSelection(iface);
683     return ITfContext_AddRef(&This->ITfContext_iface);
684 }
685 
InsertAtSelection_Release(ITfInsertAtSelection * iface)686 static ULONG WINAPI InsertAtSelection_Release(ITfInsertAtSelection *iface)
687 {
688     Context *This = impl_from_ITfInsertAtSelection(iface);
689     return ITfContext_Release(&This->ITfContext_iface);
690 }
691 
InsertAtSelection_InsertTextAtSelection(ITfInsertAtSelection * iface,TfEditCookie ec,DWORD dwFlags,const WCHAR * pchText,LONG cch,ITfRange ** ppRange)692 static HRESULT WINAPI InsertAtSelection_InsertTextAtSelection(
693         ITfInsertAtSelection *iface, TfEditCookie ec, DWORD dwFlags,
694         const WCHAR *pchText, LONG cch, ITfRange **ppRange)
695 {
696     Context *This = impl_from_ITfInsertAtSelection(iface);
697     EditCookie *cookie;
698     LONG acpStart, acpEnd;
699     TS_TEXTCHANGE change;
700     HRESULT hr;
701 
702     TRACE("(%p) %i %x %s %p\n",This, ec, dwFlags, debugstr_wn(pchText,cch), ppRange);
703 
704     if (!This->connected)
705         return TF_E_DISCONNECTED;
706 
707     if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
708         return TF_E_NOLOCK;
709 
710     cookie = get_Cookie_data(ec);
711 
712     if ((cookie->lockType & TS_LF_READWRITE) != TS_LF_READWRITE )
713         return TS_E_READONLY;
714 
715     if (!This->pITextStoreACP)
716     {
717         FIXME("Context does not have a ITextStoreACP\n");
718         return E_NOTIMPL;
719     }
720 
721     hr = ITextStoreACP_InsertTextAtSelection(This->pITextStoreACP, dwFlags, pchText, cch, &acpStart, &acpEnd, &change);
722     if (SUCCEEDED(hr))
723         Range_Constructor(&This->ITfContext_iface, This->pITextStoreACP, cookie->lockType, change.acpStart, change.acpNewEnd, ppRange);
724 
725     return hr;
726 }
727 
InsertAtSelection_InsertEmbeddedAtSelection(ITfInsertAtSelection * iface,TfEditCookie ec,DWORD dwFlags,IDataObject * pDataObject,ITfRange ** ppRange)728 static HRESULT WINAPI InsertAtSelection_InsertEmbeddedAtSelection(
729         ITfInsertAtSelection *iface, TfEditCookie ec, DWORD dwFlags,
730         IDataObject *pDataObject, ITfRange **ppRange)
731 {
732     Context *This = impl_from_ITfInsertAtSelection(iface);
733     FIXME("STUB:(%p)\n",This);
734     return E_NOTIMPL;
735 }
736 
737 static const ITfInsertAtSelectionVtbl InsertAtSelectionVtbl =
738 {
739     InsertAtSelection_QueryInterface,
740     InsertAtSelection_AddRef,
741     InsertAtSelection_Release,
742     InsertAtSelection_InsertTextAtSelection,
743     InsertAtSelection_InsertEmbeddedAtSelection,
744 };
745 
746 /*****************************************************
747  * ITfSourceSingle functions
748  *****************************************************/
SourceSingle_QueryInterface(ITfSourceSingle * iface,REFIID iid,LPVOID * ppvOut)749 static HRESULT WINAPI SourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
750 {
751     Context *This = impl_from_ITfSourceSingle(iface);
752     return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
753 }
754 
SourceSingle_AddRef(ITfSourceSingle * iface)755 static ULONG WINAPI SourceSingle_AddRef(ITfSourceSingle *iface)
756 {
757     Context *This = impl_from_ITfSourceSingle(iface);
758     return ITfContext_AddRef(&This->ITfContext_iface);
759 }
760 
SourceSingle_Release(ITfSourceSingle * iface)761 static ULONG WINAPI SourceSingle_Release(ITfSourceSingle *iface)
762 {
763     Context *This = impl_from_ITfSourceSingle(iface);
764     return ITfContext_Release(&This->ITfContext_iface);
765 }
766 
SourceSingle_AdviseSingleSink(ITfSourceSingle * iface,TfClientId tid,REFIID riid,IUnknown * punk)767 static HRESULT WINAPI SourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
768     TfClientId tid, REFIID riid, IUnknown *punk)
769 {
770     Context *This = impl_from_ITfSourceSingle(iface);
771     FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
772     return E_NOTIMPL;
773 }
774 
SourceSingle_UnadviseSingleSink(ITfSourceSingle * iface,TfClientId tid,REFIID riid)775 static HRESULT WINAPI SourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
776     TfClientId tid, REFIID riid)
777 {
778     Context *This = impl_from_ITfSourceSingle(iface);
779     FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
780     return E_NOTIMPL;
781 }
782 
783 static const ITfSourceSingleVtbl ContextSourceSingleVtbl =
784 {
785     SourceSingle_QueryInterface,
786     SourceSingle_AddRef,
787     SourceSingle_Release,
788     SourceSingle_AdviseSingleSink,
789     SourceSingle_UnadviseSingleSink,
790 };
791 
792 /**************************************************************************
793  *  ITextStoreACPSink
794  **************************************************************************/
795 
TextStoreACPSink_QueryInterface(ITextStoreACPSink * iface,REFIID iid,LPVOID * ppvOut)796 static HRESULT WINAPI TextStoreACPSink_QueryInterface(ITextStoreACPSink *iface, REFIID iid, LPVOID *ppvOut)
797 {
798     Context *This = impl_from_ITextStoreACPSink(iface);
799 
800     *ppvOut = NULL;
801 
802     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACPSink))
803     {
804         *ppvOut = &This->ITextStoreACPSink_iface;
805     }
806     else if (IsEqualIID(iid, &IID_ITextStoreACPServices))
807         *ppvOut = &This->ITextStoreACPServices_iface;
808 
809     if (*ppvOut)
810     {
811         ITextStoreACPSink_AddRef(iface);
812         return S_OK;
813     }
814 
815     WARN("unsupported interface: %s\n", debugstr_guid(iid));
816     return E_NOINTERFACE;
817 }
818 
TextStoreACPSink_AddRef(ITextStoreACPSink * iface)819 static ULONG WINAPI TextStoreACPSink_AddRef(ITextStoreACPSink *iface)
820 {
821     Context *This = impl_from_ITextStoreACPSink(iface);
822     return ITfContext_AddRef(&This->ITfContext_iface);
823 }
824 
TextStoreACPSink_Release(ITextStoreACPSink * iface)825 static ULONG WINAPI TextStoreACPSink_Release(ITextStoreACPSink *iface)
826 {
827     Context *This = impl_from_ITextStoreACPSink(iface);
828     return ITfContext_Release(&This->ITfContext_iface);
829 }
830 
831 /*****************************************************
832  * ITextStoreACPSink functions
833  *****************************************************/
834 
TextStoreACPSink_OnTextChange(ITextStoreACPSink * iface,DWORD dwFlags,const TS_TEXTCHANGE * pChange)835 static HRESULT WINAPI TextStoreACPSink_OnTextChange(ITextStoreACPSink *iface,
836         DWORD dwFlags, const TS_TEXTCHANGE *pChange)
837 {
838     Context *This = impl_from_ITextStoreACPSink(iface);
839     FIXME("STUB:(%p)\n",This);
840     return S_OK;
841 }
842 
TextStoreACPSink_OnSelectionChange(ITextStoreACPSink * iface)843 static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface)
844 {
845     Context *This = impl_from_ITextStoreACPSink(iface);
846     FIXME("STUB:(%p)\n",This);
847     return S_OK;
848 }
849 
TextStoreACPSink_OnLayoutChange(ITextStoreACPSink * iface,TsLayoutCode lcode,TsViewCookie vcView)850 static HRESULT WINAPI TextStoreACPSink_OnLayoutChange(ITextStoreACPSink *iface,
851     TsLayoutCode lcode, TsViewCookie vcView)
852 {
853     Context *This = impl_from_ITextStoreACPSink(iface);
854     FIXME("STUB:(%p)\n",This);
855     return S_OK;
856 }
857 
TextStoreACPSink_OnStatusChange(ITextStoreACPSink * iface,DWORD dwFlags)858 static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface,
859         DWORD dwFlags)
860 {
861     Context *This = impl_from_ITextStoreACPSink(iface);
862     HRESULT hr, hrSession;
863 
864     TRACE("(%p) %x\n",This, dwFlags);
865 
866     if (!This->pITextStoreACP)
867     {
868         FIXME("Context does not have a ITextStoreACP\n");
869         return E_NOTIMPL;
870     }
871 
872     hr = ITextStoreACP_RequestLock(This->pITextStoreACP, TS_LF_READ, &hrSession);
873 
874     if(SUCCEEDED(hr) && SUCCEEDED(hrSession))
875         This->documentStatus.dwDynamicFlags = dwFlags;
876 
877     return S_OK;
878 }
879 
TextStoreACPSink_OnAttrsChange(ITextStoreACPSink * iface,LONG acpStart,LONG acpEnd,ULONG cAttrs,const TS_ATTRID * paAttrs)880 static HRESULT WINAPI TextStoreACPSink_OnAttrsChange(ITextStoreACPSink *iface,
881         LONG acpStart, LONG acpEnd, ULONG cAttrs, const TS_ATTRID *paAttrs)
882 {
883     Context *This = impl_from_ITextStoreACPSink(iface);
884     FIXME("STUB:(%p)\n",This);
885     return E_NOTIMPL;
886 }
887 
TextStoreACPSink_OnLockGranted(ITextStoreACPSink * iface,DWORD dwLockFlags)888 static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface,
889         DWORD dwLockFlags)
890 {
891     Context *This = impl_from_ITextStoreACPSink(iface);
892     HRESULT hr;
893     EditCookie *cookie,*sinkcookie;
894     TfEditCookie ec;
895     struct list *cursor;
896 
897     TRACE("(%p) %x\n",This, dwLockFlags);
898 
899     if (!This->currentEditSession)
900     {
901         FIXME("OnLockGranted called for something other than an EditSession\n");
902         return S_OK;
903     }
904 
905     cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
906     if (!cookie)
907         return E_OUTOFMEMORY;
908 
909     sinkcookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
910     if (!sinkcookie)
911     {
912         HeapFree(GetProcessHeap(), 0, cookie);
913         return E_OUTOFMEMORY;
914     }
915 
916     cookie->lockType = dwLockFlags;
917     cookie->pOwningContext = This;
918     ec = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, cookie);
919 
920     hr = ITfEditSession_DoEditSession(This->currentEditSession, ec);
921 
922     if ((dwLockFlags&TS_LF_READWRITE) == TS_LF_READWRITE)
923     {
924         ITfTextEditSink *sink;
925         TfEditCookie sc;
926 
927         sinkcookie->lockType = TS_LF_READ;
928         sinkcookie->pOwningContext = This;
929         sc = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, sinkcookie);
930 
931         /*TODO: implement ITfEditRecord */
932         SINK_FOR_EACH(cursor, &This->pTextEditSink, ITfTextEditSink, sink)
933         {
934             ITfTextEditSink_OnEndEdit(sink, &This->ITfContext_iface, sc, NULL);
935         }
936         sinkcookie = remove_Cookie(sc);
937     }
938     HeapFree(GetProcessHeap(),0,sinkcookie);
939 
940     ITfEditSession_Release(This->currentEditSession);
941     This->currentEditSession = NULL;
942 
943     /* Edit Cookie is only valid during the edit session */
944     cookie = remove_Cookie(ec);
945     HeapFree(GetProcessHeap(),0,cookie);
946 
947     return hr;
948 }
949 
TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink * iface)950 static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface)
951 {
952     Context *This = impl_from_ITextStoreACPSink(iface);
953     FIXME("STUB:(%p)\n",This);
954     return E_NOTIMPL;
955 }
956 
TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink * iface)957 static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface)
958 {
959     Context *This = impl_from_ITextStoreACPSink(iface);
960     FIXME("STUB:(%p)\n",This);
961     return E_NOTIMPL;
962 }
963 
964 static const ITextStoreACPSinkVtbl TextStoreACPSinkVtbl =
965 {
966     TextStoreACPSink_QueryInterface,
967     TextStoreACPSink_AddRef,
968     TextStoreACPSink_Release,
969     TextStoreACPSink_OnTextChange,
970     TextStoreACPSink_OnSelectionChange,
971     TextStoreACPSink_OnLayoutChange,
972     TextStoreACPSink_OnStatusChange,
973     TextStoreACPSink_OnAttrsChange,
974     TextStoreACPSink_OnLockGranted,
975     TextStoreACPSink_OnStartEditTransaction,
976     TextStoreACPSink_OnEndEditTransaction
977 };
978 
TextStoreACPServices_QueryInterface(ITextStoreACPServices * iface,REFIID riid,void ** obj)979 static HRESULT WINAPI TextStoreACPServices_QueryInterface(ITextStoreACPServices *iface, REFIID riid, void **obj)
980 {
981     Context *This = impl_from_ITextStoreACPServices(iface);
982     return ITextStoreACPSink_QueryInterface(&This->ITextStoreACPSink_iface, riid, obj);
983 }
984 
TextStoreACPServices_AddRef(ITextStoreACPServices * iface)985 static ULONG WINAPI TextStoreACPServices_AddRef(ITextStoreACPServices *iface)
986 {
987     Context *This = impl_from_ITextStoreACPServices(iface);
988     return ITextStoreACPSink_AddRef(&This->ITextStoreACPSink_iface);
989 }
990 
TextStoreACPServices_Release(ITextStoreACPServices * iface)991 static ULONG WINAPI TextStoreACPServices_Release(ITextStoreACPServices *iface)
992 {
993     Context *This = impl_from_ITextStoreACPServices(iface);
994     return ITextStoreACPSink_Release(&This->ITextStoreACPSink_iface);
995 }
996 
TextStoreACPServices_Serialize(ITextStoreACPServices * iface,ITfProperty * prop,ITfRange * range,TF_PERSISTENT_PROPERTY_HEADER_ACP * header,IStream * stream)997 static HRESULT WINAPI TextStoreACPServices_Serialize(ITextStoreACPServices *iface, ITfProperty *prop, ITfRange *range,
998     TF_PERSISTENT_PROPERTY_HEADER_ACP *header, IStream *stream)
999 {
1000     Context *This = impl_from_ITextStoreACPServices(iface);
1001 
1002     FIXME("stub: %p %p %p %p %p\n", This, prop, range, header, stream);
1003 
1004     return E_NOTIMPL;
1005 }
1006 
TextStoreACPServices_Unserialize(ITextStoreACPServices * iface,ITfProperty * prop,const TF_PERSISTENT_PROPERTY_HEADER_ACP * header,IStream * stream,ITfPersistentPropertyLoaderACP * loader)1007 static HRESULT WINAPI TextStoreACPServices_Unserialize(ITextStoreACPServices *iface, ITfProperty *prop,
1008     const TF_PERSISTENT_PROPERTY_HEADER_ACP *header, IStream *stream, ITfPersistentPropertyLoaderACP *loader)
1009 {
1010     Context *This = impl_from_ITextStoreACPServices(iface);
1011 
1012     FIXME("stub: %p %p %p %p %p\n", This, prop, header, stream, loader);
1013 
1014     return E_NOTIMPL;
1015 }
1016 
TextStoreACPServices_ForceLoadProperty(ITextStoreACPServices * iface,ITfProperty * prop)1017 static HRESULT WINAPI TextStoreACPServices_ForceLoadProperty(ITextStoreACPServices *iface, ITfProperty *prop)
1018 {
1019     Context *This = impl_from_ITextStoreACPServices(iface);
1020 
1021     FIXME("stub: %p %p\n", This, prop);
1022 
1023     return E_NOTIMPL;
1024 }
1025 
TextStoreACPServices_CreateRange(ITextStoreACPServices * iface,LONG start,LONG end,ITfRangeACP ** range)1026 static HRESULT WINAPI TextStoreACPServices_CreateRange(ITextStoreACPServices *iface,
1027     LONG start, LONG end, ITfRangeACP **range)
1028 {
1029     Context *This = impl_from_ITextStoreACPServices(iface);
1030 
1031     FIXME("stub: %p %d %d %p\n", This, start, end, range);
1032 
1033     return S_OK;
1034 }
1035 
1036 static const ITextStoreACPServicesVtbl TextStoreACPServicesVtbl =
1037 {
1038     TextStoreACPServices_QueryInterface,
1039     TextStoreACPServices_AddRef,
1040     TextStoreACPServices_Release,
1041     TextStoreACPServices_Serialize,
1042     TextStoreACPServices_Unserialize,
1043     TextStoreACPServices_ForceLoadProperty,
1044     TextStoreACPServices_CreateRange
1045 };
1046 
Context_Constructor(TfClientId tidOwner,IUnknown * punk,ITfDocumentMgr * mgr,ITfContext ** ppOut,TfEditCookie * pecTextStore)1047 HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore)
1048 {
1049     Context *This;
1050     EditCookie *cookie;
1051 
1052     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Context));
1053     if (This == NULL)
1054         return E_OUTOFMEMORY;
1055 
1056     cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
1057     if (cookie == NULL)
1058     {
1059         HeapFree(GetProcessHeap(),0,This);
1060         return E_OUTOFMEMORY;
1061     }
1062 
1063     TRACE("(%p) %x %p %p %p\n",This, tidOwner, punk, ppOut, pecTextStore);
1064 
1065     This->ITfContext_iface.lpVtbl= &ContextVtbl;
1066     This->ITfSource_iface.lpVtbl = &ContextSourceVtbl;
1067     This->ITfContextOwnerCompositionServices_iface.lpVtbl = &ContextOwnerCompositionServicesVtbl;
1068     This->ITfInsertAtSelection_iface.lpVtbl = &InsertAtSelectionVtbl;
1069     This->ITfSourceSingle_iface.lpVtbl = &ContextSourceSingleVtbl;
1070     This->ITextStoreACPSink_iface.lpVtbl = &TextStoreACPSinkVtbl;
1071     This->ITextStoreACPServices_iface.lpVtbl = &TextStoreACPServicesVtbl;
1072     This->refCount = 1;
1073     This->tidOwner = tidOwner;
1074     This->connected = FALSE;
1075     This->manager = mgr;
1076 
1077     CompartmentMgr_Constructor((IUnknown*)&This->ITfContext_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1078 
1079     cookie->lockType = TF_ES_READ;
1080     cookie->pOwningContext = This;
1081 
1082     if (punk)
1083     {
1084         IUnknown_QueryInterface(punk, &IID_ITextStoreACP,
1085                           (LPVOID*)&This->pITextStoreACP);
1086 
1087         IUnknown_QueryInterface(punk, &IID_ITfContextOwnerCompositionSink,
1088                                 (LPVOID*)&This->pITfContextOwnerCompositionSink);
1089 
1090         if (!This->pITextStoreACP && !This->pITfContextOwnerCompositionSink)
1091             FIXME("Unhandled pUnk\n");
1092     }
1093 
1094     This->defaultCookie = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE,cookie);
1095     *pecTextStore = This->defaultCookie;
1096 
1097     list_init(&This->pContextKeyEventSink);
1098     list_init(&This->pEditTransactionSink);
1099     list_init(&This->pStatusSink);
1100     list_init(&This->pTextEditSink);
1101     list_init(&This->pTextLayoutSink);
1102 
1103     *ppOut = &This->ITfContext_iface;
1104     TRACE("returning %p\n", *ppOut);
1105 
1106     return S_OK;
1107 }
1108 
Context_Initialize(ITfContext * iface,ITfDocumentMgr * manager)1109 HRESULT Context_Initialize(ITfContext *iface, ITfDocumentMgr *manager)
1110 {
1111     Context *This = impl_from_ITfContext(iface);
1112 
1113     if (This->pITextStoreACP)
1114         ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink,
1115             (IUnknown*)&This->ITextStoreACPSink_iface, TS_AS_ALL_SINKS);
1116     This->connected = TRUE;
1117     This->manager = manager;
1118     return S_OK;
1119 }
1120 
Context_Uninitialize(ITfContext * iface)1121 HRESULT Context_Uninitialize(ITfContext *iface)
1122 {
1123     Context *This = impl_from_ITfContext(iface);
1124 
1125     if (This->pITextStoreACP)
1126         ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)&This->ITextStoreACPSink_iface);
1127     This->connected = FALSE;
1128     This->manager = NULL;
1129     return S_OK;
1130 }
1131