imm32: Destroy the data of the context passed into ImmDestroyContext, not the data...
[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
615     return (HIMC)new_context;
616 }
617
618 /***********************************************************************
619  *              ImmDestroyContext (IMM32.@)
620  */
621 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
622 {
623     InputContextData *data = (InputContextData*)hIMC;
624
625     TRACE("Destroying %p\n",hIMC);
626
627     if (hIMC)
628     {
629         ImmDestroyIMCC(data->IMC.hCompStr);
630         ImmDestroyIMCC(data->IMC.hCandInfo);
631         ImmDestroyIMCC(data->IMC.hGuideLine);
632         ImmDestroyIMCC(data->IMC.hPrivate);
633         ImmDestroyIMCC(data->IMC.hMsgBuf);
634
635         if (data->textfont)
636         {
637             DeleteObject(data->textfont);
638             data->textfont = NULL;
639         }
640
641         HeapFree(GetProcessHeap(),0,data);
642     }
643     return TRUE;
644 }
645
646 /***********************************************************************
647  *              ImmDisableIME (IMM32.@)
648  */
649 BOOL WINAPI ImmDisableIME(DWORD idThread)
650 {
651     FIXME("(%d): stub\n", idThread);
652     return TRUE;
653 }
654
655 /***********************************************************************
656  *              ImmEnumRegisterWordA (IMM32.@)
657  */
658 UINT WINAPI ImmEnumRegisterWordA(
659   HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
660   LPCSTR lpszReading, DWORD dwStyle,
661   LPCSTR lpszRegister, LPVOID lpData)
662 {
663   FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
664     hKL, lpfnEnumProc,
665     debugstr_a(lpszReading), dwStyle,
666     debugstr_a(lpszRegister), lpData
667   );
668   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
669   return 0;
670 }
671
672 /***********************************************************************
673  *              ImmEnumRegisterWordW (IMM32.@)
674  */
675 UINT WINAPI ImmEnumRegisterWordW(
676   HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
677   LPCWSTR lpszReading, DWORD dwStyle,
678   LPCWSTR lpszRegister, LPVOID lpData)
679 {
680   FIXME("(%p, %p, %s, %d, %s, %p): stub\n",
681     hKL, lpfnEnumProc,
682     debugstr_w(lpszReading), dwStyle,
683     debugstr_w(lpszRegister), lpData
684   );
685   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
686   return 0;
687 }
688
689 /***********************************************************************
690  *              ImmEscapeA (IMM32.@)
691  */
692 LRESULT WINAPI ImmEscapeA(
693   HKL hKL, HIMC hIMC,
694   UINT uEscape, LPVOID lpData)
695 {
696   FIXME("(%p, %p, %d, %p): stub\n",
697     hKL, hIMC, uEscape, lpData
698   );
699   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
700   return 0;
701 }
702
703 /***********************************************************************
704  *              ImmEscapeW (IMM32.@)
705  */
706 LRESULT WINAPI ImmEscapeW(
707   HKL hKL, HIMC hIMC,
708   UINT uEscape, LPVOID lpData)
709 {
710   FIXME("(%p, %p, %d, %p): stub\n",
711     hKL, hIMC, uEscape, lpData
712   );
713   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
714   return 0;
715 }
716
717 /***********************************************************************
718  *              ImmGetCandidateListA (IMM32.@)
719  */
720 DWORD WINAPI ImmGetCandidateListA(
721   HIMC hIMC, DWORD deIndex,
722   LPCANDIDATELIST lpCandList, DWORD dwBufLen)
723 {
724   FIXME("(%p, %d, %p, %d): stub\n",
725     hIMC, deIndex,
726     lpCandList, dwBufLen
727   );
728   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
729   return 0;
730 }
731
732 /***********************************************************************
733  *              ImmGetCandidateListCountA (IMM32.@)
734  */
735 DWORD WINAPI ImmGetCandidateListCountA(
736   HIMC hIMC, LPDWORD lpdwListCount)
737 {
738   FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
739   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
740   return 0;
741 }
742
743 /***********************************************************************
744  *              ImmGetCandidateListCountW (IMM32.@)
745  */
746 DWORD WINAPI ImmGetCandidateListCountW(
747   HIMC hIMC, LPDWORD lpdwListCount)
748 {
749   FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
750   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
751   return 0;
752 }
753
754 /***********************************************************************
755  *              ImmGetCandidateListW (IMM32.@)
756  */
757 DWORD WINAPI ImmGetCandidateListW(
758   HIMC hIMC, DWORD deIndex,
759   LPCANDIDATELIST lpCandList, DWORD dwBufLen)
760 {
761   FIXME("(%p, %d, %p, %d): stub\n",
762     hIMC, deIndex,
763     lpCandList, dwBufLen
764   );
765   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
766   return 0;
767 }
768
769 /***********************************************************************
770  *              ImmGetCandidateWindow (IMM32.@)
771  */
772 BOOL WINAPI ImmGetCandidateWindow(
773   HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
774 {
775   FIXME("(%p, %d, %p): stub\n", hIMC, dwBufLen, lpCandidate);
776   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
777   return FALSE;
778 }
779
780 /***********************************************************************
781  *              ImmGetCompositionFontA (IMM32.@)
782  */
783 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
784 {
785   FIXME("(%p, %p): stub\n", hIMC, lplf);
786   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
787   return FALSE;
788 }
789
790 /***********************************************************************
791  *              ImmGetCompositionFontW (IMM32.@)
792  */
793 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
794 {
795   FIXME("(%p, %p): stub\n", hIMC, lplf);
796   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
797   return FALSE;
798 }
799
800 /***********************************************************************
801  *              ImmGetCompositionStringA (IMM32.@)
802  */
803 LONG WINAPI ImmGetCompositionStringA(
804   HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
805 {
806     CHAR *buf;
807     LONG rc = 0;
808     InputContextData *data = (InputContextData*)hIMC;
809     LPCOMPOSITIONSTRING compstr;
810     LPBYTE compdata;
811
812     TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
813
814     if (!data)
815        return FALSE;
816
817     if (!data->IMC.hCompStr)
818        return FALSE;
819
820     compdata = ImmLockIMCC(data->IMC.hCompStr);
821     compstr = (LPCOMPOSITIONSTRING)compdata;
822
823     if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
824         compstr->dwResultStrOffset > 0)
825     {
826         LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
827
828         TRACE("GSC_RESULTSTR %p %i\n",ResultStr,
829                                     compstr->dwResultStrLen);
830
831         buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwResultStrLen * 3 );
832         rc = WideCharToMultiByte(CP_ACP, 0, ResultStr,
833                                  compstr->dwResultStrLen , buf,
834                                  compstr->dwResultStrLen * 3, NULL, NULL);
835         if (dwBufLen >= rc)
836             memcpy(lpBuf,buf,rc);
837
838         data->bRead = TRUE;
839         HeapFree( GetProcessHeap(), 0, buf );
840     }
841     else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
842               compstr->dwCompStrOffset > 0)
843     {
844         LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
845
846         TRACE("GSC_COMPSTR %p %i\n", CompString, compstr->dwCompStrLen);
847
848         buf = HeapAlloc( GetProcessHeap(), 0, compstr->dwCompStrLen * 3 );
849         rc = WideCharToMultiByte(CP_ACP, 0, CompString,
850                                  compstr->dwCompStrLen, buf,
851                                  compstr->dwCompStrLen * 3, NULL, NULL);
852         if (dwBufLen >= rc)
853             memcpy(lpBuf,buf,rc);
854         HeapFree( GetProcessHeap(), 0, buf );
855     }
856     else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
857              compstr->dwCompAttrOffset > 0)
858     {
859         LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
860         TRACE("GSC_COMPATTR %p %i\n", Compattr , compstr->dwCompAttrLen);
861
862         rc = compstr->dwCompAttrLen;
863         if (dwBufLen >= rc)
864             memcpy(lpBuf,Compattr,rc);
865     }
866     else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
867              compstr->dwCompClauseOffset > 0)
868     {
869         LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
870         TRACE("GSC_COMPCLAUSE %p %i\n", Compclause, compstr->dwCompClauseLen);
871
872         rc = compstr->dwCompClauseLen;
873         if (dwBufLen >= compstr->dwCompClauseLen)
874             memcpy(lpBuf,Compclause,rc);
875     }
876     else if (dwIndex == GCS_RESULTCLAUSE && compstr->dwResultClauseLen > 0 &&
877              compstr->dwResultClauseOffset > 0)
878     {
879         LPWSTR Resultclause = (LPWSTR)(compdata + compstr->dwResultClauseOffset);
880         TRACE("GSC_RESULTCLAUSE %p %i\n", Resultclause, compstr->dwResultClauseLen);
881
882         rc = compstr->dwResultClauseLen;
883         if (dwBufLen >= compstr->dwResultClauseLen)
884             memcpy(lpBuf,Resultclause,rc);
885     }
886     else if (dwIndex == GCS_CURSORPOS)
887     {
888         TRACE("GSC_CURSORPOS\n");
889         rc = compstr->dwCursorPos;
890     }
891     else if (dwIndex == GCS_DELTASTART)
892     {
893         TRACE("GCS_DELTASTART\n");
894         rc = compstr->dwDeltaStart;
895     }
896     else
897     {
898         FIXME("Unhandled index 0x%x\n",dwIndex);
899     }
900
901     ImmUnlockIMCC(data->IMC.hCompStr);
902
903     return rc;
904 }
905
906 /***********************************************************************
907  *              ImmGetCompositionStringW (IMM32.@)
908  */
909 LONG WINAPI ImmGetCompositionStringW(
910   HIMC hIMC, DWORD dwIndex,
911   LPVOID lpBuf, DWORD dwBufLen)
912 {
913     LONG rc = 0;
914     InputContextData *data = (InputContextData*)hIMC;
915     LPCOMPOSITIONSTRING compstr;
916     LPBYTE compdata;
917
918     TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
919
920     if (!data)
921        return FALSE;
922
923     if (!data->IMC.hCompStr)
924        return FALSE;
925
926     compdata = ImmLockIMCC(data->IMC.hCompStr);
927     compstr = (LPCOMPOSITIONSTRING)compdata;
928
929     if (dwIndex == GCS_RESULTSTR && compstr->dwResultStrLen > 0 &&
930         compstr->dwResultStrOffset > 0)
931     {
932         LPWSTR ResultStr = (LPWSTR)(compdata + compstr->dwResultStrOffset);
933         data->bRead = TRUE;
934         rc =  compstr->dwResultStrLen * sizeof(WCHAR);
935
936         if (dwBufLen >= rc)
937             memcpy(lpBuf,ResultStr,rc);
938     }
939     else if (dwIndex == GCS_RESULTREADSTR && compstr->dwResultReadStrLen > 0 &&
940              compstr->dwResultReadStrOffset > 0)
941     {
942         LPWSTR ResultReadString = (LPWSTR)(compdata + compstr->dwResultReadStrOffset);
943
944         rc = compstr->dwResultReadStrLen * sizeof(WCHAR);
945         if (dwBufLen >= rc)
946             memcpy(lpBuf,ResultReadString,rc);
947     }
948     else if (dwIndex == GCS_COMPSTR && compstr->dwCompStrLen > 0 &&
949               compstr->dwCompStrOffset > 0)
950     {
951         LPWSTR CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
952         rc = compstr->dwCompStrLen * sizeof(WCHAR);
953         if (dwBufLen >= rc)
954             memcpy(lpBuf,CompString,rc);
955     }
956     else if (dwIndex == GCS_COMPATTR && compstr->dwCompAttrLen > 0 &&
957              compstr->dwCompAttrOffset > 0)
958     {
959
960         LPWSTR Compattr = (LPWSTR)(compdata + compstr->dwCompAttrOffset);
961
962         rc = compstr->dwCompAttrLen;
963         if (dwBufLen >= rc)
964             memcpy(lpBuf,Compattr,rc);
965     }
966     else if (dwIndex == GCS_COMPCLAUSE && compstr->dwCompClauseLen > 0 &&
967              compstr->dwCompClauseOffset > 0)
968     {
969         LPWSTR Compclause = (LPWSTR)(compdata + compstr->dwCompClauseOffset);
970
971         rc = compstr->dwCompClauseLen;
972         if (dwBufLen >= compstr->dwCompClauseLen)
973             memcpy(lpBuf,Compclause,rc);
974     }
975     else if (dwIndex == GCS_COMPREADSTR && compstr->dwCompReadStrLen > 0 &&
976               compstr->dwCompReadStrOffset > 0)
977     {
978         LPWSTR CompReadString = (LPWSTR)(compdata + compstr->dwCompReadStrOffset);
979
980         rc = compstr->dwCompReadStrLen * sizeof(WCHAR);
981
982         if (dwBufLen >= rc)
983             memcpy(lpBuf,CompReadString,rc);
984     }
985     else if (dwIndex == GCS_CURSORPOS)
986     {
987         TRACE("GSC_CURSORPOS\n");
988         rc = compstr->dwCursorPos;
989     }
990     else if (dwIndex == GCS_DELTASTART)
991     {
992         TRACE("GCS_DELTASTART\n");
993         rc = compstr->dwDeltaStart;
994     }
995     else
996     {
997         FIXME("Unhandled index 0x%x\n",dwIndex);
998     }   
999
1000     ImmUnlockIMCC(data->IMC.hCompStr);
1001
1002     return rc;
1003 }
1004
1005 /***********************************************************************
1006  *              ImmGetCompositionWindow (IMM32.@)
1007  */
1008 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1009 {
1010     InputContextData *data = (InputContextData*)hIMC;
1011
1012     TRACE("(%p, %p)\n", hIMC, lpCompForm);
1013
1014     if (!data)
1015         return FALSE;
1016
1017     memcpy(lpCompForm,&(data->IMC.cfCompForm),sizeof(COMPOSITIONFORM));
1018     return 1;
1019 }
1020
1021 /***********************************************************************
1022  *              ImmGetContext (IMM32.@)
1023  *
1024  */
1025 HIMC WINAPI ImmGetContext(HWND hWnd)
1026 {
1027     TRACE("%p\n", hWnd);
1028
1029     if (!root_context)
1030         return NULL;
1031
1032     root_context->IMC.hWnd = hWnd;
1033     return (HIMC)root_context;
1034 }
1035
1036 /***********************************************************************
1037  *              ImmGetConversionListA (IMM32.@)
1038  */
1039 DWORD WINAPI ImmGetConversionListA(
1040   HKL hKL, HIMC hIMC,
1041   LPCSTR pSrc, LPCANDIDATELIST lpDst,
1042   DWORD dwBufLen, UINT uFlag)
1043 {
1044   FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1045     hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
1046   );
1047   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1048   return 0;
1049 }
1050
1051 /***********************************************************************
1052  *              ImmGetConversionListW (IMM32.@)
1053  */
1054 DWORD WINAPI ImmGetConversionListW(
1055   HKL hKL, HIMC hIMC,
1056   LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1057   DWORD dwBufLen, UINT uFlag)
1058 {
1059   FIXME("(%p, %p, %s, %p, %d, %d): stub\n",
1060     hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
1061   );
1062   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1063   return 0;
1064 }
1065
1066 /***********************************************************************
1067  *              ImmGetConversionStatus (IMM32.@)
1068  */
1069 BOOL WINAPI ImmGetConversionStatus(
1070   HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1071 {
1072     TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
1073     if (lpfdwConversion)
1074         *lpfdwConversion = IME_CMODE_NATIVE;
1075     if (lpfdwSentence)
1076         *lpfdwSentence = IME_SMODE_NONE;
1077     return TRUE;
1078 }
1079
1080 /***********************************************************************
1081  *              ImmGetDefaultIMEWnd (IMM32.@)
1082  */
1083 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1084 {
1085   static int shown = 0;
1086
1087   if (!shown) {
1088         FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
1089         shown = 1;
1090   }
1091
1092   if (hwndDefault == NULL)
1093   {
1094         static const WCHAR the_name[] = {'I','M','E','\0'};
1095
1096         IMM_Register();
1097         hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
1098                 the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
1099                 hImeInst, 0);
1100
1101         TRACE("Default created (%p)\n",hwndDefault);
1102   }
1103
1104   return hwndDefault;
1105 }
1106
1107 /***********************************************************************
1108  *              ImmGetDescriptionA (IMM32.@)
1109  */
1110 UINT WINAPI ImmGetDescriptionA(
1111   HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1112 {
1113   WCHAR *buf;
1114   DWORD len;
1115
1116   TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1117
1118   /* find out how many characters in the unicode buffer */
1119   len = ImmGetDescriptionW( hKL, NULL, 0 );
1120
1121   /* allocate a buffer of that size */
1122   buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1123   if( !buf )
1124   return 0;
1125
1126   /* fetch the unicode buffer */
1127   len = ImmGetDescriptionW( hKL, buf, len + 1 );
1128
1129   /* convert it back to ASCII */
1130   len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1131                              lpszDescription, uBufLen, NULL, NULL );
1132
1133   HeapFree( GetProcessHeap(), 0, buf );
1134
1135   return len;
1136 }
1137
1138 /***********************************************************************
1139  *              ImmGetDescriptionW (IMM32.@)
1140  */
1141 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1142 {
1143   static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1144
1145   FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1146
1147   if (!uBufLen) return lstrlenW( name );
1148   lstrcpynW( lpszDescription, name, uBufLen );
1149   return lstrlenW( lpszDescription );
1150 }
1151
1152 /***********************************************************************
1153  *              ImmGetGuideLineA (IMM32.@)
1154  */
1155 DWORD WINAPI ImmGetGuideLineA(
1156   HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1157 {
1158   FIXME("(%p, %d, %s, %d): stub\n",
1159     hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1160   );
1161   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1162   return 0;
1163 }
1164
1165 /***********************************************************************
1166  *              ImmGetGuideLineW (IMM32.@)
1167  */
1168 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1169 {
1170   FIXME("(%p, %d, %s, %d): stub\n",
1171     hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1172   );
1173   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1174   return 0;
1175 }
1176
1177 /***********************************************************************
1178  *              ImmGetIMEFileNameA (IMM32.@)
1179  */
1180 UINT WINAPI ImmGetIMEFileNameA(
1181   HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1182 {
1183   FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1184   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1185   return 0;
1186 }
1187
1188 /***********************************************************************
1189  *              ImmGetIMEFileNameW (IMM32.@)
1190  */
1191 UINT WINAPI ImmGetIMEFileNameW(
1192   HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1193 {
1194   FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1195   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1196   return 0;
1197 }
1198
1199 /***********************************************************************
1200  *              ImmGetOpenStatus (IMM32.@)
1201  */
1202 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1203 {
1204   InputContextData *data = (InputContextData*)hIMC;
1205
1206     if (!data)
1207         return FALSE;
1208   FIXME("(%p): semi-stub\n", hIMC);
1209
1210   return data->IMC.fOpen;
1211 }
1212
1213 /***********************************************************************
1214  *              ImmGetProperty (IMM32.@)
1215  */
1216 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1217 {
1218     DWORD rc = 0;
1219     TRACE("(%p, %d)\n", hKL, fdwIndex);
1220
1221     switch (fdwIndex)
1222     {
1223         case IGP_PROPERTY:
1224             TRACE("(%s)\n", "IGP_PROPERTY");
1225             rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
1226             break;
1227         case IGP_CONVERSION:
1228             FIXME("(%s)\n", "IGP_CONVERSION");
1229             rc = IME_CMODE_NATIVE;
1230             break;
1231         case IGP_SENTENCE:
1232             FIXME("%s)\n", "IGP_SENTENCE");
1233             rc = IME_SMODE_AUTOMATIC;
1234             break;
1235         case IGP_SETCOMPSTR:
1236             TRACE("(%s)\n", "IGP_SETCOMPSTR");
1237             rc = 0;
1238             break;
1239         case IGP_SELECT:
1240             TRACE("(%s)\n", "IGP_SELECT");
1241             rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
1242             break;
1243         case IGP_GETIMEVERSION:
1244             TRACE("(%s)\n", "IGP_GETIMEVERSION");
1245             rc = IMEVER_0400;
1246             break;
1247         case IGP_UI:
1248             TRACE("(%s)\n", "IGP_UI");
1249             rc = 0;
1250             break;
1251         default:
1252             rc = 0;
1253     }
1254     return rc;
1255 }
1256
1257 /***********************************************************************
1258  *              ImmGetRegisterWordStyleA (IMM32.@)
1259  */
1260 UINT WINAPI ImmGetRegisterWordStyleA(
1261   HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1262 {
1263   FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1264   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1265   return 0;
1266 }
1267
1268 /***********************************************************************
1269  *              ImmGetRegisterWordStyleW (IMM32.@)
1270  */
1271 UINT WINAPI ImmGetRegisterWordStyleW(
1272   HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1273 {
1274   FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1275   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1276   return 0;
1277 }
1278
1279 /***********************************************************************
1280  *              ImmGetStatusWindowPos (IMM32.@)
1281  */
1282 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1283 {
1284   FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1285   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1286   return FALSE;
1287 }
1288
1289 /***********************************************************************
1290  *              ImmGetVirtualKey (IMM32.@)
1291  */
1292 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1293 {
1294   OSVERSIONINFOA version;
1295   FIXME("(%p): stub\n", hWnd);
1296   GetVersionExA( &version );
1297   switch(version.dwPlatformId)
1298   {
1299   case VER_PLATFORM_WIN32_WINDOWS:
1300       return VK_PROCESSKEY;
1301   case VER_PLATFORM_WIN32_NT:
1302       return 0;
1303   default:
1304       FIXME("%d not supported\n",version.dwPlatformId);
1305       return VK_PROCESSKEY;
1306   }
1307 }
1308
1309 /***********************************************************************
1310  *              ImmInstallIMEA (IMM32.@)
1311  */
1312 HKL WINAPI ImmInstallIMEA(
1313   LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1314 {
1315   FIXME("(%s, %s): stub\n",
1316     debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1317   );
1318   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1319   return NULL;
1320 }
1321
1322 /***********************************************************************
1323  *              ImmInstallIMEW (IMM32.@)
1324  */
1325 HKL WINAPI ImmInstallIMEW(
1326   LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1327 {
1328   FIXME("(%s, %s): stub\n",
1329     debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1330   );
1331   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1332   return NULL;
1333 }
1334
1335 /***********************************************************************
1336  *              ImmIsIME (IMM32.@)
1337  */
1338 BOOL WINAPI ImmIsIME(HKL hKL)
1339 {
1340   TRACE("(%p): semi-stub\n", hKL);
1341   /*
1342    * FIXME: Dead key locales will return TRUE here when they should not
1343    * There is probably a more proper way to check this.
1344    */
1345   return (root_context != NULL);
1346 }
1347
1348 /***********************************************************************
1349  *              ImmIsUIMessageA (IMM32.@)
1350  */
1351 BOOL WINAPI ImmIsUIMessageA(
1352   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1353 {
1354     BOOL rc = FALSE;
1355
1356     TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1357     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1358         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1359         (msg == WM_MSIME_SERVICE) ||
1360         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1361         (msg == WM_MSIME_MOUSE) ||
1362         (msg == WM_MSIME_RECONVERTREQUEST) ||
1363         (msg == WM_MSIME_RECONVERT) ||
1364         (msg == WM_MSIME_QUERYPOSITION) ||
1365         (msg == WM_MSIME_DOCUMENTFEED))
1366
1367     {
1368         if (!hwndDefault)
1369             ImmGetDefaultIMEWnd(NULL);
1370
1371         if (hWndIME == NULL)
1372             PostMessageA(hwndDefault, msg, wParam, lParam);
1373
1374         rc = TRUE;
1375     }
1376     return rc;
1377 }
1378
1379 /***********************************************************************
1380  *              ImmIsUIMessageW (IMM32.@)
1381  */
1382 BOOL WINAPI ImmIsUIMessageW(
1383   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1384 {
1385     BOOL rc = FALSE;
1386     TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
1387     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1388         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1389         (msg == WM_MSIME_SERVICE) ||
1390         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1391         (msg == WM_MSIME_MOUSE) ||
1392         (msg == WM_MSIME_RECONVERTREQUEST) ||
1393         (msg == WM_MSIME_RECONVERT) ||
1394         (msg == WM_MSIME_QUERYPOSITION) ||
1395         (msg == WM_MSIME_DOCUMENTFEED))
1396         rc = TRUE;
1397     return rc;
1398 }
1399
1400 /***********************************************************************
1401  *              ImmNotifyIME (IMM32.@)
1402  */
1403 BOOL WINAPI ImmNotifyIME(
1404   HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1405 {
1406     BOOL rc = FALSE;
1407
1408     TRACE("(%p, %d, %d, %d)\n",
1409         hIMC, dwAction, dwIndex, dwValue);
1410
1411     if (!root_context)
1412         return rc;
1413
1414     switch(dwAction)
1415     {
1416         case NI_CHANGECANDIDATELIST:
1417             FIXME("%s\n","NI_CHANGECANDIDATELIST");
1418             break;
1419         case NI_CLOSECANDIDATE:
1420             FIXME("%s\n","NI_CLOSECANDIDATE");
1421             break;
1422         case NI_COMPOSITIONSTR:
1423             switch (dwIndex)
1424             {
1425                 case CPS_CANCEL:
1426                     TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1427                     {
1428                         BOOL send;
1429                         LPCOMPOSITIONSTRING lpCompStr;
1430
1431                         if (pX11DRV_ForceXIMReset)
1432                             pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1433
1434                         lpCompStr = ImmLockIMCC(root_context->IMC.hCompStr);
1435                         send = (lpCompStr->dwCompStrLen != 0);
1436                         ImmUnlockIMCC(root_context->IMC.hCompStr);
1437
1438                         ImmDestroyIMCC(root_context->IMC.hCompStr);
1439                         root_context->IMC.hCompStr = ImmCreateBlankCompStr();
1440
1441                         if (send)
1442                             ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1443                                                   GCS_COMPSTR);
1444                         rc = TRUE;
1445                     }
1446                     break;
1447                 case CPS_COMPLETE:
1448                     TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1449                     if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1450                         pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1451                     {
1452                         HIMCC newCompStr;
1453                         DWORD cplen = 0;
1454                         LPWSTR cpstr;
1455                         LPCOMPOSITIONSTRING cs = NULL;
1456                         LPBYTE cdata = NULL;
1457
1458                         /* clear existing result */
1459                         newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
1460                         ImmDestroyIMCC(root_context->IMC.hCompStr);
1461                         root_context->IMC.hCompStr = newCompStr;
1462
1463                         if (root_context->IMC.hCompStr)
1464                         {
1465                             cdata = ImmLockIMCC(root_context->IMC.hCompStr);
1466                             cs = (LPCOMPOSITIONSTRING)cdata;
1467                             cplen = cs->dwCompStrLen;
1468                             cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
1469                             ImmUnlockIMCC(root_context->IMC.hCompStr);
1470                         }
1471                         if (cplen > 0)
1472                         {
1473                             WCHAR param = cpstr[0];
1474                             newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
1475                             ImmDestroyIMCC(root_context->IMC.hCompStr);
1476                             root_context->IMC.hCompStr = newCompStr;
1477                             newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1478                             ImmDestroyIMCC(root_context->IMC.hCompStr);
1479                             root_context->IMC.hCompStr = newCompStr;
1480
1481                             root_context->bRead = FALSE;
1482
1483                             ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1484                                                   GCS_COMPSTR);
1485
1486                             ImmInternalPostIMEMessage(WM_IME_COMPOSITION,
1487                                             param,
1488                                             GCS_RESULTSTR|GCS_RESULTCLAUSE);
1489                         }
1490
1491                         ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION, 0, 0);
1492                         root_context->bInComposition = FALSE;
1493                     }
1494                     break;
1495                 case CPS_CONVERT:
1496                     FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1497                     break;
1498                 case CPS_REVERT:
1499                     FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1500                     break;
1501                 default:
1502                     ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1503                     break;
1504             }
1505             break;
1506         case NI_IMEMENUSELECTED:
1507             FIXME("%s\n", "NI_IMEMENUSELECTED");
1508             break;
1509         case NI_OPENCANDIDATE:
1510             FIXME("%s\n", "NI_OPENCANDIDATE");
1511             break;
1512         case NI_SELECTCANDIDATESTR:
1513             FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1514             break;
1515         case NI_SETCANDIDATE_PAGESIZE:
1516             FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1517             break;
1518         case NI_SETCANDIDATE_PAGESTART:
1519             FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1520             break;
1521         default:
1522             ERR("Unknown\n");
1523     }
1524
1525     return rc;
1526 }
1527
1528 /***********************************************************************
1529  *              ImmRegisterWordA (IMM32.@)
1530  */
1531 BOOL WINAPI ImmRegisterWordA(
1532   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1533 {
1534   FIXME("(%p, %s, %d, %s): stub\n",
1535     hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1536   );
1537   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1538   return FALSE;
1539 }
1540
1541 /***********************************************************************
1542  *              ImmRegisterWordW (IMM32.@)
1543  */
1544 BOOL WINAPI ImmRegisterWordW(
1545   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1546 {
1547   FIXME("(%p, %s, %d, %s): stub\n",
1548     hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1549   );
1550   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1551   return FALSE;
1552 }
1553
1554 /***********************************************************************
1555  *              ImmReleaseContext (IMM32.@)
1556  */
1557 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1558 {
1559   static int shown = 0;
1560
1561   if (!shown) {
1562      FIXME("(%p, %p): stub\n", hWnd, hIMC);
1563      shown = 1;
1564   }
1565   return TRUE;
1566 }
1567
1568 /***********************************************************************
1569  *              ImmSetCandidateWindow (IMM32.@)
1570  */
1571 BOOL WINAPI ImmSetCandidateWindow(
1572   HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1573 {
1574   FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1575   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1576   return FALSE;
1577 }
1578
1579 /***********************************************************************
1580  *              ImmSetCompositionFontA (IMM32.@)
1581  */
1582 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1583 {
1584     InputContextData *data = (InputContextData*)hIMC;
1585     TRACE("(%p, %p)\n", hIMC, lplf);
1586
1587     if (!data)
1588         return FALSE;
1589
1590     memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1591     MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1592                         LF_FACESIZE);
1593
1594     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1595
1596     if (data->textfont)
1597     {
1598         DeleteObject(data->textfont);
1599         data->textfont = NULL;
1600     }
1601
1602     data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1603     return TRUE;
1604 }
1605
1606 /***********************************************************************
1607  *              ImmSetCompositionFontW (IMM32.@)
1608  */
1609 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1610 {
1611     InputContextData *data = (InputContextData*)hIMC;
1612     TRACE("(%p, %p)\n", hIMC, lplf);
1613
1614     if (!data)
1615         return FALSE;
1616
1617     memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTW));
1618     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1619
1620     if (data->textfont)
1621     {
1622         DeleteObject(data->textfont);
1623         data->textfont = NULL;
1624     }
1625     data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1626     return TRUE;
1627 }
1628
1629 /***********************************************************************
1630  *              ImmSetCompositionStringA (IMM32.@)
1631  */
1632 BOOL WINAPI ImmSetCompositionStringA(
1633   HIMC hIMC, DWORD dwIndex,
1634   LPCVOID lpComp, DWORD dwCompLen,
1635   LPCVOID lpRead, DWORD dwReadLen)
1636 {
1637     DWORD comp_len;
1638     DWORD read_len;
1639     WCHAR *CompBuffer = NULL;
1640     WCHAR *ReadBuffer = NULL;
1641     BOOL rc;
1642
1643     TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1644             hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1645
1646     comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
1647     if (comp_len)
1648     {
1649         CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
1650         MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
1651     }
1652
1653     read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
1654     if (read_len)
1655     {
1656         ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
1657         MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
1658     }
1659
1660     rc =  ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
1661                                    ReadBuffer, read_len);
1662
1663     HeapFree(GetProcessHeap(), 0, CompBuffer);
1664     HeapFree(GetProcessHeap(), 0, ReadBuffer);
1665
1666     return rc;
1667 }
1668
1669 /***********************************************************************
1670  *              ImmSetCompositionStringW (IMM32.@)
1671  */
1672 BOOL WINAPI ImmSetCompositionStringW(
1673         HIMC hIMC, DWORD dwIndex,
1674         LPCVOID lpComp, DWORD dwCompLen,
1675         LPCVOID lpRead, DWORD dwReadLen)
1676 {
1677      DWORD flags = 0;
1678      WCHAR wParam  = 0;
1679
1680      TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1681              hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1682
1683
1684      if (hIMC != (HIMC)FROM_IME)
1685          FIXME("PROBLEM: This only sets the wine level string\n");
1686
1687      /*
1688       * Explanation:
1689       *  this sets the composition string in the imm32.dll level
1690       *  of the composition buffer. we cannot manipulate the xim level
1691       *  buffer, which means that once the xim level buffer changes again
1692       *  any call to this function from the application will be lost
1693       */
1694
1695      if (lpRead && dwReadLen)
1696          FIXME("Reading string unimplemented\n");
1697
1698      /*
1699       * app operating this api to also receive the message from xim
1700       */
1701
1702     if (dwIndex == SCS_SETSTR)
1703     {
1704         HIMCC newCompStr;
1705         if (!root_context->bInComposition)
1706         {
1707             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION, 0, 0);
1708             root_context->bInComposition = TRUE;
1709         }
1710
1711         flags = GCS_COMPSTR;
1712
1713         if (dwCompLen && lpComp)
1714         {
1715             newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
1716             ImmDestroyIMCC(root_context->IMC.hCompStr);
1717             root_context->IMC.hCompStr = newCompStr;
1718
1719              wParam = ((const WCHAR*)lpComp)[0];
1720              flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
1721         }
1722         else
1723         {
1724             newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1725             ImmDestroyIMCC(root_context->IMC.hCompStr);
1726             root_context->IMC.hCompStr = newCompStr;
1727         }
1728     }
1729
1730      UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
1731
1732      ImmInternalPostIMEMessage(WM_IME_COMPOSITION, wParam, flags);
1733
1734      return TRUE;
1735 }
1736
1737 /***********************************************************************
1738  *              ImmSetCompositionWindow (IMM32.@)
1739  */
1740 BOOL WINAPI ImmSetCompositionWindow(
1741   HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1742 {
1743     BOOL reshow = FALSE;
1744     InputContextData *data = (InputContextData*)hIMC;
1745
1746     TRACE("(%p, %p)\n", hIMC, lpCompForm);
1747     TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
1748           lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
1749           lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
1750
1751     if (!data)
1752         return FALSE;
1753
1754     memcpy(&data->IMC.cfCompForm,lpCompForm,sizeof(COMPOSITIONFORM));
1755
1756     if (IsWindowVisible(hwndDefault))
1757     {
1758         reshow = TRUE;
1759         ShowWindow(hwndDefault,SW_HIDE);
1760     }
1761
1762     /* FIXME: this is a partial stub */
1763
1764     if (reshow)
1765         ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1766
1767     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONWINDOW, 0);
1768     return TRUE;
1769 }
1770
1771 /***********************************************************************
1772  *              ImmSetConversionStatus (IMM32.@)
1773  */
1774 BOOL WINAPI ImmSetConversionStatus(
1775   HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1776 {
1777   static int shown = 0;
1778
1779   if (!shown) {
1780       FIXME("(%p, %d, %d): stub\n",
1781           hIMC, fdwConversion, fdwSentence
1782       );
1783       shown = 1;
1784   }
1785   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1786   return FALSE;
1787 }
1788
1789 /***********************************************************************
1790  *              ImmSetOpenStatus (IMM32.@)
1791  */
1792 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
1793 {
1794     InputContextData *data = (InputContextData*)hIMC;
1795
1796     TRACE("%p %d\n", hIMC, fOpen);
1797
1798     if (hIMC == (HIMC)FROM_IME)
1799     {
1800         ImmInternalSetOpenStatus(fOpen);
1801         ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0);
1802         return TRUE;
1803     }
1804
1805     if (!data)
1806         return FALSE;
1807
1808     if (fOpen != data->bInternalState)
1809     {
1810         if (fOpen == FALSE && pX11DRV_ForceXIMReset)
1811             pX11DRV_ForceXIMReset(data->IMC.hWnd);
1812
1813         if (fOpen == FALSE)
1814             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1815         else
1816             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1817
1818         ImmInternalSetOpenStatus(fOpen);
1819         ImmInternalSetOpenStatus(!fOpen);
1820
1821         if (data->IMC.fOpen == FALSE)
1822             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1823         else
1824             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1825
1826         return FALSE;
1827     }
1828     return TRUE;
1829 }
1830
1831 /***********************************************************************
1832  *              ImmSetStatusWindowPos (IMM32.@)
1833  */
1834 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1835 {
1836   FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1837   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1838   return FALSE;
1839 }
1840
1841 /***********************************************************************
1842  *              ImmSimulateHotKey (IMM32.@)
1843  */
1844 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
1845 {
1846   FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
1847   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1848   return FALSE;
1849 }
1850
1851 /***********************************************************************
1852  *              ImmUnregisterWordA (IMM32.@)
1853  */
1854 BOOL WINAPI ImmUnregisterWordA(
1855   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
1856 {
1857   FIXME("(%p, %s, %d, %s): stub\n",
1858     hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
1859   );
1860   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1861   return FALSE;
1862 }
1863
1864 /***********************************************************************
1865  *              ImmUnregisterWordW (IMM32.@)
1866  */
1867 BOOL WINAPI ImmUnregisterWordW(
1868   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
1869 {
1870   FIXME("(%p, %s, %d, %s): stub\n",
1871     hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
1872   );
1873   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1874   return FALSE;
1875 }
1876
1877 /***********************************************************************
1878  *              ImmGetImeMenuItemsA (IMM32.@)
1879  */
1880 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1881    LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
1882     DWORD dwSize)
1883 {
1884   FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1885     lpImeParentMenu, lpImeMenu, dwSize);
1886   return 0;
1887 }
1888
1889 /***********************************************************************
1890 *               ImmGetImeMenuItemsW (IMM32.@)
1891 */
1892 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1893    LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
1894    DWORD dwSize)
1895 {
1896   FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1897     lpImeParentMenu, lpImeMenu, dwSize);
1898   return 0;
1899 }
1900
1901 /***********************************************************************
1902 *               ImmLockIMC(IMM32.@)
1903 */
1904 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
1905 {
1906     InputContextData *data = (InputContextData*)hIMC;
1907
1908     if (!data)
1909         return NULL;
1910     data->dwLock++;
1911     return &data->IMC;
1912 }
1913
1914 /***********************************************************************
1915 *               ImmUnlockIMC(IMM32.@)
1916 */
1917 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
1918 {
1919     InputContextData *data = (InputContextData*)hIMC;
1920     data->dwLock--;
1921     return (data->dwLock!=0);
1922 }
1923
1924 /***********************************************************************
1925 *               ImmGetIMCLockCount(IMM32.@)
1926 */
1927 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
1928 {
1929     InputContextData *data = (InputContextData*)hIMC;
1930     return data->dwLock;
1931 }
1932
1933 /***********************************************************************
1934 *               ImmCreateIMCC(IMM32.@)
1935 */
1936 HIMCC  WINAPI ImmCreateIMCC(DWORD size)
1937 {
1938     IMCCInternal *internal;
1939     int real_size = size + sizeof(IMCCInternal);
1940
1941     internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
1942     if (internal == NULL)
1943         return NULL;
1944
1945     internal->dwSize = size;
1946     return  (HIMCC)internal;
1947 }
1948
1949 /***********************************************************************
1950 *       ImmDestroyIMCC(IMM32.@)
1951 */
1952 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
1953 {
1954     HeapFree(GetProcessHeap(),0,block);
1955     return NULL;
1956 }
1957
1958 /***********************************************************************
1959 *               ImmLockIMCC(IMM32.@)
1960 */
1961 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
1962 {
1963     IMCCInternal *internal;
1964     internal = (IMCCInternal*) imcc;
1965
1966     internal->dwLock ++;
1967     return internal + 1;
1968 }
1969
1970 /***********************************************************************
1971 *               ImmUnlockIMCC(IMM32.@)
1972 */
1973 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
1974 {
1975     IMCCInternal *internal;
1976     internal = (IMCCInternal*) imcc;
1977
1978     internal->dwLock --;
1979     return (internal->dwLock!=0);
1980 }
1981
1982 /***********************************************************************
1983 *               ImmGetIMCCLockCount(IMM32.@)
1984 */
1985 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
1986 {
1987     IMCCInternal *internal;
1988     internal = (IMCCInternal*) imcc;
1989
1990     return internal->dwLock;
1991 }
1992
1993 /***********************************************************************
1994 *               ImmReSizeIMCC(IMM32.@)
1995 */
1996 HIMCC  WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
1997 {
1998     IMCCInternal *internal,*newone;
1999     int real_size = size + sizeof(IMCCInternal);
2000
2001     internal = (IMCCInternal*) imcc;
2002
2003     newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2004     newone->dwSize = size;
2005
2006     return newone;
2007 }
2008
2009 /***********************************************************************
2010 *               ImmGetIMCCSize(IMM32.@)
2011 */
2012 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2013 {
2014     IMCCInternal *internal;
2015     internal = (IMCCInternal*) imcc;
2016
2017     return internal->dwSize;
2018 }
2019
2020 /***********************************************************************
2021 *               ImmGenerateMessage(IMM32.@)
2022 */
2023 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2024 {
2025     InputContextData *data = (InputContextData*)hIMC;
2026
2027     TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2028     if (data->IMC.dwNumMsgBuf > 0)
2029     {
2030         LPTRANSMSG lpTransMsg;
2031         INT i;
2032
2033         lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
2034         for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2035             ImmInternalPostIMEMessage(lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2036
2037         ImmUnlockIMCC(data->IMC.hMsgBuf);
2038         ImmDestroyIMCC(data->IMC.hMsgBuf);
2039
2040         data->IMC.dwNumMsgBuf = 0;
2041         data->IMC.hMsgBuf = NULL;
2042     }
2043
2044     return TRUE;
2045 }
2046
2047 /*****
2048  * Internal functions to help with IME window management
2049  */
2050 static void PaintDefaultIMEWnd(HWND hwnd)
2051 {
2052     PAINTSTRUCT ps;
2053     RECT rect;
2054     HDC hdc = BeginPaint(hwnd,&ps);
2055     LPCOMPOSITIONSTRING compstr;
2056     LPBYTE compdata = NULL;
2057     HMONITOR monitor;
2058     MONITORINFO mon_info;
2059     INT offX=0, offY=0;
2060
2061     GetClientRect(hwnd,&rect);
2062     FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
2063
2064     compdata = ImmLockIMCC(root_context->IMC.hCompStr);
2065     compstr = (LPCOMPOSITIONSTRING)compdata;
2066
2067     if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
2068     {
2069         SIZE size;
2070         POINT pt;
2071         HFONT oldfont = NULL;
2072         LPWSTR CompString;
2073
2074         CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
2075         if (root_context->textfont)
2076             oldfont = SelectObject(hdc,root_context->textfont);
2077
2078
2079         GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
2080         pt.x = size.cx;
2081         pt.y = size.cy;
2082         LPtoDP(hdc,&pt,1);
2083
2084         /*
2085          * How this works based on tests on windows:
2086          * CFS_POINT: then we start our window at the point and grow it as large
2087          *    as it needs to be for the string.
2088          * CFS_RECT:  we still use the ptCurrentPos as a starting point and our
2089          *    window is only as large as we need for the string, but we do not
2090          *    grow such that our window exceeds the given rect.  Wrapping if
2091          *    needed and possible.   If our ptCurrentPos is outside of our rect
2092          *    then no window is displayed.
2093          * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
2094          *    maybe becase the default MSIME does not do any IME adjusting.
2095          */
2096         if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
2097         {
2098             POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
2099             ClientToScreen(root_context->IMC.hWnd,&cpt);
2100             rect.left = cpt.x;
2101             rect.top = cpt.y;
2102             rect.right = rect.left + pt.x;
2103             rect.bottom = rect.top + pt.y;
2104             offX=offY=10;
2105             monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
2106         }
2107         else /* CFS_DEFAULT */
2108         {
2109             /* Windows places the default IME window in the bottom left */
2110             HWND target = root_context->IMC.hWnd;
2111             if (!target) target = GetFocus();
2112
2113             GetWindowRect(target,&rect);
2114             rect.top = rect.bottom;
2115             rect.right = rect.left + pt.x + 20;
2116             rect.bottom = rect.top + pt.y + 20;
2117             offX=offY=10;
2118             monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
2119         }
2120
2121         if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
2122         {
2123             RECT client;
2124             client =root_context->IMC.cfCompForm.rcArea;
2125             MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
2126             IntersectRect(&rect,&rect,&client);
2127             /* TODO:  Wrap the input if needed */
2128         }
2129
2130         if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
2131         {
2132             /* make sure we are on the desktop */
2133             mon_info.cbSize = sizeof(mon_info);
2134             GetMonitorInfoW(monitor, &mon_info);
2135
2136             if (rect.bottom > mon_info.rcWork.bottom)
2137             {
2138                 int shift = rect.bottom - mon_info.rcWork.bottom;
2139                 rect.top -= shift;
2140                 rect.bottom -= shift;
2141             }
2142             if (rect.left < 0)
2143             {
2144                 rect.right -= rect.left;
2145                 rect.left = 0;
2146             }
2147             if (rect.right > mon_info.rcWork.right)
2148             {
2149                 int shift = rect.right - mon_info.rcWork.right;
2150                 rect.left -= shift;
2151                 rect.right -= shift;
2152             }
2153         }
2154
2155         SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
2156
2157         TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
2158
2159         if (oldfont)
2160             SelectObject(hdc,oldfont);
2161     }
2162
2163     ImmUnlockIMCC(root_context->IMC.hCompStr);
2164
2165     EndPaint(hwnd,&ps);
2166 }
2167
2168 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
2169 {
2170     LPCOMPOSITIONSTRING compstr;
2171
2172     if (root_context->IMC.hCompStr)
2173         compstr = ImmLockIMCC(root_context->IMC.hCompStr);
2174     else
2175         compstr = NULL;
2176
2177     if (compstr == NULL || compstr->dwCompStrLen == 0)
2178         ShowWindow(hwndDefault,SW_HIDE);
2179     else if (showable)
2180         ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2181
2182     RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
2183
2184     if (compstr != NULL)
2185         ImmUnlockIMCC(root_context->IMC.hCompStr);
2186 }
2187
2188 /*
2189  * The window proc for the default IME window
2190  */
2191 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
2192                                           LPARAM lParam)
2193 {
2194     LRESULT rc = 0;
2195
2196     TRACE("Incoming Message 0x%x  (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
2197            (UINT)lParam);
2198
2199     switch(msg)
2200     {
2201         case WM_PAINT:
2202             PaintDefaultIMEWnd(hwnd);
2203             return FALSE;
2204
2205         case WM_NCCREATE:
2206             return TRUE;
2207
2208         case WM_CREATE:
2209             SetWindowTextA(hwnd,"Wine Ime Active");
2210             return TRUE;
2211
2212         case WM_SETFOCUS:
2213             if (wParam)
2214                 SetFocus((HWND)wParam);
2215             else
2216                 FIXME("Received focus, should never have focus\n");
2217             break;
2218         case WM_IME_COMPOSITION:
2219             TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
2220                     "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
2221                      root_context->bRead);
2222             if (lParam & GCS_RESULTSTR)
2223                     IMM_PostResult(root_context);
2224             else
2225                  UpdateDataInDefaultIMEWindow(hwnd,TRUE);
2226             break;
2227         case WM_IME_STARTCOMPOSITION:
2228             TRACE("IME message %s, 0x%x, 0x%x\n",
2229                     "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
2230             root_context->IMC.hWnd = GetFocus();
2231             ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2232             break;
2233         case WM_IME_ENDCOMPOSITION:
2234             TRACE("IME message %s, 0x%x, 0x%x\n",
2235                     "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
2236             ShowWindow(hwndDefault,SW_HIDE);
2237             break;
2238         case WM_IME_SELECT:
2239             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
2240                 (UINT)wParam, (UINT)lParam);
2241             break;
2242         case WM_IME_CONTROL:
2243             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
2244                 (UINT)wParam, (UINT)lParam);
2245             rc = 1;
2246             break;
2247         case WM_IME_NOTIFY:
2248             TRACE("!! IME NOTIFY\n");
2249             break;
2250        default:
2251             TRACE("Non-standard message 0x%x\n",msg);
2252     }
2253     /* check the MSIME messages */
2254     if (msg == WM_MSIME_SERVICE)
2255     {
2256             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
2257                 (UINT)wParam, (UINT)lParam);
2258             rc = FALSE;
2259     }
2260     else if (msg == WM_MSIME_RECONVERTOPTIONS)
2261     {
2262             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
2263                 (UINT)wParam, (UINT)lParam);
2264     }
2265     else if (msg == WM_MSIME_MOUSE)
2266     {
2267             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
2268                 (UINT)wParam, (UINT)lParam);
2269     }
2270     else if (msg == WM_MSIME_RECONVERTREQUEST)
2271     {
2272             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
2273                 (UINT)wParam, (UINT)lParam);
2274     }
2275     else if (msg == WM_MSIME_RECONVERT)
2276     {
2277             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
2278                 (UINT)wParam, (UINT)lParam);
2279     }
2280     else if (msg == WM_MSIME_QUERYPOSITION)
2281     {
2282             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
2283                 (UINT)wParam, (UINT)lParam);
2284     }
2285     else if (msg == WM_MSIME_DOCUMENTFEED)
2286     {
2287             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
2288                 (UINT)wParam, (UINT)lParam);
2289     }
2290     /* DefWndProc if not an IME message */
2291     else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2292                       (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
2293         rc = DefWindowProcW(hwnd,msg,wParam,lParam);
2294
2295     return rc;
2296 }