comctl32: We can now store binary files in the repository.
[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   FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
1061
1062   if (hwndDefault == NULL)
1063   {
1064         static const WCHAR the_name[] = {'I','M','E','\0'};
1065
1066         IMM_Register();
1067         hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW, WC_IMECLASSNAME,
1068                 the_name, WS_POPUP, 0, 0, 1, 1, 0, 0,
1069                 hImeInst, 0);
1070
1071         TRACE("Default created (%p)\n",hwndDefault);
1072   }
1073
1074   return (HWND)hwndDefault;
1075 }
1076
1077 /***********************************************************************
1078  *              ImmGetDescriptionA (IMM32.@)
1079  */
1080 UINT WINAPI ImmGetDescriptionA(
1081   HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1082 {
1083   WCHAR *buf;
1084   DWORD len;
1085
1086   TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1087
1088   /* find out how many characters in the unicode buffer */
1089   len = ImmGetDescriptionW( hKL, NULL, 0 );
1090
1091   /* allocate a buffer of that size */
1092   buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1093   if( !buf )
1094   return 0;
1095
1096   /* fetch the unicode buffer */
1097   len = ImmGetDescriptionW( hKL, buf, len + 1 );
1098
1099   /* convert it back to ASCII */
1100   len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1101                              lpszDescription, uBufLen, NULL, NULL );
1102
1103   HeapFree( GetProcessHeap(), 0, buf );
1104
1105   return len;
1106 }
1107
1108 /***********************************************************************
1109  *              ImmGetDescriptionW (IMM32.@)
1110  */
1111 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1112 {
1113   static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1114
1115   FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1116
1117   if (!uBufLen) return lstrlenW( name );
1118   lstrcpynW( lpszDescription, name, uBufLen );
1119   return lstrlenW( lpszDescription );
1120 }
1121
1122 /***********************************************************************
1123  *              ImmGetGuideLineA (IMM32.@)
1124  */
1125 DWORD WINAPI ImmGetGuideLineA(
1126   HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1127 {
1128   FIXME("(%p, %d, %s, %d): stub\n",
1129     hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1130   );
1131   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1132   return 0;
1133 }
1134
1135 /***********************************************************************
1136  *              ImmGetGuideLineW (IMM32.@)
1137  */
1138 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1139 {
1140   FIXME("(%p, %d, %s, %d): stub\n",
1141     hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1142   );
1143   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1144   return 0;
1145 }
1146
1147 /***********************************************************************
1148  *              ImmGetIMEFileNameA (IMM32.@)
1149  */
1150 UINT WINAPI ImmGetIMEFileNameA(
1151   HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1152 {
1153   FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
1154   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1155   return 0;
1156 }
1157
1158 /***********************************************************************
1159  *              ImmGetIMEFileNameW (IMM32.@)
1160  */
1161 UINT WINAPI ImmGetIMEFileNameW(
1162   HKL hKL, LPWSTR 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  *              ImmGetOpenStatus (IMM32.@)
1171  */
1172 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1173 {
1174   InputContextData *data = (InputContextData*)hIMC;
1175
1176     if (!data)
1177         return FALSE;
1178   FIXME("(%p): semi-stub\n", hIMC);
1179
1180   return data->IMC.fOpen;
1181 }
1182
1183 /***********************************************************************
1184  *              ImmGetProperty (IMM32.@)
1185  */
1186 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1187 {
1188     DWORD rc = 0;
1189     TRACE("(%p, %d)\n", hKL, fdwIndex);
1190
1191     switch (fdwIndex)
1192     {
1193         case IGP_PROPERTY:
1194             TRACE("(%s)\n", "IGP_PROPERTY");
1195             rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
1196             break;
1197         case IGP_CONVERSION:
1198             FIXME("(%s)\n", "IGP_CONVERSION");
1199             rc = IME_CMODE_NATIVE;
1200             break;
1201         case IGP_SENTENCE:
1202             FIXME("%s)\n", "IGP_SENTENCE");
1203             rc = IME_SMODE_AUTOMATIC;
1204             break;
1205         case IGP_SETCOMPSTR:
1206             TRACE("(%s)\n", "IGP_SETCOMPSTR");
1207             rc = 0;
1208             break;
1209         case IGP_SELECT:
1210             TRACE("(%s)\n", "IGP_SELECT");
1211             rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
1212             break;
1213         case IGP_GETIMEVERSION:
1214             TRACE("(%s)\n", "IGP_GETIMEVERSION");
1215             rc = IMEVER_0400;
1216             break;
1217         case IGP_UI:
1218             TRACE("(%s)\n", "IGP_UI");
1219             rc = 0;
1220             break;
1221         default:
1222             rc = 0;
1223     }
1224     return rc;
1225 }
1226
1227 /***********************************************************************
1228  *              ImmGetRegisterWordStyleA (IMM32.@)
1229  */
1230 UINT WINAPI ImmGetRegisterWordStyleA(
1231   HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1232 {
1233   FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
1234   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1235   return 0;
1236 }
1237
1238 /***********************************************************************
1239  *              ImmGetRegisterWordStyleW (IMM32.@)
1240  */
1241 UINT WINAPI ImmGetRegisterWordStyleW(
1242   HKL hKL, UINT nItem, LPSTYLEBUFW 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  *              ImmGetStatusWindowPos (IMM32.@)
1251  */
1252 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1253 {
1254   FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1255   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1256   return FALSE;
1257 }
1258
1259 /***********************************************************************
1260  *              ImmGetVirtualKey (IMM32.@)
1261  */
1262 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1263 {
1264   OSVERSIONINFOA version;
1265   FIXME("(%p): stub\n", hWnd);
1266   GetVersionExA( &version );
1267   switch(version.dwPlatformId)
1268   {
1269   case VER_PLATFORM_WIN32_WINDOWS:
1270       return VK_PROCESSKEY;
1271   case VER_PLATFORM_WIN32_NT:
1272       return 0;
1273   default:
1274       FIXME("%d not supported\n",version.dwPlatformId);
1275       return VK_PROCESSKEY;
1276   }
1277 }
1278
1279 /***********************************************************************
1280  *              ImmInstallIMEA (IMM32.@)
1281  */
1282 HKL WINAPI ImmInstallIMEA(
1283   LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1284 {
1285   FIXME("(%s, %s): stub\n",
1286     debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1287   );
1288   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1289   return NULL;
1290 }
1291
1292 /***********************************************************************
1293  *              ImmInstallIMEW (IMM32.@)
1294  */
1295 HKL WINAPI ImmInstallIMEW(
1296   LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1297 {
1298   FIXME("(%s, %s): stub\n",
1299     debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1300   );
1301   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1302   return NULL;
1303 }
1304
1305 /***********************************************************************
1306  *              ImmIsIME (IMM32.@)
1307  */
1308 BOOL WINAPI ImmIsIME(HKL hKL)
1309 {
1310   TRACE("(%p): semi-stub\n", hKL);
1311   /*
1312    * FIXME: Dead key locales will return TRUE here when they should not
1313    * There is probably a more proper way to check this.
1314    */
1315   return (root_context != NULL);
1316 }
1317
1318 /***********************************************************************
1319  *              ImmIsUIMessageA (IMM32.@)
1320  */
1321 BOOL WINAPI ImmIsUIMessageA(
1322   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1323 {
1324     BOOL rc = FALSE;
1325
1326     TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1327     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1328         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1329         (msg == WM_MSIME_SERVICE) ||
1330         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1331         (msg == WM_MSIME_MOUSE) ||
1332         (msg == WM_MSIME_RECONVERTREQUEST) ||
1333         (msg == WM_MSIME_RECONVERT) ||
1334         (msg == WM_MSIME_QUERYPOSITION) ||
1335         (msg == WM_MSIME_DOCUMENTFEED))
1336
1337     {
1338         if (!hwndDefault)
1339             ImmGetDefaultIMEWnd(NULL);
1340
1341         if (hWndIME == NULL)
1342             PostMessageA(hwndDefault, msg, wParam, lParam);
1343
1344         rc = TRUE;
1345     }
1346     return rc;
1347 }
1348
1349 /***********************************************************************
1350  *              ImmIsUIMessageW (IMM32.@)
1351  */
1352 BOOL WINAPI ImmIsUIMessageW(
1353   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1354 {
1355     BOOL rc = FALSE;
1356     TRACE("(%p, %d, %ld, %ld): stub\n", hWndIME, msg, wParam, lParam);
1357     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1358         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1359         (msg == WM_MSIME_SERVICE) ||
1360         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1361         (msg == WM_MSIME_MOUSE) ||
1362         (msg == WM_MSIME_RECONVERTREQUEST) ||
1363         (msg == WM_MSIME_RECONVERT) ||
1364         (msg == WM_MSIME_QUERYPOSITION) ||
1365         (msg == WM_MSIME_DOCUMENTFEED))
1366         rc = TRUE;
1367     return rc;
1368 }
1369
1370 /***********************************************************************
1371  *              ImmNotifyIME (IMM32.@)
1372  */
1373 BOOL WINAPI ImmNotifyIME(
1374   HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1375 {
1376     BOOL rc = FALSE;
1377
1378     TRACE("(%p, %d, %d, %d)\n",
1379         hIMC, dwAction, dwIndex, dwValue);
1380
1381     if (!root_context)
1382         return rc;
1383
1384     switch(dwAction)
1385     {
1386         case NI_CHANGECANDIDATELIST:
1387             FIXME("%s\n","NI_CHANGECANDIDATELIST");
1388             break;
1389         case NI_CLOSECANDIDATE:
1390             FIXME("%s\n","NI_CLOSECANDIDATE");
1391             break;
1392         case NI_COMPOSITIONSTR:
1393             switch (dwIndex)
1394             {
1395                 case CPS_CANCEL:
1396                     TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1397                     {
1398                         HIMCC newCompStr;
1399                         if (pX11DRV_ForceXIMReset)
1400                             pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1401
1402                         newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1403                         ImmDestroyIMCC(root_context->IMC.hCompStr);
1404                         root_context->IMC.hCompStr = newCompStr;
1405
1406                         ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1407                                                   GCS_COMPSTR);
1408                         rc = TRUE;
1409                     }
1410                     break;
1411                 case CPS_COMPLETE:
1412                     TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1413                     if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1414                         pX11DRV_ForceXIMReset(root_context->IMC.hWnd);
1415                     {
1416                         HIMCC newCompStr;
1417                         DWORD cplen;
1418                         LPWSTR cpstr;
1419                         LPCOMPOSITIONSTRING cs = NULL;
1420                         LPBYTE cdata = NULL;
1421
1422                         /* clear existing result */
1423                         newCompStr = updateResultStr(root_context->IMC.hCompStr, NULL, 0);
1424                         ImmDestroyIMCC(root_context->IMC.hCompStr);
1425                         root_context->IMC.hCompStr = newCompStr;
1426
1427                         cdata = ImmLockIMCC(root_context->IMC.hCompStr);
1428                         cs = (LPCOMPOSITIONSTRING)cdata;
1429                         cplen = cs->dwCompStrLen;
1430                         cpstr = (LPWSTR)&(cdata[cs->dwCompStrOffset]);
1431                         ImmUnlockIMCC(root_context->IMC.hCompStr);
1432                         if (cplen > 0)
1433                         {
1434                             WCHAR param = cpstr[0];
1435                             newCompStr = updateResultStr(root_context->IMC.hCompStr, cpstr, cplen);
1436                             ImmDestroyIMCC(root_context->IMC.hCompStr);
1437                             root_context->IMC.hCompStr = newCompStr;
1438                             newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1439                             ImmDestroyIMCC(root_context->IMC.hCompStr);
1440                             root_context->IMC.hCompStr = newCompStr;
1441
1442                             root_context->bRead = FALSE;
1443
1444                             ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1445                                                   GCS_COMPSTR);
1446
1447                             ImmInternalPostIMEMessage(WM_IME_COMPOSITION,
1448                                             param,
1449                                             GCS_RESULTSTR|GCS_RESULTCLAUSE);
1450                         }
1451
1452                         ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION, 0, 0);
1453                         root_context->bInComposition = FALSE;
1454                     }
1455                     break;
1456                 case CPS_CONVERT:
1457                     FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1458                     break;
1459                 case CPS_REVERT:
1460                     FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1461                     break;
1462                 default:
1463                     ERR("%s - %s (%i)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1464                     break;
1465             }
1466             break;
1467         case NI_IMEMENUSELECTED:
1468             FIXME("%s\n", "NI_IMEMENUSELECTED");
1469             break;
1470         case NI_OPENCANDIDATE:
1471             FIXME("%s\n", "NI_OPENCANDIDATE");
1472             break;
1473         case NI_SELECTCANDIDATESTR:
1474             FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1475             break;
1476         case NI_SETCANDIDATE_PAGESIZE:
1477             FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1478             break;
1479         case NI_SETCANDIDATE_PAGESTART:
1480             FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1481             break;
1482         default:
1483             ERR("Unknown\n");
1484     }
1485
1486     return rc;
1487 }
1488
1489 /***********************************************************************
1490  *              ImmRegisterWordA (IMM32.@)
1491  */
1492 BOOL WINAPI ImmRegisterWordA(
1493   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1494 {
1495   FIXME("(%p, %s, %d, %s): stub\n",
1496     hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1497   );
1498   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1499   return FALSE;
1500 }
1501
1502 /***********************************************************************
1503  *              ImmRegisterWordW (IMM32.@)
1504  */
1505 BOOL WINAPI ImmRegisterWordW(
1506   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1507 {
1508   FIXME("(%p, %s, %d, %s): stub\n",
1509     hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1510   );
1511   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1512   return FALSE;
1513 }
1514
1515 /***********************************************************************
1516  *              ImmReleaseContext (IMM32.@)
1517  */
1518 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1519 {
1520   FIXME("(%p, %p): stub\n", hWnd, hIMC);
1521
1522     return TRUE;
1523 }
1524
1525 /***********************************************************************
1526  *              ImmSetCandidateWindow (IMM32.@)
1527  */
1528 BOOL WINAPI ImmSetCandidateWindow(
1529   HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1530 {
1531   FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1532   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1533   return FALSE;
1534 }
1535
1536 /***********************************************************************
1537  *              ImmSetCompositionFontA (IMM32.@)
1538  */
1539 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1540 {
1541     InputContextData *data = (InputContextData*)hIMC;
1542     TRACE("(%p, %p)\n", hIMC, lplf);
1543
1544     if (!data)
1545         return FALSE;
1546
1547     memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1548     MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1549                         LF_FACESIZE);
1550
1551     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1552
1553     if (data->textfont)
1554     {
1555         DeleteObject(data->textfont);
1556         data->textfont = NULL;
1557     }
1558
1559     data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1560     return TRUE;
1561 }
1562
1563 /***********************************************************************
1564  *              ImmSetCompositionFontW (IMM32.@)
1565  */
1566 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1567 {
1568     InputContextData *data = (InputContextData*)hIMC;
1569     TRACE("(%p, %p)\n", hIMC, lplf);
1570
1571     if (!data)
1572         return FALSE;
1573
1574     memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTW));
1575     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONFONT, 0);
1576
1577     if (data->textfont)
1578     {
1579         DeleteObject(data->textfont);
1580         data->textfont = NULL;
1581     }
1582     data->textfont = CreateFontIndirectW(&data->IMC.lfFont.W);
1583     return TRUE;
1584 }
1585
1586 /***********************************************************************
1587  *              ImmSetCompositionStringA (IMM32.@)
1588  */
1589 BOOL WINAPI ImmSetCompositionStringA(
1590   HIMC hIMC, DWORD dwIndex,
1591   LPCVOID lpComp, DWORD dwCompLen,
1592   LPCVOID lpRead, DWORD dwReadLen)
1593 {
1594     DWORD comp_len;
1595     DWORD read_len;
1596     WCHAR *CompBuffer = NULL;
1597     WCHAR *ReadBuffer = NULL;
1598     BOOL rc;
1599
1600     TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1601             hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1602
1603     comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
1604     if (comp_len)
1605     {
1606         CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
1607         MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
1608     }
1609
1610     read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
1611     if (read_len)
1612     {
1613         ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
1614         MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
1615     }
1616
1617     rc =  ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
1618                                    ReadBuffer, read_len);
1619
1620     HeapFree(GetProcessHeap(), 0, CompBuffer);
1621     HeapFree(GetProcessHeap(), 0, ReadBuffer);
1622
1623     return rc;
1624 }
1625
1626 /***********************************************************************
1627  *              ImmSetCompositionStringW (IMM32.@)
1628  */
1629 BOOL WINAPI ImmSetCompositionStringW(
1630         HIMC hIMC, DWORD dwIndex,
1631         LPCVOID lpComp, DWORD dwCompLen,
1632         LPCVOID lpRead, DWORD dwReadLen)
1633 {
1634      DWORD flags = 0;
1635      WCHAR wParam  = 0;
1636
1637      TRACE("(%p, %d, %p, %d, %p, %d): stub\n",
1638              hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1639
1640
1641      if (hIMC != (HIMC)FROM_IME)
1642          FIXME("PROBLEM: This only sets the wine level string\n");
1643
1644      /*
1645       * Explanation:
1646       *  this sets the composition string in the imm32.dll level
1647       *  of the composition buffer. we cannot manipulate the xim level
1648       *  buffer, which means that once the xim level buffer changes again
1649       *  any call to this function from the application will be lost
1650       */
1651
1652      if (lpRead && dwReadLen)
1653          FIXME("Reading string unimplemented\n");
1654
1655      /*
1656       * app operating this api to also receive the message from xim
1657       */
1658
1659     if (dwIndex == SCS_SETSTR)
1660     {
1661         HIMCC newCompStr;
1662         if (!root_context->bInComposition)
1663         {
1664             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION, 0, 0);
1665             root_context->bInComposition = TRUE;
1666         }
1667
1668         flags = GCS_COMPSTR;
1669
1670         if (dwCompLen && lpComp)
1671         {
1672             newCompStr = updateCompStr(root_context->IMC.hCompStr, (LPWSTR)lpComp, dwCompLen / sizeof(WCHAR));
1673             ImmDestroyIMCC(root_context->IMC.hCompStr);
1674             root_context->IMC.hCompStr = newCompStr;
1675
1676              wParam = ((const WCHAR*)lpComp)[0];
1677              flags |= GCS_COMPCLAUSE | GCS_COMPATTR | GCS_DELTASTART;
1678         }
1679         else
1680         {
1681             newCompStr = updateCompStr(root_context->IMC.hCompStr, NULL, 0);
1682             ImmDestroyIMCC(root_context->IMC.hCompStr);
1683             root_context->IMC.hCompStr = newCompStr;
1684         }
1685     }
1686
1687      UpdateDataInDefaultIMEWindow(hwndDefault,FALSE);
1688
1689      ImmInternalPostIMEMessage(WM_IME_COMPOSITION, wParam, flags);
1690
1691      return TRUE;
1692 }
1693
1694 /***********************************************************************
1695  *              ImmSetCompositionWindow (IMM32.@)
1696  */
1697 BOOL WINAPI ImmSetCompositionWindow(
1698   HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1699 {
1700     BOOL reshow = FALSE;
1701     InputContextData *data = (InputContextData*)hIMC;
1702
1703     TRACE("(%p, %p)\n", hIMC, lpCompForm);
1704     TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
1705           lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
1706           lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
1707
1708     if (!data)
1709         return FALSE;
1710
1711     memcpy(&data->IMC.cfCompForm,lpCompForm,sizeof(COMPOSITIONFORM));
1712
1713     if (IsWindowVisible(hwndDefault))
1714     {
1715         reshow = TRUE;
1716         ShowWindow(hwndDefault,SW_HIDE);
1717     }
1718
1719     /* FIXME: this is a partial stub */
1720
1721     if (reshow)
1722         ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1723
1724     ImmInternalSendIMENotify(IMN_SETCOMPOSITIONWINDOW, 0);
1725     return TRUE;
1726 }
1727
1728 /***********************************************************************
1729  *              ImmSetConversionStatus (IMM32.@)
1730  */
1731 BOOL WINAPI ImmSetConversionStatus(
1732   HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1733 {
1734   FIXME("(%p, %d, %d): stub\n",
1735     hIMC, fdwConversion, fdwSentence
1736   );
1737   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1738   return FALSE;
1739 }
1740
1741 /***********************************************************************
1742  *              ImmSetOpenStatus (IMM32.@)
1743  */
1744 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
1745 {
1746     InputContextData *data = (InputContextData*)hIMC;
1747
1748     TRACE("%p %d\n", hIMC, fOpen);
1749
1750     if (hIMC == (HIMC)FROM_IME)
1751     {
1752         ImmInternalSetOpenStatus(fOpen);
1753         ImmInternalSendIMENotify(IMN_SETOPENSTATUS, 0);
1754         return TRUE;
1755     }
1756
1757     if (!data)
1758         return FALSE;
1759
1760     if (fOpen != data->bInternalState)
1761     {
1762         if (fOpen == FALSE && pX11DRV_ForceXIMReset)
1763             pX11DRV_ForceXIMReset(data->IMC.hWnd);
1764
1765         if (fOpen == FALSE)
1766             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1767         else
1768             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1769
1770         ImmInternalSetOpenStatus(fOpen);
1771         ImmInternalSetOpenStatus(!fOpen);
1772
1773         if (data->IMC.fOpen == FALSE)
1774             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1775         else
1776             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1777
1778         return FALSE;
1779     }
1780     return TRUE;
1781 }
1782
1783 /***********************************************************************
1784  *              ImmSetStatusWindowPos (IMM32.@)
1785  */
1786 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1787 {
1788   FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1789   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1790   return FALSE;
1791 }
1792
1793 /***********************************************************************
1794  *              ImmSimulateHotKey (IMM32.@)
1795  */
1796 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
1797 {
1798   FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
1799   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1800   return FALSE;
1801 }
1802
1803 /***********************************************************************
1804  *              ImmUnregisterWordA (IMM32.@)
1805  */
1806 BOOL WINAPI ImmUnregisterWordA(
1807   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
1808 {
1809   FIXME("(%p, %s, %d, %s): stub\n",
1810     hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
1811   );
1812   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1813   return FALSE;
1814 }
1815
1816 /***********************************************************************
1817  *              ImmUnregisterWordW (IMM32.@)
1818  */
1819 BOOL WINAPI ImmUnregisterWordW(
1820   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
1821 {
1822   FIXME("(%p, %s, %d, %s): stub\n",
1823     hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
1824   );
1825   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1826   return FALSE;
1827 }
1828
1829 /***********************************************************************
1830  *              ImmGetImeMenuItemsA (IMM32.@)
1831  */
1832 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1833    LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
1834     DWORD dwSize)
1835 {
1836   FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1837     lpImeParentMenu, lpImeMenu, dwSize);
1838   return 0;
1839 }
1840
1841 /***********************************************************************
1842 *               ImmGetImeMenuItemsW (IMM32.@)
1843 */
1844 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
1845    LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
1846    DWORD dwSize)
1847 {
1848   FIXME("(%p, %i, %i, %p, %p, %i): stub\n", hIMC, dwFlags, dwType,
1849     lpImeParentMenu, lpImeMenu, dwSize);
1850   return 0;
1851 }
1852
1853 /***********************************************************************
1854 *               ImmLockIMC(IMM32.@)
1855 */
1856 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
1857 {
1858     InputContextData *data = (InputContextData*)hIMC;
1859
1860     if (!data)
1861         return NULL;
1862     data->dwLock++;
1863     return &data->IMC;
1864 }
1865
1866 /***********************************************************************
1867 *               ImmUnlockIMC(IMM32.@)
1868 */
1869 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
1870 {
1871     InputContextData *data = (InputContextData*)hIMC;
1872     data->dwLock--;
1873     return (data->dwLock!=0);
1874 }
1875
1876 /***********************************************************************
1877 *               ImmGetIMCLockCount(IMM32.@)
1878 */
1879 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
1880 {
1881     InputContextData *data = (InputContextData*)hIMC;
1882     return data->dwLock;
1883 }
1884
1885 /***********************************************************************
1886 *               ImmCreateIMCC(IMM32.@)
1887 */
1888 HIMCC  WINAPI ImmCreateIMCC(DWORD size)
1889 {
1890     IMCCInternal *internal;
1891     int real_size = size + sizeof(IMCCInternal);
1892
1893     internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
1894     if (internal == NULL)
1895         return NULL;
1896
1897     internal->dwSize = size;
1898     return  (HIMCC)internal;
1899 }
1900
1901 /***********************************************************************
1902 *       ImmDestroyIMCC(IMM32.@)
1903 */
1904 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
1905 {
1906     HeapFree(GetProcessHeap(),0,block);
1907     return NULL;
1908 }
1909
1910 /***********************************************************************
1911 *               ImmLockIMCC(IMM32.@)
1912 */
1913 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
1914 {
1915     IMCCInternal *internal;
1916     internal = (IMCCInternal*) imcc;
1917
1918     internal->dwLock ++;
1919     return internal + 1;
1920 }
1921
1922 /***********************************************************************
1923 *               ImmUnlockIMCC(IMM32.@)
1924 */
1925 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
1926 {
1927     IMCCInternal *internal;
1928     internal = (IMCCInternal*) imcc;
1929
1930     internal->dwLock --;
1931     return (internal->dwLock!=0);
1932 }
1933
1934 /***********************************************************************
1935 *               ImmGetIMCCLockCount(IMM32.@)
1936 */
1937 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
1938 {
1939     IMCCInternal *internal;
1940     internal = (IMCCInternal*) imcc;
1941
1942     return internal->dwLock;
1943 }
1944
1945 /***********************************************************************
1946 *               ImmReSizeIMCC(IMM32.@)
1947 */
1948 HIMCC  WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
1949 {
1950     IMCCInternal *internal,*newone;
1951     int real_size = size + sizeof(IMCCInternal);
1952
1953     internal = (IMCCInternal*) imcc;
1954
1955     newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
1956     newone->dwSize = size;
1957
1958     return newone;
1959 }
1960
1961 /***********************************************************************
1962 *               ImmGetIMCCSize(IMM32.@)
1963 */
1964 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
1965 {
1966     IMCCInternal *internal;
1967     internal = (IMCCInternal*) imcc;
1968
1969     return internal->dwSize;
1970 }
1971
1972 /*****
1973  * Internal functions to help with IME window management
1974  */
1975 static void PaintDefaultIMEWnd(HWND hwnd)
1976 {
1977     PAINTSTRUCT ps;
1978     RECT rect;
1979     HDC hdc = BeginPaint(hwnd,&ps);
1980     LPCOMPOSITIONSTRING compstr;
1981     LPBYTE compdata = NULL;
1982     HMONITOR monitor;
1983     MONITORINFO mon_info;
1984     INT offX=0, offY=0;
1985
1986     GetClientRect(hwnd,&rect);
1987     FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
1988
1989     compdata = ImmLockIMCC(root_context->IMC.hCompStr);
1990     compstr = (LPCOMPOSITIONSTRING)compdata;
1991
1992     if (compstr->dwCompStrLen && compstr->dwCompStrOffset)
1993     {
1994         SIZE size;
1995         POINT pt;
1996         HFONT oldfont = NULL;
1997         LPWSTR CompString;
1998
1999         CompString = (LPWSTR)(compdata + compstr->dwCompStrOffset);
2000         if (root_context->textfont)
2001             oldfont = SelectObject(hdc,root_context->textfont);
2002
2003
2004         GetTextExtentPoint32W(hdc, CompString, compstr->dwCompStrLen, &size);
2005         pt.x = size.cx;
2006         pt.y = size.cy;
2007         LPtoDP(hdc,&pt,1);
2008
2009         /*
2010          * How this works based on tests on windows:
2011          * CFS_POINT: then we start our window at the point and grow it as large
2012          *    as it needs to be for the string.
2013          * CFS_RECT:  we still use the ptCurrentPos as a starting point and our
2014          *    window is only as large as we need for the string, but we do not
2015          *    grow such that our window exceeds the given rect.  Wrapping if
2016          *    needed and possible.   If our ptCurrentPos is outside of our rect
2017          *    then no window is displayed.
2018          * CFS_FORCE_POSITION: appears to behave just like CFS_POINT
2019          *    maybe becase the default MSIME does not do any IME adjusting.
2020          */
2021         if (root_context->IMC.cfCompForm.dwStyle != CFS_DEFAULT)
2022         {
2023             POINT cpt = root_context->IMC.cfCompForm.ptCurrentPos;
2024             ClientToScreen(root_context->IMC.hWnd,&cpt);
2025             rect.left = cpt.x;
2026             rect.top = cpt.y;
2027             rect.right = rect.left + pt.x;
2028             rect.bottom = rect.top + pt.y;
2029             offX=offY=10;
2030             monitor = MonitorFromPoint(cpt, MONITOR_DEFAULTTOPRIMARY);
2031         }
2032         else /* CFS_DEFAULT */
2033         {
2034             /* Windows places the default IME window in the bottom left */
2035             HWND target = root_context->IMC.hWnd;
2036             if (!target) target = GetFocus();
2037
2038             GetWindowRect(target,&rect);
2039             rect.top = rect.bottom;
2040             rect.right = rect.left + pt.x + 20;
2041             rect.bottom = rect.top + pt.y + 20;
2042             offX=offY=10;
2043             monitor = MonitorFromWindow(target, MONITOR_DEFAULTTOPRIMARY);
2044         }
2045
2046         if (root_context->IMC.cfCompForm.dwStyle == CFS_RECT)
2047         {
2048             RECT client;
2049             client =root_context->IMC.cfCompForm.rcArea;
2050             MapWindowPoints( root_context->IMC.hWnd, 0, (POINT *)&client, 2 );
2051             IntersectRect(&rect,&rect,&client);
2052             /* TODO:  Wrap the input if needed */
2053         }
2054
2055         if (root_context->IMC.cfCompForm.dwStyle == CFS_DEFAULT)
2056         {
2057             /* make sure we are on the desktop */
2058             mon_info.cbSize = sizeof(mon_info);
2059             GetMonitorInfoW(monitor, &mon_info);
2060
2061             if (rect.bottom > mon_info.rcWork.bottom)
2062             {
2063                 int shift = rect.bottom - mon_info.rcWork.bottom;
2064                 rect.top -= shift;
2065                 rect.bottom -= shift;
2066             }
2067             if (rect.left < 0)
2068             {
2069                 rect.right -= rect.left;
2070                 rect.left = 0;
2071             }
2072             if (rect.right > mon_info.rcWork.right)
2073             {
2074                 int shift = rect.right - mon_info.rcWork.right;
2075                 rect.left -= shift;
2076                 rect.right -= shift;
2077             }
2078         }
2079
2080         SetWindowPos(hwnd, HWND_TOPMOST, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE);
2081
2082         TextOutW(hdc, offX,offY, CompString, compstr->dwCompStrLen);
2083
2084         if (oldfont)
2085             SelectObject(hdc,oldfont);
2086     }
2087
2088     ImmUnlockIMCC(root_context->IMC.hCompStr);
2089
2090     EndPaint(hwnd,&ps);
2091 }
2092
2093 static void UpdateDataInDefaultIMEWindow(HWND hwnd, BOOL showable)
2094 {
2095     LPCOMPOSITIONSTRING compstr;
2096
2097     if (root_context->IMC.hCompStr)
2098         compstr = ImmLockIMCC(root_context->IMC.hCompStr);
2099     else
2100         compstr = NULL;
2101
2102     if (compstr == NULL || compstr->dwCompStrLen == 0)
2103         ShowWindow(hwndDefault,SW_HIDE);
2104     else if (showable)
2105         ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2106
2107     RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
2108
2109     if (compstr != NULL)
2110         ImmUnlockIMCC(root_context->IMC.hCompStr);
2111 }
2112
2113 /*
2114  * The window proc for the default IME window
2115  */
2116 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
2117                                           LPARAM lParam)
2118 {
2119     LRESULT rc = 0;
2120
2121     TRACE("Incoming Message 0x%x  (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
2122            (UINT)lParam);
2123
2124     switch(msg)
2125     {
2126         case WM_PAINT:
2127             PaintDefaultIMEWnd(hwnd);
2128             return FALSE;
2129
2130         case WM_NCCREATE:
2131             return TRUE;
2132
2133         case WM_CREATE:
2134             SetWindowTextA(hwnd,"Wine Ime Active");
2135             return TRUE;
2136
2137         case WM_SETFOCUS:
2138             if (wParam)
2139                 SetFocus((HWND)wParam);
2140             else
2141                 FIXME("Received focus, should never have focus\n");
2142             break;
2143         case WM_IME_COMPOSITION:
2144             TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
2145                     "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
2146                      root_context->bRead);
2147             if (lParam & GCS_RESULTSTR)
2148                     IMM_PostResult(root_context);
2149             else
2150                  UpdateDataInDefaultIMEWindow(hwnd,TRUE);
2151             break;
2152         case WM_IME_STARTCOMPOSITION:
2153             TRACE("IME message %s, 0x%x, 0x%x\n",
2154                     "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
2155             root_context->IMC.hWnd = GetFocus();
2156             ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
2157             break;
2158         case WM_IME_ENDCOMPOSITION:
2159             TRACE("IME message %s, 0x%x, 0x%x\n",
2160                     "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
2161             ShowWindow(hwndDefault,SW_HIDE);
2162             break;
2163         case WM_IME_SELECT:
2164             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
2165                 (UINT)wParam, (UINT)lParam);
2166             break;
2167         case WM_IME_CONTROL:
2168             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
2169                 (UINT)wParam, (UINT)lParam);
2170             rc = 1;
2171             break;
2172         case WM_IME_NOTIFY:
2173             TRACE("!! IME NOTIFY\n");
2174             break;
2175        default:
2176             TRACE("Non-standard message 0x%x\n",msg);
2177     }
2178     /* check the MSIME messages */
2179     if (msg == WM_MSIME_SERVICE)
2180     {
2181             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
2182                 (UINT)wParam, (UINT)lParam);
2183             rc = FALSE;
2184     }
2185     else if (msg == WM_MSIME_RECONVERTOPTIONS)
2186     {
2187             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
2188                 (UINT)wParam, (UINT)lParam);
2189     }
2190     else if (msg == WM_MSIME_MOUSE)
2191     {
2192             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
2193                 (UINT)wParam, (UINT)lParam);
2194     }
2195     else if (msg == WM_MSIME_RECONVERTREQUEST)
2196     {
2197             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
2198                 (UINT)wParam, (UINT)lParam);
2199     }
2200     else if (msg == WM_MSIME_RECONVERT)
2201     {
2202             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
2203                 (UINT)wParam, (UINT)lParam);
2204     }
2205     else if (msg == WM_MSIME_QUERYPOSITION)
2206     {
2207             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
2208                 (UINT)wParam, (UINT)lParam);
2209     }
2210     else if (msg == WM_MSIME_DOCUMENTFEED)
2211     {
2212             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
2213                 (UINT)wParam, (UINT)lParam);
2214     }
2215     /* DefWndProc if not an IME message */
2216     else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2217                       (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
2218         rc = DefWindowProcW(hwnd,msg,wParam,lParam);
2219
2220     return rc;
2221 }