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