quartz: Silence requests for ipin on filters.
[wine] / dlls / imm32 / imm.c
1 /*
2  * IMM32 library
3  *
4  * Copyright 1998 Patrik Stridvall
5  * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winerror.h"
29 #include "wine/debug.h"
30 #include "imm.h"
31 #include "ddk/imm.h"
32 #include "winnls.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(imm);
35
36 #define FROM_IME 0xcafe1337
37
38 static void (*pX11DRV_ForceXIMReset)(HWND);
39
40 typedef struct tagIMCCInternal
41 {
42     DWORD dwLock;
43     DWORD dwSize;
44 } IMCCInternal;
45
46 typedef struct tagInputContextData
47 {
48         BOOL            bInternalState;
49         BOOL            bRead;
50         BOOL            bInComposition;
51         HFONT           textfont;
52
53         DWORD           dwLock;
54         INPUTCONTEXT    IMC;
55 } InputContextData;
56
57 typedef struct _tagTRANSMSG {
58     UINT message;
59     WPARAM wParam;
60     LPARAM lParam;
61 } TRANSMSG, *LPTRANSMSG;
62
63 static InputContextData *root_context = NULL;
64 static HWND hwndDefault = NULL;
65 static HANDLE hImeInst;
66 static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
67 static ATOM atIMEClass = 0;
68
69 /* MSIME messages */
70 static UINT WM_MSIME_SERVICE;
71 static UINT WM_MSIME_RECONVERTOPTIONS;
72 static UINT WM_MSIME_MOUSE;
73 static UINT WM_MSIME_RECONVERTREQUEST;
74 static UINT WM_MSIME_RECONVERT;
75 static UINT WM_MSIME_QUERYPOSITION;
76 static UINT WM_MSIME_DOCUMENTFEED;
77
78 /*
79  * prototypes
80  */
81 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
82                                           LPARAM lParam);
83 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable);
84 static void ImmInternalPostIMEMessage(UINT, WPARAM, LPARAM);
85 static void ImmInternalSetOpenStatus(BOOL fOpen);
86 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len);
87
88 static VOID IMM_PostResult(InputContextData *data)
89 {
90     unsigned int i;
91     LPCOMPOSITIONSTRING compstr;
92     LPBYTE compdata;
93     LPWSTR ResultStr;
94     HIMCC newCompStr;
95
96     TRACE("Posting result as IME_CHAR\n");
97     compdata = ImmLockIMCC(root_context->IMC.hCompStr);
98     compstr = (LPCOMPOSITIONSTRING)compdata;
99     ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
100
101     for (i = 0; i < compstr->dwResultStrLen; i++)
102         ImmInternalPostIMEMessage (WM_IME_CHAR, ResultStr[i], 1);
103
104     ImmUnlockIMCC(root_context->IMC.hCompStr);
105
106     /* clear the buffer */
107     newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
108     ImmDestroyIMCC(root_context->IMC.hCompStr);
109     root_context->IMC.hCompStr = newCompStr;
110 }
111
112 static void IMM_Register(void)
113 {
114     WNDCLASSW wndClass;
115     ZeroMemory(&wndClass, sizeof(WNDCLASSW));
116     wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
117     wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
118     wndClass.cbClsExtra = 0;
119     wndClass.cbWndExtra = 0;
120     wndClass.hInstance = hImeInst;
121     wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
122     wndClass.hIcon = NULL;
123     wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
124     wndClass.lpszMenuName   = 0;
125     wndClass.lpszClassName = WC_IMECLASSNAME;
126     atIMEClass = RegisterClassW(&wndClass);
127 }
128
129 static void IMM_Unregister(void)
130 {
131     if (atIMEClass) {
132         UnregisterClassW(WC_IMECLASSNAME, NULL);
133     }
134 }
135
136 static void IMM_RegisterMessages(void)
137 {
138     WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
139     WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
140     WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
141     WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
142     WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
143     WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
144     WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
145 }
146
147
148 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
149 {
150     HMODULE x11drv;
151
152     TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
153     switch (fdwReason)
154     {
155         case DLL_PROCESS_ATTACH:
156             DisableThreadLibraryCalls(hInstDLL);
157             hImeInst = hInstDLL;
158             IMM_RegisterMessages();
159             x11drv = GetModuleHandleA("winex11.drv");
160             if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset");
161             break;
162         case DLL_PROCESS_DETACH:
163             if (hwndDefault)
164             {
165                 DestroyWindow(hwndDefault);
166                 hwndDefault = 0;
167             }
168             IMM_Unregister();
169             break;
170     }
171     return TRUE;
172 }
173
174 /* for posting messages as the IME */
175 static void ImmInternalPostIMEMessage(UINT msg, WPARAM wParam, LPARAM lParam)
176 {
177     HWND target = GetFocus();
178     if (!target)
179        PostMessageW(root_context->IMC.hWnd,msg,wParam,lParam);
180     else
181        PostMessageW(target, msg, wParam, lParam);
182 }
183
184 static LRESULT ImmInternalSendIMENotify(WPARAM notify, LPARAM lParam)
185 {
186     HWND target;
187
188     target = root_context->IMC.hWnd;
189     if (!target) target = GetFocus();
190
191     if (target)
192        return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
193
194     return 0;
195 }
196
197 static HIMCC ImmCreateBlankCompStr(void)
198 {
199     HIMCC rc;
200     LPCOMPOSITIONSTRING ptr;
201     rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
202     ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc);
203     memset(ptr,0,sizeof(COMPOSITIONSTRING));
204     ptr->dwSize = sizeof(COMPOSITIONSTRING);
205     ImmUnlockIMCC(rc);
206     return rc;
207 }
208
209 static void ImmInternalSetOpenStatus(BOOL fOpen)
210 {
211     TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
212
213     if (root_context->IMC.fOpen && fOpen == FALSE)
214     {
215         ShowWindow(hwndDefault,SW_HIDE);
216         ImmDestroyIMCC(root_context->IMC.hCompStr);
217         root_context->IMC.hCompStr = ImmCreateBlankCompStr();
218     }
219
220     root_context->IMC.fOpen = fOpen;
221     root_context->bInternalState = fOpen;
222
223     ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0);
224 }
225
226 static int updateField(DWORD origLen, DWORD origOffset, DWORD currentOffset,
227                        LPBYTE target, LPBYTE source, DWORD* lenParam,
228                        DWORD* offsetParam, BOOL wchars )
229 {
230      if (origLen > 0 && origOffset > 0)
231      {
232         int truelen = origLen;
233         if (wchars)
234             truelen *= sizeof(WCHAR);
235
236         memcpy(&target[currentOffset], &source[origOffset], truelen);
237
238         *lenParam = origLen;
239         *offsetParam = currentOffset;
240         currentOffset += truelen;
241      }
242      return currentOffset;
243 }
244
245 static HIMCC updateCompStr(HIMCC old, LPWSTR compstr, DWORD len)
246 {
247     /* we need to make sure the CompStr, CompClaus and CompAttr fields are all
248      * set and correct */
249     int needed_size;
250     HIMCC   rc;
251     LPBYTE newdata = NULL;
252     LPBYTE olddata = NULL;
253     LPCOMPOSITIONSTRING new_one;
254     LPCOMPOSITIONSTRING lpcs = NULL;
255     INT current_offset = 0;
256
257     TRACE("%s, %i\n",debugstr_wn(compstr,len),len);
258
259     if (old == NULL && compstr == NULL && len == 0)
260         return NULL;
261
262     if (old != NULL)
263     {
264         olddata = ImmLockIMCC(old);
265         lpcs = (LPCOMPOSITIONSTRING)olddata;
266     }
267
268     needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
269                   len + sizeof(DWORD) * 2;
270
271     if (lpcs != NULL)
272     {
273         needed_size += lpcs->dwCompReadAttrLen;
274         needed_size += lpcs->dwCompReadClauseLen;
275         needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
276         needed_size += lpcs->dwResultReadClauseLen;
277         needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
278         needed_size += lpcs->dwResultClauseLen;
279         needed_size += lpcs->dwResultStrLen * sizeof(DWORD);
280         needed_size += lpcs->dwPrivateSize;
281     }
282     rc = ImmCreateIMCC(needed_size);
283     newdata = ImmLockIMCC(rc);
284     new_one = (LPCOMPOSITIONSTRING)newdata;
285
286     new_one->dwSize = needed_size;
287     current_offset = sizeof(COMPOSITIONSTRING);
288     if (lpcs != NULL)
289     {
290         current_offset = updateField(lpcs->dwCompReadAttrLen,
291                                      lpcs->dwCompReadAttrOffset,
292                                      current_offset, newdata, olddata,
293                                      &new_one->dwCompReadAttrLen,
294                                      &new_one->dwCompReadAttrOffset, FALSE);
295
296         current_offset = updateField(lpcs->dwCompReadClauseLen,
297                                      lpcs->dwCompReadClauseOffset,
298                                      current_offset, newdata, olddata,
299                                      &new_one->dwCompReadClauseLen,
300                                      &new_one->dwCompReadClauseOffset, FALSE);
301
302         current_offset = updateField(lpcs->dwCompReadStrLen,
303                                      lpcs->dwCompReadStrOffset,
304                                      current_offset, newdata, olddata,
305                                      &new_one->dwCompReadStrLen,
306                                      &new_one->dwCompReadStrOffset, TRUE);
307
308         /* new CompAttr, CompClause, CompStr, dwCursorPos */
309         new_one->dwDeltaStart = 0;
310
311         current_offset = updateField(lpcs->dwResultReadClauseLen,
312                                      lpcs->dwResultReadClauseOffset,
313                                      current_offset, newdata, olddata,
314                                      &new_one->dwResultReadClauseLen,
315                                      &new_one->dwResultReadClauseOffset, FALSE);
316
317         current_offset = updateField(lpcs->dwResultReadStrLen,
318                                      lpcs->dwResultReadStrOffset,
319                                      current_offset, newdata, olddata,
320                                      &new_one->dwResultReadStrLen,
321                                      &new_one->dwResultReadStrOffset, TRUE);
322
323         current_offset = updateField(lpcs->dwResultClauseLen,
324                                      lpcs->dwResultClauseOffset,
325                                      current_offset, newdata, olddata,
326                                      &new_one->dwResultClauseLen,
327                                      &new_one->dwResultClauseOffset, FALSE);
328
329         current_offset = updateField(lpcs->dwResultStrLen,
330                                      lpcs->dwResultStrOffset,
331                                      current_offset, newdata, olddata,
332                                      &new_one->dwResultStrLen,
333                                      &new_one->dwResultStrOffset, TRUE);
334
335         current_offset = updateField(lpcs->dwPrivateSize,
336                                      lpcs->dwPrivateOffset,
337                                      current_offset, newdata, olddata,
338                                      &new_one->dwPrivateSize,
339                                      &new_one->dwPrivateOffset, FALSE);
340     }
341
342     /* set new data */
343     /* CompAttr */
344     new_one->dwCompAttrLen = len;
345     if (len > 0)
346     {
347         new_one->dwCompAttrOffset = current_offset;
348         memset(&newdata[current_offset],ATTR_INPUT,len);
349         current_offset += len;
350     }
351
352     /* CompClause */
353     if (len > 0)
354     {
355         new_one->dwCompClauseLen = sizeof(DWORD) * 2;
356         new_one->dwCompClauseOffset = current_offset;
357         *(DWORD*)(&newdata[current_offset]) = 0;
358         current_offset += sizeof(DWORD);
359         *(DWORD*)(&newdata[current_offset]) = len;
360         current_offset += sizeof(DWORD);
361     }
362
363     /* CompStr */
364     new_one->dwCompStrLen = len;
365     if (len > 0)
366     {
367         new_one->dwCompStrOffset = current_offset;
368         memcpy(&newdata[current_offset],compstr,len*sizeof(WCHAR));
369     }
370
371     /* CursorPos */
372     new_one->dwCursorPos = len;
373
374     ImmUnlockIMCC(rc);
375     if (lpcs)
376         ImmUnlockIMCC(old);
377
378     return rc;
379 }
380
381 static HIMCC updateResultStr(HIMCC old, LPWSTR resultstr, DWORD len)
382 {
383     /* we need to make sure the ResultStr and ResultClause fields are all
384      * set and correct */
385     int needed_size;
386     HIMCC   rc;
387     LPBYTE newdata = NULL;
388     LPBYTE olddata = NULL;
389     LPCOMPOSITIONSTRING new_one;
390     LPCOMPOSITIONSTRING lpcs = NULL;
391     INT current_offset = 0;
392
393     TRACE("%s, %i\n",debugstr_wn(resultstr,len),len);
394
395     if (old == NULL && resultstr == NULL && len == 0)
396         return NULL;
397
398     if (old != NULL)
399     {
400         olddata = ImmLockIMCC(old);
401         lpcs = (LPCOMPOSITIONSTRING)olddata;
402     }
403
404     needed_size = sizeof(COMPOSITIONSTRING) + len * sizeof(WCHAR) +
405                   sizeof(DWORD) * 2;
406
407     if (lpcs != NULL)
408     {
409         needed_size += lpcs->dwCompReadAttrLen;
410         needed_size += lpcs->dwCompReadClauseLen;
411         needed_size += lpcs->dwCompReadStrLen * sizeof(DWORD);
412         needed_size += lpcs->dwCompAttrLen;
413         needed_size += lpcs->dwCompClauseLen;
414         needed_size += lpcs->dwCompStrLen * sizeof(DWORD);
415         needed_size += lpcs->dwResultReadClauseLen;
416         needed_size += lpcs->dwResultReadStrLen * sizeof(DWORD);
417         needed_size += lpcs->dwPrivateSize;
418     }
419     rc = ImmCreateIMCC(needed_size);
420     newdata = ImmLockIMCC(rc);
421     new_one = (LPCOMPOSITIONSTRING)newdata;
422
423     new_one->dwSize = needed_size;
424     current_offset = sizeof(COMPOSITIONSTRING);
425     if (lpcs != NULL)
426     {
427         current_offset = updateField(lpcs->dwCompReadAttrLen,
428                                      lpcs->dwCompReadAttrOffset,
429                                      current_offset, newdata, olddata,
430                                      &new_one->dwCompReadAttrLen,
431                                      &new_one->dwCompReadAttrOffset, FALSE);
432
433         current_offset = updateField(lpcs->dwCompReadClauseLen,
434                                      lpcs->dwCompReadClauseOffset,
435                                      current_offset, newdata, olddata,
436                                      &new_one->dwCompReadClauseLen,
437                                      &new_one->dwCompReadClauseOffset, FALSE);
438
439         current_offset = updateField(lpcs->dwCompReadStrLen,
440                                      lpcs->dwCompReadStrOffset,
441                                      current_offset, newdata, olddata,
442                                      &new_one->dwCompReadStrLen,
443                                      &new_one->dwCompReadStrOffset, TRUE);
444
445         current_offset = updateField(lpcs->dwCompAttrLen,
446                                      lpcs->dwCompAttrOffset,
447                                      current_offset, newdata, olddata,
448                                      &new_one->dwCompAttrLen,
449                                      &new_one->dwCompAttrOffset, FALSE);
450
451         current_offset = updateField(lpcs->dwCompClauseLen,
452                                      lpcs->dwCompClauseOffset,
453                                      current_offset, newdata, olddata,
454                                      &new_one->dwCompClauseLen,
455                                      &new_one->dwCompClauseOffset, FALSE);
456
457         current_offset = updateField(lpcs->dwCompStrLen,
458                                      lpcs->dwCompStrOffset,
459                                      current_offset, newdata, olddata,
460                                      &new_one->dwCompStrLen,
461                                      &new_one->dwCompStrOffset, TRUE);
462
463         new_one->dwCursorPos = lpcs->dwCursorPos;
464         new_one->dwDeltaStart = 0;
465
466         current_offset = updateField(lpcs->dwResultReadClauseLen,
467                                      lpcs->dwResultReadClauseOffset,
468                                      current_offset, newdata, olddata,
469                                      &new_one->dwResultReadClauseLen,
470                                      &new_one->dwResultReadClauseOffset, FALSE);
471
472         current_offset = updateField(lpcs->dwResultReadStrLen,
473                                      lpcs->dwResultReadStrOffset,
474                                      current_offset, newdata, olddata,
475                                      &new_one->dwResultReadStrLen,
476                                      &new_one->dwResultReadStrOffset, TRUE);
477
478         /* new ResultClause , ResultStr */
479
480         current_offset = updateField(lpcs->dwPrivateSize,
481                                      lpcs->dwPrivateOffset,
482                                      current_offset, newdata, olddata,
483                                      &new_one->dwPrivateSize,
484                                      &new_one->dwPrivateOffset, FALSE);
485     }
486
487     /* set new data */
488     /* ResultClause */
489     if (len > 0)
490     {
491         new_one->dwResultClauseLen = sizeof(DWORD) * 2;
492         new_one->dwResultClauseOffset = current_offset;
493         *(DWORD*)(&newdata[current_offset]) = 0;
494         current_offset += sizeof(DWORD);
495         *(DWORD*)(&newdata[current_offset]) = len;
496         current_offset += sizeof(DWORD);
497     }
498
499     /* ResultStr */
500     new_one->dwResultStrLen = len;
501     if (len > 0)
502     {
503         new_one->dwResultStrOffset = current_offset;
504         memcpy(&newdata[current_offset],resultstr,len*sizeof(WCHAR));
505     }
506     ImmUnlockIMCC(rc);
507     if (lpcs)
508         ImmUnlockIMCC(old);
509
510     return rc;
511 }
512
513
514
515 /***********************************************************************
516  *              ImmAssociateContext (IMM32.@)
517  */
518 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
519 {
520     InputContextData *data = (InputContextData*)hIMC;
521
522     WARN("(%p, %p): semi-stub\n", hWnd, hIMC);
523
524     if (!hIMC)
525         return NULL;
526
527     /*
528      * WINE SPECIFIC! MAY CONFLICT
529      * associate the root context we have an XIM created
530      */
531     if (hWnd == 0x000)
532     {
533         root_context = (InputContextData*)hIMC;
534     }
535
536     /*
537      * If already associated just return
538      */
539     if (data->IMC.hWnd == hWnd)
540         return hIMC;
541
542     if (IsWindow(data->IMC.hWnd))
543     {
544         /*
545          * Post a message that your context is switching
546          */
547         SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
548     }
549
550     data->IMC.hWnd = hWnd;
551
552     if (IsWindow(data->IMC.hWnd))
553     {
554         /*
555          * Post a message that your context is switching
556          */
557         SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
558     }
559
560     /*
561      * TODO: We need to keep track of the old context associated
562      * with a window and return it for now we will return NULL;
563      */
564     return NULL;
565 }
566
567 /***********************************************************************
568  *              ImmAssociateContextEx (IMM32.@)
569  */
570 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
571 {
572     FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
573     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
574     return FALSE;
575 }
576
577 /***********************************************************************
578  *              ImmConfigureIMEA (IMM32.@)
579  */
580 BOOL WINAPI ImmConfigureIMEA(
581   HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
582 {
583   FIXME("(%p, %p, %d, %p): stub\n",
584     hKL, hWnd, dwMode, lpData
585   );
586   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
587   return FALSE;
588 }
589
590 /***********************************************************************
591  *              ImmConfigureIMEW (IMM32.@)
592  */
593 BOOL WINAPI ImmConfigureIMEW(
594   HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
595 {
596   FIXME("(%p, %p, %d, %p): stub\n",
597     hKL, hWnd, dwMode, lpData
598   );
599   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
600   return FALSE;
601 }
602
603 /***********************************************************************
604  *              ImmCreateContext (IMM32.@)
605  */
606 HIMC WINAPI ImmCreateContext(void)
607 {
608     InputContextData *new_context;
609
610     new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
611
612     /* hCompStr is never NULL */
613     new_context->IMC.hCompStr = ImmCreateBlankCompStr();
614     new_context->IMC.hMsgBuf = ImmCreateIMCC(1);
615
616     return (HIMC)new_context;
617 }
618
619 /***********************************************************************
620  *              ImmDestroyContext (IMM32.@)
621  */
622 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
623 {
624     InputContextData *data = (InputContextData*)hIMC;
625
626     TRACE("Destroying %p\n",hIMC);
627
628     if (hIMC)
629     {
630         ImmDestroyIMCC(data->IMC.hCompStr);
631         ImmDestroyIMCC(data->IMC.hCandInfo);
632         ImmDestroyIMCC(data->IMC.hGuideLine);
633         ImmDestroyIMCC(data->IMC.hPrivate);
634         ImmDestroyIMCC(data->IMC.hMsgBuf);
635
636         if (data->textfont)
637         {
638             DeleteObject(data->textfont);
639             data->textfont = NULL;
640         }
641
642         HeapFree(GetProcessHeap(),0,data);
643     }
644     return TRUE;
645 }
646
647 /***********************************************************************
648  *              ImmDisableIME (IMM32.@)
649  */
650 BOOL WINAPI ImmDisableIME(DWORD idThread)
651 {
652     FIXME("(%d): stub\n", idThread);
653     return TRUE;
654 }
655
656 /***********************************************************************
657  *              ImmEnumRegisterWordA (IMM32.@)
658  */
659 UINT WINAPI ImmEnumRegisterWordA(
660   HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
661   LPCSTR lpszReading, DWORD dwStyle,
662   LPCSTR lpszRegister, LPVOID lpData)
663 {
664   FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
665     hKL, lpfnEnumProc,
666     debugstr_a(lpszReading), dwStyle,
667     debugstr_a(lpszRegister), lpData
668   );
669   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
670   return 0;
671 }
672
673 /***********************************************************************
674  *              ImmEnumRegisterWordW (IMM32.@)
675  */
676 UINT WINAPI ImmEnumRegisterWordW(
677   HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
678   LPCWSTR lpszReading, DWORD dwStyle,
679   LPCWSTR lpszRegister, LPVOID lpData)
680 {
681   FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
682     hKL, lpfnEnumProc,
683     debugstr_w(lpszReading), dwStyle,
684     debugstr_w(lpszRegister), lpData
685   );
686   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
687   return 0;
688 }
689
690 /***********************************************************************
691  *              ImmEscapeA (IMM32.@)
692  */
693 LRESULT WINAPI ImmEscapeA(
694   HKL hKL, HIMC hIMC,
695   UINT uEscape, LPVOID lpData)
696 {
697   FIXME("(%p, %p, %d, %p): stub\n",
698     hKL, hIMC, uEscape, lpData
699   );
700   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
701   return 0;
702 }
703
704 /***********************************************************************
705  *              ImmEscapeW (IMM32.@)
706  */
707 LRESULT WINAPI ImmEscapeW(
708   HKL hKL, HIMC hIMC,
709   UINT uEscape, LPVOID lpData)
710 {
711   FIXME("(%p, %p, %d, %p): stub\n",
712     hKL, hIMC, uEscape, lpData
713   );
714   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
715   return 0;
716 }
717
718 /***********************************************************************
719  *              ImmGetCandidateListA (IMM32.@)
720  */
721 DWORD WINAPI ImmGetCandidateListA(
722   HIMC hIMC, DWORD deIndex,
723   LPCANDIDATELIST lpCandList, DWORD dwBufLen)
724 {
725   FIXME("(%p, %d, %p, %d): stub\n",
726     hIMC, deIndex,
727     lpCandList, dwBufLen
728   );
729   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
730   return 0;
731 }
732
733 /***********************************************************************
734  *              ImmGetCandidateListCountA (IMM32.@)
735  */
736 DWORD WINAPI ImmGetCandidateListCountA(
737   HIMC hIMC, LPDWORD lpdwListCount)
738 {
739   FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
740   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
741   return 0;
742 }
743
744 /***********************************************************************
745  *              ImmGetCandidateListCountW (IMM32.@)
746  */
747 DWORD WINAPI ImmGetCandidateListCountW(
748   HIMC hIMC, LPDWORD lpdwListCount)
749 {
750   FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
751   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
752   return 0;
753 }
754
755 /***********************************************************************
756  *              ImmGetCandidateListW (IMM32.@)
757  */
758 DWORD WINAPI ImmGetCandidateListW(
759   HIMC hIMC, DWORD deIndex,
760   LPCANDIDATELIST lpCandList, DWORD dwBufLen)
761 {
762   FIXME("(%p, %d, %p, %d): stub\n",
763     hIMC, deIndex,
764     lpCandList, dwBufLen
765   );
766   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
767   return 0;
768 }
769
770 /***********************************************************************
771  *              ImmGetCandidateWindow (IMM32.@)
772  */
773 BOOL WINAPI ImmGetCandidateWindow(
774   HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
775 {
776   FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate);
777   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
778   return FALSE;
779 }
780
781 /***********************************************************************
782  *              ImmGetCompositionFontA (IMM32.@)
783  */
784 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
785 {
786   FIXME("(%p, %p): stub\n", hIMC, lplf);
787   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
788   return FALSE;
789 }
790
791 /***********************************************************************
792  *              ImmGetCompositionFontW (IMM32.@)
793  */
794 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
795 {
796   FIXME("(%p, %p): stub\n", hIMC, lplf);
797   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
798   return FALSE;
799 }
800
801 /***********************************************************************
802  *              ImmGetCompositionStringA (IMM32.@)
803  */
804 LONG WINAPI ImmGetCompositionStringA(
805   HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
806 {
807     CHAR *buf;
808     LONG rc = 0;
809     InputContextData *data = (InputContextData*)hIMC;
810     LPCOMPOSITIONSTRING compstr;
811     LPBYTE compdata;
812
813     TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
814
815     if (!data)
816        return FALSE;
817
818     if (!data->IMC.hCompStr)
819        return FALSE;
820
821     compdata = ImmLockIMCC(data->IMC.hCompStr);
822     compstr = (LPCOMPOSITIONSTRING)compdata;
823
824     if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
825         compstr->dwResultStrOffset > 0)
826     {
827         LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
828
829         TRACE("GSC_RESULTSTR %p %i\n",ResultStr,
830                                     compstr->dwResultStrLen);
831
832         buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 );
833         rc = WideCharToMultiByte(CP_ACP, 0, ResultStr,
834                                  compstr->dwResultStrLen , buf,
835                                  compstr->dwResultStrLen * 3, NULL, NULL);
836         if (dwBufLen >= rc)
837             memcpy(lpBuf,buf,rc);
838
839         data->bRead = TRUE;
840         HeapFree( GetProcessHeap(), 0, buf );
841     }
842     else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
843               compstr->dwCompStrOffset > 0)
844     {
845         LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
846
847         TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen);
848
849         buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 );
850         rc = WideCharToMultiByte(CP_ACP, 0, CompString,
851                                  compstr->dwCompStrLen, buf,
852                                  compstr->dwCompStrLen * 3, NULL, NULL);
853         if (dwBufLen >= rc)
854             memcpy(lpBuf,buf,rc);
855         HeapFree( GetProcessHeap(), 0, buf );
856     }
857     else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
858              compstr->dwCompAttrOffset > 0)
859     {
860         LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
861         TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen);
862
863         rc = compstr->dwCompAttrLen;
864         if (dwBufLen >= rc)
865             memcpy(lpBuf,Compattr,rc);
866     }
867     else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
868              compstr->dwCompClauseOffset > 0)
869     {
870         LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
871         TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen);
872
873         rc = compstr->dwCompClauseLen;
874         if (dwBufLen >= compstr->dwCompClauseLen)
875             memcpy(lpBuf,Compclause,rc);
876     }
877     else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 &&
878              compstr->dwResultClauseOffset > 0)
879     {
880         LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset);
881         TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen);
882
883         rc = compstr->dwResultClauseLen;
884         if (dwBufLen >= compstr->dwResultClauseLen)
885             memcpy(lpBuf,Resultclause,rc);
886     }
887     else if (dwIndex == GCS_CURSORPOS)
888     {
889         TRACE("GSC_CURSORPOS\n");
890         rc = compstr->dwCursorPos;
891     }
892     else if (dwIndex == GCS_DELTASTART)
893     {
894         TRACE("GCS_DELTASTART\n");
895         rc = compstr->dwDeltaStart;
896     }
897     else
898     {
899         FIXME("Unhandled index 0x%x\n",dwIndex);
900     }
901
902     ImmUnlockIMCC(data->IMC.hCompStr);
903
904     return rc;
905 }
906
907 /***********************************************************************
908  *              ImmGetCompositionStringW (IMM32.@)
909  */
910 LONG WINAPI ImmGetCompositionStringW(
911   HIMC hIMC, DWORD dwIndex,
912   LPVOID lpBuf, DWORD dwBufLen)
913 {
914     LONG rc = 0;
915     InputContextData *data = (InputContextData*)hIMC;
916     LPCOMPOSITIONSTRING compstr;
917     LPBYTE compdata;
918
919     TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
920
921     if (!data)
922        return FALSE;
923
924     if (!data->IMC.hCompStr)
925        return FALSE;
926
927     compdata = ImmLockIMCC(data->IMC.hCompStr);
928     compstr = (LPCOMPOSITIONSTRING)compdata;
929
930     if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
931         compstr->dwResultStrOffset > 0)
932     {
933         LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
934         data->bRead = TRUE;
935         rc =  compstr->dwResultStrLen * sizeof(WCHAR);
936
937         if (dwBufLen >= rc)
938             memcpy(lpBuf,ResultStr,rc);
939     }
940     else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 &&
941              compstr->dwResultReadStrOffset > 0)
942     {
943         LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset);
944
945         rc = compstr->dwResultReadStrLen * sizeof(WCHAR);
946         if (dwBufLen >= rc)
947             memcpy(lpBuf,ResultReadString,rc);
948     }
949     else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
950               compstr->dwCompStrOffset > 0)
951     {
952         LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
953         rc = compstr->dwCompStrLen * sizeof(WCHAR);
954         if (dwBufLen >= rc)
955             memcpy(lpBuf,CompString,rc);
956     }
957     else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
958              compstr->dwCompAttrOffset > 0)
959     {
960
961         LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
962
963         rc = compstr->dwCompAttrLen;
964         if (dwBufLen >= rc)
965             memcpy(lpBuf,Compattr,rc);
966     }
967     else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
968              compstr->dwCompClauseOffset > 0)
969     {
970         LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
971
972         rc = compstr->dwCompClauseLen;
973         if (dwBufLen >= compstr->dwCompClauseLen)
974             memcpy(lpBuf,Compclause,rc);
975     }
976     else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 &&
977               compstr->dwCompReadStrOffset > 0)
978     {
979         LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset);
980
981         rc = compstr->dwCompReadStrLen * sizeof(WCHAR);
982
983         if (dwBufLen >= rc)
984             memcpy(lpBuf,CompReadString,rc);
985     }
986     else if (dwIndex == GCS_CURSORPOS)
987     {
988         TRACE("GSC_CURSORPOS\n");
989         rc = compstr->dwCursorPos;
990     }
991     else if (dwIndex == GCS_DELTASTART)
992     {
993         TRACE("GCS_DELTASTART\n");
994         rc = compstr->dwDeltaStart;
995     }
996     else
997     {
998         FIXME("Unhandled index 0x%x\n",dwIndex);
999     }   
1000
1001     ImmUnlockIMCC(data->IMC.hCompStr);
1002
1003     return rc;
1004 }
1005
1006 /***********************************************************************
1007  *              ImmGetCompositionWindow (IMM32.@)
1008  */
1009 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1010 {
1011     InputContextData *data = (InputContextData*)hIMC;
1012
1013     TRACE("(%p, %p)\n", hIMC, lpCompForm);
1014
1015     if (!data)
1016         return FALSE;
1017
1018     *lpCompForm = data->IMC.cfCompForm;
1019     return 1;
1020 }
1021
1022 /***********************************************************************
1023  *              ImmGetContext (IMM32.@)
1024  *
1025  */
1026 HIMC WINAPI ImmGetContext(HWND hWnd)
1027 {
1028     TRACE("%p\n", hWnd);
1029
1030     if (!root_context)
1031         return NULL;
1032
1033     root_context->IMC.hWnd = hWnd;
1034     return (HIMC)root_context;
1035 }
1036
1037 /***********************************************************************
1038  *              ImmGetConversionListA (IMM32.@)
1039  */
1040 DWORD WINAPI ImmGetConversionListA(
1041   HKL hKL, HIMC hIMC,
1042   LPCSTR pSrc, LPCANDIDATELIST lpDst,
1043   DWORD dwBufLen, UINT uFlag)
1044 {
1045   FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1046     hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
1047   );
1048   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1049   return 0;
1050 }
1051
1052 /***********************************************************************
1053  *              ImmGetConversionListW (IMM32.@)
1054  */
1055 DWORD WINAPI ImmGetConversionListW(
1056   HKL hKL, HIMC hIMC,
1057   LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1058   DWORD dwBufLen, UINT uFlag)
1059 {
1060   FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1061     hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
1062   );
1063   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1064   return 0;
1065 }
1066
1067 /***********************************************************************
1068  *              ImmGetConversionStatus (IMM32.@)
1069  */
1070 BOOL WINAPI ImmGetConversionStatus(
1071   HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1072 {
1073     TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
1074     if (lpfdwConversion)
1075         *lpfdwConversion = IME_CMODE_NATIVE;
1076     if (lpfdwSentence)
1077         *lpfdwSentence = IME_SMODE_NONE;
1078     return TRUE;
1079 }
1080
1081 /***********************************************************************
1082  *              ImmGetDefaultIMEWnd (IMM32.@)
1083  */
1084 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1085 {
1086   static int shown = 0;
1087
1088   if (!shown) {
1089         FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
1090         shown = 1;
1091   }
1092
1093   if (hwndDefault == NULL)
1094   {
1095         static const WCHAR the_name[] = {'I','M','E','\0'};
1096
1097         IMM_Register();
1098         hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
1099                 the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
1100                 hImeInst, 0);
1101
1102         TRACE("Default created (%p)\n",hwndDefault);
1103   }
1104
1105   return hwndDefault;
1106 }
1107
1108 /***********************************************************************
1109  *              ImmGetDescriptionA (IMM32.@)
1110  */
1111 UINT WINAPI ImmGetDescriptionA(
1112   HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1113 {
1114   WCHAR *buf;
1115   DWORD len;
1116
1117   TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1118
1119   /* find out how many characters in the unicode buffer */
1120   len = ImmGetDescriptionW( hKL, NULL, 0 );
1121
1122   /* allocate a buffer of that size */
1123   buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1124   if( !buf )
1125   return 0;
1126
1127   /* fetch the unicode buffer */
1128   len = ImmGetDescriptionW( hKL, buf, len + 1 );
1129
1130   /* convert it back to ASCII */
1131   len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1132                              lpszDescription, uBufLen, NULL, NULL );
1133
1134   HeapFree( GetProcessHeap(), 0, buf );
1135
1136   return len;
1137 }
1138
1139 /***********************************************************************
1140  *              ImmGetDescriptionW (IMM32.@)
1141  */
1142 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1143 {
1144   static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1145
1146   FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1147
1148   if (!uBufLen) return lstrlenW( name );
1149   lstrcpynW( lpszDescription, name, uBufLen );
1150   return lstrlenW( lpszDescription );
1151 }
1152
1153 /***********************************************************************
1154  *              ImmGetGuideLineA (IMM32.@)
1155  */
1156 DWORD WINAPI ImmGetGuideLineA(
1157   HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1158 {
1159   FIXME("(%p, %d, %s, %d): stub\n",
1160     hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1161   );
1162   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1163   return 0;
1164 }
1165
1166 /***********************************************************************
1167  *              ImmGetGuideLineW (IMM32.@)
1168  */
1169 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1170 {
1171   FIXME("(%p, %d, %s, %d): stub\n",
1172     hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1173   );
1174   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1175   return 0;
1176 }
1177
1178 /***********************************************************************
1179  *              ImmGetIMEFileNameA (IMM32.@)
1180  */
1181 UINT WINAPI ImmGetIMEFileNameA(
1182   HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1183 {
1184   FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1185   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1186   return 0;
1187 }
1188
1189 /***********************************************************************
1190  *              ImmGetIMEFileNameW (IMM32.@)
1191  */
1192 UINT WINAPI ImmGetIMEFileNameW(
1193   HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1194 {
1195   FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1196   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1197   return 0;
1198 }
1199
1200 /***********************************************************************
1201  *              ImmGetOpenStatus (IMM32.@)
1202  */
1203 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1204 {
1205   InputContextData *data = (InputContextData*)hIMC;
1206
1207     if (!data)
1208         return FALSE;
1209   FIXME("(%p): semi-stub\n", hIMC);
1210
1211   return data->IMC.fOpen;
1212 }
1213
1214 /***********************************************************************
1215  *              ImmGetProperty (IMM32.@)
1216  */
1217 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1218 {
1219     DWORD rc = 0;
1220     TRACE("(%p, %d)\n", hKL, fdwIndex);
1221
1222     switch (fdwIndex)
1223     {
1224         case IGP_PROPERTY:
1225             TRACE("(%s)\n", "IGP_PROPERTY");
1226             rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
1227             break;
1228         case IGP_CONVERSION:
1229             FIXME("(%s)\n", "IGP_CONVERSION");
1230             rc = IME_CMODE_NATIVE;
1231             break;
1232         case IGP_SENTENCE:
1233             FIXME("%s)\n", "IGP_SENTENCE");
1234             rc = IME_SMODE_AUTOMATIC;
1235             break;
1236         case IGP_SETCOMPSTR:
1237             TRACE("(%s)\n", "IGP_SETCOMPSTR");
1238             rc = 0;
1239             break;
1240         case IGP_SELECT:
1241             TRACE("(%s)\n", "IGP_SELECT");
1242             rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
1243             break;
1244         case IGP_GETIMEVERSION:
1245             TRACE("(%s)\n", "IGP_GETIMEVERSION");
1246             rc = IMEVER_0400;
1247             break;
1248         case IGP_UI:
1249             TRACE("(%s)\n", "IGP_UI");
1250             rc = 0;
1251             break;
1252         default:
1253             rc = 0;
1254     }
1255     return rc;
1256 }
1257
1258 /***********************************************************************
1259  *              ImmGetRegisterWordStyleA (IMM32.@)
1260  */
1261 UINT WINAPI ImmGetRegisterWordStyleA(
1262   HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1263 {
1264   FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1265   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1266   return 0;
1267 }
1268
1269 /***********************************************************************
1270  *              ImmGetRegisterWordStyleW (IMM32.@)
1271  */
1272 UINT WINAPI ImmGetRegisterWordStyleW(
1273   HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1274 {
1275   FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1276   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1277   return 0;
1278 }
1279
1280 /***********************************************************************
1281  *              ImmGetStatusWindowPos (IMM32.@)
1282  */
1283 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1284 {
1285   FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1286   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1287   return FALSE;
1288 }
1289
1290 /***********************************************************************
1291  *              ImmGetVirtualKey (IMM32.@)
1292  */
1293 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1294 {
1295   OSVERSIONINFOA version;
1296   FIXME("(%p): stub\n", hWnd);
1297   GetVersionExA( &version );
1298   switch(version.dwPlatformId)
1299   {
1300   case VER_PLATFORM_WIN32_WINDOWS:
1301       return VK_PROCESSKEY;
1302   case VER_PLATFORM_WIN32_NT:
1303       return 0;
1304   default:
1305       FIXME("%d not supported\n",version.dwPlatformId);
1306       return VK_PROCESSKEY;
1307   }
1308 }
1309
1310 /***********************************************************************
1311  *              ImmInstallIMEA (IMM32.@)
1312  */
1313 HKL WINAPI ImmInstallIMEA(
1314   LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1315 {
1316   FIXME("(%s, %s): stub\n",
1317     debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1318   );
1319   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1320   return NULL;
1321 }
1322
1323 /***********************************************************************
1324  *              ImmInstallIMEW (IMM32.@)
1325  */
1326 HKL WINAPI ImmInstallIMEW(
1327   LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1328 {
1329   FIXME("(%s, %s): stub\n",
1330     debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1331   );
1332   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1333   return NULL;
1334 }
1335
1336 /***********************************************************************
1337  *              ImmIsIME (IMM32.@)
1338  */
1339 BOOL WINAPI ImmIsIME(HKL hKL)
1340 {
1341   TRACE("(%p): semi-stub\n", hKL);
1342   /*
1343    * FIXME: Dead key locales will return TRUE here when they should not
1344    * There is probably a more proper way to check this.
1345    */
1346   return (root_context != NULL);
1347 }
1348
1349 /***********************************************************************
1350  *              ImmIsUIMessageA (IMM32.@)
1351  */
1352 BOOL WINAPI ImmIsUIMessageA(
1353   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1354 {
1355     BOOL rc = FALSE;
1356
1357     TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1358     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1359         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1360         (msg == WM_MSIME_SERVICE) ||
1361         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1362         (msg == WM_MSIME_MOUSE) ||
1363         (msg == WM_MSIME_RECONVERTREQUEST) ||
1364         (msg == WM_MSIME_RECONVERT) ||
1365         (msg == WM_MSIME_QUERYPOSITION) ||
1366         (msg == WM_MSIME_DOCUMENTFEED))
1367
1368     {
1369         if (!hwndDefault)
1370             ImmGetDefaultIMEWnd(NULL);
1371
1372         if (hWndIME == NULL)
1373             PostMessageA(hwndDefault, msg, wParam, lParam);
1374
1375         rc = TRUE;
1376     }
1377     return rc;
1378 }
1379
1380 /***********************************************************************
1381  *              ImmIsUIMessageW (IMM32.@)
1382  */
1383 BOOL WINAPI ImmIsUIMessageW(
1384   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1385 {
1386     BOOL rc = FALSE;
1387     TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
1388     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1389         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1390         (msg == WM_MSIME_SERVICE) ||
1391         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1392         (msg == WM_MSIME_MOUSE) ||
1393         (msg == WM_MSIME_RECONVERTREQUEST) ||
1394         (msg == WM_MSIME_RECONVERT) ||
1395         (msg == WM_MSIME_QUERYPOSITION) ||
1396         (msg == WM_MSIME_DOCUMENTFEED))
1397         rc = TRUE;
1398     return rc;
1399 }
1400
1401 /***********************************************************************
1402  *              ImmNotifyIME (IMM32.@)
1403  */
1404 BOOL WINAPI ImmNotifyIME(
1405   HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1406 {
1407     BOOL rc = FALSE;
1408
1409     TRACE("(%p, %d, %d, %d)\n",
1410         hIMC, dwAction, dwIndex, dwValue);
1411
1412     if (!root_context)
1413         return rc;
1414
1415     switch(dwAction)
1416     {
1417         case NI_CHANGECANDIDATELIST:
1418             FIXME("%s\n","NI_CHANGECANDIDATELIST");
1419             break;
1420         case NI_CLOSECANDIDATE:
1421             FIXME("%s\n","NI_CLOSECANDIDATE");
1422             break;
1423         case NI_COMPOSITIONSTR:
1424             switch (dwIndex)
1425             {
1426                 case CPS_CANCEL:
1427                     TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1428                     {
1429                         BOOL send;
1430                         LPCOMPOSITIONSTRING lpCompStr;
1431
1432                         if (pX11DRV_ForceXIMReset)
1433                             pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1434
1435                         lpCompStr = ImmLockIMCC(root_context->IMC.hCompStr);
1436                         send = (lpCompStr->dwCompStrLen != 0);
1437                         ImmUnlockIMCC(root_context->IMC.hCompStr);
1438
1439                         ImmDestroyIMCC(root_context->IMC.hCompStr);
1440                         root_context->IMC.hCompStr = ImmCreateBlankCompStr();
1441
1442                         if (send)
1443                             ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1444                                                   GCS_COMPSTR);
1445                         rc = TRUE;
1446                     }
1447                     break;
1448                 case CPS_COMPLETE:
1449                     TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1450                     if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1451                         pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1452                     {
1453                         HIMCC newCompStr;
1454                         DWORD cplen = 0;
1455                         LPWSTR cpstr;
1456                         LPCOMPOSITIONSTRING cs = NULL;
1457                         LPBYTE cdata = NULL;
1458
1459                         /* clear existing result */
1460                         newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
1461                         ImmDestroyIMCC(root_context->IMC.hCompStr);
1462                         root_context->IMC.hCompStr = newCompStr;
1463
1464                         if (root_context->IMC.hCompStr)
1465                         {
1466                             cdata = ImmLockIMCC(root_context->IMC.hCompStr);
1467                             cs = (LPCOMPOSITIONSTRING)cdata;
1468                             cplen = cs->dwCompStrLen;
1469                             cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
1470                             ImmUnlockIMCC(root_context->IMC.hCompStr);
1471                         }
1472                         if (cplen > 0)
1473                         {
1474                             WCHAR param = cpstr[0];
1475                             newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
1476                             ImmDestroyIMCC(root_context->IMC.hCompStr);
1477                             root_context->IMC.hCompStr = newCompStr;
1478                             newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1479                             ImmDestroyIMCC(root_context->IMC.hCompStr);
1480                             root_context->IMC.hCompStr = newCompStr;
1481
1482                             root_context->bRead = FALSE;
1483
1484                             ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1485                                                   GCS_COMPSTR);
1486
1487                             ImmInternalPostIMEMessage(WM_IME_COMPOSITION,
1488                                             param,
1489                                             GCS_RESULTSTR|GCS_RESULTCLAUSE);
1490                         }
1491
1492                         ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION, 0, 0);
1493                         root_context->bInComposition = FALSE;
1494                     }
1495                     break;
1496                 case CPS_CONVERT:
1497                     FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1498                     break;
1499                 case CPS_REVERT:
1500                     FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1501                     break;
1502                 default:
1503                     ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1504                     break;
1505             }
1506             break;
1507         case NI_IMEMENUSELECTED:
1508             FIXME("%s\n", "NI_IMEMENUSELECTED");
1509             break;
1510         case NI_OPENCANDIDATE:
1511             FIXME("%s\n", "NI_OPENCANDIDATE");
1512             break;
1513         case NI_SELECTCANDIDATESTR:
1514             FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1515             break;
1516         case NI_SETCANDIDATE_PAGESIZE:
1517             FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1518             break;
1519         case NI_SETCANDIDATE_PAGESTART:
1520             FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1521             break;
1522         default:
1523             ERR("Unknown\n");
1524     }
1525
1526     return rc;
1527 }
1528
1529 /***********************************************************************
1530  *              ImmRegisterWordA (IMM32.@)
1531  */
1532 BOOL WINAPI ImmRegisterWordA(
1533   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1534 {
1535   FIXME("(%p, %s, %d, %s): stub\n",
1536     hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1537   );
1538   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1539   return FALSE;
1540 }
1541
1542 /***********************************************************************
1543  *              ImmRegisterWordW (IMM32.@)
1544  */
1545 BOOL WINAPI ImmRegisterWordW(
1546   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1547 {
1548   FIXME("(%p, %s, %d, %s): stub\n",
1549     hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1550   );
1551   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1552   return FALSE;
1553 }
1554
1555 /***********************************************************************
1556  *              ImmReleaseContext (IMM32.@)
1557  */
1558 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1559 {
1560   static int shown = 0;
1561
1562   if (!shown) {
1563      FIXME("(%p, %p): stub\n", hWnd, hIMC);
1564      shown = 1;
1565   }
1566   return TRUE;
1567 }
1568
1569 /***********************************************************************
1570  *              ImmSetCandidateWindow (IMM32.@)
1571  */
1572 BOOL WINAPI ImmSetCandidateWindow(
1573   HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1574 {
1575   FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1576   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1577   return FALSE;
1578 }
1579
1580 /***********************************************************************
1581  *              ImmSetCompositionFontA (IMM32.@)
1582  */
1583 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1584 {
1585     InputContextData *data = (InputContextData*)hIMC;
1586     TRACE("(%p, %p)\n", hIMC, lplf);
1587
1588     if (!data)
1589         return FALSE;
1590
1591     memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1592     MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1593                         LF_FACESIZE);
1594
1595     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1596
1597     if (data->textfont)
1598     {
1599         DeleteObject(data->textfont);
1600         data->textfont = NULL;
1601     }
1602
1603     data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1604     return TRUE;
1605 }
1606
1607 /***********************************************************************
1608  *              ImmSetCompositionFontW (IMM32.@)
1609  */
1610 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1611 {
1612     InputContextData *data = (InputContextData*)hIMC;
1613     TRACE("(%p, %p)\n", hIMC, lplf);
1614
1615     if (!data)
1616         return FALSE;
1617
1618     data->IMC.lfFont.W = *lplf;
1619     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1620
1621     if (data->textfont)
1622     {
1623         DeleteObject(data->textfont);
1624         data->textfont = NULL;
1625     }
1626     data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1627     return TRUE;
1628 }
1629
1630 /***********************************************************************
1631  *              ImmSetCompositionStringA (IMM32.@)
1632  */
1633 BOOL WINAPI ImmSetCompositionStringA(
1634   HIMC hIMC, DWORD dwIndex,
1635   LPCVOID lpComp, DWORD dwCompLen,
1636   LPCVOID lpRead, DWORD dwReadLen)
1637 {
1638     DWORD comp_len;
1639     DWORD read_len;
1640     WCHAR *CompBuffer = NULL;
1641     WCHAR *ReadBuffer = NULL;
1642     BOOL rc;
1643
1644     TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1645             hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1646
1647     comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
1648     if (comp_len)
1649     {
1650         CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
1651         MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
1652     }
1653
1654     read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
1655     if (read_len)
1656     {
1657         ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
1658         MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
1659     }
1660
1661     rc =  ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
1662                                    ReadBuffer, read_len);
1663
1664     HeapFree(GetProcessHeap(), 0, CompBuffer);
1665     HeapFree(GetProcessHeap(), 0, ReadBuffer);
1666
1667     return rc;
1668 }
1669
1670 /***********************************************************************
1671  *              ImmSetCompositionStringW (IMM32.@)
1672  */
1673 BOOL WINAPI ImmSetCompositionStringW(
1674         HIMC hIMC, DWORD dwIndex,
1675         LPCVOID lpComp, DWORD dwCompLen,
1676         LPCVOID lpRead, DWORD dwReadLen)
1677 {
1678      DWORD flags = 0;
1679      WCHAR wParam  = 0;
1680
1681      TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1682              hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1683
1684
1685      if (hIMC != (HIMC)FROM_IME)
1686          FIXME("PROBLEM: This only sets the wine level string\n");
1687
1688      /*
1689       * Explanation:
1690       *  this sets the composition string in the imm32.dll level
1691       *  of the composition buffer. we cannot manipulate the xim level
1692       *  buffer, which means that once the xim level buffer changes again
1693       *  any call to this function from the application will be lost
1694       */
1695
1696      if (lpRead && dwReadLen)
1697          FIXME("Reading string unimplemented\n");
1698
1699      /*
1700       * app operating this api to also receive the message from xim
1701       */
1702
1703     if (dwIndex == SCS_SETSTR)
1704     {
1705         HIMCC newCompStr;
1706         if (!root_context->bInComposition)
1707         {
1708             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION, 0, 0);
1709             root_context->bInComposition = TRUE;
1710         }
1711
1712         flags = GCS_COMPSTR;
1713
1714         if (dwCompLen && lpComp)
1715         {
1716             newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
1717             ImmDestroyIMCC(root_context->IMC.hCompStr);
1718             root_context->IMC.hCompStr = newCompStr;
1719
1720              wParam = ((const WCHAR*)lpComp)[0];
1721              flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
1722         }
1723         else
1724         {
1725             newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1726             ImmDestroyIMCC(root_context->IMC.hCompStr);
1727             root_context->IMC.hCompStr = newCompStr;
1728         }
1729     }
1730
1731      UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
1732
1733      ImmInternalPostIMEMessage(WM_IME_COMPOSITION, wParam, flags);
1734
1735      return TRUE;
1736 }
1737
1738 /***********************************************************************
1739  *              ImmSetCompositionWindow (IMM32.@)
1740  */
1741 BOOL WINAPI ImmSetCompositionWindow(
1742   HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1743 {
1744     BOOL reshow = FALSE;
1745     InputContextData *data = (InputContextData*)hIMC;
1746
1747     TRACE("(%p, %p)\n", hIMC, lpCompForm);
1748     TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
1749           lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
1750           lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
1751
1752     if (!data)
1753         return FALSE;
1754
1755     data->IMC.cfCompForm = *lpCompForm;
1756
1757     if (IsWindowVisible(hwndDefault))
1758     {
1759         reshow = TRUE;
1760         ShowWindow(hwndDefault,SW_HIDE);
1761     }
1762
1763     /* FIXME: this is a partial stub */
1764
1765     if (reshow)
1766         ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1767
1768     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONWINDOW, 0);
1769     return TRUE;
1770 }
1771
1772 /***********************************************************************
1773  *              ImmSetConversionStatus (IMM32.@)
1774  */
1775 BOOL WINAPI ImmSetConversionStatus(
1776   HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1777 {
1778   static int shown = 0;
1779
1780   if (!shown) {
1781       FIXME("(%p, %d, %d): stub\n",
1782           hIMC, fdwConversion, fdwSentence
1783       );
1784       shown = 1;
1785   }
1786   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1787   return FALSE;
1788 }
1789
1790 /***********************************************************************
1791  *              ImmSetOpenStatus (IMM32.@)
1792  */
1793 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
1794 {
1795     InputContextData *data = (InputContextData*)hIMC;
1796
1797     TRACE("%p %d\n", hIMC, fOpen);
1798
1799     if (hIMC == (HIMC)FROM_IME)
1800     {
1801         ImmInternalSetOpenStatus(fOpen);
1802         ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0);
1803         return TRUE;
1804     }
1805
1806     if (!data)
1807         return FALSE;
1808
1809     if (fOpen != data->bInternalState)
1810     {
1811         if (fOpen == FALSE && pX11DRV_ForceXIMReset)
1812             pX11DRV_ForceXIMReset(data->IMC.hWnd);
1813
1814         if (fOpen == FALSE)
1815             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1816         else
1817             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1818
1819         ImmInternalSetOpenStatus(fOpen);
1820         ImmInternalSetOpenStatus(!fOpen);
1821
1822         if (data->IMC.fOpen == FALSE)
1823             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1824         else
1825             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1826
1827         return FALSE;
1828     }
1829     return TRUE;
1830 }
1831
1832 /***********************************************************************
1833  *              ImmSetStatusWindowPos (IMM32.@)
1834  */
1835 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1836 {
1837   FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1838   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1839   return FALSE;
1840 }
1841
1842 /***********************************************************************
1843  *              ImmSimulateHotKey (IMM32.@)
1844  */
1845 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
1846 {
1847   FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
1848   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1849   return FALSE;
1850 }
1851
1852 /***********************************************************************
1853  *              ImmUnregisterWordA (IMM32.@)
1854  */
1855 BOOL WINAPI ImmUnregisterWordA(
1856   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
1857 {
1858   FIXME("(%p, %s, %d, %s): stub\n",
1859     hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
1860   );
1861   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1862   return FALSE;
1863 }
1864
1865 /***********************************************************************
1866  *              ImmUnregisterWordW (IMM32.@)
1867  */
1868 BOOL WINAPI ImmUnregisterWordW(
1869   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
1870 {
1871   FIXME("(%p, %s, %d, %s): stub\n",
1872     hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
1873   );
1874   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1875   return FALSE;
1876 }
1877
1878 /***********************************************************************
1879  *              ImmGetImeMenuItemsA (IMM32.@)
1880  */
1881 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1882    LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
1883     DWORD dwSize)
1884 {
1885   FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1886     lpImeParentMenu, lpImeMenu, dwSize);
1887   return 0;
1888 }
1889
1890 /***********************************************************************
1891 *               ImmGetImeMenuItemsW (IMM32.@)
1892 */
1893 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1894    LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
1895    DWORD dwSize)
1896 {
1897   FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1898     lpImeParentMenu, lpImeMenu, dwSize);
1899   return 0;
1900 }
1901
1902 /***********************************************************************
1903 *               ImmLockIMC(IMM32.@)
1904 */
1905 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
1906 {
1907     InputContextData *data = (InputContextData*)hIMC;
1908
1909     if (!data)
1910         return NULL;
1911     data->dwLock++;
1912     return &data->IMC;
1913 }
1914
1915 /***********************************************************************
1916 *               ImmUnlockIMC(IMM32.@)
1917 */
1918 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
1919 {
1920     InputContextData *data = (InputContextData*)hIMC;
1921     data->dwLock--;
1922     return (data->dwLock!=0);
1923 }
1924
1925 /***********************************************************************
1926 *               ImmGetIMCLockCount(IMM32.@)
1927 */
1928 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
1929 {
1930     InputContextData *data = (InputContextData*)hIMC;
1931     return data->dwLock;
1932 }
1933
1934 /***********************************************************************
1935 *               ImmCreateIMCC(IMM32.@)
1936 */
1937 HIMCC  WINAPI ImmCreateIMCC(DWORD size)
1938 {
1939     IMCCInternal *internal;
1940     int real_size = size + sizeof(IMCCInternal);
1941
1942     internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
1943     if (internal == NULL)
1944         return NULL;
1945
1946     internal->dwSize = size;
1947     return  (HIMCC)internal;
1948 }
1949
1950 /***********************************************************************
1951 *       ImmDestroyIMCC(IMM32.@)
1952 */
1953 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
1954 {
1955     HeapFree(GetProcessHeap(),0,block);
1956     return NULL;
1957 }
1958
1959 /***********************************************************************
1960 *               ImmLockIMCC(IMM32.@)
1961 */
1962 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
1963 {
1964     IMCCInternal *internal;
1965     internal = (IMCCInternal*) imcc;
1966
1967     internal->dwLock ++;
1968     return internal + 1;
1969 }
1970
1971 /***********************************************************************
1972 *               ImmUnlockIMCC(IMM32.@)
1973 */
1974 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
1975 {
1976     IMCCInternal *internal;
1977     internal = (IMCCInternal*) imcc;
1978
1979     internal->dwLock --;
1980     return (internal->dwLock!=0);
1981 }
1982
1983 /***********************************************************************
1984 *               ImmGetIMCCLockCount(IMM32.@)
1985 */
1986 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
1987 {
1988     IMCCInternal *internal;
1989     internal = (IMCCInternal*) imcc;
1990
1991     return internal->dwLock;
1992 }
1993
1994 /***********************************************************************
1995 *               ImmReSizeIMCC(IMM32.@)
1996 */
1997 HIMCC  WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
1998 {
1999     IMCCInternal *internal,*newone;
2000     int real_size = size + sizeof(IMCCInternal);
2001
2002     internal = (IMCCInternal*) imcc;
2003
2004     newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2005     newone->dwSize = size;
2006
2007     return newone;
2008 }
2009
2010 /***********************************************************************
2011 *               ImmGetIMCCSize(IMM32.@)
2012 */
2013 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2014 {
2015     IMCCInternal *internal;
2016     internal = (IMCCInternal*) imcc;
2017
2018     return internal->dwSize;
2019 }
2020
2021 /***********************************************************************
2022 *               ImmGenerateMessage(IMM32.@)
2023 */
2024 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2025 {
2026     InputContextData *data = (InputContextData*)hIMC;
2027
2028     TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2029     if (data->IMC.dwNumMsgBuf > 0)
2030     {
2031         LPTRANSMSG lpTransMsg;
2032         INT i;
2033
2034         lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
2035         for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2036             ImmInternalPostIMEMessage(lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2037
2038         ImmUnlockIMCC(data->IMC.hMsgBuf);
2039
2040         data->IMC.dwNumMsgBuf = 0;
2041     }
2042
2043     return TRUE;
2044 }
2045
2046 /*****
2047  * Internal functions to help with IME window management
2048  */
2049 static void PaintDefaultIMEWnd(HWND hwnd)
2050 {
2051     PAINTSTRUCT ps;
2052     RECT rect;
2053     HDC hdc = BeginPaint(hwnd,&ps);
2054     LPCOMPOSITIONSTRING compstr;
2055     LPBYTE compdata = NULL;
2056     HMONITOR monitor;
2057     MONITORINFO mon_info;
2058     INT offX=0, offY=0;
2059
2060     GetClientRect(hwnd,&rect);
2061     FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
2062
2063     compdata = ImmLockIMCC(root_context->IMC.hCompStr);
2064     compstr = (LPCOMPOSITIONSTRING)compdata;
2065
2066     if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
2067     {
2068         SIZE size;
2069         POINT pt;
2070         HFONT oldfont = NULL;
2071         LPWSTR CompString;
2072
2073         CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
2074         if (root_context->textfont)
2075             oldfont = SelectObject(hdc,root_context->textfont);
2076
2077
2078         GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
2079         pt.x = size.cx;
2080         pt.y = size.cy;
2081         LPtoDP(hdc,&pt,1);
2082
2083         /*
2084          * How this works based on tests on windows:
2085          * CFS_POINT: then we start our window at the point and grow it as large
2086          *    as it needs to be for the string.
2087          * CFS_RECT:  we still use the ptCurrentPos as a starting point and our
2088          *    window is only as large as we need for the string, but we do not
2089          *    grow such that our window exceeds the given rect.  Wrapping if
2090          *    needed and possible.   If our ptCurrentPos is outside of our rect
2091          *    then no window is displayed.
2092          * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
2093          *    maybe becase the default MSIME does not do any IME adjusting.
2094          */
2095         if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
2096         {
2097             POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
2098             ClientToScreen(root_context->IMC.hWnd,&cpt);
2099             rect.left = cpt.x;
2100             rect.top = cpt.y;
2101             rect.right = rect.left + pt.x;
2102             rect.bottom = rect.top + pt.y;
2103             monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
2104         }
2105         else /* CFS_DEFAULT */
2106         {
2107             /* Windows places the default IME window in the bottom left */
2108             HWND target = root_context->IMC.hWnd;
2109             if (!target) target = GetFocus();
2110
2111             GetWindowRect(target,&rect);
2112             rect.top = rect.bottom;
2113             rect.right = rect.left + pt.x + 20;
2114             rect.bottom = rect.top + pt.y + 20;
2115             offX=offY=10;
2116             monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
2117         }
2118
2119         if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
2120         {
2121             RECT client;
2122             client =root_context->IMC.cfCompForm.rcArea;
2123             MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
2124             IntersectRect(&rect,&rect,&client);
2125             /* TODO:  Wrap the input if needed */
2126         }
2127
2128         if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
2129         {
2130             /* make sure we are on the desktop */
2131             mon_info.cbSize = sizeof(mon_info);
2132             GetMonitorInfoW(monitor, &mon_info);
2133
2134             if (rect.bottom > mon_info.rcWork.bottom)
2135             {
2136                 int shift = rect.bottom - mon_info.rcWork.bottom;
2137                 rect.top -= shift;
2138                 rect.bottom -= shift;
2139             }
2140             if (rect.left < 0)
2141             {
2142                 rect.right -= rect.left;
2143                 rect.left = 0;
2144             }
2145             if (rect.right > mon_info.rcWork.right)
2146             {
2147                 int shift = rect.right - mon_info.rcWork.right;
2148                 rect.left -= shift;
2149                 rect.right -= shift;
2150             }
2151         }
2152
2153         SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
2154
2155         TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
2156
2157         if (oldfont)
2158             SelectObject(hdc,oldfont);
2159     }
2160
2161     ImmUnlockIMCC(root_context->IMC.hCompStr);
2162
2163     EndPaint(hwnd,&ps);
2164 }
2165
2166 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
2167 {
2168     LPCOMPOSITIONSTRING compstr;
2169
2170     if (root_context->IMC.hCompStr)
2171         compstr = ImmLockIMCC(root_context->IMC.hCompStr);
2172     else
2173         compstr = NULL;
2174
2175     if (compstr == NULL || compstr->dwCompStrLen == 0)
2176         ShowWindow(hwndDefault,SW_HIDE);
2177     else if (showable)
2178         ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2179
2180     RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
2181
2182     if (compstr != NULL)
2183         ImmUnlockIMCC(root_context->IMC.hCompStr);
2184 }
2185
2186 /*
2187  * The window proc for the default IME window
2188  */
2189 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
2190                                           LPARAM lParam)
2191 {
2192     LRESULT rc = 0;
2193
2194     TRACE("Incoming Message 0x%x  (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
2195            (UINT)lParam);
2196
2197     switch(msg)
2198     {
2199         case WM_PAINT:
2200             PaintDefaultIMEWnd(hwnd);
2201             return FALSE;
2202
2203         case WM_NCCREATE:
2204             return TRUE;
2205
2206         case WM_CREATE:
2207             SetWindowTextA(hwnd,"Wine Ime Active");
2208             return TRUE;
2209
2210         case WM_SETFOCUS:
2211             if (wParam)
2212                 SetFocus((HWND)wParam);
2213             else
2214                 FIXME("Received focus, should never have focus\n");
2215             break;
2216         case WM_IME_COMPOSITION:
2217             TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
2218                     "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
2219                      root_context->bRead);
2220             if (lParam & GCS_RESULTSTR)
2221                     IMM_PostResult(root_context);
2222             else
2223                  UpdateDataInDefaultIMEWindow(hwnd,TRUE);
2224             break;
2225         case WM_IME_STARTCOMPOSITION:
2226             TRACE("IME message %s, 0x%x, 0x%x\n",
2227                     "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
2228             root_context->IMC.hWnd = GetFocus();
2229             ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2230             break;
2231         case WM_IME_ENDCOMPOSITION:
2232             TRACE("IME message %s, 0x%x, 0x%x\n",
2233                     "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
2234             ShowWindow(hwndDefault,SW_HIDE);
2235             break;
2236         case WM_IME_SELECT:
2237             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
2238                 (UINT)wParam, (UINT)lParam);
2239             break;
2240         case WM_IME_CONTROL:
2241             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
2242                 (UINT)wParam, (UINT)lParam);
2243             rc = 1;
2244             break;
2245         case WM_IME_NOTIFY:
2246             TRACE("!! IME NOTIFY\n");
2247             break;
2248        default:
2249             TRACE("Non-standard message 0x%x\n",msg);
2250     }
2251     /* check the MSIME messages */
2252     if (msg == WM_MSIME_SERVICE)
2253     {
2254             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
2255                 (UINT)wParam, (UINT)lParam);
2256             rc = FALSE;
2257     }
2258     else if (msg == WM_MSIME_RECONVERTOPTIONS)
2259     {
2260             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
2261                 (UINT)wParam, (UINT)lParam);
2262     }
2263     else if (msg == WM_MSIME_MOUSE)
2264     {
2265             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
2266                 (UINT)wParam, (UINT)lParam);
2267     }
2268     else if (msg == WM_MSIME_RECONVERTREQUEST)
2269     {
2270             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
2271                 (UINT)wParam, (UINT)lParam);
2272     }
2273     else if (msg == WM_MSIME_RECONVERT)
2274     {
2275             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
2276                 (UINT)wParam, (UINT)lParam);
2277     }
2278     else if (msg == WM_MSIME_QUERYPOSITION)
2279     {
2280             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
2281                 (UINT)wParam, (UINT)lParam);
2282     }
2283     else if (msg == WM_MSIME_DOCUMENTFEED)
2284     {
2285             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
2286                 (UINT)wParam, (UINT)lParam);
2287     }
2288     /* DefWndProc if not an IME message */
2289     else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2290                       (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
2291         rc = DefWindowProcW(hwnd,msg,wParam,lParam);
2292
2293     return rc;
2294 }