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