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