2 * ITfContext 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"
37 #include "wine/unicode.h"
38 #include "wine/list.h"
41 #include "msctf_internal.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf
);
45 typedef struct tagContextSink
{
50 /* ITfContextKeyEventSink *pITfContextKeyEventSink; */
51 /* ITfEditTransactionSink *pITfEditTransactionSink; */
52 /* ITfStatusSink *pITfStatusSink; */
53 ITfTextEditSink
*pITfTextEditSink
;
54 /* ITfTextLayoutSink *pITfTextLayoutSink; */
58 typedef struct tagContext
{
59 ITfContext ITfContext_iface
;
60 ITfSource ITfSource_iface
;
61 /* const ITfContextCompositionVtbl *ContextCompositionVtbl; */
62 /* const ITfContextOwnerCompositionServicesVtbl *ContextOwnerCompositionServicesVtbl; */
63 /* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */
64 ITfInsertAtSelection ITfInsertAtSelection_iface
;
65 /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */
66 /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */
67 ITfSourceSingle ITfSourceSingle_iface
;
72 ITfCompartmentMgr
*CompartmentMgr
;
75 TfEditCookie defaultCookie
;
76 TS_STATUS documentStatus
;
77 ITfDocumentMgr
*manager
;
79 ITextStoreACP
*pITextStoreACP
;
80 ITfContextOwnerCompositionSink
*pITfContextOwnerCompositionSink
;
82 ITextStoreACPSink
*pITextStoreACPSink
;
83 ITfEditSession
* currentEditSession
;
85 /* kept as separate lists to reduce unnecessary iterations */
86 struct list pContextKeyEventSink
;
87 struct list pEditTransactionSink
;
88 struct list pStatusSink
;
89 struct list pTextEditSink
;
90 struct list pTextLayoutSink
;
94 typedef struct tagEditCookie
{
96 Context
*pOwningContext
;
99 typedef struct tagTextStoreACPSink
{
100 ITextStoreACPSink ITextStoreACPSink_iface
;
101 /* const ITextStoreACPServicesVtbl *TextStoreACPServicesVtbl; */
108 static HRESULT
TextStoreACPSink_Constructor(ITextStoreACPSink
**ppOut
, Context
*pContext
);
110 static inline Context
*impl_from_ITfContext(ITfContext
*iface
)
112 return CONTAINING_RECORD(iface
, Context
, ITfContext_iface
);
115 static inline Context
*impl_from_ITfSource(ITfSource
*iface
)
117 return CONTAINING_RECORD(iface
, Context
, ITfSource_iface
);
120 static inline Context
*impl_from_ITfInsertAtSelection(ITfInsertAtSelection
*iface
)
122 return CONTAINING_RECORD(iface
, Context
, ITfInsertAtSelection_iface
);
125 static inline Context
*impl_from_ITfSourceSingle(ITfSourceSingle
* iface
)
127 return CONTAINING_RECORD(iface
, Context
, ITfSourceSingle_iface
);
130 static inline TextStoreACPSink
*impl_from_ITextStoreACPSink(ITextStoreACPSink
*iface
)
132 return CONTAINING_RECORD(iface
, TextStoreACPSink
, ITextStoreACPSink_iface
);
135 static void free_sink(ContextSink
*sink
)
137 IUnknown_Release(sink
->interfaces
.pIUnknown
);
138 HeapFree(GetProcessHeap(),0,sink
);
141 static void Context_Destructor(Context
*This
)
143 struct list
*cursor
, *cursor2
;
145 TRACE("destroying %p\n", This
);
147 if (This
->pITextStoreACPSink
)
149 ITextStoreACP_UnadviseSink(This
->pITextStoreACP
, (IUnknown
*)This
->pITextStoreACPSink
);
150 ITextStoreACPSink_Release(This
->pITextStoreACPSink
);
153 if (This
->pITextStoreACP
)
154 ITextStoreACP_Release(This
->pITextStoreACP
);
156 if (This
->pITfContextOwnerCompositionSink
)
157 ITfContextOwnerCompositionSink_Release(This
->pITfContextOwnerCompositionSink
);
159 if (This
->defaultCookie
)
161 cookie
= remove_Cookie(This
->defaultCookie
);
162 HeapFree(GetProcessHeap(),0,cookie
);
163 This
->defaultCookie
= 0;
166 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pContextKeyEventSink
)
168 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
172 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pEditTransactionSink
)
174 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
178 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pStatusSink
)
180 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
184 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pTextEditSink
)
186 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
190 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pTextLayoutSink
)
192 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
197 CompartmentMgr_Destructor(This
->CompartmentMgr
);
198 HeapFree(GetProcessHeap(),0,This
);
201 static HRESULT WINAPI
Context_QueryInterface(ITfContext
*iface
, REFIID iid
, LPVOID
*ppvOut
)
203 Context
*This
= impl_from_ITfContext(iface
);
206 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfContext
))
208 *ppvOut
= &This
->ITfContext_iface
;
210 else if (IsEqualIID(iid
, &IID_ITfSource
))
212 *ppvOut
= &This
->ITfSource_iface
;
214 else if (IsEqualIID(iid
, &IID_ITfInsertAtSelection
))
216 *ppvOut
= &This
->ITfInsertAtSelection_iface
;
218 else if (IsEqualIID(iid
, &IID_ITfCompartmentMgr
))
220 *ppvOut
= This
->CompartmentMgr
;
222 else if (IsEqualIID(iid
, &IID_ITfSourceSingle
))
224 *ppvOut
= &This
->ITfSourceSingle_iface
;
229 ITfContext_AddRef(iface
);
233 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
234 return E_NOINTERFACE
;
237 static ULONG WINAPI
Context_AddRef(ITfContext
*iface
)
239 Context
*This
= impl_from_ITfContext(iface
);
240 return InterlockedIncrement(&This
->refCount
);
243 static ULONG WINAPI
Context_Release(ITfContext
*iface
)
245 Context
*This
= impl_from_ITfContext(iface
);
248 ret
= InterlockedDecrement(&This
->refCount
);
250 Context_Destructor(This
);
254 /*****************************************************
255 * ITfContext functions
256 *****************************************************/
257 static HRESULT WINAPI
Context_RequestEditSession (ITfContext
*iface
,
258 TfClientId tid
, ITfEditSession
*pes
, DWORD dwFlags
,
261 Context
*This
= impl_from_ITfContext(iface
);
263 DWORD dwLockFlags
= 0x0;
265 TRACE("(%p) %i %p %x %p\n",This
, tid
, pes
, dwFlags
, phrSession
);
267 if (!(dwFlags
& TF_ES_READ
) && !(dwFlags
& TF_ES_READWRITE
))
269 *phrSession
= E_FAIL
;
273 if (!This
->pITextStoreACP
)
275 FIXME("No ITextStoreACP available\n");
276 *phrSession
= E_FAIL
;
280 if (!(dwFlags
& TF_ES_ASYNC
))
281 dwLockFlags
|= TS_LF_SYNC
;
283 if ((dwFlags
& TF_ES_READWRITE
) == TF_ES_READWRITE
)
284 dwLockFlags
|= TS_LF_READWRITE
;
285 else if (dwFlags
& TF_ES_READ
)
286 dwLockFlags
|= TS_LF_READ
;
288 if (!This
->documentStatus
.dwDynamicFlags
)
289 ITextStoreACP_GetStatus(This
->pITextStoreACP
, &This
->documentStatus
);
291 if (((dwFlags
& TF_ES_READWRITE
) == TF_ES_READWRITE
) && (This
->documentStatus
.dwDynamicFlags
& TS_SD_READONLY
))
293 *phrSession
= TS_E_READONLY
;
297 if (FAILED (ITfEditSession_QueryInterface(pes
, &IID_ITfEditSession
, (LPVOID
*)&This
->currentEditSession
)))
299 *phrSession
= E_FAIL
;
303 hr
= ITextStoreACP_RequestLock(This
->pITextStoreACP
, dwLockFlags
, phrSession
);
308 static HRESULT WINAPI
Context_InWriteSession (ITfContext
*iface
,
310 BOOL
*pfWriteSession
)
312 Context
*This
= impl_from_ITfContext(iface
);
313 FIXME("STUB:(%p)\n",This
);
317 static HRESULT WINAPI
Context_GetSelection (ITfContext
*iface
,
318 TfEditCookie ec
, ULONG ulIndex
, ULONG ulCount
,
319 TF_SELECTION
*pSelection
, ULONG
*pcFetched
)
321 Context
*This
= impl_from_ITfContext(iface
);
324 ULONG totalFetched
= 0;
327 if (!pSelection
|| !pcFetched
)
332 if (!This
->connected
)
333 return TF_E_DISCONNECTED
;
335 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
338 if (!This
->pITextStoreACP
)
340 FIXME("Context does not have a ITextStoreACP\n");
344 cookie
= get_Cookie_data(ec
);
346 if (ulIndex
== TF_DEFAULT_SELECTION
)
351 for (i
= 0; i
< count
; i
++)
354 TS_SELECTION_ACP acps
;
356 hr
= ITextStoreACP_GetSelection(This
->pITextStoreACP
, ulIndex
+ i
,
359 if (hr
== TS_E_NOLOCK
)
361 else if (SUCCEEDED(hr
))
363 pSelection
[totalFetched
].style
.ase
= acps
.style
.ase
;
364 pSelection
[totalFetched
].style
.fInterimChar
= acps
.style
.fInterimChar
;
365 Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, acps
.acpStart
, acps
.acpEnd
, &pSelection
[totalFetched
].range
);
372 *pcFetched
= totalFetched
;
377 static HRESULT WINAPI
Context_SetSelection (ITfContext
*iface
,
378 TfEditCookie ec
, ULONG ulCount
, const TF_SELECTION
*pSelection
)
380 Context
*This
= impl_from_ITfContext(iface
);
381 TS_SELECTION_ACP
*acp
;
385 TRACE("(%p) %i %i %p\n",This
,ec
,ulCount
,pSelection
);
387 if (!This
->pITextStoreACP
)
389 FIXME("Context does not have a ITextStoreACP\n");
393 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
396 acp
= HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP
) * ulCount
);
398 return E_OUTOFMEMORY
;
400 for (i
= 0; i
< ulCount
; i
++)
401 if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection
[i
], &acp
[i
])))
403 TRACE("Selection Conversion Failed\n");
404 HeapFree(GetProcessHeap(), 0 , acp
);
408 hr
= ITextStoreACP_SetSelection(This
->pITextStoreACP
, ulCount
, acp
);
410 HeapFree(GetProcessHeap(), 0, acp
);
415 static HRESULT WINAPI
Context_GetStart (ITfContext
*iface
,
416 TfEditCookie ec
, ITfRange
**ppStart
)
418 Context
*This
= impl_from_ITfContext(iface
);
420 TRACE("(%p) %i %p\n",This
,ec
,ppStart
);
427 if (!This
->connected
)
428 return TF_E_DISCONNECTED
;
430 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
433 cookie
= get_Cookie_data(ec
);
434 return Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, 0, 0, ppStart
);
437 static HRESULT WINAPI
Context_GetEnd (ITfContext
*iface
,
438 TfEditCookie ec
, ITfRange
**ppEnd
)
440 Context
*This
= impl_from_ITfContext(iface
);
443 TRACE("(%p) %i %p\n",This
,ec
,ppEnd
);
450 if (!This
->connected
)
451 return TF_E_DISCONNECTED
;
453 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
456 if (!This
->pITextStoreACP
)
458 FIXME("Context does not have a ITextStoreACP\n");
462 cookie
= get_Cookie_data(ec
);
463 ITextStoreACP_GetEndACP(This
->pITextStoreACP
,&end
);
465 return Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, end
, end
, ppEnd
);
468 static HRESULT WINAPI
Context_GetActiveView (ITfContext
*iface
,
469 ITfContextView
**ppView
)
471 Context
*This
= impl_from_ITfContext(iface
);
472 FIXME("STUB:(%p)\n",This
);
476 static HRESULT WINAPI
Context_EnumViews (ITfContext
*iface
,
477 IEnumTfContextViews
**ppEnum
)
479 Context
*This
= impl_from_ITfContext(iface
);
480 FIXME("STUB:(%p)\n",This
);
484 static HRESULT WINAPI
Context_GetStatus (ITfContext
*iface
,
487 Context
*This
= impl_from_ITfContext(iface
);
488 TRACE("(%p) %p\n",This
,pdcs
);
490 if (!This
->connected
)
491 return TF_E_DISCONNECTED
;
496 if (!This
->pITextStoreACP
)
498 FIXME("Context does not have a ITextStoreACP\n");
502 ITextStoreACP_GetStatus(This
->pITextStoreACP
, &This
->documentStatus
);
504 *pdcs
= This
->documentStatus
;
509 static HRESULT WINAPI
Context_GetProperty (ITfContext
*iface
,
510 REFGUID guidProp
, ITfProperty
**ppProp
)
512 Context
*This
= impl_from_ITfContext(iface
);
513 FIXME("STUB:(%p)\n",This
);
517 static HRESULT WINAPI
Context_GetAppProperty (ITfContext
*iface
,
518 REFGUID guidProp
, ITfReadOnlyProperty
**ppProp
)
520 Context
*This
= impl_from_ITfContext(iface
);
521 FIXME("STUB:(%p)\n",This
);
525 static HRESULT WINAPI
Context_TrackProperties (ITfContext
*iface
,
526 const GUID
**prgProp
, ULONG cProp
, const GUID
**prgAppProp
,
527 ULONG cAppProp
, ITfReadOnlyProperty
**ppProperty
)
529 Context
*This
= impl_from_ITfContext(iface
);
530 FIXME("STUB:(%p)\n",This
);
534 static HRESULT WINAPI
Context_EnumProperties (ITfContext
*iface
,
535 IEnumTfProperties
**ppEnum
)
537 Context
*This
= impl_from_ITfContext(iface
);
538 FIXME("STUB:(%p)\n",This
);
542 static HRESULT WINAPI
Context_GetDocumentMgr (ITfContext
*iface
,
543 ITfDocumentMgr
**ppDm
)
545 Context
*This
= impl_from_ITfContext(iface
);
546 TRACE("(%p) %p\n",This
,ppDm
);
551 *ppDm
= This
->manager
;
555 ITfDocumentMgr_AddRef(This
->manager
);
560 static HRESULT WINAPI
Context_CreateRangeBackup (ITfContext
*iface
,
561 TfEditCookie ec
, ITfRange
*pRange
, ITfRangeBackup
**ppBackup
)
563 Context
*This
= impl_from_ITfContext(iface
);
564 FIXME("STUB:(%p)\n",This
);
568 static const ITfContextVtbl ContextVtbl
=
570 Context_QueryInterface
,
573 Context_RequestEditSession
,
574 Context_InWriteSession
,
575 Context_GetSelection
,
576 Context_SetSelection
,
579 Context_GetActiveView
,
583 Context_GetAppProperty
,
584 Context_TrackProperties
,
585 Context_EnumProperties
,
586 Context_GetDocumentMgr
,
587 Context_CreateRangeBackup
590 static HRESULT WINAPI
ContextSource_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
592 Context
*This
= impl_from_ITfSource(iface
);
593 return ITfContext_QueryInterface(&This
->ITfContext_iface
, iid
, ppvOut
);
596 static ULONG WINAPI
ContextSource_AddRef(ITfSource
*iface
)
598 Context
*This
= impl_from_ITfSource(iface
);
599 return ITfContext_AddRef(&This
->ITfContext_iface
);
602 static ULONG WINAPI
ContextSource_Release(ITfSource
*iface
)
604 Context
*This
= impl_from_ITfSource(iface
);
605 return ITfContext_Release(&This
->ITfContext_iface
);
608 /*****************************************************
609 * ITfSource functions
610 *****************************************************/
611 static HRESULT WINAPI
ContextSource_AdviseSink(ITfSource
*iface
,
612 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
614 Context
*This
= impl_from_ITfSource(iface
);
616 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
618 if (!riid
|| !punk
|| !pdwCookie
)
621 if (IsEqualIID(riid
, &IID_ITfTextEditSink
))
623 es
= HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink
));
625 return E_OUTOFMEMORY
;
626 if (FAILED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&es
->interfaces
.pITfTextEditSink
)))
628 HeapFree(GetProcessHeap(),0,es
);
629 return CONNECT_E_CANNOTCONNECT
;
631 list_add_head(&This
->pTextEditSink
,&es
->entry
);
632 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_CONTEXTSINK
, es
);
636 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
640 TRACE("cookie %x\n",*pdwCookie
);
644 static HRESULT WINAPI
ContextSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
646 Context
*This
= impl_from_ITfSource(iface
);
649 TRACE("(%p) %x\n",This
,pdwCookie
);
651 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_CONTEXTSINK
)
654 sink
= remove_Cookie(pdwCookie
);
656 return CONNECT_E_NOCONNECTION
;
658 list_remove(&sink
->entry
);
664 static const ITfSourceVtbl ContextSourceVtbl
=
666 ContextSource_QueryInterface
,
667 ContextSource_AddRef
,
668 ContextSource_Release
,
669 ContextSource_AdviseSink
,
670 ContextSource_UnadviseSink
673 /*****************************************************
674 * ITfInsertAtSelection functions
675 *****************************************************/
676 static HRESULT WINAPI
InsertAtSelection_QueryInterface(ITfInsertAtSelection
*iface
, REFIID iid
, LPVOID
*ppvOut
)
678 Context
*This
= impl_from_ITfInsertAtSelection(iface
);
679 return ITfContext_QueryInterface(&This
->ITfContext_iface
, iid
, ppvOut
);
682 static ULONG WINAPI
InsertAtSelection_AddRef(ITfInsertAtSelection
*iface
)
684 Context
*This
= impl_from_ITfInsertAtSelection(iface
);
685 return ITfContext_AddRef(&This
->ITfContext_iface
);
688 static ULONG WINAPI
InsertAtSelection_Release(ITfInsertAtSelection
*iface
)
690 Context
*This
= impl_from_ITfInsertAtSelection(iface
);
691 return ITfContext_Release(&This
->ITfContext_iface
);
694 static HRESULT WINAPI
InsertAtSelection_InsertTextAtSelection(
695 ITfInsertAtSelection
*iface
, TfEditCookie ec
, DWORD dwFlags
,
696 const WCHAR
*pchText
, LONG cch
, ITfRange
**ppRange
)
698 Context
*This
= impl_from_ITfInsertAtSelection(iface
);
700 LONG acpStart
, acpEnd
;
701 TS_TEXTCHANGE change
;
704 TRACE("(%p) %i %x %s %p\n",This
, ec
, dwFlags
, debugstr_wn(pchText
,cch
), ppRange
);
706 if (!This
->connected
)
707 return TF_E_DISCONNECTED
;
709 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
712 cookie
= get_Cookie_data(ec
);
714 if ((cookie
->lockType
& TS_LF_READWRITE
) != TS_LF_READWRITE
)
715 return TS_E_READONLY
;
717 if (!This
->pITextStoreACP
)
719 FIXME("Context does not have a ITextStoreACP\n");
723 hr
= ITextStoreACP_InsertTextAtSelection(This
->pITextStoreACP
, dwFlags
, pchText
, cch
, &acpStart
, &acpEnd
, &change
);
725 Range_Constructor(&This
->ITfContext_iface
, This
->pITextStoreACP
, cookie
->lockType
, change
.acpStart
, change
.acpNewEnd
, ppRange
);
730 static HRESULT WINAPI
InsertAtSelection_InsertEmbeddedAtSelection(
731 ITfInsertAtSelection
*iface
, TfEditCookie ec
, DWORD dwFlags
,
732 IDataObject
*pDataObject
, ITfRange
**ppRange
)
734 Context
*This
= impl_from_ITfInsertAtSelection(iface
);
735 FIXME("STUB:(%p)\n",This
);
739 static const ITfInsertAtSelectionVtbl InsertAtSelectionVtbl
=
741 InsertAtSelection_QueryInterface
,
742 InsertAtSelection_AddRef
,
743 InsertAtSelection_Release
,
744 InsertAtSelection_InsertTextAtSelection
,
745 InsertAtSelection_InsertEmbeddedAtSelection
,
748 /*****************************************************
749 * ITfSourceSingle functions
750 *****************************************************/
751 static HRESULT WINAPI
SourceSingle_QueryInterface(ITfSourceSingle
*iface
, REFIID iid
, LPVOID
*ppvOut
)
753 Context
*This
= impl_from_ITfSourceSingle(iface
);
754 return ITfContext_QueryInterface(&This
->ITfContext_iface
, iid
, ppvOut
);
757 static ULONG WINAPI
SourceSingle_AddRef(ITfSourceSingle
*iface
)
759 Context
*This
= impl_from_ITfSourceSingle(iface
);
760 return ITfContext_AddRef(&This
->ITfContext_iface
);
763 static ULONG WINAPI
SourceSingle_Release(ITfSourceSingle
*iface
)
765 Context
*This
= impl_from_ITfSourceSingle(iface
);
766 return ITfContext_Release(&This
->ITfContext_iface
);
769 static HRESULT WINAPI
SourceSingle_AdviseSingleSink( ITfSourceSingle
*iface
,
770 TfClientId tid
, REFIID riid
, IUnknown
*punk
)
772 Context
*This
= impl_from_ITfSourceSingle(iface
);
773 FIXME("STUB:(%p) %i %s %p\n",This
, tid
, debugstr_guid(riid
),punk
);
777 static HRESULT WINAPI
SourceSingle_UnadviseSingleSink( ITfSourceSingle
*iface
,
778 TfClientId tid
, REFIID riid
)
780 Context
*This
= impl_from_ITfSourceSingle(iface
);
781 FIXME("STUB:(%p) %i %s\n",This
, tid
, debugstr_guid(riid
));
785 static const ITfSourceSingleVtbl ContextSourceSingleVtbl
=
787 SourceSingle_QueryInterface
,
789 SourceSingle_Release
,
790 SourceSingle_AdviseSingleSink
,
791 SourceSingle_UnadviseSingleSink
,
794 HRESULT
Context_Constructor(TfClientId tidOwner
, IUnknown
*punk
, ITfDocumentMgr
*mgr
, ITfContext
**ppOut
, TfEditCookie
*pecTextStore
)
799 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Context
));
801 return E_OUTOFMEMORY
;
803 cookie
= HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie
));
806 HeapFree(GetProcessHeap(),0,This
);
807 return E_OUTOFMEMORY
;
810 TRACE("(%p) %x %p %p %p\n",This
, tidOwner
, punk
, ppOut
, pecTextStore
);
812 This
->ITfContext_iface
.lpVtbl
= &ContextVtbl
;
813 This
->ITfSource_iface
.lpVtbl
= &ContextSourceVtbl
;
814 This
->ITfInsertAtSelection_iface
.lpVtbl
= &InsertAtSelectionVtbl
;
815 This
->ITfSourceSingle_iface
.lpVtbl
= &ContextSourceSingleVtbl
;
817 This
->tidOwner
= tidOwner
;
818 This
->connected
= FALSE
;
821 CompartmentMgr_Constructor((IUnknown
*)&This
->ITfContext_iface
, &IID_IUnknown
, (IUnknown
**)&This
->CompartmentMgr
);
823 cookie
->lockType
= TF_ES_READ
;
824 cookie
->pOwningContext
= This
;
828 IUnknown_QueryInterface(punk
, &IID_ITextStoreACP
,
829 (LPVOID
*)&This
->pITextStoreACP
);
831 IUnknown_QueryInterface(punk
, &IID_ITfContextOwnerCompositionSink
,
832 (LPVOID
*)&This
->pITfContextOwnerCompositionSink
);
834 if (!This
->pITextStoreACP
&& !This
->pITfContextOwnerCompositionSink
)
835 FIXME("Unhandled pUnk\n");
838 This
->defaultCookie
= generate_Cookie(COOKIE_MAGIC_EDITCOOKIE
,cookie
);
839 *pecTextStore
= This
->defaultCookie
;
841 list_init(&This
->pContextKeyEventSink
);
842 list_init(&This
->pEditTransactionSink
);
843 list_init(&This
->pStatusSink
);
844 list_init(&This
->pTextEditSink
);
845 list_init(&This
->pTextLayoutSink
);
847 *ppOut
= &This
->ITfContext_iface
;
848 TRACE("returning %p\n", *ppOut
);
853 HRESULT
Context_Initialize(ITfContext
*iface
, ITfDocumentMgr
*manager
)
855 Context
*This
= impl_from_ITfContext(iface
);
857 if (This
->pITextStoreACP
)
859 if (SUCCEEDED(TextStoreACPSink_Constructor(&This
->pITextStoreACPSink
, This
)))
860 ITextStoreACP_AdviseSink(This
->pITextStoreACP
, &IID_ITextStoreACPSink
,
861 (IUnknown
*)This
->pITextStoreACPSink
, TS_AS_ALL_SINKS
);
863 This
->connected
= TRUE
;
864 This
->manager
= manager
;
868 HRESULT
Context_Uninitialize(ITfContext
*iface
)
870 Context
*This
= impl_from_ITfContext(iface
);
872 if (This
->pITextStoreACPSink
)
874 ITextStoreACP_UnadviseSink(This
->pITextStoreACP
, (IUnknown
*)This
->pITextStoreACPSink
);
875 if (ITextStoreACPSink_Release(This
->pITextStoreACPSink
) == 0)
876 This
->pITextStoreACPSink
= NULL
;
878 This
->connected
= FALSE
;
879 This
->manager
= NULL
;
883 /**************************************************************************
885 **************************************************************************/
887 static void TextStoreACPSink_Destructor(TextStoreACPSink
*This
)
889 TRACE("destroying %p\n", This
);
890 HeapFree(GetProcessHeap(),0,This
);
893 static HRESULT WINAPI
TextStoreACPSink_QueryInterface(ITextStoreACPSink
*iface
, REFIID iid
, LPVOID
*ppvOut
)
895 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
898 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITextStoreACPSink
))
900 *ppvOut
= &This
->ITextStoreACPSink_iface
;
905 ITextStoreACPSink_AddRef(iface
);
909 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
910 return E_NOINTERFACE
;
913 static ULONG WINAPI
TextStoreACPSink_AddRef(ITextStoreACPSink
*iface
)
915 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
916 return InterlockedIncrement(&This
->refCount
);
919 static ULONG WINAPI
TextStoreACPSink_Release(ITextStoreACPSink
*iface
)
921 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
924 ret
= InterlockedDecrement(&This
->refCount
);
926 TextStoreACPSink_Destructor(This
);
930 /*****************************************************
931 * ITextStoreACPSink functions
932 *****************************************************/
934 static HRESULT WINAPI
TextStoreACPSink_OnTextChange(ITextStoreACPSink
*iface
,
935 DWORD dwFlags
, const TS_TEXTCHANGE
*pChange
)
937 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
938 FIXME("STUB:(%p)\n",This
);
942 static HRESULT WINAPI
TextStoreACPSink_OnSelectionChange(ITextStoreACPSink
*iface
)
944 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
945 FIXME("STUB:(%p)\n",This
);
949 static HRESULT WINAPI
TextStoreACPSink_OnLayoutChange(ITextStoreACPSink
*iface
,
950 TsLayoutCode lcode
, TsViewCookie vcView
)
952 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
953 FIXME("STUB:(%p)\n",This
);
957 static HRESULT WINAPI
TextStoreACPSink_OnStatusChange(ITextStoreACPSink
*iface
,
960 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
961 HRESULT hr
, hrSession
;
963 TRACE("(%p) %x\n",This
, dwFlags
);
967 ERR("No context?\n");
971 if (!This
->pContext
->pITextStoreACP
)
973 FIXME("Context does not have a ITextStoreACP\n");
977 hr
= ITextStoreACP_RequestLock(This
->pContext
->pITextStoreACP
, TS_LF_READ
, &hrSession
);
979 if(SUCCEEDED(hr
) && SUCCEEDED(hrSession
))
980 This
->pContext
->documentStatus
.dwDynamicFlags
= dwFlags
;
985 static HRESULT WINAPI
TextStoreACPSink_OnAttrsChange(ITextStoreACPSink
*iface
,
986 LONG acpStart
, LONG acpEnd
, ULONG cAttrs
, const TS_ATTRID
*paAttrs
)
988 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
989 FIXME("STUB:(%p)\n",This
);
993 static HRESULT WINAPI
TextStoreACPSink_OnLockGranted(ITextStoreACPSink
*iface
,
996 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
998 EditCookie
*cookie
,*sinkcookie
;
1000 struct list
*cursor
;
1002 TRACE("(%p) %x\n",This
, dwLockFlags
);
1004 if (!This
->pContext
)
1006 ERR("OnLockGranted called without a context\n");
1010 if (!This
->pContext
->currentEditSession
)
1012 FIXME("OnLockGranted called for something other than an EditSession\n");
1016 cookie
= HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie
));
1018 return E_OUTOFMEMORY
;
1020 sinkcookie
= HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie
));
1023 HeapFree(GetProcessHeap(), 0, cookie
);
1024 return E_OUTOFMEMORY
;
1027 cookie
->lockType
= dwLockFlags
;
1028 cookie
->pOwningContext
= This
->pContext
;
1029 ec
= generate_Cookie(COOKIE_MAGIC_EDITCOOKIE
, cookie
);
1031 hr
= ITfEditSession_DoEditSession(This
->pContext
->currentEditSession
, ec
);
1033 if ((dwLockFlags
&TS_LF_READWRITE
) == TS_LF_READWRITE
)
1037 sinkcookie
->lockType
= TS_LF_READ
;
1038 sinkcookie
->pOwningContext
= This
->pContext
;
1039 sc
= generate_Cookie(COOKIE_MAGIC_EDITCOOKIE
, sinkcookie
);
1041 /*TODO: implement ITfEditRecord */
1042 LIST_FOR_EACH(cursor
, &This
->pContext
->pTextEditSink
)
1044 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
1045 ITfTextEditSink_OnEndEdit(sink
->interfaces
.pITfTextEditSink
,
1046 (ITfContext
*) &This
->pContext
, sc
, NULL
);
1048 sinkcookie
= remove_Cookie(sc
);
1050 HeapFree(GetProcessHeap(),0,sinkcookie
);
1052 ITfEditSession_Release(This
->pContext
->currentEditSession
);
1053 This
->pContext
->currentEditSession
= NULL
;
1055 /* Edit Cookie is only valid during the edit session */
1056 cookie
= remove_Cookie(ec
);
1057 HeapFree(GetProcessHeap(),0,cookie
);
1062 static HRESULT WINAPI
TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink
*iface
)
1064 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
1065 FIXME("STUB:(%p)\n",This
);
1069 static HRESULT WINAPI
TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink
*iface
)
1071 TextStoreACPSink
*This
= impl_from_ITextStoreACPSink(iface
);
1072 FIXME("STUB:(%p)\n",This
);
1076 static const ITextStoreACPSinkVtbl TextStoreACPSinkVtbl
=
1078 TextStoreACPSink_QueryInterface
,
1079 TextStoreACPSink_AddRef
,
1080 TextStoreACPSink_Release
,
1081 TextStoreACPSink_OnTextChange
,
1082 TextStoreACPSink_OnSelectionChange
,
1083 TextStoreACPSink_OnLayoutChange
,
1084 TextStoreACPSink_OnStatusChange
,
1085 TextStoreACPSink_OnAttrsChange
,
1086 TextStoreACPSink_OnLockGranted
,
1087 TextStoreACPSink_OnStartEditTransaction
,
1088 TextStoreACPSink_OnEndEditTransaction
1091 static HRESULT
TextStoreACPSink_Constructor(ITextStoreACPSink
**ppOut
, Context
*pContext
)
1093 TextStoreACPSink
*This
;
1095 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(TextStoreACPSink
));
1097 return E_OUTOFMEMORY
;
1099 This
->ITextStoreACPSink_iface
.lpVtbl
= &TextStoreACPSinkVtbl
;
1102 This
->pContext
= pContext
;
1104 *ppOut
= &This
->ITextStoreACPSink_iface
;
1105 TRACE("returning %p\n", *ppOut
);