wined3d: Pack hardcoded local constants in ARB.
[wine] / dlls / msctf / threadmgr.c
1 /*
2  *  ITfThreadMgr implementation
3  *
4  *  Copyright 2008 Aric Stewart, CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #define COBJMACROS
26
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"
36
37 #include "wine/unicode.h"
38 #include "wine/list.h"
39
40 #include "msctf.h"
41 #include "msctf_internal.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
44
45 typedef struct tagThreadMgrSink {
46     struct list         entry;
47     union {
48         /* ThreadMgr Sinks */
49         IUnknown            *pIUnknown;
50         /* ITfActiveLanguageProfileNotifySink *pITfActiveLanguageProfileNotifySink; */
51         /* ITfDisplayAttributeNotifySink *pITfDisplayAttributeNotifySink; */
52         /* ITfKeyTraceEventSink *pITfKeyTraceEventSink; */
53         /* ITfPreservedKeyNotifySink *pITfPreservedKeyNotifySink; */
54         /* ITfThreadFocusSink *pITfThreadFocusSink; */
55         ITfThreadMgrEventSink *pITfThreadMgrEventSink;
56     } interfaces;
57 } ThreadMgrSink;
58
59 typedef struct tagACLMulti {
60     const ITfThreadMgrVtbl *ThreadMgrVtbl;
61     const ITfSourceVtbl *SourceVtbl;
62     const ITfKeystrokeMgrVtbl *KeystrokeMgrVtbl;
63     const ITfMessagePumpVtbl *MessagePumpVtbl;
64     LONG refCount;
65
66     const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
67
68     ITfDocumentMgr *focus;
69
70     /* kept as separate lists to reduce unnecessary iterations */
71     struct list     ActiveLanguageProfileNotifySink;
72     struct list     DisplayAttributeNotifySink;
73     struct list     KeyTraceEventSink;
74     struct list     PreservedKeyNotifySink;
75     struct list     ThreadFocusSink;
76     struct list     ThreadMgrEventSink;
77 } ThreadMgr;
78
79 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
80 {
81     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
82 }
83
84 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
85 {
86     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
87 }
88
89 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
90 {
91     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
92 }
93
94 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
95 {
96     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
97 }
98
99 static void free_sink(ThreadMgrSink *sink)
100 {
101         IUnknown_Release(sink->interfaces.pIUnknown);
102         HeapFree(GetProcessHeap(),0,sink);
103 }
104
105 static void ThreadMgr_Destructor(ThreadMgr *This)
106 {
107     struct list *cursor, *cursor2;
108
109     TlsSetValue(tlsIndex,NULL);
110     TRACE("destroying %p\n", This);
111     if (This->focus)
112         ITfDocumentMgr_Release(This->focus);
113
114     /* free sinks */
115     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
116     {
117         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
118         list_remove(cursor);
119         free_sink(sink);
120     }
121     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
122     {
123         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
124         list_remove(cursor);
125         free_sink(sink);
126     }
127     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
128     {
129         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
130         list_remove(cursor);
131         free_sink(sink);
132     }
133     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
134     {
135         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
136         list_remove(cursor);
137         free_sink(sink);
138     }
139     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
140     {
141         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
142         list_remove(cursor);
143         free_sink(sink);
144     }
145     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
146     {
147         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
148         list_remove(cursor);
149         free_sink(sink);
150     }
151
152     HeapFree(GetProcessHeap(),0,This);
153 }
154
155 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
156 {
157     ThreadMgr *This = (ThreadMgr *)iface;
158     *ppvOut = NULL;
159
160     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
161     {
162         *ppvOut = This;
163     }
164     else if (IsEqualIID(iid, &IID_ITfSource))
165     {
166         *ppvOut = &This->SourceVtbl;
167     }
168     else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
169     {
170         *ppvOut = &This->KeystrokeMgrVtbl;
171     }
172     else if (IsEqualIID(iid, &IID_ITfMessagePump))
173     {
174         *ppvOut = &This->MessagePumpVtbl;
175     }
176
177     if (*ppvOut)
178     {
179         IUnknown_AddRef(iface);
180         return S_OK;
181     }
182
183     WARN("unsupported interface: %s\n", debugstr_guid(iid));
184     return E_NOINTERFACE;
185 }
186
187 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
188 {
189     ThreadMgr *This = (ThreadMgr *)iface;
190     return InterlockedIncrement(&This->refCount);
191 }
192
193 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
194 {
195     ThreadMgr *This = (ThreadMgr *)iface;
196     ULONG ret;
197
198     ret = InterlockedDecrement(&This->refCount);
199     if (ret == 0)
200         ThreadMgr_Destructor(This);
201     return ret;
202 }
203
204 /*****************************************************
205  * ITfThreadMgr functions
206  *****************************************************/
207
208 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
209 {
210     ThreadMgr *This = (ThreadMgr *)iface;
211     FIXME("STUB:(%p)\n",This);
212     return E_NOTIMPL;
213 }
214
215 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
216 {
217     ThreadMgr *This = (ThreadMgr *)iface;
218     FIXME("STUB:(%p)\n",This);
219
220     if (This->focus)
221     {
222         ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
223         ITfDocumentMgr_Release(This->focus);
224         This->focus = 0;
225     }
226
227     return E_NOTIMPL;
228 }
229
230 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
231 **ppdim)
232 {
233     ThreadMgr *This = (ThreadMgr *)iface;
234     TRACE("(%p)\n",iface);
235     return DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
236 }
237
238 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
239 **ppEnum)
240 {
241     ThreadMgr *This = (ThreadMgr *)iface;
242     FIXME("STUB:(%p)\n",This);
243     return E_NOTIMPL;
244 }
245
246 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
247 **ppdimFocus)
248 {
249     ThreadMgr *This = (ThreadMgr *)iface;
250     TRACE("(%p)\n",This);
251
252     if (!ppdimFocus)
253         return E_INVALIDARG;
254
255     *ppdimFocus = This->focus;
256
257     TRACE("->%p\n",This->focus);
258
259     if (This->focus == NULL)
260         return S_FALSE;
261
262     ITfDocumentMgr_AddRef(This->focus);
263
264     return S_OK;
265 }
266
267 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
268 {
269     ITfDocumentMgr *check;
270     ThreadMgr *This = (ThreadMgr *)iface;
271
272     TRACE("(%p) %p\n",This,pdimFocus);
273
274     if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
275         return E_INVALIDARG;
276
277     ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
278
279     if (This->focus)
280         ITfDocumentMgr_Release(This->focus);
281
282     This->focus = check;
283     return S_OK;
284 }
285
286 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
287 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
288 {
289     ThreadMgr *This = (ThreadMgr *)iface;
290     FIXME("STUB:(%p)\n",This);
291     return E_NOTIMPL;
292 }
293
294 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
295 {
296     ThreadMgr *This = (ThreadMgr *)iface;
297     FIXME("STUB:(%p)\n",This);
298     return E_NOTIMPL;
299 }
300
301 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
302 ITfFunctionProvider **ppFuncProv)
303 {
304     ThreadMgr *This = (ThreadMgr *)iface;
305     FIXME("STUB:(%p)\n",This);
306     return E_NOTIMPL;
307 }
308
309 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
310 IEnumTfFunctionProviders **ppEnum)
311 {
312     ThreadMgr *This = (ThreadMgr *)iface;
313     FIXME("STUB:(%p)\n",This);
314     return E_NOTIMPL;
315 }
316
317 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
318 ITfCompartmentMgr **ppCompMgr)
319 {
320     ThreadMgr *This = (ThreadMgr *)iface;
321     FIXME("STUB:(%p)\n",This);
322     return E_NOTIMPL;
323 }
324
325 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
326 {
327     ThreadMgr_QueryInterface,
328     ThreadMgr_AddRef,
329     ThreadMgr_Release,
330
331     ThreadMgr_fnActivate,
332     ThreadMgr_fnDeactivate,
333     ThreadMgr_CreateDocumentMgr,
334     ThreadMgr_EnumDocumentMgrs,
335     ThreadMgr_GetFocus,
336     ThreadMgr_SetFocus,
337     ThreadMgr_AssociateFocus,
338     ThreadMgr_IsThreadFocus,
339     ThreadMgr_GetFunctionProvider,
340     ThreadMgr_EnumFunctionProviders,
341     ThreadMgr_GetGlobalCompartment
342 };
343
344
345 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
346 {
347     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
348     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
349 }
350
351 static ULONG WINAPI Source_AddRef(ITfSource *iface)
352 {
353     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
354     return ThreadMgr_AddRef((ITfThreadMgr*)This);
355 }
356
357 static ULONG WINAPI Source_Release(ITfSource *iface)
358 {
359     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
360     return ThreadMgr_Release((ITfThreadMgr *)This);
361 }
362
363 /*****************************************************
364  * ITfSource functions
365  *****************************************************/
366 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
367         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
368 {
369     ThreadMgrSink *tms;
370     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
371
372     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
373
374     if (!riid || !punk || !pdwCookie)
375         return E_INVALIDARG;
376
377     if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
378     {
379         tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
380         if (!tms)
381             return E_OUTOFMEMORY;
382         if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&tms->interfaces.pITfThreadMgrEventSink)))
383         {
384             HeapFree(GetProcessHeap(),0,tms);
385             return CONNECT_E_CANNOTCONNECT;
386         }
387         list_add_head(&This->ThreadMgrEventSink,&tms->entry);
388         *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
389     }
390     else
391     {
392         FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
393         return E_NOTIMPL;
394     }
395
396     TRACE("cookie %x\n",*pdwCookie);
397
398     return S_OK;
399 }
400
401 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
402 {
403     ThreadMgrSink *sink;
404     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
405
406     TRACE("(%p) %x\n",This,pdwCookie);
407
408     if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
409         return E_INVALIDARG;
410
411     sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
412     if (!sink)
413         return CONNECT_E_NOCONNECTION;
414
415     list_remove(&sink->entry);
416     free_sink(sink);
417
418     return S_OK;
419 }
420
421 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
422 {
423     Source_QueryInterface,
424     Source_AddRef,
425     Source_Release,
426
427     ThreadMgrSource_AdviseSink,
428     ThreadMgrSource_UnadviseSink,
429 };
430
431 /*****************************************************
432  * ITfKeystrokeMgr functions
433  *****************************************************/
434
435 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
436 {
437     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
438     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
439 }
440
441 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
442 {
443     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
444     return ThreadMgr_AddRef((ITfThreadMgr*)This);
445 }
446
447 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
448 {
449     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
450     return ThreadMgr_Release((ITfThreadMgr *)This);
451 }
452
453 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
454         TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
455 {
456     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
457     FIXME("STUB:(%p)\n",This);
458     return E_NOTIMPL;
459 }
460
461 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
462         TfClientId tid)
463 {
464     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
465     FIXME("STUB:(%p)\n",This);
466     return E_NOTIMPL;
467 }
468
469 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
470         CLSID *pclsid)
471 {
472     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
473     FIXME("STUB:(%p)\n",This);
474     return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
478         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
479 {
480     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
481     FIXME("STUB:(%p)\n",This);
482     return E_NOTIMPL;
483 }
484
485 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
486         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
487 {
488     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
489     FIXME("STUB:(%p)\n",This);
490     return E_NOTIMPL;
491 }
492
493 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
494         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
495 {
496     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
497     FIXME("STUB:(%p)\n",This);
498     return E_NOTIMPL;
499 }
500
501 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
502         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
503 {
504     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
505     FIXME("STUB:(%p)\n",This);
506     return E_NOTIMPL;
507 }
508
509 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
510         ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
511 {
512     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
513     FIXME("STUB:(%p)\n",This);
514     return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
518         REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
519 {
520     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
521     FIXME("STUB:(%p)\n",This);
522     return E_NOTIMPL;
523 }
524
525 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
526         TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
527         const WCHAR *pchDesc, ULONG cchDesc)
528 {
529     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
530     FIXME("STUB:(%p)\n",This);
531     return E_NOTIMPL;
532 }
533
534 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
535         REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
536 {
537     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
538     FIXME("STUB:(%p)\n",This);
539     return E_NOTIMPL;
540 }
541
542 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
543         REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
544 {
545     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
546     FIXME("STUB:(%p)\n",This);
547     return E_NOTIMPL;
548 }
549
550 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
551         REFGUID rguid, BSTR *pbstrDesc)
552 {
553     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
554     FIXME("STUB:(%p)\n",This);
555     return E_NOTIMPL;
556 }
557
558 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
559         ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
560 {
561     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
562     FIXME("STUB:(%p)\n",This);
563     return E_NOTIMPL;
564 }
565
566 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
567 {
568     KeystrokeMgr_QueryInterface,
569     KeystrokeMgr_AddRef,
570     KeystrokeMgr_Release,
571
572     KeystrokeMgr_AdviseKeyEventSink,
573     KeystrokeMgr_UnadviseKeyEventSink,
574     KeystrokeMgr_GetForeground,
575     KeystrokeMgr_TestKeyDown,
576     KeystrokeMgr_TestKeyUp,
577     KeystrokeMgr_KeyDown,
578     KeystrokeMgr_KeyUp,
579     KeystrokeMgr_GetPreservedKey,
580     KeystrokeMgr_IsPreservedKey,
581     KeystrokeMgr_PreserveKey,
582     KeystrokeMgr_UnpreserveKey,
583     KeystrokeMgr_SetPreservedKeyDescription,
584     KeystrokeMgr_GetPreservedKeyDescription,
585     KeystrokeMgr_SimulatePreservedKey
586 };
587
588 /*****************************************************
589  * ITfMessagePump functions
590  *****************************************************/
591
592 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
593 {
594     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
595     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
596 }
597
598 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
599 {
600     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
601     return ThreadMgr_AddRef((ITfThreadMgr*)This);
602 }
603
604 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
605 {
606     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
607     return ThreadMgr_Release((ITfThreadMgr *)This);
608 }
609
610 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
611         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
612         UINT wRemoveMsg, BOOL *pfResult)
613 {
614     if (!pfResult)
615         return E_INVALIDARG;
616     *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
617     return S_OK;
618 }
619
620 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
621         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
622         BOOL *pfResult)
623 {
624     if (!pfResult)
625         return E_INVALIDARG;
626     *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
627     return S_OK;
628 }
629
630 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
631         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
632         UINT wRemoveMsg, BOOL *pfResult)
633 {
634     if (!pfResult)
635         return E_INVALIDARG;
636     *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
637     return S_OK;
638 }
639
640 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
641         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
642         BOOL *pfResult)
643 {
644     if (!pfResult)
645         return E_INVALIDARG;
646     *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
647     return S_OK;
648 }
649
650 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
651 {
652     MessagePump_QueryInterface,
653     MessagePump_AddRef,
654     MessagePump_Release,
655
656     MessagePump_PeekMessageA,
657     MessagePump_GetMessageA,
658     MessagePump_PeekMessageW,
659     MessagePump_GetMessageW
660 };
661
662 /*****************************************************
663  * ITfThreadMgrEventSink functions  (internal)
664  *****************************************************/
665 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
666 {
667     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
668     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
669 }
670
671 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
672 {
673     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
674     return ThreadMgr_AddRef((ITfThreadMgr*)This);
675 }
676
677 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
678 {
679     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
680     return ThreadMgr_Release((ITfThreadMgr *)This);
681 }
682
683
684 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
685         ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
686 {
687     struct list *cursor;
688     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
689
690     TRACE("(%p) %p\n",This,pdim);
691
692     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
693     {
694         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
695         ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
696     }
697
698     return S_OK;
699 }
700
701 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
702         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
703 {
704     struct list *cursor;
705     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
706
707     TRACE("(%p) %p\n",This,pdim);
708
709     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
710     {
711         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
712         ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
713     }
714
715     return S_OK;
716 }
717
718 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
719         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
720         ITfDocumentMgr *pdimPrevFocus)
721 {
722     struct list *cursor;
723     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
724
725     TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
726
727     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
728     {
729         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
730         ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
731     }
732
733     return S_OK;
734 }
735
736 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
737         ITfThreadMgrEventSink *iface, ITfContext *pic)
738 {
739     struct list *cursor;
740     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
741
742     TRACE("(%p) %p\n",This,pic);
743
744     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
745     {
746         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
747         ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
748     }
749
750     return S_OK;
751 }
752
753 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
754         ITfThreadMgrEventSink *iface, ITfContext *pic)
755 {
756     struct list *cursor;
757     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
758
759     TRACE("(%p) %p\n",This,pic);
760
761     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
762     {
763         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
764         ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
765     }
766
767     return S_OK;
768 }
769
770 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
771 {
772     ThreadMgrEventSink_QueryInterface,
773     ThreadMgrEventSink_AddRef,
774     ThreadMgrEventSink_Release,
775
776     ThreadMgrEventSink_OnInitDocumentMgr,
777     ThreadMgrEventSink_OnUninitDocumentMgr,
778     ThreadMgrEventSink_OnSetFocus,
779     ThreadMgrEventSink_OnPushContext,
780     ThreadMgrEventSink_OnPopContext
781 };
782
783 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
784 {
785     ThreadMgr *This;
786     if (pUnkOuter)
787         return CLASS_E_NOAGGREGATION;
788
789     /* Only 1 ThreadMgr is created per thread */
790     This = TlsGetValue(tlsIndex);
791     if (This)
792     {
793         ThreadMgr_AddRef((ITfThreadMgr*)This);
794         *ppOut = (IUnknown*)This;
795         return S_OK;
796     }
797
798     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
799     if (This == NULL)
800         return E_OUTOFMEMORY;
801
802     This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
803     This->SourceVtbl = &ThreadMgr_SourceVtbl;
804     This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
805     This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
806     This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
807     This->refCount = 1;
808     TlsSetValue(tlsIndex,This);
809
810     list_init(&This->ActiveLanguageProfileNotifySink);
811     list_init(&This->DisplayAttributeNotifySink);
812     list_init(&This->KeyTraceEventSink);
813     list_init(&This->PreservedKeyNotifySink);
814     list_init(&This->ThreadFocusSink);
815     list_init(&This->ThreadMgrEventSink);
816
817     TRACE("returning %p\n", This);
818     *ppOut = (IUnknown *)This;
819     return S_OK;
820 }