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