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 void free_sink(ContextSink
*sink
)
122 IUnknown_Release(sink
->interfaces
.pIUnknown
);
123 HeapFree(GetProcessHeap(),0,sink
);
126 static void Context_Destructor(Context
*This
)
128 struct list
*cursor
, *cursor2
;
130 TRACE("destroying %p\n", This
);
132 if (This
->pITextStoreACPSink
)
134 ITextStoreACP_UnadviseSink(This
->pITextStoreACP
, (IUnknown
*)This
->pITextStoreACPSink
);
135 ITextStoreACPSink_Release(This
->pITextStoreACPSink
);
138 if (This
->pITextStoreACP
)
139 ITextStoreACPSink_Release(This
->pITextStoreACP
);
141 if (This
->pITfContextOwnerCompositionSink
)
142 ITextStoreACPSink_Release(This
->pITfContextOwnerCompositionSink
);
144 if (This
->defaultCookie
)
146 cookie
= remove_Cookie(This
->defaultCookie
);
147 HeapFree(GetProcessHeap(),0,cookie
);
148 This
->defaultCookie
= 0;
151 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pContextKeyEventSink
)
153 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
157 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pEditTransactionSink
)
159 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
163 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pStatusSink
)
165 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
169 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pTextEditSink
)
171 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
175 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pTextLayoutSink
)
177 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
182 CompartmentMgr_Destructor(This
->CompartmentMgr
);
183 HeapFree(GetProcessHeap(),0,This
);
186 static HRESULT WINAPI
Context_QueryInterface(ITfContext
*iface
, REFIID iid
, LPVOID
*ppvOut
)
188 Context
*This
= (Context
*)iface
;
191 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfContext
))
195 else if (IsEqualIID(iid
, &IID_ITfSource
))
197 *ppvOut
= &This
->SourceVtbl
;
199 else if (IsEqualIID(iid
, &IID_ITfInsertAtSelection
))
201 *ppvOut
= &This
->InsertAtSelectionVtbl
;
203 else if (IsEqualIID(iid
, &IID_ITfCompartmentMgr
))
205 *ppvOut
= This
->CompartmentMgr
;
210 IUnknown_AddRef(iface
);
214 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
215 return E_NOINTERFACE
;
218 static ULONG WINAPI
Context_AddRef(ITfContext
*iface
)
220 Context
*This
= (Context
*)iface
;
221 return InterlockedIncrement(&This
->refCount
);
224 static ULONG WINAPI
Context_Release(ITfContext
*iface
)
226 Context
*This
= (Context
*)iface
;
229 ret
= InterlockedDecrement(&This
->refCount
);
231 Context_Destructor(This
);
235 /*****************************************************
236 * ITfContext functions
237 *****************************************************/
238 static HRESULT WINAPI
Context_RequestEditSession (ITfContext
*iface
,
239 TfClientId tid
, ITfEditSession
*pes
, DWORD dwFlags
,
243 Context
*This
= (Context
*)iface
;
244 DWORD dwLockFlags
= 0x0;
246 TRACE("(%p) %i %p %x %p\n",This
, tid
, pes
, dwFlags
, phrSession
);
248 if (!(dwFlags
& TF_ES_READ
) && !(dwFlags
& TF_ES_READWRITE
))
250 *phrSession
= E_FAIL
;
254 if (!This
->pITextStoreACP
)
256 FIXME("No ITextStoreACP avaliable\n");
257 *phrSession
= E_FAIL
;
261 if (!(dwFlags
& TF_ES_ASYNC
))
262 dwLockFlags
|= TS_LF_SYNC
;
264 if ((dwFlags
& TF_ES_READWRITE
) == TF_ES_READWRITE
)
265 dwLockFlags
|= TS_LF_READWRITE
;
266 else if (dwFlags
& TF_ES_READ
)
267 dwLockFlags
|= TS_LF_READ
;
269 if (!This
->documentStatus
.dwDynamicFlags
)
270 ITextStoreACP_GetStatus(This
->pITextStoreACP
, &This
->documentStatus
);
272 if (((dwFlags
& TF_ES_READWRITE
) == TF_ES_READWRITE
) && (This
->documentStatus
.dwDynamicFlags
& TS_SD_READONLY
))
274 *phrSession
= TS_E_READONLY
;
278 if (FAILED (ITfEditSession_QueryInterface(pes
, &IID_ITfEditSession
, (LPVOID
*)&This
->currentEditSession
)))
280 *phrSession
= E_FAIL
;
284 hr
= ITextStoreACP_RequestLock(This
->pITextStoreACP
, dwLockFlags
, phrSession
);
289 static HRESULT WINAPI
Context_InWriteSession (ITfContext
*iface
,
291 BOOL
*pfWriteSession
)
293 Context
*This
= (Context
*)iface
;
294 FIXME("STUB:(%p)\n",This
);
298 static HRESULT WINAPI
Context_GetSelection (ITfContext
*iface
,
299 TfEditCookie ec
, ULONG ulIndex
, ULONG ulCount
,
300 TF_SELECTION
*pSelection
, ULONG
*pcFetched
)
302 Context
*This
= (Context
*)iface
;
305 ULONG totalFetched
= 0;
308 if (!pSelection
|| !pcFetched
)
313 if (!This
->connected
)
314 return TF_E_DISCONNECTED
;
316 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
319 if (!This
->pITextStoreACP
)
321 FIXME("Context does not have a ITextStoreACP\n");
325 cookie
= get_Cookie_data(ec
);
327 if (ulIndex
== TF_DEFAULT_SELECTION
)
332 for (i
= 0; i
< count
; i
++)
335 TS_SELECTION_ACP acps
;
337 hr
= ITextStoreACP_GetSelection(This
->pITextStoreACP
, ulIndex
+ i
,
340 if (hr
== TS_E_NOLOCK
)
342 else if (SUCCEEDED(hr
))
344 pSelection
[totalFetched
].style
.ase
= acps
.style
.ase
;
345 pSelection
[totalFetched
].style
.fInterimChar
= acps
.style
.fInterimChar
;
346 Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, acps
.acpStart
, acps
.acpEnd
, &pSelection
[totalFetched
].range
);
353 *pcFetched
= totalFetched
;
358 static HRESULT WINAPI
Context_SetSelection (ITfContext
*iface
,
359 TfEditCookie ec
, ULONG ulCount
, const TF_SELECTION
*pSelection
)
361 TS_SELECTION_ACP
*acp
;
362 Context
*This
= (Context
*)iface
;
366 TRACE("(%p) %i %i %p\n",This
,ec
,ulCount
,pSelection
);
368 if (!This
->pITextStoreACP
)
370 FIXME("Context does not have a ITextStoreACP\n");
374 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
377 acp
= HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP
) * ulCount
);
379 return E_OUTOFMEMORY
;
381 for (i
= 0; i
< ulCount
; i
++)
382 if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection
[i
], &acp
[i
])))
384 TRACE("Selection Conversion Failed\n");
385 HeapFree(GetProcessHeap(), 0 , acp
);
389 hr
= ITextStoreACP_SetSelection(This
->pITextStoreACP
, ulCount
, acp
);
391 HeapFree(GetProcessHeap(), 0, acp
);
396 static HRESULT WINAPI
Context_GetStart (ITfContext
*iface
,
397 TfEditCookie ec
, ITfRange
**ppStart
)
399 Context
*This
= (Context
*)iface
;
401 TRACE("(%p) %i %p\n",This
,ec
,ppStart
);
408 if (!This
->connected
)
409 return TF_E_DISCONNECTED
;
411 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
414 cookie
= get_Cookie_data(ec
);
415 return Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, 0, 0, ppStart
);
418 static HRESULT WINAPI
Context_GetEnd (ITfContext
*iface
,
419 TfEditCookie ec
, ITfRange
**ppEnd
)
421 Context
*This
= (Context
*)iface
;
424 TRACE("(%p) %i %p\n",This
,ec
,ppEnd
);
431 if (!This
->connected
)
432 return TF_E_DISCONNECTED
;
434 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
437 if (!This
->pITextStoreACP
)
439 FIXME("Context does not have a ITextStoreACP\n");
443 cookie
= get_Cookie_data(ec
);
444 ITextStoreACP_GetEndACP(This
->pITextStoreACP
,&end
);
446 return Range_Constructor(iface
, This
->pITextStoreACP
, cookie
->lockType
, end
, end
, ppEnd
);
449 static HRESULT WINAPI
Context_GetActiveView (ITfContext
*iface
,
450 ITfContextView
**ppView
)
452 Context
*This
= (Context
*)iface
;
453 FIXME("STUB:(%p)\n",This
);
457 static HRESULT WINAPI
Context_EnumViews (ITfContext
*iface
,
458 IEnumTfContextViews
**ppEnum
)
460 Context
*This
= (Context
*)iface
;
461 FIXME("STUB:(%p)\n",This
);
465 static HRESULT WINAPI
Context_GetStatus (ITfContext
*iface
,
468 Context
*This
= (Context
*)iface
;
469 TRACE("(%p) %p\n",This
,pdcs
);
471 if (!This
->connected
)
472 return TF_E_DISCONNECTED
;
477 if (!This
->pITextStoreACP
)
479 FIXME("Context does not have a ITextStoreACP\n");
483 ITextStoreACP_GetStatus(This
->pITextStoreACP
, &This
->documentStatus
);
485 *pdcs
= This
->documentStatus
;
490 static HRESULT WINAPI
Context_GetProperty (ITfContext
*iface
,
491 REFGUID guidProp
, ITfProperty
**ppProp
)
493 Context
*This
= (Context
*)iface
;
494 FIXME("STUB:(%p)\n",This
);
498 static HRESULT WINAPI
Context_GetAppProperty (ITfContext
*iface
,
499 REFGUID guidProp
, ITfReadOnlyProperty
**ppProp
)
501 Context
*This
= (Context
*)iface
;
502 FIXME("STUB:(%p)\n",This
);
506 static HRESULT WINAPI
Context_TrackProperties (ITfContext
*iface
,
507 const GUID
**prgProp
, ULONG cProp
, const GUID
**prgAppProp
,
508 ULONG cAppProp
, ITfReadOnlyProperty
**ppProperty
)
510 Context
*This
= (Context
*)iface
;
511 FIXME("STUB:(%p)\n",This
);
515 static HRESULT WINAPI
Context_EnumProperties (ITfContext
*iface
,
516 IEnumTfProperties
**ppEnum
)
518 Context
*This
= (Context
*)iface
;
519 FIXME("STUB:(%p)\n",This
);
523 static HRESULT WINAPI
Context_GetDocumentMgr (ITfContext
*iface
,
524 ITfDocumentMgr
**ppDm
)
526 Context
*This
= (Context
*)iface
;
527 TRACE("(%p) %p\n",This
,ppDm
);
532 *ppDm
= This
->manager
;
536 ITfDocumentMgr_AddRef(This
->manager
);
541 static HRESULT WINAPI
Context_CreateRangeBackup (ITfContext
*iface
,
542 TfEditCookie ec
, ITfRange
*pRange
, ITfRangeBackup
**ppBackup
)
544 Context
*This
= (Context
*)iface
;
545 FIXME("STUB:(%p)\n",This
);
549 static const ITfContextVtbl Context_ContextVtbl
=
551 Context_QueryInterface
,
555 Context_RequestEditSession
,
556 Context_InWriteSession
,
557 Context_GetSelection
,
558 Context_SetSelection
,
561 Context_GetActiveView
,
565 Context_GetAppProperty
,
566 Context_TrackProperties
,
567 Context_EnumProperties
,
568 Context_GetDocumentMgr
,
569 Context_CreateRangeBackup
572 static HRESULT WINAPI
Source_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
574 Context
*This
= impl_from_ITfSourceVtbl(iface
);
575 return Context_QueryInterface((ITfContext
*)This
, iid
, *ppvOut
);
578 static ULONG WINAPI
Source_AddRef(ITfSource
*iface
)
580 Context
*This
= impl_from_ITfSourceVtbl(iface
);
581 return Context_AddRef((ITfContext
*)This
);
584 static ULONG WINAPI
Source_Release(ITfSource
*iface
)
586 Context
*This
= impl_from_ITfSourceVtbl(iface
);
587 return Context_Release((ITfContext
*)This
);
590 /*****************************************************
591 * ITfSource functions
592 *****************************************************/
593 static WINAPI HRESULT
ContextSource_AdviseSink(ITfSource
*iface
,
594 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
597 Context
*This
= impl_from_ITfSourceVtbl(iface
);
598 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
600 if (!riid
|| !punk
|| !pdwCookie
)
603 if (IsEqualIID(riid
, &IID_ITfTextEditSink
))
605 es
= HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink
));
607 return E_OUTOFMEMORY
;
608 if (FAILED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&es
->interfaces
.pITfTextEditSink
)))
610 HeapFree(GetProcessHeap(),0,es
);
611 return CONNECT_E_CANNOTCONNECT
;
613 list_add_head(&This
->pTextEditSink
,&es
->entry
);
614 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_CONTEXTSINK
, es
);
618 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
622 TRACE("cookie %x\n",*pdwCookie
);
626 static WINAPI HRESULT
ContextSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
629 Context
*This
= impl_from_ITfSourceVtbl(iface
);
631 TRACE("(%p) %x\n",This
,pdwCookie
);
633 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_CONTEXTSINK
)
636 sink
= (ContextSink
*)remove_Cookie(pdwCookie
);
638 return CONNECT_E_NOCONNECTION
;
640 list_remove(&sink
->entry
);
646 static const ITfSourceVtbl Context_SourceVtbl
=
648 Source_QueryInterface
,
652 ContextSource_AdviseSink
,
653 ContextSource_UnadviseSink
,
656 /*****************************************************
657 * ITfInsertAtSelection functions
658 *****************************************************/
659 static HRESULT WINAPI
InsertAtSelection_QueryInterface(ITfInsertAtSelection
*iface
, REFIID iid
, LPVOID
*ppvOut
)
661 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
662 return Context_QueryInterface((ITfContext
*)This
, iid
, *ppvOut
);
665 static ULONG WINAPI
InsertAtSelection_AddRef(ITfInsertAtSelection
*iface
)
667 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
668 return Context_AddRef((ITfContext
*)This
);
671 static ULONG WINAPI
InsertAtSelection_Release(ITfInsertAtSelection
*iface
)
673 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
674 return Context_Release((ITfContext
*)This
);
677 static WINAPI HRESULT
InsertAtSelection_InsertTextAtSelection(
678 ITfInsertAtSelection
*iface
, TfEditCookie ec
, DWORD dwFlags
,
679 const WCHAR
*pchText
, LONG cch
, ITfRange
**ppRange
)
681 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
683 LONG acpStart
, acpEnd
;
684 TS_TEXTCHANGE change
;
687 TRACE("(%p) %i %x %s %p\n",This
, ec
, dwFlags
, debugstr_wn(pchText
,cch
), ppRange
);
689 if (!This
->connected
)
690 return TF_E_DISCONNECTED
;
692 if (get_Cookie_magic(ec
)!=COOKIE_MAGIC_EDITCOOKIE
)
695 cookie
= get_Cookie_data(ec
);
697 if ((cookie
->lockType
& TS_LF_READWRITE
) != TS_LF_READWRITE
)
698 return TS_E_READONLY
;
700 if (!This
->pITextStoreACP
)
702 FIXME("Context does not have a ITextStoreACP\n");
706 hr
= ITextStoreACP_InsertTextAtSelection(This
->pITextStoreACP
, dwFlags
, pchText
, cch
, &acpStart
, &acpEnd
, &change
);
708 Range_Constructor((ITfContext
*)This
, This
->pITextStoreACP
, cookie
->lockType
, change
.acpStart
, change
.acpNewEnd
, ppRange
);
713 static WINAPI HRESULT
InsertAtSelection_InsertEmbeddedAtSelection(
714 ITfInsertAtSelection
*iface
, TfEditCookie ec
, DWORD dwFlags
,
715 IDataObject
*pDataObject
, ITfRange
**ppRange
)
717 Context
*This
= impl_from_ITfInsertAtSelectionVtbl(iface
);
718 FIXME("STUB:(%p)\n",This
);
722 static const ITfInsertAtSelectionVtbl Context_InsertAtSelectionVtbl
=
724 InsertAtSelection_QueryInterface
,
725 InsertAtSelection_AddRef
,
726 InsertAtSelection_Release
,
728 InsertAtSelection_InsertTextAtSelection
,
729 InsertAtSelection_InsertEmbeddedAtSelection
,
732 HRESULT
Context_Constructor(TfClientId tidOwner
, IUnknown
*punk
, ITfDocumentMgr
*mgr
, ITfContext
**ppOut
, TfEditCookie
*pecTextStore
)
737 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Context
));
739 return E_OUTOFMEMORY
;
741 cookie
= HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie
));
744 HeapFree(GetProcessHeap(),0,This
);
745 return E_OUTOFMEMORY
;
748 TRACE("(%p) %x %p %p %p\n",This
, tidOwner
, punk
, ppOut
, pecTextStore
);
750 This
->ContextVtbl
= &Context_ContextVtbl
;
751 This
->SourceVtbl
= &Context_SourceVtbl
;
752 This
->InsertAtSelectionVtbl
= &Context_InsertAtSelectionVtbl
;
754 This
->tidOwner
= tidOwner
;
755 This
->connected
= FALSE
;
758 CompartmentMgr_Constructor((IUnknown
*)This
, &IID_IUnknown
, (IUnknown
**)&This
->CompartmentMgr
);
760 cookie
->lockType
= TF_ES_READ
;
761 cookie
->pOwningContext
= This
;
765 IUnknown_QueryInterface(punk
, &IID_ITextStoreACP
,
766 (LPVOID
*)&This
->pITextStoreACP
);
768 IUnknown_QueryInterface(punk
, &IID_ITfContextOwnerCompositionSink
,
769 (LPVOID
*)&This
->pITfContextOwnerCompositionSink
);
771 if (!This
->pITextStoreACP
&& !This
->pITfContextOwnerCompositionSink
)
772 FIXME("Unhandled pUnk\n");
775 This
->defaultCookie
= generate_Cookie(COOKIE_MAGIC_EDITCOOKIE
,cookie
);
776 *pecTextStore
= This
->defaultCookie
;
778 list_init(&This
->pContextKeyEventSink
);
779 list_init(&This
->pEditTransactionSink
);
780 list_init(&This
->pStatusSink
);
781 list_init(&This
->pTextEditSink
);
782 list_init(&This
->pTextLayoutSink
);
784 *ppOut
= (ITfContext
*)This
;
785 TRACE("returning %p\n", This
);
790 HRESULT
Context_Initialize(ITfContext
*iface
, ITfDocumentMgr
*manager
)
792 Context
*This
= (Context
*)iface
;
794 if (This
->pITextStoreACP
)
796 if (SUCCEEDED(TextStoreACPSink_Constructor(&This
->pITextStoreACPSink
, This
)))
797 ITextStoreACP_AdviseSink(This
->pITextStoreACP
, &IID_ITextStoreACPSink
,
798 (IUnknown
*)This
->pITextStoreACPSink
, TS_AS_ALL_SINKS
);
800 This
->connected
= TRUE
;
801 This
->manager
= manager
;
805 HRESULT
Context_Uninitialize(ITfContext
*iface
)
807 Context
*This
= (Context
*)iface
;
809 if (This
->pITextStoreACPSink
)
811 ITextStoreACP_UnadviseSink(This
->pITextStoreACP
, (IUnknown
*)This
->pITextStoreACPSink
);
812 if (ITextStoreACPSink_Release(This
->pITextStoreACPSink
) == 0)
813 This
->pITextStoreACPSink
= NULL
;
815 This
->connected
= FALSE
;
816 This
->manager
= NULL
;
820 /**************************************************************************
822 **************************************************************************/
824 static void TextStoreACPSink_Destructor(TextStoreACPSink
*This
)
826 TRACE("destroying %p\n", This
);
827 HeapFree(GetProcessHeap(),0,This
);
830 static HRESULT WINAPI
TextStoreACPSink_QueryInterface(ITextStoreACPSink
*iface
, REFIID iid
, LPVOID
*ppvOut
)
832 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
835 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITextStoreACPSink
))
842 IUnknown_AddRef(iface
);
846 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
847 return E_NOINTERFACE
;
850 static ULONG WINAPI
TextStoreACPSink_AddRef(ITextStoreACPSink
*iface
)
852 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
853 return InterlockedIncrement(&This
->refCount
);
856 static ULONG WINAPI
TextStoreACPSink_Release(ITextStoreACPSink
*iface
)
858 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
861 ret
= InterlockedDecrement(&This
->refCount
);
863 TextStoreACPSink_Destructor(This
);
867 /*****************************************************
868 * ITextStoreACPSink functions
869 *****************************************************/
871 static HRESULT WINAPI
TextStoreACPSink_OnTextChange(ITextStoreACPSink
*iface
,
872 DWORD dwFlags
, const TS_TEXTCHANGE
*pChange
)
874 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
875 FIXME("STUB:(%p)\n",This
);
879 static HRESULT WINAPI
TextStoreACPSink_OnSelectionChange(ITextStoreACPSink
*iface
)
881 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
882 FIXME("STUB:(%p)\n",This
);
886 static HRESULT WINAPI
TextStoreACPSink_OnLayoutChange(ITextStoreACPSink
*iface
,
887 TsLayoutCode lcode
, TsViewCookie vcView
)
889 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
890 FIXME("STUB:(%p)\n",This
);
894 static HRESULT WINAPI
TextStoreACPSink_OnStatusChange(ITextStoreACPSink
*iface
,
897 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
898 HRESULT hr
, hrSession
;
900 TRACE("(%p) %x\n",This
, dwFlags
);
904 ERR("No context?\n");
908 if (!This
->pContext
->pITextStoreACP
)
910 FIXME("Context does not have a ITextStoreACP\n");
914 hr
= ITextStoreACP_RequestLock(This
->pContext
->pITextStoreACP
, TS_LF_READ
, &hrSession
);
916 if(SUCCEEDED(hr
) && SUCCEEDED(hrSession
))
917 This
->pContext
->documentStatus
.dwDynamicFlags
= dwFlags
;
922 static HRESULT WINAPI
TextStoreACPSink_OnAttrsChange(ITextStoreACPSink
*iface
,
923 LONG acpStart
, LONG acpEnd
, ULONG cAttrs
, const TS_ATTRID
*paAttrs
)
925 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
926 FIXME("STUB:(%p)\n",This
);
930 static HRESULT WINAPI
TextStoreACPSink_OnLockGranted(ITextStoreACPSink
*iface
,
933 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
938 TRACE("(%p) %x\n",This
, dwLockFlags
);
942 ERR("OnLockGranted called without a context\n");
946 if (!This
->pContext
->currentEditSession
)
948 FIXME("OnLockGranted called for something other than an EditSession\n");
952 cookie
= HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie
));
954 return E_OUTOFMEMORY
;
956 cookie
->lockType
= dwLockFlags
;
957 cookie
->pOwningContext
= This
->pContext
;
958 ec
= generate_Cookie(COOKIE_MAGIC_EDITCOOKIE
, cookie
);
960 hr
= ITfEditSession_DoEditSession(This
->pContext
->currentEditSession
, ec
);
962 ITfEditSession_Release(This
->pContext
->currentEditSession
);
963 This
->pContext
->currentEditSession
= NULL
;
965 /* Edit Cookie is only valid during the edit session */
966 cookie
= remove_Cookie(ec
);
967 HeapFree(GetProcessHeap(),0,cookie
);
972 static HRESULT WINAPI
TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink
*iface
)
974 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
975 FIXME("STUB:(%p)\n",This
);
979 static HRESULT WINAPI
TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink
*iface
)
981 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
982 FIXME("STUB:(%p)\n",This
);
986 static const ITextStoreACPSinkVtbl TextStoreACPSink_TextStoreACPSinkVtbl
=
988 TextStoreACPSink_QueryInterface
,
989 TextStoreACPSink_AddRef
,
990 TextStoreACPSink_Release
,
992 TextStoreACPSink_OnTextChange
,
993 TextStoreACPSink_OnSelectionChange
,
994 TextStoreACPSink_OnLayoutChange
,
995 TextStoreACPSink_OnStatusChange
,
996 TextStoreACPSink_OnAttrsChange
,
997 TextStoreACPSink_OnLockGranted
,
998 TextStoreACPSink_OnStartEditTransaction
,
999 TextStoreACPSink_OnEndEditTransaction
1002 static HRESULT
TextStoreACPSink_Constructor(ITextStoreACPSink
**ppOut
, Context
*pContext
)
1004 TextStoreACPSink
*This
;
1006 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(TextStoreACPSink
));
1008 return E_OUTOFMEMORY
;
1010 This
->TextStoreACPSinkVtbl
= &TextStoreACPSink_TextStoreACPSinkVtbl
;
1013 This
->pContext
= pContext
;
1015 TRACE("returning %p\n", This
);
1016 *ppOut
= (ITextStoreACPSink
*)This
;