qedit: Stub out AMTimeline.
[wine.git] / dlls / msctf / context.c
blob5a45466f4113758971b0492d493d9f52dd8b1701
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 "config.h"
23 #include <stdarg.h>
25 #define COBJMACROS
27 #include "wine/debug.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winuser.h"
32 #include "shlwapi.h"
33 #include "winerror.h"
34 #include "objbase.h"
35 #include "olectl.h"
37 #include "wine/unicode.h"
38 #include "wine/list.h"
40 #include "msctf.h"
41 #include "msctf_internal.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
45 typedef struct tagContextSink {
46 struct list entry;
47 union {
48 /* Context Sinks */
49 IUnknown *pIUnknown;
50 /* ITfContextKeyEventSink *pITfContextKeyEventSink; */
51 /* ITfEditTransactionSink *pITfEditTransactionSink; */
52 /* ITfStatusSink *pITfStatusSink; */
53 ITfTextEditSink *pITfTextEditSink;
54 /* ITfTextLayoutSink *pITfTextLayoutSink; */
55 } interfaces;
56 } ContextSink;
58 typedef struct tagContext {
59 ITfContext ITfContext_iface;
60 ITfSource ITfSource_iface;
61 /* const ITfContextCompositionVtbl *ContextCompositionVtbl; */
62 /* const ITfContextOwnerCompositionServicesVtbl *ContextOwnerCompositionServicesVtbl; */
63 /* const ITfContextOwnerServicesVtbl *ContextOwnerServicesVtbl; */
64 ITfInsertAtSelection ITfInsertAtSelection_iface;
65 /* const ITfMouseTrackerVtbl *MouseTrackerVtbl; */
66 /* const ITfQueryEmbeddedVtbl *QueryEmbeddedVtbl; */
67 ITfSourceSingle ITfSourceSingle_iface;
68 ITextStoreACPSink ITextStoreACPSink_iface;
69 ITextStoreACPServices ITextStoreACPServices_iface;
70 LONG refCount;
71 BOOL connected;
73 /* Aggregation */
74 ITfCompartmentMgr *CompartmentMgr;
76 TfClientId tidOwner;
77 TfEditCookie defaultCookie;
78 TS_STATUS documentStatus;
79 ITfDocumentMgr *manager;
81 ITextStoreACP *pITextStoreACP;
82 ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink;
84 ITfEditSession* currentEditSession;
86 /* kept as separate lists to reduce unnecessary iterations */
87 struct list pContextKeyEventSink;
88 struct list pEditTransactionSink;
89 struct list pStatusSink;
90 struct list pTextEditSink;
91 struct list pTextLayoutSink;
93 } Context;
95 typedef struct tagEditCookie {
96 DWORD lockType;
97 Context *pOwningContext;
98 } EditCookie;
100 static inline Context *impl_from_ITfContext(ITfContext *iface)
102 return CONTAINING_RECORD(iface, Context, ITfContext_iface);
105 static inline Context *impl_from_ITfSource(ITfSource *iface)
107 return CONTAINING_RECORD(iface, Context, ITfSource_iface);
110 static inline Context *impl_from_ITfInsertAtSelection(ITfInsertAtSelection *iface)
112 return CONTAINING_RECORD(iface, Context, ITfInsertAtSelection_iface);
115 static inline Context *impl_from_ITfSourceSingle(ITfSourceSingle* iface)
117 return CONTAINING_RECORD(iface, Context, ITfSourceSingle_iface);
120 static inline Context *impl_from_ITextStoreACPSink(ITextStoreACPSink *iface)
122 return CONTAINING_RECORD(iface, Context, ITextStoreACPSink_iface);
125 static inline Context *impl_from_ITextStoreACPServices(ITextStoreACPServices *iface)
127 return CONTAINING_RECORD(iface, Context, ITextStoreACPServices_iface);
130 static void free_sink(ContextSink *sink)
132 IUnknown_Release(sink->interfaces.pIUnknown);
133 HeapFree(GetProcessHeap(),0,sink);
136 static void Context_Destructor(Context *This)
138 struct list *cursor, *cursor2;
139 EditCookie *cookie;
140 TRACE("destroying %p\n", This);
142 if (This->pITextStoreACP)
144 ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)&This->ITextStoreACPSink_iface);
145 ITextStoreACP_Release(This->pITextStoreACP);
148 if (This->pITfContextOwnerCompositionSink)
149 ITfContextOwnerCompositionSink_Release(This->pITfContextOwnerCompositionSink);
151 if (This->defaultCookie)
153 cookie = remove_Cookie(This->defaultCookie);
154 HeapFree(GetProcessHeap(),0,cookie);
155 This->defaultCookie = 0;
158 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pContextKeyEventSink)
160 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
161 list_remove(cursor);
162 free_sink(sink);
164 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pEditTransactionSink)
166 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
167 list_remove(cursor);
168 free_sink(sink);
170 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pStatusSink)
172 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
173 list_remove(cursor);
174 free_sink(sink);
176 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextEditSink)
178 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
179 list_remove(cursor);
180 free_sink(sink);
182 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextLayoutSink)
184 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
185 list_remove(cursor);
186 free_sink(sink);
189 CompartmentMgr_Destructor(This->CompartmentMgr);
190 HeapFree(GetProcessHeap(),0,This);
193 static HRESULT WINAPI Context_QueryInterface(ITfContext *iface, REFIID iid, LPVOID *ppvOut)
195 Context *This = impl_from_ITfContext(iface);
196 *ppvOut = NULL;
198 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfContext))
200 *ppvOut = &This->ITfContext_iface;
202 else if (IsEqualIID(iid, &IID_ITfSource))
204 *ppvOut = &This->ITfSource_iface;
206 else if (IsEqualIID(iid, &IID_ITfInsertAtSelection))
208 *ppvOut = &This->ITfInsertAtSelection_iface;
210 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
212 *ppvOut = This->CompartmentMgr;
214 else if (IsEqualIID(iid, &IID_ITfSourceSingle))
216 *ppvOut = &This->ITfSourceSingle_iface;
219 if (*ppvOut)
221 ITfContext_AddRef(iface);
222 return S_OK;
225 WARN("unsupported interface: %s\n", debugstr_guid(iid));
226 return E_NOINTERFACE;
229 static ULONG WINAPI Context_AddRef(ITfContext *iface)
231 Context *This = impl_from_ITfContext(iface);
232 return InterlockedIncrement(&This->refCount);
235 static ULONG WINAPI Context_Release(ITfContext *iface)
237 Context *This = impl_from_ITfContext(iface);
238 ULONG ret;
240 ret = InterlockedDecrement(&This->refCount);
241 if (ret == 0)
242 Context_Destructor(This);
243 return ret;
246 /*****************************************************
247 * ITfContext functions
248 *****************************************************/
249 static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface,
250 TfClientId tid, ITfEditSession *pes, DWORD dwFlags,
251 HRESULT *phrSession)
253 Context *This = impl_from_ITfContext(iface);
254 HRESULT hr;
255 DWORD dwLockFlags = 0x0;
257 TRACE("(%p) %i %p %x %p\n",This, tid, pes, dwFlags, phrSession);
259 if (!(dwFlags & TF_ES_READ) && !(dwFlags & TF_ES_READWRITE))
261 *phrSession = E_FAIL;
262 return E_INVALIDARG;
265 if (!This->pITextStoreACP)
267 FIXME("No ITextStoreACP available\n");
268 *phrSession = E_FAIL;
269 return E_FAIL;
272 if (!(dwFlags & TF_ES_ASYNC))
273 dwLockFlags |= TS_LF_SYNC;
275 if ((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE)
276 dwLockFlags |= TS_LF_READWRITE;
277 else if (dwFlags & TF_ES_READ)
278 dwLockFlags |= TS_LF_READ;
280 if (!This->documentStatus.dwDynamicFlags)
281 ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
283 if (((dwFlags & TF_ES_READWRITE) == TF_ES_READWRITE) && (This->documentStatus.dwDynamicFlags & TS_SD_READONLY))
285 *phrSession = TS_E_READONLY;
286 return S_OK;
289 if (FAILED (ITfEditSession_QueryInterface(pes, &IID_ITfEditSession, (LPVOID*)&This->currentEditSession)))
291 *phrSession = E_FAIL;
292 return E_INVALIDARG;
295 hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession);
297 return hr;
300 static HRESULT WINAPI Context_InWriteSession (ITfContext *iface,
301 TfClientId tid,
302 BOOL *pfWriteSession)
304 Context *This = impl_from_ITfContext(iface);
305 FIXME("STUB:(%p)\n",This);
306 return E_NOTIMPL;
309 static HRESULT WINAPI Context_GetSelection (ITfContext *iface,
310 TfEditCookie ec, ULONG ulIndex, ULONG ulCount,
311 TF_SELECTION *pSelection, ULONG *pcFetched)
313 Context *This = impl_from_ITfContext(iface);
314 EditCookie *cookie;
315 ULONG count, i;
316 ULONG totalFetched = 0;
317 HRESULT hr = S_OK;
319 if (!pSelection || !pcFetched)
320 return E_INVALIDARG;
322 *pcFetched = 0;
324 if (!This->connected)
325 return TF_E_DISCONNECTED;
327 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
328 return TF_E_NOLOCK;
330 if (!This->pITextStoreACP)
332 FIXME("Context does not have a ITextStoreACP\n");
333 return E_NOTIMPL;
336 cookie = get_Cookie_data(ec);
338 if (ulIndex == TF_DEFAULT_SELECTION)
339 count = 1;
340 else
341 count = ulCount;
343 for (i = 0; i < count; i++)
345 DWORD fetched;
346 TS_SELECTION_ACP acps;
348 hr = ITextStoreACP_GetSelection(This->pITextStoreACP, ulIndex + i,
349 1, &acps, &fetched);
351 if (hr == TS_E_NOLOCK)
352 return TF_E_NOLOCK;
353 else if (SUCCEEDED(hr))
355 pSelection[totalFetched].style.ase = acps.style.ase;
356 pSelection[totalFetched].style.fInterimChar = acps.style.fInterimChar;
357 Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, acps.acpStart, acps.acpEnd, &pSelection[totalFetched].range);
358 totalFetched ++;
360 else
361 break;
364 *pcFetched = totalFetched;
366 return hr;
369 static HRESULT WINAPI Context_SetSelection (ITfContext *iface,
370 TfEditCookie ec, ULONG ulCount, const TF_SELECTION *pSelection)
372 Context *This = impl_from_ITfContext(iface);
373 TS_SELECTION_ACP *acp;
374 ULONG i;
375 HRESULT hr;
377 TRACE("(%p) %i %i %p\n",This,ec,ulCount,pSelection);
379 if (!This->pITextStoreACP)
381 FIXME("Context does not have a ITextStoreACP\n");
382 return E_NOTIMPL;
385 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
386 return TF_E_NOLOCK;
388 acp = HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP) * ulCount);
389 if (!acp)
390 return E_OUTOFMEMORY;
392 for (i = 0; i < ulCount; i++)
393 if (FAILED(TF_SELECTION_to_TS_SELECTION_ACP(&pSelection[i], &acp[i])))
395 TRACE("Selection Conversion Failed\n");
396 HeapFree(GetProcessHeap(), 0 , acp);
397 return E_FAIL;
400 hr = ITextStoreACP_SetSelection(This->pITextStoreACP, ulCount, acp);
402 HeapFree(GetProcessHeap(), 0, acp);
404 return hr;
407 static HRESULT WINAPI Context_GetStart (ITfContext *iface,
408 TfEditCookie ec, ITfRange **ppStart)
410 Context *This = impl_from_ITfContext(iface);
411 EditCookie *cookie;
412 TRACE("(%p) %i %p\n",This,ec,ppStart);
414 if (!ppStart)
415 return E_INVALIDARG;
417 *ppStart = NULL;
419 if (!This->connected)
420 return TF_E_DISCONNECTED;
422 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
423 return TF_E_NOLOCK;
425 cookie = get_Cookie_data(ec);
426 return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, 0, 0, ppStart);
429 static HRESULT WINAPI Context_GetEnd (ITfContext *iface,
430 TfEditCookie ec, ITfRange **ppEnd)
432 Context *This = impl_from_ITfContext(iface);
433 EditCookie *cookie;
434 LONG end;
435 TRACE("(%p) %i %p\n",This,ec,ppEnd);
437 if (!ppEnd)
438 return E_INVALIDARG;
440 *ppEnd = NULL;
442 if (!This->connected)
443 return TF_E_DISCONNECTED;
445 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
446 return TF_E_NOLOCK;
448 if (!This->pITextStoreACP)
450 FIXME("Context does not have a ITextStoreACP\n");
451 return E_NOTIMPL;
454 cookie = get_Cookie_data(ec);
455 ITextStoreACP_GetEndACP(This->pITextStoreACP,&end);
457 return Range_Constructor(iface, This->pITextStoreACP, cookie->lockType, end, end, ppEnd);
460 static HRESULT WINAPI Context_GetActiveView (ITfContext *iface,
461 ITfContextView **ppView)
463 Context *This = impl_from_ITfContext(iface);
464 FIXME("STUB:(%p)\n",This);
465 return E_NOTIMPL;
468 static HRESULT WINAPI Context_EnumViews (ITfContext *iface,
469 IEnumTfContextViews **ppEnum)
471 Context *This = impl_from_ITfContext(iface);
472 FIXME("STUB:(%p)\n",This);
473 return E_NOTIMPL;
476 static HRESULT WINAPI Context_GetStatus (ITfContext *iface,
477 TF_STATUS *pdcs)
479 Context *This = impl_from_ITfContext(iface);
480 TRACE("(%p) %p\n",This,pdcs);
482 if (!This->connected)
483 return TF_E_DISCONNECTED;
485 if (!pdcs)
486 return E_INVALIDARG;
488 if (!This->pITextStoreACP)
490 FIXME("Context does not have a ITextStoreACP\n");
491 return E_NOTIMPL;
494 ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
496 *pdcs = This->documentStatus;
498 return S_OK;
501 static HRESULT WINAPI Context_GetProperty (ITfContext *iface,
502 REFGUID guidProp, ITfProperty **ppProp)
504 Context *This = impl_from_ITfContext(iface);
505 FIXME("STUB:(%p)\n",This);
506 return E_NOTIMPL;
509 static HRESULT WINAPI Context_GetAppProperty (ITfContext *iface,
510 REFGUID guidProp, ITfReadOnlyProperty **ppProp)
512 Context *This = impl_from_ITfContext(iface);
513 FIXME("STUB:(%p)\n",This);
514 return E_NOTIMPL;
517 static HRESULT WINAPI Context_TrackProperties (ITfContext *iface,
518 const GUID **prgProp, ULONG cProp, const GUID **prgAppProp,
519 ULONG cAppProp, ITfReadOnlyProperty **ppProperty)
521 Context *This = impl_from_ITfContext(iface);
522 FIXME("STUB:(%p)\n",This);
523 return E_NOTIMPL;
526 static HRESULT WINAPI Context_EnumProperties (ITfContext *iface,
527 IEnumTfProperties **ppEnum)
529 Context *This = impl_from_ITfContext(iface);
530 FIXME("STUB:(%p)\n",This);
531 return E_NOTIMPL;
534 static HRESULT WINAPI Context_GetDocumentMgr (ITfContext *iface,
535 ITfDocumentMgr **ppDm)
537 Context *This = impl_from_ITfContext(iface);
538 TRACE("(%p) %p\n",This,ppDm);
540 if (!ppDm)
541 return E_INVALIDARG;
543 *ppDm = This->manager;
544 if (!This->manager)
545 return S_FALSE;
547 ITfDocumentMgr_AddRef(This->manager);
549 return S_OK;
552 static HRESULT WINAPI Context_CreateRangeBackup (ITfContext *iface,
553 TfEditCookie ec, ITfRange *pRange, ITfRangeBackup **ppBackup)
555 Context *This = impl_from_ITfContext(iface);
556 FIXME("STUB:(%p)\n",This);
557 return E_NOTIMPL;
560 static const ITfContextVtbl ContextVtbl =
562 Context_QueryInterface,
563 Context_AddRef,
564 Context_Release,
565 Context_RequestEditSession,
566 Context_InWriteSession,
567 Context_GetSelection,
568 Context_SetSelection,
569 Context_GetStart,
570 Context_GetEnd,
571 Context_GetActiveView,
572 Context_EnumViews,
573 Context_GetStatus,
574 Context_GetProperty,
575 Context_GetAppProperty,
576 Context_TrackProperties,
577 Context_EnumProperties,
578 Context_GetDocumentMgr,
579 Context_CreateRangeBackup
582 static HRESULT WINAPI ContextSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
584 Context *This = impl_from_ITfSource(iface);
585 return ITfContext_QueryInterface(&This->ITfContext_iface, iid, ppvOut);
588 static ULONG WINAPI ContextSource_AddRef(ITfSource *iface)
590 Context *This = impl_from_ITfSource(iface);
591 return ITfContext_AddRef(&This->ITfContext_iface);
594 static ULONG WINAPI ContextSource_Release(ITfSource *iface)
596 Context *This = impl_from_ITfSource(iface);
597 return ITfContext_Release(&This->ITfContext_iface);
600 /*****************************************************
601 * ITfSource functions
602 *****************************************************/
603 static HRESULT WINAPI ContextSource_AdviseSink(ITfSource *iface,
604 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
606 Context *This = impl_from_ITfSource(iface);
607 ContextSink *es;
608 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
610 if (!riid || !punk || !pdwCookie)
611 return E_INVALIDARG;
613 if (IsEqualIID(riid, &IID_ITfTextEditSink))
615 es = HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink));
616 if (!es)
617 return E_OUTOFMEMORY;
618 if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&es->interfaces.pITfTextEditSink)))
620 HeapFree(GetProcessHeap(),0,es);
621 return CONNECT_E_CANNOTCONNECT;
623 list_add_head(&This->pTextEditSink ,&es->entry);
624 *pdwCookie = generate_Cookie(COOKIE_MAGIC_CONTEXTSINK, es);
626 else
628 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
629 return E_NOTIMPL;
632 TRACE("cookie %x\n",*pdwCookie);
633 return S_OK;
636 static HRESULT WINAPI ContextSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
638 Context *This = impl_from_ITfSource(iface);
639 ContextSink *sink;
641 TRACE("(%p) %x\n",This,pdwCookie);
643 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_CONTEXTSINK)
644 return E_INVALIDARG;
646 sink = remove_Cookie(pdwCookie);
647 if (!sink)
648 return CONNECT_E_NOCONNECTION;
650 list_remove(&sink->entry);
651 free_sink(sink);
653 return S_OK;
656 static const ITfSourceVtbl ContextSourceVtbl =
658 ContextSource_QueryInterface,
659 ContextSource_AddRef,
660 ContextSource_Release,
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_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) %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)
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, This->pITextStoreACP, cookie->lockType, 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) %i %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) %i %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 E_NOTIMPL;
837 static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface)
839 Context *This = impl_from_ITextStoreACPSink(iface);
840 FIXME("STUB:(%p)\n",This);
841 return E_NOTIMPL;
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 E_NOTIMPL;
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) %x\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) %x\n",This, dwLockFlags);
893 if (!This->currentEditSession)
895 FIXME("OnLockGranted called for something other than an EditSession\n");
896 return S_OK;
899 cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
900 if (!cookie)
901 return E_OUTOFMEMORY;
903 sinkcookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
904 if (!sinkcookie)
906 HeapFree(GetProcessHeap(), 0, 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 TfEditCookie sc;
920 sinkcookie->lockType = TS_LF_READ;
921 sinkcookie->pOwningContext = This;
922 sc = generate_Cookie(COOKIE_MAGIC_EDITCOOKIE, sinkcookie);
924 /*TODO: implement ITfEditRecord */
925 LIST_FOR_EACH(cursor, &This->pTextEditSink)
927 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
928 ITfTextEditSink_OnEndEdit(sink->interfaces.pITfTextEditSink,
929 (ITfContext*) &This->ITfContext_iface, sc, NULL);
931 sinkcookie = remove_Cookie(sc);
933 HeapFree(GetProcessHeap(),0,sinkcookie);
935 ITfEditSession_Release(This->currentEditSession);
936 This->currentEditSession = NULL;
938 /* Edit Cookie is only valid during the edit session */
939 cookie = remove_Cookie(ec);
940 HeapFree(GetProcessHeap(),0,cookie);
942 return hr;
945 static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface)
947 Context *This = impl_from_ITextStoreACPSink(iface);
948 FIXME("STUB:(%p)\n",This);
949 return E_NOTIMPL;
952 static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface)
954 Context *This = impl_from_ITextStoreACPSink(iface);
955 FIXME("STUB:(%p)\n",This);
956 return E_NOTIMPL;
959 static const ITextStoreACPSinkVtbl TextStoreACPSinkVtbl =
961 TextStoreACPSink_QueryInterface,
962 TextStoreACPSink_AddRef,
963 TextStoreACPSink_Release,
964 TextStoreACPSink_OnTextChange,
965 TextStoreACPSink_OnSelectionChange,
966 TextStoreACPSink_OnLayoutChange,
967 TextStoreACPSink_OnStatusChange,
968 TextStoreACPSink_OnAttrsChange,
969 TextStoreACPSink_OnLockGranted,
970 TextStoreACPSink_OnStartEditTransaction,
971 TextStoreACPSink_OnEndEditTransaction
974 static HRESULT WINAPI TextStoreACPServices_QueryInterface(ITextStoreACPServices *iface, REFIID riid, void **obj)
976 Context *This = impl_from_ITextStoreACPServices(iface);
977 return ITextStoreACPSink_QueryInterface(&This->ITextStoreACPSink_iface, riid, obj);
980 static ULONG WINAPI TextStoreACPServices_AddRef(ITextStoreACPServices *iface)
982 Context *This = impl_from_ITextStoreACPServices(iface);
983 return ITextStoreACPSink_AddRef(&This->ITextStoreACPSink_iface);
986 static ULONG WINAPI TextStoreACPServices_Release(ITextStoreACPServices *iface)
988 Context *This = impl_from_ITextStoreACPServices(iface);
989 return ITextStoreACPSink_Release(&This->ITextStoreACPSink_iface);
992 static HRESULT WINAPI TextStoreACPServices_Serialize(ITextStoreACPServices *iface, ITfProperty *prop, ITfRange *range,
993 TF_PERSISTENT_PROPERTY_HEADER_ACP *header, IStream *stream)
995 Context *This = impl_from_ITextStoreACPServices(iface);
997 FIXME("stub: %p %p %p %p %p\n", This, prop, range, header, stream);
999 return E_NOTIMPL;
1002 static HRESULT WINAPI TextStoreACPServices_Unserialize(ITextStoreACPServices *iface, ITfProperty *prop,
1003 const TF_PERSISTENT_PROPERTY_HEADER_ACP *header, IStream *stream, ITfPersistentPropertyLoaderACP *loader)
1005 Context *This = impl_from_ITextStoreACPServices(iface);
1007 FIXME("stub: %p %p %p %p %p\n", This, prop, header, stream, loader);
1009 return E_NOTIMPL;
1012 static HRESULT WINAPI TextStoreACPServices_ForceLoadProperty(ITextStoreACPServices *iface, ITfProperty *prop)
1014 Context *This = impl_from_ITextStoreACPServices(iface);
1016 FIXME("stub: %p %p\n", This, prop);
1018 return E_NOTIMPL;
1021 static HRESULT WINAPI TextStoreACPServices_CreateRange(ITextStoreACPServices *iface,
1022 LONG start, LONG end, ITfRangeACP **range)
1024 Context *This = impl_from_ITextStoreACPServices(iface);
1026 FIXME("stub: %p %d %d %p\n", This, start, end, range);
1028 return S_OK;
1031 static const ITextStoreACPServicesVtbl TextStoreACPServicesVtbl =
1033 TextStoreACPServices_QueryInterface,
1034 TextStoreACPServices_AddRef,
1035 TextStoreACPServices_Release,
1036 TextStoreACPServices_Serialize,
1037 TextStoreACPServices_Unserialize,
1038 TextStoreACPServices_ForceLoadProperty,
1039 TextStoreACPServices_CreateRange
1042 HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfDocumentMgr *mgr, ITfContext **ppOut, TfEditCookie *pecTextStore)
1044 Context *This;
1045 EditCookie *cookie;
1047 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Context));
1048 if (This == NULL)
1049 return E_OUTOFMEMORY;
1051 cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
1052 if (cookie == NULL)
1054 HeapFree(GetProcessHeap(),0,This);
1055 return E_OUTOFMEMORY;
1058 TRACE("(%p) %x %p %p %p\n",This, tidOwner, punk, ppOut, pecTextStore);
1060 This->ITfContext_iface.lpVtbl= &ContextVtbl;
1061 This->ITfSource_iface.lpVtbl = &ContextSourceVtbl;
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;