include: Add STORAGE_HOTPLUG_INFO structure.
[wine.git] / dlls / msctf / context.c
blob2a7feafae1e9c885ed975a4e876a64967b660aa6
1 /*
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
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "wine/debug.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winuser.h"
30 #include "shlwapi.h"
31 #include "winerror.h"
32 #include "objbase.h"
33 #include "olectl.h"
35 #include "msctf.h"
36 #include "msctf_internal.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
40 typedef struct tagContext {
41 ITfContext ITfContext_iface;
42 ITfSource ITfSource_iface;
43 /* const ITfContextCompositionVtbl *ContextCompositionVtbl; */
44 ITfContextOwnerCompositionServices ITfContextOwnerCompositionServices_iface;
45 /* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */
46 ITfInsertAtSelection ITfInsertAtSelection_iface;
47 /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */
48 /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */
49 ITfSourceSingle ITfSourceSingle_iface;
50 ITextStoreACPSink ITextStoreACPSink_iface;
51 ITextStoreACPServices ITextStoreACPServices_iface;
52 LONG refCount;
53 BOOL connected;
55 /* Aggregation */
56 ITfCompartmentMgr *CompartmentMgr;
58 TfClientId tidOwner;
59 TfEditCookie defaultCookie;
60 TS_STATUS documentStatus;
61 ITfDocumentMgr *manager;
63 ITextStoreACP *pITextStoreACP;
64 ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink;
66 ITfEditSession* currentEditSession;
68 /* kept as separate lists to reduce unnecessary iterations */
69 struct list pContextKeyEventSink;
70 struct list pEditTransactionSink;
71 struct list pStatusSink;
72 struct list pTextEditSink;
73 struct list pTextLayoutSink;
75 } Context;
77 typedef struct tagEditCookie {
78 DWORD lockType;
79 Context *pOwningContext;
80 } EditCookie;
82 static inline Context *impl_from_ITfContext(ITfContext *iface)
84 return CONTAINING_RECORD(iface, Context, ITfContext_iface);
87 static inline Context *impl_from_ITfSource(ITfSource *iface)
89 return CONTAINING_RECORD(iface, Context, ITfSource_iface);
92 static inline Context *impl_from_ITfContextOwnerCompositionServices(ITfContextOwnerCompositionServices *iface)
94 return CONTAINING_RECORD(iface, Context, ITfContextOwnerCompositionServices_iface);
97 static inline Context *impl_from_ITfInsertAtSelection(ITfInsertAtSelection *iface)
99 return CONTAINING_RECORD(iface, Context, ITfInsertAtSelection_iface);
102 static inline Context *impl_from_ITfSourceSingle(ITfSourceSingle* iface)
104 return CONTAINING_RECORD(iface, Context, ITfSourceSingle_iface);
107 static inline Context *impl_from_ITextStoreACPSink(ITextStoreACPSink *iface)
109 return CONTAINING_RECORD(iface, Context, ITextStoreACPSink_iface);
112 static inline Context *impl_from_ITextStoreACPServices(ITextStoreACPServices *iface)
114 return CONTAINING_RECORD(iface, Context, ITextStoreACPServices_iface);
117 static void Context_Destructor(Context *This)
119 EditCookie *cookie;
120 TRACE("destroying %p\n", This);
122 if (This->pITextStoreACP)
123 ITextStoreACP_Release(This->pITextStoreACP);
125 if (This->pITfContextOwnerCompositionSink)
126 ITfContextOwnerCompositionSink_Release(This->pITfContextOwnerCompositionSink);
128 if (This->defaultCookie)
130 cookie = remove_Cookie(This->defaultCookie);
131 free(cookie);
132 This->defaultCookie = 0;
135 free_sinks(&This->pContextKeyEventSink);
136 free_sinks(&This->pEditTransactionSink);
137 free_sinks(&This->pStatusSink);
138 free_sinks(&This->pTextEditSink);
139 free_sinks(&This->pTextLayoutSink);
141 CompartmentMgr_Destructor(This->CompartmentMgr);
142 free(This);
145 static HRESULT WINAPI Context_QueryInterface(ITfContext *iface, REFIID iid, LPVOID *ppvOut)
147 Context *This = impl_from_ITfContext(iface);
148 *ppvOut = NULL;
150 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfContext))
152 *ppvOut = &This->ITfContext_iface;
154 else if (IsEqualIID(iid, &IID_ITfSource))
156 *ppvOut = &This->ITfSource_iface;
158 else if (IsEqualIID(iid, &IID_ITfContextOwnerCompositionServices))
160 *ppvOut = &This->ITfContextOwnerCompositionServices_iface;
162 else if (IsEqualIID(iid, &IID_ITfInsertAtSelection))
164 *ppvOut = &This->ITfInsertAtSelection_iface;
166 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
168 *ppvOut = This->CompartmentMgr;
170 else if (IsEqualIID(iid, &IID_ITfSourceSingle))
172 *ppvOut = &This->ITfSourceSingle_iface;
175 if (*ppvOut)
177 ITfContext_AddRef(iface);
178 return S_OK;
181 WARN("unsupported interface: %s\n", debugstr_guid(iid));
182 return E_NOINTERFACE;
185 static ULONG WINAPI Context_AddRef(ITfContext *iface)
187 Context *This = impl_from_ITfContext(iface);
188 return InterlockedIncrement(&This->refCount);
191 static ULONG WINAPI Context_Release(ITfContext *iface)
193 Context *This = impl_from_ITfContext(iface);
194 ULONG ret;
196 ret = InterlockedDecrement(&This->refCount);
197 if (ret == 0)
198 Context_Destructor(This);
199 return ret;
202 /*****************************************************
203 * ITfContext functions
204 *****************************************************/
205 static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface,
206 TfClientId tid, ITfEditSession *pes, DWORD dwFlags,
207 HRESULT *phrSession)
209 Context *This = impl_from_ITfContext(iface);
210 HRESULT hr;
211 DWORD dwLockFlags = 0x0;
213 TRACE("(%p) %li %p %lx %p\n",This, tid, pes, dwFlags, phrSession);
215 if (!(dwFlags & TF_ES_READ) && !(dwFlags & TF_ES_READWRITE))
217 *phrSession = E_FAIL;
218 return E_INVALIDARG;
221 if (!This->pITextStoreACP)
223 FIXME("No ITextStoreACP available\n");
224 *phrSession = E_FAIL;
225 return E_FAIL;
228 if (!(dwFlags & TF_ES_ASYNC))
229 dwLockFlags |= TS_LF_SYNC;
231 if ((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE)
232 dwLockFlags |= TS_LF_READWRITE;
233 else if (dwFlags & TF_ES_READ)
234 dwLockFlags |= TS_LF_READ;
236 if (!This->documentStatus.dwDynamicFlags)
237 ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
239 if (((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) && (This->documentStatus.dwDynamicFlags & TS_SD_READONLY))
241 *phrSession = TS_E_READONLY;
242 return S_OK;
245 if (FAILED (ITfEditSession_QueryInterface(pes, &IID_ITfEditSession, (LPVOID*)&This->currentEditSession)))
247 *phrSession = E_FAIL;
248 return E_INVALIDARG;
251 hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession);
253 return hr;
256 static HRESULT WINAPI Context_InWriteSession (ITfContext *iface,
257 TfClientId tid,
258 BOOL *pfWriteSession)
260 Context *This = impl_from_ITfContext(iface);
261 FIXME("STUB:(%p)\n",This);
262 return E_NOTIMPL;
265 static HRESULT WINAPI Context_GetSelection (ITfContext *iface,
266 TfEditCookie ec, ULONG ulIndex, ULONG ulCount,
267 TF_SELECTION *pSelection, ULONG *pcFetched)
269 Context *This = impl_from_ITfContext(iface);
270 ULONG count, i;
271 ULONG totalFetched = 0;
272 HRESULT hr = S_OK;
274 if (!pSelection || !pcFetched)
275 return E_INVALIDARG;
277 *pcFetched = 0;
279 if (!This->connected)
280 return TF_E_DISCONNECTED;
282 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
283 return TF_E_NOLOCK;
285 if (!This->pITextStoreACP)
287 FIXME("Context does not have a ITextStoreACP\n");
288 return E_NOTIMPL;
291 if (ulIndex == TF_DEFAULT_SELECTION)
292 count = 1;
293 else
294 count = ulCount;
296 for (i = 0; i < count; i++)
298 DWORD fetched;
299 TS_SELECTION_ACP acps;
301 hr = ITextStoreACP_GetSelection(This->pITextStoreACP, ulIndex + i,
302 1, &acps, &fetched);
304 if (hr == TS_E_NOLOCK)
305 return TF_E_NOLOCK;
306 else if (SUCCEEDED(hr))
308 pSelection[totalFetched].style.ase = (TfActiveSelEnd)acps.style.ase;
309 pSelection[totalFetched].style.fInterimChar = acps.style.fInterimChar;
310 Range_Constructor(iface, acps.acpStart, acps.acpEnd, &pSelection[totalFetched].range);
311 totalFetched ++;
313 else
314 break;
317 *pcFetched = totalFetched;
319 return hr;
322 static HRESULT WINAPI Context_SetSelection (ITfContext *iface,
323 TfEditCookie ec, ULONG ulCount, const TF_SELECTION *pSelection)
325 Context *This = impl_from_ITfContext(iface);
326 TS_SELECTION_ACP *acp;
327 ULONG i;
328 HRESULT hr;
330 TRACE("(%p) %li %li %p\n",This,ec,ulCount,pSelection);
332 if (!This->pITextStoreACP)
334 FIXME("Context does not have a ITextStoreACP\n");
335 return E_NOTIMPL;
338 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
339 return TF_E_NOLOCK;
341 acp = malloc(sizeof(TS_SELECTION_ACP) * ulCount);
342 if (!acp)
343 return E_OUTOFMEMORY;
345 for (i = 0; i < ulCount; i++)
346 if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection[i], &acp[i])))
348 TRACE("Selection Conversion Failed\n");
349 free(acp);
350 return E_FAIL;
353 hr = ITextStoreACP_SetSelection(This->pITextStoreACP, ulCount, acp);
355 free(acp);
357 return hr;
360 static HRESULT WINAPI Context_GetStart (ITfContext *iface,
361 TfEditCookie ec, ITfRange **ppStart)
363 Context *This = impl_from_ITfContext(iface);
365 TRACE("(%p) %li %p\n",This,ec,ppStart);
367 if (!ppStart)
368 return E_INVALIDARG;
370 *ppStart = NULL;
372 if (!This->connected)
373 return TF_E_DISCONNECTED;
375 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
376 return TF_E_NOLOCK;
378 return Range_Constructor(iface, 0, 0, ppStart);
381 static HRESULT WINAPI Context_GetEnd (ITfContext *iface,
382 TfEditCookie ec, ITfRange **ppEnd)
384 Context *This = impl_from_ITfContext(iface);
385 LONG end;
386 TRACE("(%p) %li %p\n",This,ec,ppEnd);
388 if (!ppEnd)
389 return E_INVALIDARG;
391 *ppEnd = NULL;
393 if (!This->connected)
394 return TF_E_DISCONNECTED;
396 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
397 return TF_E_NOLOCK;
399 if (!This->pITextStoreACP)
401 FIXME("Context does not have a ITextStoreACP\n");
402 return E_NOTIMPL;
405 ITextStoreACP_GetEndACP(This->pITextStoreACP,&end);
407 return Range_Constructor(iface, end, end, ppEnd);
410 static HRESULT WINAPI Context_GetActiveView (ITfContext *iface,
411 ITfContextView **ppView)
413 Context *This = impl_from_ITfContext(iface);
414 FIXME("STUB:(%p)\n",This);
415 return E_NOTIMPL;
418 static HRESULT WINAPI Context_EnumViews (ITfContext *iface,
419 IEnumTfContextViews **ppEnum)
421 Context *This = impl_from_ITfContext(iface);
422 FIXME("STUB:(%p)\n",This);
423 return E_NOTIMPL;
426 static HRESULT WINAPI Context_GetStatus (ITfContext *iface,
427 TF_STATUS *pdcs)
429 Context *This = impl_from_ITfContext(iface);
430 TRACE("(%p) %p\n",This,pdcs);
432 if (!This->connected)
433 return TF_E_DISCONNECTED;
435 if (!pdcs)
436 return E_INVALIDARG;
438 if (!This->pITextStoreACP)
440 FIXME("Context does not have a ITextStoreACP\n");
441 return E_NOTIMPL;
444 ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
446 *pdcs = This->documentStatus;
448 return S_OK;
451 static HRESULT WINAPI Context_GetProperty (ITfContext *iface,
452 REFGUID guidProp, ITfProperty **ppProp)
454 Context *This = impl_from_ITfContext(iface);
455 FIXME("STUB:(%p)\n",This);
456 return E_NOTIMPL;
459 static HRESULT WINAPI Context_GetAppProperty (ITfContext *iface,
460 REFGUID guidProp, ITfReadOnlyProperty **ppProp)
462 Context *This = impl_from_ITfContext(iface);
463 FIXME("STUB:(%p)\n",This);
464 return E_NOTIMPL;
467 static HRESULT WINAPI Context_TrackProperties (ITfContext *iface,
468 const GUID **prgProp, ULONG cProp, const GUID **prgAppProp,
469 ULONG cAppProp, ITfReadOnlyProperty **ppProperty)
471 Context *This = impl_from_ITfContext(iface);
472 FIXME("STUB:(%p)\n",This);
473 return E_NOTIMPL;
476 static HRESULT WINAPI Context_EnumProperties (ITfContext *iface,
477 IEnumTfProperties **ppEnum)
479 Context *This = impl_from_ITfContext(iface);
480 FIXME("STUB:(%p)\n",This);
481 return E_NOTIMPL;
484 static HRESULT WINAPI Context_GetDocumentMgr (ITfContext *iface,
485 ITfDocumentMgr **ppDm)
487 Context *This = impl_from_ITfContext(iface);
488 TRACE("(%p) %p\n",This,ppDm);
490 if (!ppDm)
491 return E_INVALIDARG;
493 *ppDm = This->manager;
494 if (!This->manager)
495 return S_FALSE;
497 ITfDocumentMgr_AddRef(This->manager);
499 return S_OK;
502 static HRESULT WINAPI Context_CreateRangeBackup (ITfContext *iface,
503 TfEditCookie ec, ITfRange *pRange, ITfRangeBackup **ppBackup)
505 Context *This = impl_from_ITfContext(iface);
506 FIXME("STUB:(%p)\n",This);
507 return E_NOTIMPL;
510 static const ITfContextVtbl ContextVtbl =
512 Context_QueryInterface,
513 Context_AddRef,
514 Context_Release,
515 Context_RequestEditSession,
516 Context_InWriteSession,
517 Context_GetSelection,
518 Context_SetSelection,
519 Context_GetStart,
520 Context_GetEnd,
521 Context_GetActiveView,
522 Context_EnumViews,
523 Context_GetStatus,
524 Context_GetProperty,
525 Context_GetAppProperty,
526 Context_TrackProperties,
527 Context_EnumProperties,
528 Context_GetDocumentMgr,
529 Context_CreateRangeBackup
532 /*****************************************************
533 * ITfSource functions
534 *****************************************************/
535 static HRESULT WINAPI ContextSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
537 Context *This = impl_from_ITfSource(iface);
538 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
541 static ULONG WINAPI ContextSource_AddRef(ITfSource *iface)
543 Context *This = impl_from_ITfSource(iface);
544 return ITfContext_AddRef(&This->ITfContext_iface);
547 static ULONG WINAPI ContextSource_Release(ITfSource *iface)
549 Context *This = impl_from_ITfSource(iface);
550 return ITfContext_Release(&This->ITfContext_iface);
553 static HRESULT WINAPI ContextSource_AdviseSink(ITfSource *iface,
554 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
556 Context *This = impl_from_ITfSource(iface);
558 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
560 if (!riid || !punk || !pdwCookie)
561 return E_INVALIDARG;
563 if (IsEqualIID(riid, &IID_ITfTextEditSink))
564 return advise_sink(&This->pTextEditSink, &IID_ITfTextEditSink, COOKIE_MAGIC_CONTEXTSINK, punk, pdwCookie);
566 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
567 return E_NOTIMPL;
570 static HRESULT WINAPI ContextSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
572 Context *This = impl_from_ITfSource(iface);
574 TRACE("(%p) %lx\n",This,pdwCookie);
576 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_CONTEXTSINK)
577 return E_INVALIDARG;
579 return unadvise_sink(pdwCookie);
582 static const ITfSourceVtbl ContextSourceVtbl =
584 ContextSource_QueryInterface,
585 ContextSource_AddRef,
586 ContextSource_Release,
587 ContextSource_AdviseSink,
588 ContextSource_UnadviseSink
591 /*****************************************************
592 * ITfContextOwnerCompositionServices functions
593 *****************************************************/
594 static HRESULT WINAPI ContextOwnerCompositionServices_QueryInterface(ITfContextOwnerCompositionServices *iface,
595 REFIID iid, LPVOID *ppvOut)
597 Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
598 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
601 static ULONG WINAPI ContextOwnerCompositionServices_AddRef(ITfContextOwnerCompositionServices *iface)
603 Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
604 return ITfContext_AddRef(&This->ITfContext_iface);
607 static ULONG WINAPI ContextOwnerCompositionServices_Release(ITfContextOwnerCompositionServices *iface)
609 Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
610 return ITfContext_Release(&This->ITfContext_iface);
613 static HRESULT WINAPI ContextOwnerCompositionServices_StartComposition(ITfContextOwnerCompositionServices *iface,
614 TfEditCookie ecWrite, ITfRange *pCompositionRange, ITfCompositionSink *pSink, ITfComposition **ppComposition)
616 Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
617 FIXME("STUB:(%p) %#lx %p %p %p\n", This, ecWrite, pCompositionRange, pSink, ppComposition);
618 return E_NOTIMPL;
621 static HRESULT WINAPI ContextOwnerCompositionServices_EnumCompositions(ITfContextOwnerCompositionServices *iface,
622 IEnumITfCompositionView **ppEnum)
624 Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
625 FIXME("STUB:(%p) %p\n", This, ppEnum);
626 return E_NOTIMPL;
629 static HRESULT WINAPI ContextOwnerCompositionServices_FindComposition(ITfContextOwnerCompositionServices *iface,
630 TfEditCookie ecRead, ITfRange *pTestRange, IEnumITfCompositionView **ppEnum)
632 Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
633 FIXME("STUB:(%p) %#lx %p %p\n", This, ecRead, pTestRange, ppEnum);
634 return E_NOTIMPL;
637 static HRESULT WINAPI ContextOwnerCompositionServices_TakeOwnership(ITfContextOwnerCompositionServices *iface,
638 TfEditCookie ecWrite, ITfCompositionView *pComposition, ITfCompositionSink *pSink, ITfComposition **ppComposition)
640 Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
641 FIXME("STUB:(%p) %#lx %p %p %p\n", This, ecWrite, pComposition, pSink, ppComposition);
642 return E_NOTIMPL;
645 static HRESULT WINAPI ContextOwnerCompositionServices_TerminateComposition(ITfContextOwnerCompositionServices *iface,
646 ITfCompositionView *pComposition)
648 Context *This = impl_from_ITfContextOwnerCompositionServices(iface);
649 FIXME("STUB:(%p) %p\n", This, pComposition);
650 return E_NOTIMPL;
653 static const ITfContextOwnerCompositionServicesVtbl ContextOwnerCompositionServicesVtbl =
655 ContextOwnerCompositionServices_QueryInterface,
656 ContextOwnerCompositionServices_AddRef,
657 ContextOwnerCompositionServices_Release,
658 ContextOwnerCompositionServices_StartComposition,
659 ContextOwnerCompositionServices_EnumCompositions,
660 ContextOwnerCompositionServices_FindComposition,
661 ContextOwnerCompositionServices_TakeOwnership,
662 ContextOwnerCompositionServices_TerminateComposition
665 /*****************************************************
666 * ITfInsertAtSelection functions
667 *****************************************************/
668 static HRESULT WINAPI InsertAtSelection_QueryInterface(ITfInsertAtSelection *iface, REFIID iid, LPVOID *ppvOut)
670 Context *This = impl_from_ITfInsertAtSelection(iface);
671 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
674 static ULONG WINAPI InsertAtSelection_AddRef(ITfInsertAtSelection *iface)
676 Context *This = impl_from_ITfInsertAtSelection(iface);
677 return ITfContext_AddRef(&This->ITfContext_iface);
680 static ULONG WINAPI InsertAtSelection_Release(ITfInsertAtSelection *iface)
682 Context *This = impl_from_ITfInsertAtSelection(iface);
683 return ITfContext_Release(&This->ITfContext_iface);
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_ITfInsertAtSelection(iface);
691 EditCookie *cookie;
692 LONG acpStart, acpEnd;
693 TS_TEXTCHANGE change;
694 HRESULT hr;
696 TRACE("(%p) %li %lx %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)
702 return TF_E_NOLOCK;
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");
712 return E_NOTIMPL;
715 hr = ITextStoreACP_InsertTextAtSelection(This->pITextStoreACP, dwFlags, pchText, cch, &acpStart, &acpEnd, &change);
716 if (SUCCEEDED(hr))
717 Range_Constructor(&This->ITfContext_iface, change.acpStart, change.acpNewEnd, ppRange);
719 return hr;
722 static HRESULT WINAPI InsertAtSelection_InsertEmbeddedAtSelection(
723 ITfInsertAtSelection *iface, TfEditCookie ec, DWORD dwFlags,
724 IDataObject *pDataObject, ITfRange **ppRange)
726 Context *This = impl_from_ITfInsertAtSelection(iface);
727 FIXME("STUB:(%p)\n",This);
728 return E_NOTIMPL;
731 static const ITfInsertAtSelectionVtbl InsertAtSelectionVtbl =
733 InsertAtSelection_QueryInterface,
734 InsertAtSelection_AddRef,
735 InsertAtSelection_Release,
736 InsertAtSelection_InsertTextAtSelection,
737 InsertAtSelection_InsertEmbeddedAtSelection,
740 /*****************************************************
741 * ITfSourceSingle functions
742 *****************************************************/
743 static HRESULT WINAPI SourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
745 Context *This = impl_from_ITfSourceSingle(iface);
746 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
749 static ULONG WINAPI SourceSingle_AddRef(ITfSourceSingle *iface)
751 Context *This = impl_from_ITfSourceSingle(iface);
752 return ITfContext_AddRef(&This->ITfContext_iface);
755 static ULONG WINAPI SourceSingle_Release(ITfSourceSingle *iface)
757 Context *This = impl_from_ITfSourceSingle(iface);
758 return ITfContext_Release(&This->ITfContext_iface);
761 static HRESULT WINAPI SourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
762 TfClientId tid, REFIID riid, IUnknown *punk)
764 Context *This = impl_from_ITfSourceSingle(iface);
765 FIXME("STUB:(%p) %li %s %p\n",This, tid, debugstr_guid(riid),punk);
766 return E_NOTIMPL;
769 static HRESULT WINAPI SourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
770 TfClientId tid, REFIID riid)
772 Context *This = impl_from_ITfSourceSingle(iface);
773 FIXME("STUB:(%p) %li %s\n",This, tid, debugstr_guid(riid));
774 return E_NOTIMPL;
777 static const ITfSourceSingleVtbl ContextSourceSingleVtbl =
779 SourceSingle_QueryInterface,
780 SourceSingle_AddRef,
781 SourceSingle_Release,
782 SourceSingle_AdviseSingleSink,
783 SourceSingle_UnadviseSingleSink,
786 /**************************************************************************
787 * ITextStoreACPSink
788 **************************************************************************/
790 static HRESULT WINAPI TextStoreACPSink_QueryInterface(ITextStoreACPSink *iface, REFIID iid, LPVOID *ppvOut)
792 Context *This = impl_from_ITextStoreACPSink(iface);
794 *ppvOut = NULL;
796 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACPSink))
798 *ppvOut = &This->ITextStoreACPSink_iface;
800 else if (IsEqualIID(iid, &IID_ITextStoreACPServices))
801 *ppvOut = &This->ITextStoreACPServices_iface;
803 if (*ppvOut)
805 ITextStoreACPSink_AddRef(iface);
806 return S_OK;
809 WARN("unsupported interface: %s\n", debugstr_guid(iid));
810 return E_NOINTERFACE;
813 static ULONG WINAPI TextStoreACPSink_AddRef(ITextStoreACPSink *iface)
815 Context *This = impl_from_ITextStoreACPSink(iface);
816 return ITfContext_AddRef(&This->ITfContext_iface);
819 static ULONG WINAPI TextStoreACPSink_Release(ITextStoreACPSink *iface)
821 Context *This = impl_from_ITextStoreACPSink(iface);
822 return ITfContext_Release(&This->ITfContext_iface);
825 /*****************************************************
826 * ITextStoreACPSink functions
827 *****************************************************/
829 static HRESULT WINAPI TextStoreACPSink_OnTextChange(ITextStoreACPSink *iface,
830 DWORD dwFlags, const TS_TEXTCHANGE *pChange)
832 Context *This = impl_from_ITextStoreACPSink(iface);
833 FIXME("STUB:(%p)\n",This);
834 return S_OK;
837 static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface)
839 Context *This = impl_from_ITextStoreACPSink(iface);
840 FIXME("STUB:(%p)\n",This);
841 return S_OK;
844 static HRESULT WINAPI TextStoreACPSink_OnLayoutChange(ITextStoreACPSink *iface,
845 TsLayoutCode lcode, TsViewCookie vcView)
847 Context *This = impl_from_ITextStoreACPSink(iface);
848 FIXME("STUB:(%p)\n",This);
849 return S_OK;
852 static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface,
853 DWORD dwFlags)
855 Context *This = impl_from_ITextStoreACPSink(iface);
856 HRESULT hr, hrSession;
858 TRACE("(%p) %lx\n",This, dwFlags);
860 if (!This->pITextStoreACP)
862 FIXME("Context does not have a ITextStoreACP\n");
863 return E_NOTIMPL;
866 hr = ITextStoreACP_RequestLock(This->pITextStoreACP, TS_LF_READ, &hrSession);
868 if(SUCCEEDED(hr) && SUCCEEDED(hrSession))
869 This->documentStatus.dwDynamicFlags = dwFlags;
871 return S_OK;
874 static HRESULT WINAPI TextStoreACPSink_OnAttrsChange(ITextStoreACPSink *iface,
875 LONG acpStart, LONG acpEnd, ULONG cAttrs, const TS_ATTRID *paAttrs)
877 Context *This = impl_from_ITextStoreACPSink(iface);
878 FIXME("STUB:(%p)\n",This);
879 return E_NOTIMPL;
882 static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface,
883 DWORD dwLockFlags)
885 Context *This = impl_from_ITextStoreACPSink(iface);
886 HRESULT hr;
887 EditCookie *cookie,*sinkcookie;
888 TfEditCookie ec;
889 struct list *cursor;
891 TRACE("(%p) %lx\n",This, dwLockFlags);
893 if (!This->currentEditSession)
895 FIXME("OnLockGranted called for something other than an EditSession\n");
896 return S_OK;
899 cookie = malloc(sizeof(EditCookie));
900 if (!cookie)
901 return E_OUTOFMEMORY;
903 sinkcookie = malloc(sizeof(EditCookie));
904 if (!sinkcookie)
906 free(cookie);
907 return E_OUTOFMEMORY;
910 cookie->lockType = dwLockFlags;
911 cookie->pOwningContext = This;
912 ec = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, cookie);
914 hr = ITfEditSession_DoEditSession(This->currentEditSession, ec);
916 if ((dwLockFlags&TS_LF_READWRITE) == TS_LF_READWRITE)
918 ITfTextEditSink *sink;
919 TfEditCookie sc;
921 sinkcookie->lockType = TS_LF_READ;
922 sinkcookie->pOwningContext = This;
923 sc = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, sinkcookie);
925 /*TODO: implement ITfEditRecord */
926 SINK_FOR_EACH(cursor, &This->pTextEditSink, ITfTextEditSink, sink)
928 ITfTextEditSink_OnEndEdit(sink, &This->ITfContext_iface, sc, NULL);
930 sinkcookie = remove_Cookie(sc);
932 free(sinkcookie);
934 ITfEditSession_Release(This->currentEditSession);
935 This->currentEditSession = NULL;
937 /* Edit Cookie is only valid during the edit session */
938 cookie = remove_Cookie(ec);
939 free(cookie);
941 return hr;
944 static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface)
946 Context *This = impl_from_ITextStoreACPSink(iface);
947 FIXME("STUB:(%p)\n",This);
948 return E_NOTIMPL;
951 static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface)
953 Context *This = impl_from_ITextStoreACPSink(iface);
954 FIXME("STUB:(%p)\n",This);
955 return E_NOTIMPL;
958 static const ITextStoreACPSinkVtbl TextStoreACPSinkVtbl =
960 TextStoreACPSink_QueryInterface,
961 TextStoreACPSink_AddRef,
962 TextStoreACPSink_Release,
963 TextStoreACPSink_OnTextChange,
964 TextStoreACPSink_OnSelectionChange,
965 TextStoreACPSink_OnLayoutChange,
966 TextStoreACPSink_OnStatusChange,
967 TextStoreACPSink_OnAttrsChange,
968 TextStoreACPSink_OnLockGranted,
969 TextStoreACPSink_OnStartEditTransaction,
970 TextStoreACPSink_OnEndEditTransaction
973 static HRESULT WINAPI TextStoreACPServices_QueryInterface(ITextStoreACPServices *iface, REFIID riid, void **obj)
975 Context *This = impl_from_ITextStoreACPServices(iface);
976 return ITextStoreACPSink_QueryInterface(&This->ITextStoreACPSink_iface, riid, obj);
979 static ULONG WINAPI TextStoreACPServices_AddRef(ITextStoreACPServices *iface)
981 Context *This = impl_from_ITextStoreACPServices(iface);
982 return ITextStoreACPSink_AddRef(&This->ITextStoreACPSink_iface);
985 static ULONG WINAPI TextStoreACPServices_Release(ITextStoreACPServices *iface)
987 Context *This = impl_from_ITextStoreACPServices(iface);
988 return ITextStoreACPSink_Release(&This->ITextStoreACPSink_iface);
991 static HRESULT WINAPI TextStoreACPServices_Serialize(ITextStoreACPServices *iface, ITfProperty *prop, ITfRange *range,
992 TF_PERSISTENT_PROPERTY_HEADER_ACP *header, IStream *stream)
994 Context *This = impl_from_ITextStoreACPServices(iface);
996 FIXME("stub: %p %p %p %p %p\n", This, prop, range, header, stream);
998 return E_NOTIMPL;
1001 static HRESULT WINAPI TextStoreACPServices_Unserialize(ITextStoreACPServices *iface, ITfProperty *prop,
1002 const TF_PERSISTENT_PROPERTY_HEADER_ACP *header, IStream *stream, ITfPersistentPropertyLoaderACP *loader)
1004 Context *This = impl_from_ITextStoreACPServices(iface);
1006 FIXME("stub: %p %p %p %p %p\n", This, prop, header, stream, loader);
1008 return E_NOTIMPL;
1011 static HRESULT WINAPI TextStoreACPServices_ForceLoadProperty(ITextStoreACPServices *iface, ITfProperty *prop)
1013 Context *This = impl_from_ITextStoreACPServices(iface);
1015 FIXME("stub: %p %p\n", This, prop);
1017 return E_NOTIMPL;
1020 static HRESULT WINAPI TextStoreACPServices_CreateRange(ITextStoreACPServices *iface,
1021 LONG start, LONG end, ITfRangeACP **range)
1023 Context *This = impl_from_ITextStoreACPServices(iface);
1025 TRACE("%p, %ld, %ld, %p.\n", This, start, end, range);
1027 return Range_Constructor(&This->ITfContext_iface, start, end, (ITfRange **)range);
1030 static const ITextStoreACPServicesVtbl TextStoreACPServicesVtbl =
1032 TextStoreACPServices_QueryInterface,
1033 TextStoreACPServices_AddRef,
1034 TextStoreACPServices_Release,
1035 TextStoreACPServices_Serialize,
1036 TextStoreACPServices_Unserialize,
1037 TextStoreACPServices_ForceLoadProperty,
1038 TextStoreACPServices_CreateRange
1041 HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore)
1043 Context *This;
1044 EditCookie *cookie;
1046 This = calloc(1, sizeof(Context));
1047 if (This == NULL)
1048 return E_OUTOFMEMORY;
1050 cookie = malloc(sizeof(EditCookie));
1051 if (cookie == NULL)
1053 free(This);
1054 return E_OUTOFMEMORY;
1057 TRACE("(%p) %lx %p %p %p\n",This, tidOwner, punk, ppOut, pecTextStore);
1059 This->ITfContext_iface.lpVtbl= &ContextVtbl;
1060 This->ITfSource_iface.lpVtbl = &ContextSourceVtbl;
1061 This->ITfContextOwnerCompositionServices_iface.lpVtbl = &ContextOwnerCompositionServicesVtbl;
1062 This->ITfInsertAtSelection_iface.lpVtbl = &InsertAtSelectionVtbl;
1063 This->ITfSourceSingle_iface.lpVtbl = &ContextSourceSingleVtbl;
1064 This->ITextStoreACPSink_iface.lpVtbl = &TextStoreACPSinkVtbl;
1065 This->ITextStoreACPServices_iface.lpVtbl = &TextStoreACPServicesVtbl;
1066 This->refCount = 1;
1067 This->tidOwner = tidOwner;
1068 This->connected = FALSE;
1069 This->manager = mgr;
1071 CompartmentMgr_Constructor((IUnknown*)&This->ITfContext_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1073 cookie->lockType = TF_ES_READ;
1074 cookie->pOwningContext = This;
1076 if (punk)
1078 IUnknown_QueryInterface(punk, &IID_ITextStoreACP,
1079 (LPVOID*)&This->pITextStoreACP);
1081 IUnknown_QueryInterface(punk, &IID_ITfContextOwnerCompositionSink,
1082 (LPVOID*)&This->pITfContextOwnerCompositionSink);
1084 if (!This->pITextStoreACP && !This->pITfContextOwnerCompositionSink)
1085 FIXME("Unhandled pUnk\n");
1088 This->defaultCookie = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE,cookie);
1089 *pecTextStore = This->defaultCookie;
1091 list_init(&This->pContextKeyEventSink);
1092 list_init(&This->pEditTransactionSink);
1093 list_init(&This->pStatusSink);
1094 list_init(&This->pTextEditSink);
1095 list_init(&This->pTextLayoutSink);
1097 *ppOut = &This->ITfContext_iface;
1098 TRACE("returning %p\n", *ppOut);
1100 return S_OK;
1103 HRESULT Context_Initialize(ITfContext *iface, ITfDocumentMgr *manager)
1105 Context *This = impl_from_ITfContext(iface);
1107 if (This->pITextStoreACP)
1108 ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink,
1109 (IUnknown*)&This->ITextStoreACPSink_iface, TS_AS_ALL_SINKS);
1110 This->connected = TRUE;
1111 This->manager = manager;
1112 return S_OK;
1115 HRESULT Context_Uninitialize(ITfContext *iface)
1117 Context *This = impl_from_ITfContext(iface);
1119 if (This->pITextStoreACP)
1120 ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)&This->ITextStoreACPSink_iface);
1121 This->connected = FALSE;
1122 This->manager = NULL;
1123 return S_OK;