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 ITextStoreACP
*pITextStoreACP
;
73 ITfContextOwnerCompositionSink
*pITfContextOwnerCompositionSink
;
75 ITextStoreACPSink
*pITextStoreACPSink
;
77 /* kept as separate lists to reduce unnecessary iterations */
78 struct list pContextKeyEventSink
;
79 struct list pEditTransactionSink
;
80 struct list pStatusSink
;
81 struct list pTextEditSink
;
82 struct list pTextLayoutSink
;
87 typedef struct tagTextStoreACPSink
{
88 const ITextStoreACPSinkVtbl
*TextStoreACPSinkVtbl
;
89 /* const ITextStoreACPServicesVtbl *TextStoreACPServicesVtbl; */
96 static HRESULT
TextStoreACPSink_Constructor(ITextStoreACPSink
**ppOut
, Context
*pContext
);
98 static inline Context
*impl_from_ITfSourceVtbl(ITfSource
*iface
)
100 return (Context
*)((char *)iface
- FIELD_OFFSET(Context
,SourceVtbl
));
103 static void free_sink(ContextSink
*sink
)
105 IUnknown_Release(sink
->interfaces
.pIUnknown
);
106 HeapFree(GetProcessHeap(),0,sink
);
109 static void Context_Destructor(Context
*This
)
111 struct list
*cursor
, *cursor2
;
112 TRACE("destroying %p\n", This
);
114 if (This
->pITextStoreACPSink
)
116 ITextStoreACP_UnadviseSink(This
->pITextStoreACP
, (IUnknown
*)This
->pITextStoreACPSink
);
117 ITextStoreACPSink_Release(This
->pITextStoreACPSink
);
120 if (This
->pITextStoreACP
)
121 ITextStoreACPSink_Release(This
->pITextStoreACP
);
123 if (This
->pITfContextOwnerCompositionSink
)
124 ITextStoreACPSink_Release(This
->pITfContextOwnerCompositionSink
);
126 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pContextKeyEventSink
)
128 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
132 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pEditTransactionSink
)
134 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
138 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pStatusSink
)
140 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
144 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pTextEditSink
)
146 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
150 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->pTextLayoutSink
)
152 ContextSink
* sink
= LIST_ENTRY(cursor
,ContextSink
,entry
);
157 HeapFree(GetProcessHeap(),0,This
);
160 static HRESULT WINAPI
Context_QueryInterface(ITfContext
*iface
, REFIID iid
, LPVOID
*ppvOut
)
162 Context
*This
= (Context
*)iface
;
165 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfContext
))
169 else if (IsEqualIID(iid
, &IID_ITfSource
))
171 *ppvOut
= &This
->SourceVtbl
;
176 IUnknown_AddRef(iface
);
180 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
181 return E_NOINTERFACE
;
184 static ULONG WINAPI
Context_AddRef(ITfContext
*iface
)
186 Context
*This
= (Context
*)iface
;
187 return InterlockedIncrement(&This
->refCount
);
190 static ULONG WINAPI
Context_Release(ITfContext
*iface
)
192 Context
*This
= (Context
*)iface
;
195 ret
= InterlockedDecrement(&This
->refCount
);
197 Context_Destructor(This
);
201 /*****************************************************
202 * ITfContext functions
203 *****************************************************/
204 static HRESULT WINAPI
Context_RequestEditSession (ITfContext
*iface
,
205 TfClientId tid
, ITfEditSession
*pes
, DWORD dwFlags
,
208 Context
*This
= (Context
*)iface
;
209 FIXME("STUB:(%p)\n",This
);
213 static HRESULT WINAPI
Context_InWriteSession (ITfContext
*iface
,
215 BOOL
*pfWriteSession
)
217 Context
*This
= (Context
*)iface
;
218 FIXME("STUB:(%p)\n",This
);
222 static HRESULT WINAPI
Context_GetSelection (ITfContext
*iface
,
223 TfEditCookie ec
, ULONG ulIndex
, ULONG ulCount
,
224 TF_SELECTION
*pSelection
, ULONG
*pcFetched
)
226 Context
*This
= (Context
*)iface
;
227 FIXME("STUB:(%p)\n",This
);
231 static HRESULT WINAPI
Context_SetSelection (ITfContext
*iface
,
232 TfEditCookie ec
, ULONG ulCount
, const TF_SELECTION
*pSelection
)
234 Context
*This
= (Context
*)iface
;
235 FIXME("STUB:(%p)\n",This
);
239 static HRESULT WINAPI
Context_GetStart (ITfContext
*iface
,
240 TfEditCookie ec
, ITfRange
**ppStart
)
242 Context
*This
= (Context
*)iface
;
243 FIXME("STUB:(%p)\n",This
);
247 static HRESULT WINAPI
Context_GetEnd (ITfContext
*iface
,
248 TfEditCookie ec
, ITfRange
**ppEnd
)
250 Context
*This
= (Context
*)iface
;
251 FIXME("STUB:(%p)\n",This
);
255 static HRESULT WINAPI
Context_GetActiveView (ITfContext
*iface
,
256 ITfContextView
**ppView
)
258 Context
*This
= (Context
*)iface
;
259 FIXME("STUB:(%p)\n",This
);
263 static HRESULT WINAPI
Context_EnumViews (ITfContext
*iface
,
264 IEnumTfContextViews
**ppEnum
)
266 Context
*This
= (Context
*)iface
;
267 FIXME("STUB:(%p)\n",This
);
271 static HRESULT WINAPI
Context_GetStatus (ITfContext
*iface
,
274 Context
*This
= (Context
*)iface
;
275 FIXME("STUB:(%p)\n",This
);
279 static HRESULT WINAPI
Context_GetProperty (ITfContext
*iface
,
280 REFGUID guidProp
, ITfProperty
**ppProp
)
282 Context
*This
= (Context
*)iface
;
283 FIXME("STUB:(%p)\n",This
);
287 static HRESULT WINAPI
Context_GetAppProperty (ITfContext
*iface
,
288 REFGUID guidProp
, ITfReadOnlyProperty
**ppProp
)
290 Context
*This
= (Context
*)iface
;
291 FIXME("STUB:(%p)\n",This
);
295 static HRESULT WINAPI
Context_TrackProperties (ITfContext
*iface
,
296 const GUID
**prgProp
, ULONG cProp
, const GUID
**prgAppProp
,
297 ULONG cAppProp
, ITfReadOnlyProperty
**ppProperty
)
299 Context
*This
= (Context
*)iface
;
300 FIXME("STUB:(%p)\n",This
);
304 static HRESULT WINAPI
Context_EnumProperties (ITfContext
*iface
,
305 IEnumTfProperties
**ppEnum
)
307 Context
*This
= (Context
*)iface
;
308 FIXME("STUB:(%p)\n",This
);
312 static HRESULT WINAPI
Context_GetDocumentMgr (ITfContext
*iface
,
313 ITfDocumentMgr
**ppDm
)
315 Context
*This
= (Context
*)iface
;
316 FIXME("STUB:(%p)\n",This
);
320 static HRESULT WINAPI
Context_CreateRangeBackup (ITfContext
*iface
,
321 TfEditCookie ec
, ITfRange
*pRange
, ITfRangeBackup
**ppBackup
)
323 Context
*This
= (Context
*)iface
;
324 FIXME("STUB:(%p)\n",This
);
328 static const ITfContextVtbl Context_ContextVtbl
=
330 Context_QueryInterface
,
334 Context_RequestEditSession
,
335 Context_InWriteSession
,
336 Context_GetSelection
,
337 Context_SetSelection
,
340 Context_GetActiveView
,
344 Context_GetAppProperty
,
345 Context_TrackProperties
,
346 Context_EnumProperties
,
347 Context_GetDocumentMgr
,
348 Context_CreateRangeBackup
351 static HRESULT WINAPI
Source_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
353 Context
*This
= impl_from_ITfSourceVtbl(iface
);
354 return Context_QueryInterface((ITfContext
*)This
, iid
, *ppvOut
);
357 static ULONG WINAPI
Source_AddRef(ITfSource
*iface
)
359 Context
*This
= impl_from_ITfSourceVtbl(iface
);
360 return Context_AddRef((ITfContext
*)This
);
363 static ULONG WINAPI
Source_Release(ITfSource
*iface
)
365 Context
*This
= impl_from_ITfSourceVtbl(iface
);
366 return Context_Release((ITfContext
*)This
);
369 /*****************************************************
370 * ITfSource functions
371 *****************************************************/
372 static WINAPI HRESULT
ContextSource_AdviseSink(ITfSource
*iface
,
373 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
376 Context
*This
= impl_from_ITfSourceVtbl(iface
);
377 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
379 if (!riid
|| !punk
|| !pdwCookie
)
382 if (IsEqualIID(riid
, &IID_ITfTextEditSink
))
384 es
= HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink
));
386 return E_OUTOFMEMORY
;
387 if (!SUCCEEDED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&es
->interfaces
.pITfTextEditSink
)))
389 HeapFree(GetProcessHeap(),0,es
);
390 return CONNECT_E_CANNOTCONNECT
;
392 list_add_head(&This
->pTextEditSink
,&es
->entry
);
393 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_CONTEXTSINK
, es
);
397 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
401 TRACE("cookie %x\n",*pdwCookie
);
405 static WINAPI HRESULT
ContextSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
408 Context
*This
= impl_from_ITfSourceVtbl(iface
);
410 TRACE("(%p) %x\n",This
,pdwCookie
);
412 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_CONTEXTSINK
)
415 sink
= (ContextSink
*)remove_Cookie(pdwCookie
);
417 return CONNECT_E_NOCONNECTION
;
419 list_remove(&sink
->entry
);
425 static const ITfSourceVtbl Context_SourceVtbl
=
427 Source_QueryInterface
,
431 ContextSource_AdviseSink
,
432 ContextSource_UnadviseSink
,
435 HRESULT
Context_Constructor(TfClientId tidOwner
, IUnknown
*punk
, ITfContext
**ppOut
, TfEditCookie
*pecTextStore
)
439 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(Context
));
441 return E_OUTOFMEMORY
;
443 TRACE("(%p) %x %p %p %p\n",This
, tidOwner
, punk
, ppOut
, pecTextStore
);
445 This
->ContextVtbl
= &Context_ContextVtbl
;
446 This
->SourceVtbl
= &Context_SourceVtbl
;
448 This
->tidOwner
= tidOwner
;
452 if (SUCCEEDED(IUnknown_QueryInterface(punk
, &IID_ITextStoreACP
,
453 (LPVOID
*)&This
->pITextStoreACP
)))
455 if (SUCCEEDED(TextStoreACPSink_Constructor(&This
->pITextStoreACPSink
, This
)))
456 ITextStoreACP_AdviseSink(This
->pITextStoreACP
, &IID_ITextStoreACPSink
,
457 (IUnknown
*)This
->pITextStoreACPSink
, TS_AS_ALL_SINKS
);
460 IUnknown_QueryInterface(punk
, &IID_ITfContextOwnerCompositionSink
,
461 (LPVOID
*)&This
->pITfContextOwnerCompositionSink
);
463 if (!This
->pITextStoreACP
&& !This
->pITfContextOwnerCompositionSink
)
464 FIXME("Unhandled pUnk\n");
467 TRACE("returning %p\n", This
);
468 *ppOut
= (ITfContext
*)This
;
470 *pecTextStore
= 0xdeaddead;
472 list_init(&This
->pContextKeyEventSink
);
473 list_init(&This
->pEditTransactionSink
);
474 list_init(&This
->pStatusSink
);
475 list_init(&This
->pTextEditSink
);
476 list_init(&This
->pTextLayoutSink
);
481 /**************************************************************************
483 **************************************************************************/
485 static void TextStoreACPSink_Destructor(TextStoreACPSink
*This
)
487 TRACE("destroying %p\n", This
);
488 HeapFree(GetProcessHeap(),0,This
);
491 static HRESULT WINAPI
TextStoreACPSink_QueryInterface(ITextStoreACPSink
*iface
, REFIID iid
, LPVOID
*ppvOut
)
493 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
496 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITextStoreACPSink
))
503 IUnknown_AddRef(iface
);
507 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
508 return E_NOINTERFACE
;
511 static ULONG WINAPI
TextStoreACPSink_AddRef(ITextStoreACPSink
*iface
)
513 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
514 return InterlockedIncrement(&This
->refCount
);
517 static ULONG WINAPI
TextStoreACPSink_Release(ITextStoreACPSink
*iface
)
519 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
522 ret
= InterlockedDecrement(&This
->refCount
);
524 TextStoreACPSink_Destructor(This
);
528 /*****************************************************
529 * ITextStoreACPSink functions
530 *****************************************************/
532 static HRESULT WINAPI
TextStoreACPSink_OnTextChange(ITextStoreACPSink
*iface
,
533 DWORD dwFlags
, const TS_TEXTCHANGE
*pChange
)
535 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
536 FIXME("STUB:(%p)\n",This
);
540 static HRESULT WINAPI
TextStoreACPSink_OnSelectionChange(ITextStoreACPSink
*iface
)
542 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
543 FIXME("STUB:(%p)\n",This
);
547 static HRESULT WINAPI
TextStoreACPSink_OnLayoutChange(ITextStoreACPSink
*iface
,
548 TsLayoutCode lcode
, TsViewCookie vcView
)
550 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
551 FIXME("STUB:(%p)\n",This
);
555 static HRESULT WINAPI
TextStoreACPSink_OnStatusChange(ITextStoreACPSink
*iface
,
558 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
559 FIXME("STUB:(%p)\n",This
);
563 static HRESULT WINAPI
TextStoreACPSink_OnAttrsChange(ITextStoreACPSink
*iface
,
564 LONG acpStart
, LONG acpEnd
, ULONG cAttrs
, const TS_ATTRID
*paAttrs
)
566 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
567 FIXME("STUB:(%p)\n",This
);
571 static HRESULT WINAPI
TextStoreACPSink_OnLockGranted(ITextStoreACPSink
*iface
,
574 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
575 FIXME("STUB:(%p)\n",This
);
579 static HRESULT WINAPI
TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink
*iface
)
581 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
582 FIXME("STUB:(%p)\n",This
);
586 static HRESULT WINAPI
TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink
*iface
)
588 TextStoreACPSink
*This
= (TextStoreACPSink
*)iface
;
589 FIXME("STUB:(%p)\n",This
);
593 static const ITextStoreACPSinkVtbl TextStoreACPSink_TextStoreACPSinkVtbl
=
595 TextStoreACPSink_QueryInterface
,
596 TextStoreACPSink_AddRef
,
597 TextStoreACPSink_Release
,
599 TextStoreACPSink_OnTextChange
,
600 TextStoreACPSink_OnSelectionChange
,
601 TextStoreACPSink_OnLayoutChange
,
602 TextStoreACPSink_OnStatusChange
,
603 TextStoreACPSink_OnAttrsChange
,
604 TextStoreACPSink_OnLockGranted
,
605 TextStoreACPSink_OnStartEditTransaction
,
606 TextStoreACPSink_OnEndEditTransaction
609 static HRESULT
TextStoreACPSink_Constructor(ITextStoreACPSink
**ppOut
, Context
*pContext
)
611 TextStoreACPSink
*This
;
613 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(TextStoreACPSink
));
615 return E_OUTOFMEMORY
;
617 This
->TextStoreACPSinkVtbl
= &TextStoreACPSink_TextStoreACPSinkVtbl
;
620 This
->pContext
= pContext
;
622 TRACE("returning %p\n", This
);
623 *ppOut
= (ITextStoreACPSink
*)This
;