makedep: Add support for multiple object file extensions.
[wine/wine-gecko.git] / dlls / msctf / context.c
blob5be06d3e747506bea2f2729a3b06e5d26503e4e9
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 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; */
68 LONG refCount;
69 BOOL connected;
71 /* Aggregation */
72 ITfCompartmentMgr *CompartmentMgr;
74 TfClientId tidOwner;
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;
92 } Context;
94 typedef struct tagEditCookie {
95 DWORD lockType;
96 Context *pOwningContext;
97 } EditCookie;
99 typedef struct tagTextStoreACPSink {
100 const ITextStoreACPSinkVtbl *TextStoreACPSinkVtbl;
101 /* const ITextStoreACPServicesVtbl *TextStoreACPServicesVtbl; */
102 LONG refCount;
104 Context *pContext;
105 } TextStoreACPSink;
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;
129 EditCookie *cookie;
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);
154 list_remove(cursor);
155 free_sink(sink);
157 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pEditTransactionSink)
159 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
160 list_remove(cursor);
161 free_sink(sink);
163 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pStatusSink)
165 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
166 list_remove(cursor);
167 free_sink(sink);
169 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextEditSink)
171 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
172 list_remove(cursor);
173 free_sink(sink);
175 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextLayoutSink)
177 ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry);
178 list_remove(cursor);
179 free_sink(sink);
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;
189 *ppvOut = NULL;
191 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfContext))
193 *ppvOut = This;
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;
208 if (*ppvOut)
210 IUnknown_AddRef(iface);
211 return S_OK;
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;
227 ULONG ret;
229 ret = InterlockedDecrement(&This->refCount);
230 if (ret == 0)
231 Context_Destructor(This);
232 return ret;
235 /*****************************************************
236 * ITfContext functions
237 *****************************************************/
238 static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface,
239 TfClientId tid, ITfEditSession *pes, DWORD dwFlags,
240 HRESULT *phrSession)
242 HRESULT hr;
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;
251 return E_INVALIDARG;
254 if (!This->pITextStoreACP)
256 FIXME("No ITextStoreACP avaliable\n");
257 *phrSession = E_FAIL;
258 return 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;
275 return S_OK;
278 if (FAILED (ITfEditSession_QueryInterface(pes, &IID_ITfEditSession, (LPVOID*)&This->currentEditSession)))
280 *phrSession = E_FAIL;
281 return E_INVALIDARG;
284 hr = ITextStoreACP_RequestLock(This->pITextStoreACP, dwLockFlags, phrSession);
286 return hr;
289 static HRESULT WINAPI Context_InWriteSession (ITfContext *iface,
290 TfClientId tid,
291 BOOL *pfWriteSession)
293 Context *This = (Context *)iface;
294 FIXME("STUB:(%p)\n",This);
295 return E_NOTIMPL;
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;
303 EditCookie *cookie;
304 ULONG count, i;
305 ULONG totalFetched = 0;
306 HRESULT hr = S_OK;
308 if (!pSelection || !pcFetched)
309 return E_INVALIDARG;
311 *pcFetched = 0;
313 if (!This->connected)
314 return TF_E_DISCONNECTED;
316 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
317 return TF_E_NOLOCK;
319 if (!This->pITextStoreACP)
321 FIXME("Context does not have a ITextStoreACP\n");
322 return E_NOTIMPL;
325 cookie = get_Cookie_data(ec);
327 if (ulIndex == TF_DEFAULT_SELECTION)
328 count = 1;
329 else
330 count = ulCount;
332 for (i = 0; i < count; i++)
334 DWORD fetched;
335 TS_SELECTION_ACP acps;
337 hr = ITextStoreACP_GetSelection(This->pITextStoreACP, ulIndex + i,
338 1, &acps, &fetched);
340 if (hr == TS_E_NOLOCK)
341 return TF_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);
347 totalFetched ++;
349 else
350 break;
353 *pcFetched = totalFetched;
355 return hr;
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;
363 INT i;
364 HRESULT hr;
366 TRACE("(%p) %i %i %p\n",This,ec,ulCount,pSelection);
368 if (!This->pITextStoreACP)
370 FIXME("Context does not have a ITextStoreACP\n");
371 return E_NOTIMPL;
374 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
375 return TF_E_NOLOCK;
377 acp = HeapAlloc(GetProcessHeap(), 0, sizeof(TS_SELECTION_ACP) * ulCount);
378 if (!acp)
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);
386 return E_FAIL;
389 hr = ITextStoreACP_SetSelection(This->pITextStoreACP, ulCount, acp);
391 HeapFree(GetProcessHeap(), 0, acp);
393 return hr;
396 static HRESULT WINAPI Context_GetStart (ITfContext *iface,
397 TfEditCookie ec, ITfRange **ppStart)
399 Context *This = (Context *)iface;
400 EditCookie *cookie;
401 TRACE("(%p) %i %p\n",This,ec,ppStart);
403 if (!ppStart)
404 return E_INVALIDARG;
406 *ppStart = NULL;
408 if (!This->connected)
409 return TF_E_DISCONNECTED;
411 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
412 return TF_E_NOLOCK;
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;
422 EditCookie *cookie;
423 LONG end;
424 TRACE("(%p) %i %p\n",This,ec,ppEnd);
426 if (!ppEnd)
427 return E_INVALIDARG;
429 *ppEnd = NULL;
431 if (!This->connected)
432 return TF_E_DISCONNECTED;
434 if (get_Cookie_magic(ec)!=COOKIE_MAGIC_EDITCOOKIE)
435 return TF_E_NOLOCK;
437 if (!This->pITextStoreACP)
439 FIXME("Context does not have a ITextStoreACP\n");
440 return E_NOTIMPL;
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);
454 return E_NOTIMPL;
457 static HRESULT WINAPI Context_EnumViews (ITfContext *iface,
458 IEnumTfContextViews **ppEnum)
460 Context *This = (Context *)iface;
461 FIXME("STUB:(%p)\n",This);
462 return E_NOTIMPL;
465 static HRESULT WINAPI Context_GetStatus (ITfContext *iface,
466 TF_STATUS *pdcs)
468 Context *This = (Context *)iface;
469 TRACE("(%p) %p\n",This,pdcs);
471 if (!This->connected)
472 return TF_E_DISCONNECTED;
474 if (!pdcs)
475 return E_INVALIDARG;
477 if (!This->pITextStoreACP)
479 FIXME("Context does not have a ITextStoreACP\n");
480 return E_NOTIMPL;
483 ITextStoreACP_GetStatus(This->pITextStoreACP, &This->documentStatus);
485 *pdcs = This->documentStatus;
487 return S_OK;
490 static HRESULT WINAPI Context_GetProperty (ITfContext *iface,
491 REFGUID guidProp, ITfProperty **ppProp)
493 Context *This = (Context *)iface;
494 FIXME("STUB:(%p)\n",This);
495 return E_NOTIMPL;
498 static HRESULT WINAPI Context_GetAppProperty (ITfContext *iface,
499 REFGUID guidProp, ITfReadOnlyProperty **ppProp)
501 Context *This = (Context *)iface;
502 FIXME("STUB:(%p)\n",This);
503 return E_NOTIMPL;
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);
512 return E_NOTIMPL;
515 static HRESULT WINAPI Context_EnumProperties (ITfContext *iface,
516 IEnumTfProperties **ppEnum)
518 Context *This = (Context *)iface;
519 FIXME("STUB:(%p)\n",This);
520 return E_NOTIMPL;
523 static HRESULT WINAPI Context_GetDocumentMgr (ITfContext *iface,
524 ITfDocumentMgr **ppDm)
526 Context *This = (Context *)iface;
527 TRACE("(%p) %p\n",This,ppDm);
529 if (!ppDm)
530 return E_INVALIDARG;
532 *ppDm = This->manager;
533 if (!This->manager)
534 return S_FALSE;
536 ITfDocumentMgr_AddRef(This->manager);
538 return S_OK;
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);
546 return E_NOTIMPL;
549 static const ITfContextVtbl Context_ContextVtbl =
551 Context_QueryInterface,
552 Context_AddRef,
553 Context_Release,
555 Context_RequestEditSession,
556 Context_InWriteSession,
557 Context_GetSelection,
558 Context_SetSelection,
559 Context_GetStart,
560 Context_GetEnd,
561 Context_GetActiveView,
562 Context_EnumViews,
563 Context_GetStatus,
564 Context_GetProperty,
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)
596 ContextSink *es;
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)
601 return E_INVALIDARG;
603 if (IsEqualIID(riid, &IID_ITfTextEditSink))
605 es = HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink));
606 if (!es)
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);
616 else
618 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
619 return E_NOTIMPL;
622 TRACE("cookie %x\n",*pdwCookie);
623 return S_OK;
626 static WINAPI HRESULT ContextSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
628 ContextSink *sink;
629 Context *This = impl_from_ITfSourceVtbl(iface);
631 TRACE("(%p) %x\n",This,pdwCookie);
633 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_CONTEXTSINK)
634 return E_INVALIDARG;
636 sink = (ContextSink*)remove_Cookie(pdwCookie);
637 if (!sink)
638 return CONNECT_E_NOCONNECTION;
640 list_remove(&sink->entry);
641 free_sink(sink);
643 return S_OK;
646 static const ITfSourceVtbl Context_SourceVtbl =
648 Source_QueryInterface,
649 Source_AddRef,
650 Source_Release,
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);
682 EditCookie *cookie;
683 LONG acpStart, acpEnd;
684 TS_TEXTCHANGE change;
685 HRESULT hr;
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)
693 return TF_E_NOLOCK;
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");
703 return E_NOTIMPL;
706 hr = ITextStoreACP_InsertTextAtSelection(This->pITextStoreACP, dwFlags, pchText, cch, &acpStart, &acpEnd, &change);
707 if (SUCCEEDED(hr))
708 Range_Constructor((ITfContext*)This, This->pITextStoreACP, cookie->lockType, change.acpStart, change.acpNewEnd, ppRange);
710 return hr;
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);
719 return E_NOTIMPL;
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)
734 Context *This;
735 EditCookie *cookie;
737 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Context));
738 if (This == NULL)
739 return E_OUTOFMEMORY;
741 cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
742 if (cookie == NULL)
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;
753 This->refCount = 1;
754 This->tidOwner = tidOwner;
755 This->connected = FALSE;
756 This->manager = mgr;
758 CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
760 cookie->lockType = TF_ES_READ;
761 cookie->pOwningContext = This;
763 if (punk)
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);
787 return S_OK;
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;
802 return S_OK;
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;
817 return S_OK;
820 /**************************************************************************
821 * ITextStoreACPSink
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;
833 *ppvOut = NULL;
835 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACPSink))
837 *ppvOut = This;
840 if (*ppvOut)
842 IUnknown_AddRef(iface);
843 return S_OK;
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;
859 ULONG ret;
861 ret = InterlockedDecrement(&This->refCount);
862 if (ret == 0)
863 TextStoreACPSink_Destructor(This);
864 return ret;
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);
876 return E_NOTIMPL;
879 static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface)
881 TextStoreACPSink *This = (TextStoreACPSink *)iface;
882 FIXME("STUB:(%p)\n",This);
883 return E_NOTIMPL;
886 static HRESULT WINAPI TextStoreACPSink_OnLayoutChange(ITextStoreACPSink *iface,
887 TsLayoutCode lcode, TsViewCookie vcView)
889 TextStoreACPSink *This = (TextStoreACPSink *)iface;
890 FIXME("STUB:(%p)\n",This);
891 return E_NOTIMPL;
894 static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface,
895 DWORD dwFlags)
897 TextStoreACPSink *This = (TextStoreACPSink *)iface;
898 HRESULT hr, hrSession;
900 TRACE("(%p) %x\n",This, dwFlags);
902 if (!This->pContext)
904 ERR("No context?\n");
905 return E_FAIL;
908 if (!This->pContext->pITextStoreACP)
910 FIXME("Context does not have a ITextStoreACP\n");
911 return E_NOTIMPL;
914 hr = ITextStoreACP_RequestLock(This->pContext->pITextStoreACP, TS_LF_READ, &hrSession);
916 if(SUCCEEDED(hr) && SUCCEEDED(hrSession))
917 This->pContext->documentStatus.dwDynamicFlags = dwFlags;
919 return S_OK;
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);
927 return E_NOTIMPL;
930 static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface,
931 DWORD dwLockFlags)
933 TextStoreACPSink *This = (TextStoreACPSink *)iface;
934 HRESULT hr;
935 EditCookie *cookie;
936 TfEditCookie ec;
938 TRACE("(%p) %x\n",This, dwLockFlags);
940 if (!This->pContext)
942 ERR("OnLockGranted called without a context\n");
943 return E_FAIL;
946 if (!This->pContext->currentEditSession)
948 FIXME("OnLockGranted called for something other than an EditSession\n");
949 return S_OK;
952 cookie = HeapAlloc(GetProcessHeap(),0,sizeof(EditCookie));
953 if (!cookie)
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);
969 return hr;
972 static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface)
974 TextStoreACPSink *This = (TextStoreACPSink *)iface;
975 FIXME("STUB:(%p)\n",This);
976 return E_NOTIMPL;
979 static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface)
981 TextStoreACPSink *This = (TextStoreACPSink *)iface;
982 FIXME("STUB:(%p)\n",This);
983 return E_NOTIMPL;
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));
1007 if (This == NULL)
1008 return E_OUTOFMEMORY;
1010 This->TextStoreACPSinkVtbl= &TextStoreACPSink_TextStoreACPSinkVtbl;
1011 This->refCount = 1;
1013 This->pContext = pContext;
1015 TRACE("returning %p\n", This);
1016 *ppOut = (ITextStoreACPSink*)This;
1017 return S_OK;