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 const ITfContextVtbl
*ContextVtbl
;
60 const ITfSourceVtbl
*SourceVtbl
;
61 /* const ITfContextCompositionVtbl *ContextCompositionVtbl; */
62 /* const ITfContextOwnerCompositionServicesVtbl *ContextOwnerCompositionServicesVtbl; */
63 /* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */
64 const ITfInsertAtSelectionVtbl
*InsertAtSelectionVtbl
;
65 /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */
66 /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */
67 const ITfSourceSingleVtbl
*SourceSingleVtbl
;
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 const ITextStoreACPSinkVtbl
*TextStoreACPSinkVtbl
;
101 /* const ITextStoreACPServicesVtbl *TextStoreACPServicesVtbl; */
108 static HRESULT
TextStoreACPSink_Constructor(ITextStoreACPSink
**ppOut
, Context
*pContext
);
110 static inline Context
*impl_from_ITfSourceVtbl(ITfSource
*iface
)
112 return (Context
*)((char *)iface
- FIELD_OFFSET(Context
,SourceVtbl
));
115 static inline Context
*impl_from_ITfInsertAtSelectionVtbl(ITfInsertAtSelection
*iface
)
117 return (Context
*)((char *)iface
- FIELD_OFFSET(Context
,InsertAtSelectionVtbl
));
120 static inline Context
*impl_from_ITfSourceSingleVtbl(ITfSourceSingle
* iface
)
122 return (Context
*)((char *)iface
- FIELD_OFFSET(Context
,SourceSingleVtbl
));
125 static void free_sink(ContextSink
*sink
)
127 IUnknown_Release(sink
->interfaces
.pIUnknown
);
128 HeapFree(GetProcessHeap(),0,sink
);
131 static void Context_Destructor(Context
*This
)
133 struct list
*cursor
, *cursor2
;
135 TRACE("destroying %p\n", This
);
137 if (This
->pITextStoreACPSink
)
139 ITextStoreACP_UnadviseSink(This
->pITextStoreACP
, (IUnknown
*)This
->pITextStoreACPSink
);
140 ITextStoreACPSink_Release(This
->pITextStoreACPSink
);
143 if (This
->pITextStoreACP
)
144 ITextStoreACP_Release(This
->pITextStoreACP
);
146 if (This
->pITfContextOwnerCompositionSink
)
147 ITfContextOwnerCompositionSink_Release(This
->pITfContextOwnerCompositionSink
);
149 if (This
->defaultCookie
)
151 cookie
= remove_Cookie(This
->defaultCookie
);
152 HeapFree(GetProcessHeap(),0,cookie
);
153 This
->defaultCookie
= 0;
156 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pContextKeyEventSink
)
158 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
162 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pEditTransactionSink
)
164 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
168 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pStatusSink
)
170 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
174 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pTextEditSink
)
176 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
180 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pTextLayoutSink
)
182 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
187 CompartmentMgr_Destructor(This
->CompartmentMgr
);
188 HeapFree(GetProcessHeap(),0,This
);
191 static HRESULT WINAPI
Context_QueryInterface(ITfContext
*iface
, REFIID iid
, LPVOID
*ppvOut
)
193 Context
*This
= (Context
*)iface
;
196 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfContext
))
200 else if (IsEqualIID(iid
, &IID_ITfSource
))
202 *ppvOut
= &This
->SourceVtbl
;
204 else if (IsEqualIID(iid
, &IID_ITfInsertAtSelection
))
206 *ppvOut
= &This
->InsertAtSelectionVtbl
;
208 else if (IsEqualIID(iid
, &IID_ITfCompartmentMgr
))
210 *ppvOut
= This
->CompartmentMgr
;
212 else if (IsEqualIID(iid
, &IID_ITfSourceSingle
))
214 *ppvOut
= &This
->SourceSingleVtbl
;
219 ITfContext_AddRef(iface
);
223 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
224 return E_NOINTERFACE
;
227 static ULONG WINAPI
Context_AddRef(ITfContext
*iface
)
229 Context
*This
= (Context
*)iface
;
230 return InterlockedIncrement(&This
->refCount
);
233 static ULONG WINAPI
Context_Release(ITfContext
*iface
)
235 Context
*This
= (Context
*)iface
;
238 ret
= InterlockedDecrement(&This
->refCount
);
240 Context_Destructor(This
);
244 /*****************************************************
245 * ITfContext functions
246 *****************************************************/
247 static HRESULT WINAPI
Context_RequestEditSession (ITfContext
*iface
,
248 TfClientId tid
, ITfEditSession
*pes
, DWORD dwFlags
,
252 Context
*This
= (Context
*)iface
;
253 DWORD dwLockFlags
= 0x0;
255 TRACE("(%p) %i %p %x %p\n",This
, tid
, pes
, dwFlags
, phrSession
);
257 if (!(dwFlags
& TF_ES_READ
) && !(dwFlags
& TF_ES_READWRITE
))
259 *phrSession
= E_FAIL
;
263 if (!This
->pITextStoreACP
)
265 FIXME("No ITextStoreACP available\n");
266 *phrSession
= E_FAIL
;
270 if (!(dwFlags
& TF_ES_ASYNC
))
271 dwLockFlags
|= TS_LF_SYNC
;
273 if ((dwFlags
& TF_ES_READWRITE
) == TF_ES_READWRITE
)
274 dwLockFlags
|= TS_LF_READWRITE
;
275 else if (dwFlags
& TF_ES_READ
)
276 dwLockFlags
|= TS_LF_READ
;
278 if (!This
->documentStatus
.dwDynamicFlags
)
279 ITextStoreACP_GetStatus(This
->pITextStoreACP
, &This
->documentStatus
);
281 if (((dwFlags
& TF_ES_READWRITE
) == TF_ES_READWRITE
) && (This
->documentStatus
.dwDynamicFlags
& TS_SD_READONLY
))
283 *phrSession
= TS_E_READONLY
;
287 if (FAILED (ITfEditSession_QueryInterface(pes
, &IID_ITfEditSession
, (LPVOID
*)&This
->currentEditSession
)))
289 *phrSession
= E_FAIL
;
293 hr
= ITextStoreACP_RequestLock(This
->pITextStoreACP
, dwLockFlags
, phrSession
);
298 static HRESULT WINAPI
Context_InWriteSession (ITfContext
*iface
,
300 BOOL
*pfWriteSession
)
302 Context
*This
= (Context
*)iface
;
303 FIXME("STUB:(%p)\n",This
);
307 static HRESULT WINAPI
Context_GetSelection (ITfContext
*iface
,
308 TfEditCookie ec
, ULONG ulIndex
, ULONG ulCount
,
309 TF_SELECTION
*pSelection
, ULONG
*pcFetched
)
311 Context
*This
= (Context
*)iface
;
314 ULONG totalFetched
= 0;
317 if (!pSelection
|| !pcFetched
)
322 if (!This
->connected
)
323 return TF_E_DISCONNECTED
;
325 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
328 if (!This
->pITextStoreACP
)
330 FIXME("Context does not have a ITextStoreACP\n");
334 cookie
= get_Cookie_data(ec
);
336 if (ulIndex
== TF_DEFAULT_SELECTION
)
341 for (i
= 0; i
< count
; i
++)
344 TS_SELECTION_ACP acps
;
346 hr
= ITextStoreACP_GetSelection(This
->pITextStoreACP
, ulIndex
+ i
,
349 if (hr
== TS_E_NOLOCK
)
351 else if (SUCCEEDED(hr
))
353 pSelection
[totalFetched
].style
.ase
= acps
.style
.ase
;
354 pSelection
[totalFetched
].style
.fInterimChar
= acps
.style
.fInterimChar
;
355 Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, acps
.acpStart
, acps
.acpEnd
, &pSelection
[totalFetched
].range
);
362 *pcFetched
= totalFetched
;
367 static HRESULT WINAPI
Context_SetSelection (ITfContext
*iface
,
368 TfEditCookie ec
, ULONG ulCount
, const TF_SELECTION
*pSelection
)
370 TS_SELECTION_ACP
*acp
;
371 Context
*This
= (Context
*)iface
;
375 TRACE("(%p) %i %i %p\n",This
,ec
,ulCount
,pSelection
);
377 if (!This
->pITextStoreACP
)
379 FIXME("Context does not have a ITextStoreACP\n");
383 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
386 acp
= HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP
) * ulCount
);
388 return E_OUTOFMEMORY
;
390 for (i
= 0; i
< ulCount
; i
++)
391 if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection
[i
], &acp
[i
])))
393 TRACE("Selection Conversion Failed\n");
394 HeapFree(GetProcessHeap(), 0 , acp
);
398 hr
= ITextStoreACP_SetSelection(This
->pITextStoreACP
, ulCount
, acp
);
400 HeapFree(GetProcessHeap(), 0, acp
);
405 static HRESULT WINAPI
Context_GetStart (ITfContext
*iface
,
406 TfEditCookie ec
, ITfRange
**ppStart
)
408 Context
*This
= (Context
*)iface
;
410 TRACE("(%p) %i %p\n",This
,ec
,ppStart
);
417 if (!This
->connected
)
418 return TF_E_DISCONNECTED
;
420 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
423 cookie
= get_Cookie_data(ec
);
424 return Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, 0, 0, ppStart
);
427 static HRESULT WINAPI
Context_GetEnd (ITfContext
*iface
,
428 TfEditCookie ec
, ITfRange
**ppEnd
)
430 Context
*This
= (Context
*)iface
;
433 TRACE("(%p) %i %p\n",This
,ec
,ppEnd
);
440 if (!This
->connected
)
441 return TF_E_DISCONNECTED
;
443 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
446 if (!This
->pITextStoreACP
)
448 FIXME("Context does not have a ITextStoreACP\n");
452 cookie
= get_Cookie_data(ec
);
453 ITextStoreACP_GetEndACP(This
->pITextStoreACP
,&end
);
455 return Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, end
, end
, ppEnd
);
458 static HRESULT WINAPI
Context_GetActiveView (ITfContext
*iface
,
459 ITfContextView
**ppView
)
461 Context
*This
= (Context
*)iface
;
462 FIXME("STUB:(%p)\n",This
);
466 static HRESULT WINAPI
Context_EnumViews (ITfContext
*iface
,
467 IEnumTfContextViews
**ppEnum
)
469 Context
*This
= (Context
*)iface
;
470 FIXME("STUB:(%p)\n",This
);
474 static HRESULT WINAPI
Context_GetStatus (ITfContext
*iface
,
477 Context
*This
= (Context
*)iface
;
478 TRACE("(%p) %p\n",This
,pdcs
);
480 if (!This
->connected
)
481 return TF_E_DISCONNECTED
;
486 if (!This
->pITextStoreACP
)
488 FIXME("Context does not have a ITextStoreACP\n");
492 ITextStoreACP_GetStatus(This
->pITextStoreACP
, &This
->documentStatus
);
494 *pdcs
= This
->documentStatus
;
499 static HRESULT WINAPI
Context_GetProperty (ITfContext
*iface
,
500 REFGUID guidProp
, ITfProperty
**ppProp
)
502 Context
*This
= (Context
*)iface
;
503 FIXME("STUB:(%p)\n",This
);
507 static HRESULT WINAPI
Context_GetAppProperty (ITfContext
*iface
,
508 REFGUID guidProp
, ITfReadOnlyProperty
**ppProp
)
510 Context
*This
= (Context
*)iface
;
511 FIXME("STUB:(%p)\n",This
);
515 static HRESULT WINAPI
Context_TrackProperties (ITfContext
*iface
,
516 const GUID
**prgProp
, ULONG cProp
, const GUID
**prgAppProp
,
517 ULONG cAppProp
, ITfReadOnlyProperty
**ppProperty
)
519 Context
*This
= (Context
*)iface
;
520 FIXME("STUB:(%p)\n",This
);
524 static HRESULT WINAPI
Context_EnumProperties (ITfContext
*iface
,
525 IEnumTfProperties
**ppEnum
)
527 Context
*This
= (Context
*)iface
;
528 FIXME("STUB:(%p)\n",This
);
532 static HRESULT WINAPI
Context_GetDocumentMgr (ITfContext
*iface
,
533 ITfDocumentMgr
**ppDm
)
535 Context
*This
= (Context
*)iface
;
536 TRACE("(%p) %p\n",This
,ppDm
);
541 *ppDm
= This
->manager
;
545 ITfDocumentMgr_AddRef(This
->manager
);
550 static HRESULT WINAPI
Context_CreateRangeBackup (ITfContext
*iface
,
551 TfEditCookie ec
, ITfRange
*pRange
, ITfRangeBackup
**ppBackup
)
553 Context
*This
= (Context
*)iface
;
554 FIXME("STUB:(%p)\n",This
);
558 static const ITfContextVtbl Context_ContextVtbl
=
560 Context_QueryInterface
,
564 Context_RequestEditSession
,
565 Context_InWriteSession
,
566 Context_GetSelection
,
567 Context_SetSelection
,
570 Context_GetActiveView
,
574 Context_GetAppProperty
,
575 Context_TrackProperties
,
576 Context_EnumProperties
,
577 Context_GetDocumentMgr
,
578 Context_CreateRangeBackup
581 static HRESULT WINAPI
Source_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
583 Context
*This
= impl_from_ITfSourceVtbl(iface
);
584 return Context_QueryInterface((ITfContext
*)This
, iid
, *ppvOut
);
587 static ULONG WINAPI
Source_AddRef(ITfSource
*iface
)
589 Context
*This
= impl_from_ITfSourceVtbl(iface
);
590 return Context_AddRef((ITfContext
*)This
);
593 static ULONG WINAPI
Source_Release(ITfSource
*iface
)
595 Context
*This
= impl_from_ITfSourceVtbl(iface
);
596 return Context_Release((ITfContext
*)This
);
599 /*****************************************************
600 * ITfSource functions
601 *****************************************************/
602 static HRESULT WINAPI
ContextSource_AdviseSink(ITfSource
*iface
,
603 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
606 Context
*This
= impl_from_ITfSourceVtbl(iface
);
607 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
609 if (!riid
|| !punk
|| !pdwCookie
)
612 if (IsEqualIID(riid
, &IID_ITfTextEditSink
))
614 es
= HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink
));
616 return E_OUTOFMEMORY
;
617 if (FAILED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&es
->interfaces
.pITfTextEditSink
)))
619 HeapFree(GetProcessHeap(),0,es
);
620 return CONNECT_E_CANNOTCONNECT
;
622 list_add_head(&This
->pTextEditSink
,&es
->entry
);
623 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_CONTEXTSINK
, es
);
627 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
631 TRACE("cookie %x\n",*pdwCookie
);
635 static HRESULT WINAPI
ContextSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
638 Context
*This
= impl_from_ITfSourceVtbl(iface
);
640 TRACE("(%p) %x\n",This
,pdwCookie
);
642 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_CONTEXTSINK
)
645 sink
= (ContextSink
*)remove_Cookie(pdwCookie
);
647 return CONNECT_E_NOCONNECTION
;
649 list_remove(&sink
->entry
);
655 static const ITfSourceVtbl Context_SourceVtbl
=
657 Source_QueryInterface
,
661 ContextSource_AdviseSink
,
662 ContextSource_UnadviseSink
,
665 /*****************************************************
666 * ITfInsertAtSelection functions
667 *****************************************************/
668 static HRESULT WINAPI
InsertAtSelection_QueryInterface(ITfInsertAtSelection
*iface
, REFIID iid
, LPVOID
*ppvOut
)
670 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
671 return Context_QueryInterface((ITfContext
*)This
, iid
, *ppvOut
);
674 static ULONG WINAPI
InsertAtSelection_AddRef(ITfInsertAtSelection
*iface
)
676 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
677 return Context_AddRef((ITfContext
*)This
);
680 static ULONG WINAPI
InsertAtSelection_Release(ITfInsertAtSelection
*iface
)
682 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
683 return Context_Release((ITfContext
*)This
);
686 static HRESULT WINAPI
InsertAtSelection_InsertTextAtSelection(
687 ITfInsertAtSelection
*iface
, TfEditCookie ec
, DWORD dwFlags
,
688 const WCHAR
*pchText
, LONG cch
, ITfRange
**ppRange
)
690 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
692 LONG acpStart
, acpEnd
;
693 TS_TEXTCHANGE change
;
696 TRACE("(%p) %i %x %s %p\n",This
, ec
, dwFlags
, debugstr_wn(pchText
,cch
), ppRange
);
698 if (!This
->connected
)
699 return TF_E_DISCONNECTED
;
701 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
704 cookie
= get_Cookie_data(ec
);
706 if ((cookie
->lockType
& TS_LF_READWRITE
) != TS_LF_READWRITE
)
707 return TS_E_READONLY
;
709 if (!This
->pITextStoreACP
)
711 FIXME("Context does not have a ITextStoreACP\n");
715 hr
= ITextStoreACP_InsertTextAtSelection(This
->pITextStoreACP
, dwFlags
, pchText
, cch
, &acpStart
, &acpEnd
, &change
);
717 Range_Constructor((ITfContext
*)This
, This
->pITextStoreACP
, cookie
->lockType
, change
.acpStart
, change
.acpNewEnd
, ppRange
);
722 static HRESULT WINAPI
InsertAtSelection_InsertEmbeddedAtSelection(
723 ITfInsertAtSelection
*iface
, TfEditCookie ec
, DWORD dwFlags
,
724 IDataObject
*pDataObject
, ITfRange
**ppRange
)
726 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
727 FIXME("STUB:(%p)\n",This
);
731 static const ITfInsertAtSelectionVtbl Context_InsertAtSelectionVtbl
=
733 InsertAtSelection_QueryInterface
,
734 InsertAtSelection_AddRef
,
735 InsertAtSelection_Release
,
737 InsertAtSelection_InsertTextAtSelection
,
738 InsertAtSelection_InsertEmbeddedAtSelection
,
741 /*****************************************************
742 * ITfSourceSingle functions
743 *****************************************************/
744 static HRESULT WINAPI
SourceSingle_QueryInterface(ITfSourceSingle
*iface
, REFIID iid
, LPVOID
*ppvOut
)
746 Context
*This
= impl_from_ITfSourceSingleVtbl(iface
);
747 return Context_QueryInterface((ITfContext
*)This
, iid
, *ppvOut
);
750 static ULONG WINAPI
SourceSingle_AddRef(ITfSourceSingle
*iface
)
752 Context
*This
= impl_from_ITfSourceSingleVtbl(iface
);
753 return Context_AddRef((ITfContext
*)This
);
756 static ULONG WINAPI
SourceSingle_Release(ITfSourceSingle
*iface
)
758 Context
*This
= impl_from_ITfSourceSingleVtbl(iface
);
759 return Context_Release((ITfContext
*)This
);
762 static HRESULT WINAPI
SourceSingle_AdviseSingleSink( ITfSourceSingle
*iface
,
763 TfClientId tid
, REFIID riid
, IUnknown
*punk
)
765 Context
*This
= impl_from_ITfSourceSingleVtbl(iface
);
766 FIXME("STUB:(%p) %i %s %p\n",This
, tid
, debugstr_guid(riid
),punk
);
770 static HRESULT WINAPI
SourceSingle_UnadviseSingleSink( ITfSourceSingle
*iface
,
771 TfClientId tid
, REFIID riid
)
773 Context
*This
= impl_from_ITfSourceSingleVtbl(iface
);
774 FIXME("STUB:(%p) %i %s\n",This
, tid
, debugstr_guid(riid
));
778 static const ITfSourceSingleVtbl Context_SourceSingleVtbl
=
780 SourceSingle_QueryInterface
,
782 SourceSingle_Release
,
784 SourceSingle_AdviseSingleSink
,
785 SourceSingle_UnadviseSingleSink
,
788 HRESULT
Context_Constructor(TfClientId tidOwner
, IUnknown
*punk
, ITfDocumentMgr
*mgr
, ITfContext
**ppOut
, TfEditCookie
*pecTextStore
)
793 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Context
));
795 return E_OUTOFMEMORY
;
797 cookie
= HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie
));
800 HeapFree(GetProcessHeap(),0,This
);
801 return E_OUTOFMEMORY
;
804 TRACE("(%p) %x %p %p %p\n",This
, tidOwner
, punk
, ppOut
, pecTextStore
);
806 This
->ContextVtbl
= &Context_ContextVtbl
;
807 This
->SourceVtbl
= &Context_SourceVtbl
;
808 This
->InsertAtSelectionVtbl
= &Context_InsertAtSelectionVtbl
;
809 This
->SourceSingleVtbl
= &Context_SourceSingleVtbl
;
811 This
->tidOwner
= tidOwner
;
812 This
->connected
= FALSE
;
815 CompartmentMgr_Constructor((IUnknown
*)This
, &IID_IUnknown
, (IUnknown
**)&This
->CompartmentMgr
);
817 cookie
->lockType
= TF_ES_READ
;
818 cookie
->pOwningContext
= This
;
822 IUnknown_QueryInterface(punk
, &IID_ITextStoreACP
,
823 (LPVOID
*)&This
->pITextStoreACP
);
825 IUnknown_QueryInterface(punk
, &IID_ITfContextOwnerCompositionSink
,
826 (LPVOID
*)&This
->pITfContextOwnerCompositionSink
);
828 if (!This
->pITextStoreACP
&& !This
->pITfContextOwnerCompositionSink
)
829 FIXME("Unhandled pUnk\n");
832 This
->defaultCookie
= generate_Cookie(COOKIE_MAGIC_EDITCOOKIE
,cookie
);
833 *pecTextStore
= This
->defaultCookie
;
835 list_init(&This
->pContextKeyEventSink
);
836 list_init(&This
->pEditTransactionSink
);
837 list_init(&This
->pStatusSink
);
838 list_init(&This
->pTextEditSink
);
839 list_init(&This
->pTextLayoutSink
);
841 *ppOut
= (ITfContext
*)This
;
842 TRACE("returning %p\n", This
);
847 HRESULT
Context_Initialize(ITfContext
*iface
, ITfDocumentMgr
*manager
)
849 Context
*This
= (Context
*)iface
;
851 if (This
->pITextStoreACP
)
853 if (SUCCEEDED(TextStoreACPSink_Constructor(&This
->pITextStoreACPSink
, This
)))
854 ITextStoreACP_AdviseSink(This
->pITextStoreACP
, &IID_ITextStoreACPSink
,
855 (IUnknown
*)This
->pITextStoreACPSink
, TS_AS_ALL_SINKS
);
857 This
->connected
= TRUE
;
858 This
->manager
= manager
;
862 HRESULT
Context_Uninitialize(ITfContext
*iface
)
864 Context
*This
= (Context
*)iface
;
866 if (This
->pITextStoreACPSink
)
868 ITextStoreACP_UnadviseSink(This
->pITextStoreACP
, (IUnknown
*)This
->pITextStoreACPSink
);
869 if (ITextStoreACPSink_Release(This
->pITextStoreACPSink
) == 0)
870 This
->pITextStoreACPSink
= NULL
;
872 This
->connected
= FALSE
;
873 This
->manager
= NULL
;
877 /**************************************************************************
879 **************************************************************************/
881 static void TextStoreACPSink_Destructor(TextStoreACPSink
*This
)
883 TRACE("destroying %p\n", This
);
884 HeapFree(GetProcessHeap(),0,This
);
887 static HRESULT WINAPI
TextStoreACPSink_QueryInterface(ITextStoreACPSink
*iface
, REFIID iid
, LPVOID
*ppvOut
)
889 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
892 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITextStoreACPSink
))
899 ITextStoreACPSink_AddRef(iface
);
903 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
904 return E_NOINTERFACE
;
907 static ULONG WINAPI
TextStoreACPSink_AddRef(ITextStoreACPSink
*iface
)
909 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
910 return InterlockedIncrement(&This
->refCount
);
913 static ULONG WINAPI
TextStoreACPSink_Release(ITextStoreACPSink
*iface
)
915 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
918 ret
= InterlockedDecrement(&This
->refCount
);
920 TextStoreACPSink_Destructor(This
);
924 /*****************************************************
925 * ITextStoreACPSink functions
926 *****************************************************/
928 static HRESULT WINAPI
TextStoreACPSink_OnTextChange(ITextStoreACPSink
*iface
,
929 DWORD dwFlags
, const TS_TEXTCHANGE
*pChange
)
931 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
932 FIXME("STUB:(%p)\n",This
);
936 static HRESULT WINAPI
TextStoreACPSink_OnSelectionChange(ITextStoreACPSink
*iface
)
938 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
939 FIXME("STUB:(%p)\n",This
);
943 static HRESULT WINAPI
TextStoreACPSink_OnLayoutChange(ITextStoreACPSink
*iface
,
944 TsLayoutCode lcode
, TsViewCookie vcView
)
946 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
947 FIXME("STUB:(%p)\n",This
);
951 static HRESULT WINAPI
TextStoreACPSink_OnStatusChange(ITextStoreACPSink
*iface
,
954 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
955 HRESULT hr
, hrSession
;
957 TRACE("(%p) %x\n",This
, dwFlags
);
961 ERR("No context?\n");
965 if (!This
->pContext
->pITextStoreACP
)
967 FIXME("Context does not have a ITextStoreACP\n");
971 hr
= ITextStoreACP_RequestLock(This
->pContext
->pITextStoreACP
, TS_LF_READ
, &hrSession
);
973 if(SUCCEEDED(hr
) && SUCCEEDED(hrSession
))
974 This
->pContext
->documentStatus
.dwDynamicFlags
= dwFlags
;
979 static HRESULT WINAPI
TextStoreACPSink_OnAttrsChange(ITextStoreACPSink
*iface
,
980 LONG acpStart
, LONG acpEnd
, ULONG cAttrs
, const TS_ATTRID
*paAttrs
)
982 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
983 FIXME("STUB:(%p)\n",This
);
987 static HRESULT WINAPI
TextStoreACPSink_OnLockGranted(ITextStoreACPSink
*iface
,
990 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
992 EditCookie
*cookie
,*sinkcookie
;
996 TRACE("(%p) %x\n",This
, dwLockFlags
);
1000 ERR("OnLockGranted called without a context\n");
1004 if (!This
->pContext
->currentEditSession
)
1006 FIXME("OnLockGranted called for something other than an EditSession\n");
1010 cookie
= HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie
));
1012 return E_OUTOFMEMORY
;
1014 sinkcookie
= HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie
));
1017 HeapFree(GetProcessHeap(), 0, cookie
);
1018 return E_OUTOFMEMORY
;
1021 cookie
->lockType
= dwLockFlags
;
1022 cookie
->pOwningContext
= This
->pContext
;
1023 ec
= generate_Cookie(COOKIE_MAGIC_EDITCOOKIE
, cookie
);
1025 hr
= ITfEditSession_DoEditSession(This
->pContext
->currentEditSession
, ec
);
1027 if ((dwLockFlags
&TS_LF_READWRITE
) == TS_LF_READWRITE
)
1031 sinkcookie
->lockType
= TS_LF_READ
;
1032 sinkcookie
->pOwningContext
= This
->pContext
;
1033 sc
= generate_Cookie(COOKIE_MAGIC_EDITCOOKIE
, sinkcookie
);
1035 /*TODO: implement ITfEditRecord */
1036 LIST_FOR_EACH(cursor
, &This
->pContext
->pTextEditSink
)
1038 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
1039 ITfTextEditSink_OnEndEdit(sink
->interfaces
.pITfTextEditSink
,
1040 (ITfContext
*) &This
->pContext
, sc
, NULL
);
1042 sinkcookie
= remove_Cookie(sc
);
1044 HeapFree(GetProcessHeap(),0,sinkcookie
);
1046 ITfEditSession_Release(This
->pContext
->currentEditSession
);
1047 This
->pContext
->currentEditSession
= NULL
;
1049 /* Edit Cookie is only valid during the edit session */
1050 cookie
= remove_Cookie(ec
);
1051 HeapFree(GetProcessHeap(),0,cookie
);
1056 static HRESULT WINAPI
TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink
*iface
)
1058 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
1059 FIXME("STUB:(%p)\n",This
);
1063 static HRESULT WINAPI
TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink
*iface
)
1065 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
1066 FIXME("STUB:(%p)\n",This
);
1070 static const ITextStoreACPSinkVtbl TextStoreACPSink_TextStoreACPSinkVtbl
=
1072 TextStoreACPSink_QueryInterface
,
1073 TextStoreACPSink_AddRef
,
1074 TextStoreACPSink_Release
,
1076 TextStoreACPSink_OnTextChange
,
1077 TextStoreACPSink_OnSelectionChange
,
1078 TextStoreACPSink_OnLayoutChange
,
1079 TextStoreACPSink_OnStatusChange
,
1080 TextStoreACPSink_OnAttrsChange
,
1081 TextStoreACPSink_OnLockGranted
,
1082 TextStoreACPSink_OnStartEditTransaction
,
1083 TextStoreACPSink_OnEndEditTransaction
1086 static HRESULT
TextStoreACPSink_Constructor(ITextStoreACPSink
**ppOut
, Context
*pContext
)
1088 TextStoreACPSink
*This
;
1090 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(TextStoreACPSink
));
1092 return E_OUTOFMEMORY
;
1094 This
->TextStoreACPSinkVtbl
= &TextStoreACPSink_TextStoreACPSinkVtbl
;
1097 This
->pContext
= pContext
;
1099 TRACE("returning %p\n", This
);
1100 *ppOut
= (ITextStoreACPSink
*)This
;