2 * ITfThreadMgr implementation
4 * Copyright 2008 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 tagThreadMgrSink {
50 /* ITfActiveLanguageProfileNotifySink *pITfActiveLanguageProfileNotifySink; */
51 /* ITfDisplayAttributeNotifySink *pITfDisplayAttributeNotifySink; */
52 /* ITfKeyTraceEventSink *pITfKeyTraceEventSink; */
53 /* ITfPreservedKeyNotifySink *pITfPreservedKeyNotifySink; */
54 /* ITfThreadFocusSink *pITfThreadFocusSink; */
55 ITfThreadMgrEventSink *pITfThreadMgrEventSink;
59 typedef struct tagPreservedKey
63 TF_PRESERVEDKEY prekey;
68 typedef struct tagDocumentMgrs
71 ITfDocumentMgr *docmgr;
74 typedef struct tagACLMulti {
75 const ITfThreadMgrVtbl *ThreadMgrVtbl;
76 const ITfSourceVtbl *SourceVtbl;
77 const ITfKeystrokeMgrVtbl *KeystrokeMgrVtbl;
78 const ITfMessagePumpVtbl *MessagePumpVtbl;
79 const ITfClientIdVtbl *ClientIdVtbl;
80 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
81 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
82 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
83 /* const ITfUIElementMgrVtbl *UIElementMgrVtbl; */
84 /* const ITfSourceSingleVtbl *SourceSingleVtbl; */
88 ITfCompartmentMgr *CompartmentMgr;
90 const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
92 ITfDocumentMgr *focus;
95 ITfKeyEventSink *forgroundKeyEventSink;
96 CLSID forgroundTextService;
98 struct list CurrentPreservedKeys;
99 struct list CreatedDocumentMgrs;
101 /* kept as separate lists to reduce unnecessary iterations */
102 struct list ActiveLanguageProfileNotifySink;
103 struct list DisplayAttributeNotifySink;
104 struct list KeyTraceEventSink;
105 struct list PreservedKeyNotifySink;
106 struct list ThreadFocusSink;
107 struct list ThreadMgrEventSink;
110 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
112 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
115 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
117 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
120 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
122 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
125 static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface)
127 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl));
130 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
132 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
135 static void free_sink(ThreadMgrSink *sink)
137 IUnknown_Release(sink->interfaces.pIUnknown);
138 HeapFree(GetProcessHeap(),0,sink);
141 static void ThreadMgr_Destructor(ThreadMgr *This)
143 struct list *cursor, *cursor2;
145 TlsSetValue(tlsIndex,NULL);
146 TRACE("destroying %p\n", This);
148 ITfDocumentMgr_Release(This->focus);
151 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
153 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
157 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
159 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
163 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
165 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
169 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
171 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
175 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
177 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
181 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
183 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
188 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
190 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
192 HeapFree(GetProcessHeap(),0,key->description);
193 HeapFree(GetProcessHeap(),0,key);
196 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs)
198 DocumentMgrEntry *mgr = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
200 FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n");
201 HeapFree(GetProcessHeap(),0,mgr);
204 CompartmentMgr_Destructor(This->CompartmentMgr);
206 HeapFree(GetProcessHeap(),0,This);
209 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
211 ThreadMgr *This = (ThreadMgr *)iface;
214 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
218 else if (IsEqualIID(iid, &IID_ITfSource))
220 *ppvOut = &This->SourceVtbl;
222 else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
224 *ppvOut = &This->KeystrokeMgrVtbl;
226 else if (IsEqualIID(iid, &IID_ITfMessagePump))
228 *ppvOut = &This->MessagePumpVtbl;
230 else if (IsEqualIID(iid, &IID_ITfClientId))
232 *ppvOut = &This->ClientIdVtbl;
234 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
236 *ppvOut = This->CompartmentMgr;
241 IUnknown_AddRef(iface);
245 WARN("unsupported interface: %s\n", debugstr_guid(iid));
246 return E_NOINTERFACE;
249 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
251 ThreadMgr *This = (ThreadMgr *)iface;
252 return InterlockedIncrement(&This->refCount);
255 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
257 ThreadMgr *This = (ThreadMgr *)iface;
260 ret = InterlockedDecrement(&This->refCount);
262 ThreadMgr_Destructor(This);
266 /*****************************************************
267 * ITfThreadMgr functions
268 *****************************************************/
270 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
272 ThreadMgr *This = (ThreadMgr *)iface;
274 TRACE("(%p) %p\n",This, ptid);
283 ITfClientId_GetClientId((ITfClientId*)&This->ClientIdVtbl,&guid,&processId);
286 activate_textservices(iface);
287 This->activationCount++;
292 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
294 ThreadMgr *This = (ThreadMgr *)iface;
295 TRACE("(%p)\n",This);
297 if (This->activationCount == 0)
300 This->activationCount --;
302 if (This->activationCount == 0)
306 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
307 ITfDocumentMgr_Release(This->focus);
312 deactivate_textservices();
317 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
320 ThreadMgr *This = (ThreadMgr *)iface;
321 DocumentMgrEntry *mgrentry;
324 TRACE("(%p)\n",iface);
325 mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry));
326 if (mgrentry == NULL)
327 return E_OUTOFMEMORY;
329 hr = DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
333 mgrentry->docmgr = *ppdim;
334 list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry);
337 HeapFree(GetProcessHeap(),0,mgrentry);
342 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
345 ThreadMgr *This = (ThreadMgr *)iface;
346 FIXME("STUB:(%p)\n",This);
350 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
353 ThreadMgr *This = (ThreadMgr *)iface;
354 TRACE("(%p)\n",This);
359 *ppdimFocus = This->focus;
361 TRACE("->%p\n",This->focus);
363 if (This->focus == NULL)
366 ITfDocumentMgr_AddRef(This->focus);
371 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
373 ITfDocumentMgr *check;
374 ThreadMgr *This = (ThreadMgr *)iface;
376 TRACE("(%p) %p\n",This,pdimFocus);
378 if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
381 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
384 ITfDocumentMgr_Release(This->focus);
390 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
391 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
393 ThreadMgr *This = (ThreadMgr *)iface;
394 FIXME("STUB:(%p)\n",This);
398 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
401 ThreadMgr *This = (ThreadMgr *)iface;
402 TRACE("(%p) %p\n",This,pfThreadFocus);
404 *pfThreadFocus = (focus == NULL);
408 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
409 ITfFunctionProvider **ppFuncProv)
411 ThreadMgr *This = (ThreadMgr *)iface;
412 FIXME("STUB:(%p)\n",This);
416 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
417 IEnumTfFunctionProviders **ppEnum)
419 ThreadMgr *This = (ThreadMgr *)iface;
420 FIXME("STUB:(%p)\n",This);
424 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
425 ITfCompartmentMgr **ppCompMgr)
427 ThreadMgr *This = (ThreadMgr *)iface;
429 TRACE("(%p) %p\n",This, ppCompMgr);
434 if (!globalCompartmentMgr)
436 hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
441 ITfCompartmentMgr_AddRef(globalCompartmentMgr);
442 *ppCompMgr = globalCompartmentMgr;
446 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
448 ThreadMgr_QueryInterface,
452 ThreadMgr_fnActivate,
453 ThreadMgr_fnDeactivate,
454 ThreadMgr_CreateDocumentMgr,
455 ThreadMgr_EnumDocumentMgrs,
458 ThreadMgr_AssociateFocus,
459 ThreadMgr_IsThreadFocus,
460 ThreadMgr_GetFunctionProvider,
461 ThreadMgr_EnumFunctionProviders,
462 ThreadMgr_GetGlobalCompartment
466 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
468 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
469 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
472 static ULONG WINAPI Source_AddRef(ITfSource *iface)
474 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
475 return ThreadMgr_AddRef((ITfThreadMgr*)This);
478 static ULONG WINAPI Source_Release(ITfSource *iface)
480 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
481 return ThreadMgr_Release((ITfThreadMgr *)This);
484 /*****************************************************
485 * ITfSource functions
486 *****************************************************/
487 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
488 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
491 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
493 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
495 if (!riid || !punk || !pdwCookie)
498 if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
500 tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
502 return E_OUTOFMEMORY;
503 if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
505 HeapFree(GetProcessHeap(),0,tms);
506 return CONNECT_E_CANNOTCONNECT;
508 list_add_head(&This->ThreadMgrEventSink,&tms->entry);
509 *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
513 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
517 TRACE("cookie %x\n",*pdwCookie);
522 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
525 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
527 TRACE("(%p) %x\n",This,pdwCookie);
529 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
532 sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
534 return CONNECT_E_NOCONNECTION;
536 list_remove(&sink->entry);
542 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
544 Source_QueryInterface,
548 ThreadMgrSource_AdviseSink,
549 ThreadMgrSource_UnadviseSink,
552 /*****************************************************
553 * ITfKeystrokeMgr functions
554 *****************************************************/
556 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
558 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
559 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
562 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
564 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
565 return ThreadMgr_AddRef((ITfThreadMgr*)This);
568 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
570 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
571 return ThreadMgr_Release((ITfThreadMgr *)This);
574 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
575 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
577 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
579 ITfKeyEventSink *check = NULL;
581 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
586 textservice = get_textservice_clsid(tid);
587 if (IsEqualCLSID(&GUID_NULL,&textservice))
590 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
592 return CONNECT_E_ADVISELIMIT;
594 if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
597 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
601 if (This->forgroundKeyEventSink)
603 ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
604 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
606 ITfKeyEventSink_AddRef(check);
607 ITfKeyEventSink_OnSetFocus(check, TRUE);
608 This->forgroundKeyEventSink = check;
609 This->forgroundTextService = textservice;
614 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
617 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
619 ITfKeyEventSink *check = NULL;
620 TRACE("(%p) %x\n",This,tid);
625 textservice = get_textservice_clsid(tid);
626 if (IsEqualCLSID(&GUID_NULL,&textservice))
629 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
632 return CONNECT_E_NOCONNECTION;
634 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
635 ITfKeyEventSink_Release(check);
637 if (This->forgroundKeyEventSink == check)
639 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
640 This->forgroundKeyEventSink = NULL;
641 This->forgroundTextService = GUID_NULL;
646 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
649 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
650 TRACE("(%p) %p\n",This,pclsid);
654 if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
657 *pclsid = This->forgroundTextService;
661 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
662 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
664 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
665 FIXME("STUB:(%p)\n",This);
669 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
670 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
672 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
673 FIXME("STUB:(%p)\n",This);
677 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
678 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
680 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
681 FIXME("STUB:(%p)\n",This);
685 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
686 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
688 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
689 FIXME("STUB:(%p)\n",This);
693 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
694 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
696 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
697 FIXME("STUB:(%p)\n",This);
701 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
702 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
704 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
707 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
709 if (!rguid || !pprekey || !pfRegistered)
712 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
714 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
715 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
717 *pfRegistered = TRUE;
722 *pfRegistered = FALSE;
726 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
727 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
728 const WCHAR *pchDesc, ULONG cchDesc)
730 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
732 PreservedKey *newkey;
734 TRACE("(%p) %x %s (%x,%x) %s\n",This,tid, debugstr_guid(rguid),(prekey)?prekey->uVKey:0,(prekey)?prekey->uModifiers:0,debugstr_wn(pchDesc,cchDesc));
736 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
739 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
741 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
742 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
743 return TF_E_ALREADY_EXISTS;
746 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
748 return E_OUTOFMEMORY;
750 newkey->guid = *rguid;
751 newkey->prekey = *prekey;
755 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
756 if (!newkey->description)
758 HeapFree(GetProcessHeap(),0,newkey);
759 return E_OUTOFMEMORY;
761 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
764 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
769 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
770 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
772 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
773 PreservedKey* key = NULL;
775 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
777 if (!pprekey || !rguid)
780 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
782 key = LIST_ENTRY(cursor,PreservedKey,entry);
783 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
789 return CONNECT_E_NOCONNECTION;
791 list_remove(&key->entry);
792 HeapFree(GetProcessHeap(),0,key->description);
793 HeapFree(GetProcessHeap(),0,key);
798 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
799 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
801 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
802 FIXME("STUB:(%p)\n",This);
806 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
807 REFGUID rguid, BSTR *pbstrDesc)
809 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
810 FIXME("STUB:(%p)\n",This);
814 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
815 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
817 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
818 FIXME("STUB:(%p)\n",This);
822 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
824 KeystrokeMgr_QueryInterface,
826 KeystrokeMgr_Release,
828 KeystrokeMgr_AdviseKeyEventSink,
829 KeystrokeMgr_UnadviseKeyEventSink,
830 KeystrokeMgr_GetForeground,
831 KeystrokeMgr_TestKeyDown,
832 KeystrokeMgr_TestKeyUp,
833 KeystrokeMgr_KeyDown,
835 KeystrokeMgr_GetPreservedKey,
836 KeystrokeMgr_IsPreservedKey,
837 KeystrokeMgr_PreserveKey,
838 KeystrokeMgr_UnpreserveKey,
839 KeystrokeMgr_SetPreservedKeyDescription,
840 KeystrokeMgr_GetPreservedKeyDescription,
841 KeystrokeMgr_SimulatePreservedKey
844 /*****************************************************
845 * ITfMessagePump functions
846 *****************************************************/
848 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
850 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
851 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
854 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
856 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
857 return ThreadMgr_AddRef((ITfThreadMgr*)This);
860 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
862 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
863 return ThreadMgr_Release((ITfThreadMgr *)This);
866 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
867 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
868 UINT wRemoveMsg, BOOL *pfResult)
872 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
876 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
877 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
882 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
886 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
887 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
888 UINT wRemoveMsg, BOOL *pfResult)
892 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
896 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
897 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
902 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
906 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
908 MessagePump_QueryInterface,
912 MessagePump_PeekMessageA,
913 MessagePump_GetMessageA,
914 MessagePump_PeekMessageW,
915 MessagePump_GetMessageW
918 /*****************************************************
919 * ITfClientId functions
920 *****************************************************/
922 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
924 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
925 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
928 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
930 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
931 return ThreadMgr_AddRef((ITfThreadMgr*)This);
934 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
936 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
937 return ThreadMgr_Release((ITfThreadMgr *)This);
940 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
941 REFCLSID rclsid, TfClientId *ptid)
945 ITfCategoryMgr *catmgr;
946 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
948 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
950 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
951 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
952 ITfCategoryMgr_Release(catmgr);
957 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
959 ClientId_QueryInterface,
966 /*****************************************************
967 * ITfThreadMgrEventSink functions (internal)
968 *****************************************************/
969 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
971 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
972 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
975 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
977 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
978 return ThreadMgr_AddRef((ITfThreadMgr*)This);
981 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
983 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
984 return ThreadMgr_Release((ITfThreadMgr *)This);
988 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
989 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
992 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
994 TRACE("(%p) %p\n",This,pdim);
996 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
998 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
999 ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1005 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
1006 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1008 struct list *cursor;
1009 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1011 TRACE("(%p) %p\n",This,pdim);
1013 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1015 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1016 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1022 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
1023 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1024 ITfDocumentMgr *pdimPrevFocus)
1026 struct list *cursor;
1027 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1029 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1031 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1033 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1034 ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
1040 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
1041 ITfThreadMgrEventSink *iface, ITfContext *pic)
1043 struct list *cursor;
1044 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1046 TRACE("(%p) %p\n",This,pic);
1048 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1050 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1051 ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1057 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
1058 ITfThreadMgrEventSink *iface, ITfContext *pic)
1060 struct list *cursor;
1061 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1063 TRACE("(%p) %p\n",This,pic);
1065 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1067 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1068 ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1074 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
1076 ThreadMgrEventSink_QueryInterface,
1077 ThreadMgrEventSink_AddRef,
1078 ThreadMgrEventSink_Release,
1080 ThreadMgrEventSink_OnInitDocumentMgr,
1081 ThreadMgrEventSink_OnUninitDocumentMgr,
1082 ThreadMgrEventSink_OnSetFocus,
1083 ThreadMgrEventSink_OnPushContext,
1084 ThreadMgrEventSink_OnPopContext
1087 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1091 return CLASS_E_NOAGGREGATION;
1093 /* Only 1 ThreadMgr is created per thread */
1094 This = TlsGetValue(tlsIndex);
1097 ThreadMgr_AddRef((ITfThreadMgr*)This);
1098 *ppOut = (IUnknown*)This;
1102 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1104 return E_OUTOFMEMORY;
1106 This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
1107 This->SourceVtbl = &ThreadMgr_SourceVtbl;
1108 This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
1109 This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
1110 This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
1111 This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
1113 TlsSetValue(tlsIndex,This);
1115 CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1117 list_init(&This->CurrentPreservedKeys);
1118 list_init(&This->CreatedDocumentMgrs);
1120 list_init(&This->ActiveLanguageProfileNotifySink);
1121 list_init(&This->DisplayAttributeNotifySink);
1122 list_init(&This->KeyTraceEventSink);
1123 list_init(&This->PreservedKeyNotifySink);
1124 list_init(&This->ThreadFocusSink);
1125 list_init(&This->ThreadMgrEventSink);
1127 TRACE("returning %p\n", This);
1128 *ppOut = (IUnknown *)This;
1132 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr)
1134 ThreadMgr *This = (ThreadMgr *)tm;
1135 struct list *cursor;
1136 LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1138 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1139 if (mgrentry->docmgr == mgr)
1141 list_remove(cursor);
1142 HeapFree(GetProcessHeap(),0,mgrentry);
1146 FIXME("ITfDocumenMgr %p not found in this thread\n",mgr);