Fixed some issues found by winapi_check.
[wine] / dlls / imm32 / imm.c
1 /*
2  * IMM32 library
3  *
4  * Copyright 1998 Patrik Stridvall
5  * Copyright 2002, 2003 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "winnls.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(imm);
34
35 #define FROM_IME 0xcafe1337
36
37 static void (*pX11DRV_ForceXIMReset)(HWND);
38
39 typedef struct tagInputContextData
40 {
41         LPBYTE          CompositionString;
42         LPBYTE          CompositionReadingString;
43         LPBYTE          ResultString;
44         LPBYTE          ResultReadingString;
45         DWORD           dwCompStringSize;   /* buffer size */
46         DWORD           dwCompStringLength; /* string length (in bytes) */
47         DWORD           dwCompReadStringSize;
48         DWORD           dwResultStringSize;
49         DWORD           dwResultReadStringSize;
50         HWND            hwnd;
51         BOOL            bOpen;
52         BOOL            bInternalState;
53         BOOL            bRead;
54         LOGFONTW        font;
55         HFONT           textfont;
56         COMPOSITIONFORM CompForm;
57 } InputContextData;
58
59 static InputContextData *root_context = NULL;
60 static HWND hwndDefault = NULL;
61 static HANDLE hImeInst;
62 static const WCHAR WC_IMECLASSNAME[] = {'I','M','E',0};
63
64 /* MSIME messages */
65 static UINT WM_MSIME_SERVICE;
66 static UINT WM_MSIME_RECONVERTOPTIONS;
67 static UINT WM_MSIME_MOUSE;
68 static UINT WM_MSIME_RECONVERTREQUEST;
69 static UINT WM_MSIME_RECONVERT;
70 static UINT WM_MSIME_QUERYPOSITION;
71 static UINT WM_MSIME_DOCUMENTFEED;
72
73 /*
74  * prototypes
75  */
76 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
77                                           LPARAM lParam);
78 static void UpdateDataInDefaultIMEWindow(HWND hwnd);
79 static void ImmInternalPostIMEMessage(UINT, WPARAM, LPARAM);
80 static void ImmInternalSetOpenStatus(BOOL fOpen);
81
82 static VOID IMM_PostResult(InputContextData *data)
83 {
84     int i;
85     TRACE("Posting result as IME_CHAR\n");
86
87     for (i = 0; i < data->dwResultStringSize / sizeof (WCHAR); i++)
88         ImmInternalPostIMEMessage (WM_IME_CHAR, ((WCHAR*)data->ResultString)[i],
89                      1);
90
91     /* clear the buffer */
92     if (data->dwResultStringSize)
93         HeapFree(GetProcessHeap(),0,data->ResultString);
94     data->dwResultStringSize = 0;
95     data->ResultString = NULL;
96 }
97
98 static void IMM_Register(void)
99 {
100     WNDCLASSW wndClass;
101     ZeroMemory(&wndClass, sizeof(WNDCLASSW));
102     wndClass.style = CS_GLOBALCLASS | CS_IME | CS_HREDRAW | CS_VREDRAW;
103     wndClass.lpfnWndProc = (WNDPROC) IME_WindowProc;
104     wndClass.cbClsExtra = 0;
105     wndClass.cbWndExtra = 0;
106     wndClass.hInstance = hImeInst;
107     wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
108     wndClass.hIcon = NULL;
109     wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW +1);
110     wndClass.lpszMenuName   = 0;
111     wndClass.lpszClassName = WC_IMECLASSNAME;
112     RegisterClassW(&wndClass);
113 }
114
115 static void IMM_Unregister(void)
116 {
117     UnregisterClassW(WC_IMECLASSNAME, NULL);
118 }
119
120 static void IMM_RegisterMessages(void)
121 {
122     WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
123     WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
124     WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
125     WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
126     WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
127     WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
128     WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
129 }
130
131
132 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
133 {
134     HMODULE x11drv;
135
136     TRACE("%p, %lx, %p\n",hInstDLL,fdwReason,lpReserved);
137     switch (fdwReason)
138     {
139         case DLL_PROCESS_ATTACH:
140             DisableThreadLibraryCalls(hInstDLL);
141             hImeInst = hInstDLL;
142             IMM_RegisterMessages();
143             x11drv = GetModuleHandleA("x11drv.dll");
144             if (x11drv) pX11DRV_ForceXIMReset = (void *)GetProcAddress( x11drv, "ForceXIMReset");
145             break;
146         case DLL_PROCESS_DETACH:
147             if (hwndDefault)
148             {
149                 DestroyWindow(hwndDefault);
150                 hwndDefault = 0;
151             }
152             IMM_Unregister();
153             break;
154     }
155     return TRUE;
156 }
157
158 /* for posting messages as the IME */
159 static void ImmInternalPostIMEMessage(UINT msg, WPARAM wParam, LPARAM lParam)
160 {
161     HWND target = GetFocus();
162     if (!target)
163        PostMessageW(root_context->hwnd,msg,wParam,lParam);
164     else 
165        PostMessageW(target, msg, wParam, lParam);
166 }
167
168
169 static void ImmInternalSetOpenStatus(BOOL fOpen)
170 {
171     TRACE("Setting internal state to %s\n",(fOpen)?"OPEN":"CLOSED");
172
173    root_context->bOpen = fOpen;
174    root_context->bInternalState = fOpen;
175
176    if (fOpen == FALSE)
177    {
178         ShowWindow(hwndDefault,SW_HIDE);
179
180         if (root_context->dwCompStringSize)
181             HeapFree(GetProcessHeap(),0,root_context->CompositionString);
182         if (root_context->dwCompReadStringSize)
183             HeapFree(GetProcessHeap(),0,root_context->CompositionReadingString);
184         if (root_context->dwResultStringSize)
185             HeapFree(GetProcessHeap(),0,root_context->ResultString);
186         if (root_context->dwResultReadStringSize)
187             HeapFree(GetProcessHeap(),0,root_context->ResultReadingString);
188         root_context->dwCompStringSize = 0;
189         root_context->dwCompStringLength = 0;
190         root_context->CompositionString = NULL;
191         root_context->dwCompReadStringSize = 0;
192         root_context->CompositionReadingString = NULL;
193         root_context->dwResultStringSize = 0;
194         root_context->ResultString = NULL;
195         root_context->dwResultReadStringSize = 0;
196         root_context->ResultReadingString = NULL;
197     }
198     else
199         ShowWindow(hwndDefault, SW_SHOWNOACTIVATE);
200
201    SendMessageW(root_context->hwnd, WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0);
202 }
203
204
205 /***********************************************************************
206  *              ImmAssociateContext (IMM32.@)
207  */
208 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
209 {
210     InputContextData *data = (InputContextData*)hIMC;
211
212     WARN("(%p, %p): semi-stub\n",hWnd,hIMC);
213
214     if (!data)
215         return FALSE;
216
217     /*
218      * WINE SPECIFIC! MAY CONFLICT
219      * associate the root context we have an XIM created
220      */
221     if (hWnd == 0x000)
222     {
223         root_context = (InputContextData*)hIMC;
224     }
225
226     /*
227      * If already associated just return
228      */
229     if (data->hwnd == hWnd)
230         return (HIMC)data;
231
232     if (IsWindow(data->hwnd))
233     {
234         /*
235          * Post a message that your context is switching
236          */
237         SendMessageW(data->hwnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
238     }
239
240     data->hwnd = hWnd;
241
242     if (IsWindow(data->hwnd))
243     {
244         /*
245          * Post a message that your context is switching
246          */
247         SendMessageW(data->hwnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
248     }
249
250     /*
251      * TODO: We need to keep track of the old context associated
252      * with a window and return it for now we will return NULL;
253      */
254     return (HIMC)NULL;
255 }
256
257 /***********************************************************************
258  *              ImmConfigureIMEA (IMM32.@)
259  */
260 BOOL WINAPI ImmConfigureIMEA(
261   HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
262 {
263   FIXME("(%p, %p, %ld, %p): stub\n",
264     hKL, hWnd, dwMode, lpData
265   );
266   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
267   return FALSE;
268 }
269
270 /***********************************************************************
271  *              ImmConfigureIMEW (IMM32.@)
272  */
273 BOOL WINAPI ImmConfigureIMEW(
274   HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
275 {
276   FIXME("(%p, %p, %ld, %p): stub\n",
277     hKL, hWnd, dwMode, lpData
278   );
279   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
280   return FALSE;
281 }
282
283 /***********************************************************************
284  *              ImmCreateContext (IMM32.@)
285  */
286 HIMC WINAPI ImmCreateContext(void)
287 {
288     InputContextData *new_context;
289
290     new_context = HeapAlloc(GetProcessHeap(),0,sizeof(InputContextData));
291     ZeroMemory(new_context,sizeof(InputContextData));
292
293     return (HIMC)new_context;
294 }
295
296 /***********************************************************************
297  *              ImmDestroyContext (IMM32.@)
298  */
299 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
300 {
301     InputContextData *data = (InputContextData*)hIMC;
302
303     TRACE("Destroying %p\n",hIMC);
304
305     if (hIMC)
306     {
307         if (data->dwCompStringSize)
308             HeapFree(GetProcessHeap(),0,data->CompositionString);
309         if (data->dwCompReadStringSize)
310             HeapFree(GetProcessHeap(),0,data->CompositionReadingString);
311         if (data->dwResultStringSize)
312             HeapFree(GetProcessHeap(),0,data->ResultString);
313         if (data->dwResultReadStringSize)
314             HeapFree(GetProcessHeap(),0,data->ResultReadingString);
315
316         if (data->textfont)
317         {
318             DeleteObject(data->textfont);
319             data->textfont = NULL;
320         }
321
322         HeapFree(GetProcessHeap(),0,data);
323     }
324     return TRUE;
325 }
326
327 /***********************************************************************
328  *              ImmDisableIME (IMM32.@)
329  */
330 BOOL WINAPI ImmDisableIME(DWORD idThread)
331 {
332     FIXME("(%ld): stub\n", idThread);
333     return TRUE;
334 }
335
336 /***********************************************************************
337  *              ImmEnumRegisterWordA (IMM32.@)
338  */
339 UINT WINAPI ImmEnumRegisterWordA(
340   HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
341   LPCSTR lpszReading, DWORD dwStyle,
342   LPCSTR lpszRegister, LPVOID lpData)
343 {
344   FIXME("(%p, %p, %s, %ld, %s, %p): stub\n",
345     hKL, lpfnEnumProc,
346     debugstr_a(lpszReading), dwStyle,
347     debugstr_a(lpszRegister), lpData
348   );
349   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
350   return 0;
351 }
352
353 /***********************************************************************
354  *              ImmEnumRegisterWordW (IMM32.@)
355  */
356 UINT WINAPI ImmEnumRegisterWordW(
357   HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
358   LPCWSTR lpszReading, DWORD dwStyle,
359   LPCWSTR lpszRegister, LPVOID lpData)
360 {
361   FIXME("(%p, %p, %s, %ld, %s, %p): stub\n",
362     hKL, lpfnEnumProc,
363     debugstr_w(lpszReading), dwStyle,
364     debugstr_w(lpszRegister), lpData
365   );
366   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
367   return 0;
368 }
369
370 /***********************************************************************
371  *              ImmEscapeA (IMM32.@)
372  */
373 LRESULT WINAPI ImmEscapeA(
374   HKL hKL, HIMC hIMC,
375   UINT uEscape, LPVOID lpData)
376 {
377   FIXME("(%p, %p, %d, %p): stub\n",
378     hKL, hIMC, uEscape, lpData
379   );
380   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
381   return 0;
382 }
383
384 /***********************************************************************
385  *              ImmEscapeW (IMM32.@)
386  */
387 LRESULT WINAPI ImmEscapeW(
388   HKL hKL, HIMC hIMC,
389   UINT uEscape, LPVOID lpData)
390 {
391   FIXME("(%p, %p, %d, %p): stub\n",
392     hKL, hIMC, uEscape, lpData
393   );
394   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
395   return 0;
396 }
397
398 /***********************************************************************
399  *              ImmGetCandidateListA (IMM32.@)
400  */
401 DWORD WINAPI ImmGetCandidateListA(
402   HIMC hIMC, DWORD deIndex,
403   LPCANDIDATELIST lpCandList, DWORD dwBufLen)
404 {
405   FIXME("(%p, %ld, %p, %ld): stub\n",
406     hIMC, deIndex,
407     lpCandList, dwBufLen
408   );
409   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
410   return 0;
411 }
412
413 /***********************************************************************
414  *              ImmGetCandidateListCountA (IMM32.@)
415  */
416 DWORD WINAPI ImmGetCandidateListCountA(
417   HIMC hIMC, LPDWORD lpdwListCount)
418 {
419   FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
420   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
421   return 0;
422 }
423
424 /***********************************************************************
425  *              ImmGetCandidateListCountW (IMM32.@)
426  */
427 DWORD WINAPI ImmGetCandidateListCountW(
428   HIMC hIMC, LPDWORD lpdwListCount)
429 {
430   FIXME("(%p, %p): stub\n", hIMC, lpdwListCount);
431   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
432   return 0;
433 }
434
435 /***********************************************************************
436  *              ImmGetCandidateListW (IMM32.@)
437  */
438 DWORD WINAPI ImmGetCandidateListW(
439   HIMC hIMC, DWORD deIndex,
440   LPCANDIDATELIST lpCandList, DWORD dwBufLen)
441 {
442   FIXME("(%p, %ld, %p, %ld): stub\n",
443     hIMC, deIndex,
444     lpCandList, dwBufLen
445   );
446   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
447   return 0;
448 }
449
450 /***********************************************************************
451  *              ImmGetCandidateWindow (IMM32.@)
452  */
453 BOOL WINAPI ImmGetCandidateWindow(
454   HIMC hIMC, DWORD dwBufLen, LPCANDIDATEFORM lpCandidate)
455 {
456   FIXME("(%p, %ld, %p): stub\n", hIMC, dwBufLen, lpCandidate);
457   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
458   return FALSE;
459 }
460
461 /***********************************************************************
462  *              ImmGetCompositionFontA (IMM32.@)
463  */
464 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
465 {
466   FIXME("(%p, %p): stub\n", hIMC, lplf);
467   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
468   return FALSE;
469 }
470
471 /***********************************************************************
472  *              ImmGetCompositionFontW (IMM32.@)
473  */
474 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
475 {
476   FIXME("(%p, %p): stub\n", hIMC, lplf);
477   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
478   return FALSE;
479 }
480
481 /***********************************************************************
482  *              ImmGetCompositionStringA (IMM32.@)
483  */
484 LONG WINAPI ImmGetCompositionStringA(
485   HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
486 {
487     CHAR *buf;
488     LONG rc = 0;
489     InputContextData *data = (InputContextData*)hIMC;
490
491     TRACE("(%p, 0x%lx, %p, %ld)\n", hIMC, dwIndex, lpBuf, dwBufLen);
492
493     if (!data)
494        return FALSE;
495
496     if (dwIndex == GCS_RESULTSTR)
497     {
498         TRACE("GSC_RESULTSTR %p %li\n",data->ResultString,
499                                     data->dwResultStringSize);
500
501         buf = HeapAlloc( GetProcessHeap(), 0, data->dwResultStringSize * 3 );
502         rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)data->ResultString,
503                                  data->dwResultStringSize / sizeof(WCHAR), buf,
504                                  data->dwResultStringSize * 3, NULL, NULL);
505         if (dwBufLen >= rc)
506             memcpy(lpBuf,buf,rc);
507
508         data->bRead = TRUE;
509         HeapFree( GetProcessHeap(), 0, buf );
510     }
511     else if (dwIndex == GCS_COMPSTR)
512     {
513          TRACE("GSC_COMPSTR %p %li\n",data->CompositionString,
514                                      data->dwCompStringLength/ sizeof(WCHAR));
515
516         buf = HeapAlloc( GetProcessHeap(), 0, data->dwCompStringLength * 3 );
517         rc = WideCharToMultiByte(CP_ACP, 0,(LPWSTR)data->CompositionString,
518                                  data->dwCompStringLength/ sizeof(WCHAR), buf,
519                                  data->dwCompStringLength* 3, NULL, NULL);
520         if (dwBufLen >= rc)
521             memcpy(lpBuf,buf,rc);
522         HeapFree( GetProcessHeap(), 0, buf );
523     }
524     else if (dwIndex == GCS_COMPATTR)
525     {
526         TRACE("GSC_COMPATTR %p %li\n",data->CompositionString,
527                                     data->dwCompStringLength/ sizeof(WCHAR));
528
529         rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)data->CompositionString,
530                                  data->dwCompStringLength/ sizeof(WCHAR), NULL,
531                                  0, NULL, NULL);
532  
533         if (dwBufLen >= rc)
534         {
535             int i=0;
536             for (i = 0;  i < rc; i++)
537                 ((LPBYTE)lpBuf)[i] = ATTR_INPUT;
538     }
539     }
540     else if (dwIndex == GCS_COMPCLAUSE)
541     {
542         TRACE("GSC_COMPCLAUSE %p %li\n",data->CompositionString,
543                                     data->dwCompStringLength/ sizeof(WCHAR));
544  
545         rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)data->CompositionString,
546                                  data->dwCompStringLength/ sizeof(WCHAR), NULL,
547                                  0, NULL, NULL);
548
549         if (dwBufLen >= sizeof(DWORD)*2)
550         {
551             ((LPDWORD)lpBuf)[0] = 0;
552             ((LPDWORD)lpBuf)[1] = rc;
553         }
554         rc = sizeof(DWORD)*2;
555     }
556     else
557     {
558         FIXME("Unhandled index 0x%lx\n",dwIndex);
559     }
560
561     return rc;
562 }
563
564 /***********************************************************************
565  *              ImmGetCompositionStringW (IMM32.@)
566  */
567 LONG WINAPI ImmGetCompositionStringW(
568   HIMC hIMC, DWORD dwIndex,
569   LPVOID lpBuf, DWORD dwBufLen)
570 {
571   LONG rc = 0;
572   InputContextData *data = (InputContextData*)hIMC;
573
574   TRACE("(%p, 0x%lx, %p, %ld)\n",
575     hIMC, dwIndex, lpBuf, dwBufLen
576   );
577
578     if (!data)
579        return FALSE;
580
581     if (dwIndex == GCS_RESULTSTR)
582     {
583         data->bRead = TRUE;
584
585         if (dwBufLen >= data->dwResultStringSize)
586             memcpy(lpBuf,data->ResultString,data->dwResultStringSize);
587         
588         rc =  data->dwResultStringSize;
589     }
590     else if (dwIndex == GCS_RESULTREADSTR)
591     {
592         if (dwBufLen >= data->dwResultReadStringSize)
593             memcpy(lpBuf,data->ResultReadingString,
594                     data->dwResultReadStringSize);
595         
596         rc = data->dwResultReadStringSize;
597     }   
598     else if (dwIndex == GCS_COMPSTR)
599     {
600         if (dwBufLen >= data->dwCompStringLength)
601             memcpy(lpBuf,data->CompositionString,data->dwCompStringLength);
602
603         rc = data->dwCompStringLength;
604     }
605     else if (dwIndex == GCS_COMPATTR)
606     {
607         int len = data->dwCompStringLength;
608         
609         if (dwBufLen >= len)
610         {
611             int i=0;
612             for (i = 0;  i < len; i++)
613                 ((LPBYTE)lpBuf)[i] = ATTR_INPUT;
614         }
615
616         rc = len;
617     }
618     else if (dwIndex == GCS_COMPCLAUSE)
619     {
620         if (dwBufLen >= sizeof(DWORD)*2)
621         {
622             ((LPDWORD)lpBuf)[0] = 0;
623             ((LPDWORD)lpBuf)[1] = data->dwCompStringLength/sizeof(WCHAR);
624         }
625         rc = sizeof(DWORD)*2;
626     }
627     else if (dwIndex == GCS_COMPREADSTR)
628     {
629         if (dwBufLen >= data->dwCompReadStringSize)
630             memcpy(lpBuf,data->CompositionReadingString,
631                     data->dwCompReadStringSize);
632         
633         rc = data->dwCompReadStringSize;
634     }   
635     else
636     {
637         FIXME("Unhandled index 0x%lx\n",dwIndex);
638     }   
639
640     return rc;
641 }
642
643 /***********************************************************************
644  *              ImmGetCompositionWindow (IMM32.@)
645  */
646 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
647 {
648     InputContextData *data = (InputContextData*)hIMC;
649
650     TRACE("(%p, %p)\n", hIMC, lpCompForm);
651
652     if (!data)
653         return FALSE;
654
655     memcpy(lpCompForm,&(data->CompForm),sizeof(COMPOSITIONFORM));
656     return 1;
657 }
658
659 /***********************************************************************
660  *              ImmGetContext (IMM32.@)
661  *
662  */
663 HIMC WINAPI ImmGetContext(HWND hWnd)
664 {
665     FIXME("(%p): stub\n", hWnd);
666
667     if (!root_context)
668         return NULL;
669
670     root_context->hwnd = hWnd;
671     return (HIMC)root_context;
672 }
673
674 /***********************************************************************
675  *              ImmGetConversionListA (IMM32.@)
676  */
677 DWORD WINAPI ImmGetConversionListA(
678   HKL hKL, HIMC hIMC,
679   LPCSTR pSrc, LPCANDIDATELIST lpDst,
680   DWORD dwBufLen, UINT uFlag)
681 {
682   FIXME("(%p, %p, %s, %p, %ld, %d): stub\n",
683     hKL, hIMC, debugstr_a(pSrc), lpDst, dwBufLen, uFlag
684   );
685   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
686   return 0;
687 }
688
689 /***********************************************************************
690  *              ImmGetConversionListW (IMM32.@)
691  */
692 DWORD WINAPI ImmGetConversionListW(
693   HKL hKL, HIMC hIMC,
694   LPCWSTR pSrc, LPCANDIDATELIST lpDst,
695   DWORD dwBufLen, UINT uFlag)
696 {
697   FIXME("(%p, %p, %s, %p, %ld, %d): stub\n",
698     hKL, hIMC, debugstr_w(pSrc), lpDst, dwBufLen, uFlag
699   );
700   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
701   return 0;
702 }
703
704 /***********************************************************************
705  *              ImmGetConversionStatus (IMM32.@)
706  */
707 BOOL WINAPI ImmGetConversionStatus(
708   HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
709 {
710     TRACE("(%p, %p, %p): best guess\n", hIMC, lpfdwConversion, lpfdwSentence);
711     if (lpfdwConversion)
712         *lpfdwConversion = IME_CMODE_NATIVE;
713     if (lpfdwSentence)
714         *lpfdwSentence = IME_SMODE_NONE;
715     return TRUE;
716 }
717
718 /***********************************************************************
719  *              ImmGetDefaultIMEWnd (IMM32.@)
720  */
721 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
722 {
723   FIXME("(%p - %p %p ): semi-stub\n", hWnd,hwndDefault, root_context);
724
725   if (hwndDefault == NULL)
726   {
727         static const WCHAR the_name[] = {'I','M','E','\0'};
728
729         IMM_Register();
730         hwndDefault = CreateWindowExW( WS_EX_CLIENTEDGE, WC_IMECLASSNAME,
731                 the_name, WS_POPUPWINDOW|WS_CAPTION, 0, 0, 120, 55, 0, 0,
732                 hImeInst, 0);
733
734         TRACE("Default created (0x%x)\n",(INT)hwndDefault);
735   }
736
737   return (HWND)hwndDefault;
738 }
739
740 /***********************************************************************
741  *              ImmGetDescriptionA (IMM32.@)
742  */
743 UINT WINAPI ImmGetDescriptionA(
744   HKL hKL, LPSTR lpszDescription, UINT uBufLen)
745 {
746   WCHAR *buf;
747   DWORD len;
748
749   TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
750
751   /* find out how many characters in the unicode buffer */
752   len = ImmGetDescriptionW( hKL, NULL, 0 );
753
754   /* allocate a buffer of that size */
755   buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
756   if( !buf )
757   return 0;
758
759   /* fetch the unicode buffer */
760   len = ImmGetDescriptionW( hKL, buf, len + 1 );
761
762   /* convert it back to ASCII */
763   len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
764                              lpszDescription, uBufLen, NULL, NULL );
765
766   HeapFree( GetProcessHeap(), 0, buf );
767
768   return len;
769 }
770
771 /***********************************************************************
772  *              ImmGetDescriptionW (IMM32.@)
773  */
774 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
775 {
776   static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
777
778   FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
779
780   if (!uBufLen) return lstrlenW( name );
781   lstrcpynW( lpszDescription, name, uBufLen );
782   return lstrlenW( lpszDescription );
783 }
784
785 /***********************************************************************
786  *              ImmGetGuideLineA (IMM32.@)
787  */
788 DWORD WINAPI ImmGetGuideLineA(
789   HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
790 {
791   FIXME("(%p, %ld, %s, %ld): stub\n",
792     hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
793   );
794   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
795   return 0;
796 }
797
798 /***********************************************************************
799  *              ImmGetGuideLineW (IMM32.@)
800  */
801 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
802 {
803   FIXME("(%p, %ld, %s, %ld): stub\n",
804     hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
805   );
806   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
807   return 0;
808 }
809
810 /***********************************************************************
811  *              ImmGetIMEFileNameA (IMM32.@)
812  */
813 UINT WINAPI ImmGetIMEFileNameA(
814   HKL hKL, LPSTR lpszFileName, UINT uBufLen)
815 {
816   FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
817   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
818   return 0;
819 }
820
821 /***********************************************************************
822  *              ImmGetIMEFileNameW (IMM32.@)
823  */
824 UINT WINAPI ImmGetIMEFileNameW(
825   HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
826 {
827   FIXME("(%p, %p, %d): stub\n", hKL, lpszFileName, uBufLen);
828   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
829   return 0;
830 }
831
832 /***********************************************************************
833  *              ImmGetOpenStatus (IMM32.@)
834  */
835 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
836 {
837   InputContextData *data = (InputContextData*)hIMC;
838
839     if (!data)
840         return FALSE;
841   FIXME("(%p): semi-stub\n", hIMC);
842
843   return data->bOpen;
844 }
845
846 /***********************************************************************
847  *              ImmGetProperty (IMM32.@)
848  */
849 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
850 {
851     DWORD rc = 0;
852     TRACE("(%p, %ld)\n", hKL, fdwIndex);
853
854     switch (fdwIndex)
855     {
856         case IGP_PROPERTY:
857             TRACE("(%s)\n", "IGP_PROPERTY");
858             rc = IME_PROP_UNICODE | IME_PROP_AT_CARET;
859             break;
860         case IGP_CONVERSION:
861             FIXME("(%s)\n", "IGP_CONVERSION");
862             rc = IME_CMODE_NATIVE;
863             break;
864         case IGP_SENTENCE:
865             FIXME("%s)\n", "IGP_SENTENCE");
866             rc = IME_SMODE_AUTOMATIC;
867             break;
868         case IGP_SETCOMPSTR:
869             TRACE("(%s)\n", "IGP_SETCOMPSTR");
870             rc = 0;
871             break;
872         case IGP_SELECT:
873             TRACE("(%s)\n", "IGP_SELECT");
874             rc = SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE;
875             break;
876         case IGP_GETIMEVERSION:
877             TRACE("(%s)\n", "IGP_GETIMEVERSION");
878             rc = IMEVER_0400;
879             break;
880         case IGP_UI:
881             TRACE("(%s)\n", "IGP_UI");
882             rc = 0;
883             break;
884         default:
885             rc = 0;
886     }
887     return rc;
888 }
889
890 /***********************************************************************
891  *              ImmGetRegisterWordStyleA (IMM32.@)
892  */
893 UINT WINAPI ImmGetRegisterWordStyleA(
894   HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
895 {
896   FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
897   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
898   return 0;
899 }
900
901 /***********************************************************************
902  *              ImmGetRegisterWordStyleW (IMM32.@)
903  */
904 UINT WINAPI ImmGetRegisterWordStyleW(
905   HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
906 {
907   FIXME("(%p, %d, %p): stub\n", hKL, nItem, lpStyleBuf);
908   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
909   return 0;
910 }
911
912 /***********************************************************************
913  *              ImmGetStatusWindowPos (IMM32.@)
914  */
915 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
916 {
917   FIXME("(%p, %p): stub\n", hIMC, lpptPos);
918   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
919   return FALSE;
920 }
921
922 /***********************************************************************
923  *              ImmGetVirtualKey (IMM32.@)
924  */
925 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
926 {
927   OSVERSIONINFOA version;
928   FIXME("(%p): stub\n", hWnd);
929   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
930   GetVersionExA( &version );
931   switch(version.dwPlatformId)
932   {
933   case VER_PLATFORM_WIN32_WINDOWS:
934       return VK_PROCESSKEY;
935   case VER_PLATFORM_WIN32_NT:
936       return 0;
937   default:
938       FIXME("%ld not supported\n",version.dwPlatformId);
939       return VK_PROCESSKEY;
940   }
941 }
942
943 /***********************************************************************
944  *              ImmInstallIMEA (IMM32.@)
945  */
946 HKL WINAPI ImmInstallIMEA(
947   LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
948 {
949   FIXME("(%s, %s): stub\n",
950     debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
951   );
952   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
953   return NULL;
954 }
955
956 /***********************************************************************
957  *              ImmInstallIMEW (IMM32.@)
958  */
959 HKL WINAPI ImmInstallIMEW(
960   LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
961 {
962   FIXME("(%s, %s): stub\n",
963     debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
964   );
965   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
966   return NULL;
967 }
968
969 /***********************************************************************
970  *              ImmIsIME (IMM32.@)
971  */
972 BOOL WINAPI ImmIsIME(HKL hKL)
973 {
974   FIXME("(%p): semi-stub\n", hKL);
975   /*
976    * Dead key locales will return TRUE here when they should not
977    * There is probibly a more proper way to check this.
978    */
979   return (root_context != NULL);
980 }
981
982 /***********************************************************************
983  *              ImmIsUIMessageA (IMM32.@)
984  */
985 BOOL WINAPI ImmIsUIMessageA(
986   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
987 {
988     BOOL rc = FALSE;
989
990     TRACE("(%p, %x, %d, %ld)\n", hWndIME, msg, wParam, lParam);
991     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
992         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
993         (msg == WM_MSIME_SERVICE) ||
994         (msg == WM_MSIME_RECONVERTOPTIONS) ||
995         (msg == WM_MSIME_MOUSE) ||
996         (msg == WM_MSIME_RECONVERTREQUEST) ||
997         (msg == WM_MSIME_RECONVERT) ||
998         (msg == WM_MSIME_QUERYPOSITION) ||
999         (msg == WM_MSIME_DOCUMENTFEED))
1000
1001     {
1002         if (!hwndDefault)
1003             ImmGetDefaultIMEWnd(NULL);
1004
1005         if (hWndIME == NULL)
1006             PostMessageA(hwndDefault, msg, wParam, lParam);
1007
1008         rc = TRUE;
1009     }
1010     return rc;
1011 }
1012
1013 /***********************************************************************
1014  *              ImmIsUIMessageW (IMM32.@)
1015  */
1016 BOOL WINAPI ImmIsUIMessageW(
1017   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1018 {
1019     BOOL rc = FALSE;
1020     TRACE("(%p, %d, %d, %ld): stub\n", hWndIME, msg, wParam, lParam);
1021     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1022         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1023         (msg == WM_MSIME_SERVICE) ||
1024         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1025         (msg == WM_MSIME_MOUSE) ||
1026         (msg == WM_MSIME_RECONVERTREQUEST) ||
1027         (msg == WM_MSIME_RECONVERT) ||
1028         (msg == WM_MSIME_QUERYPOSITION) ||
1029         (msg == WM_MSIME_DOCUMENTFEED))
1030         rc = TRUE;
1031     return rc;
1032 }
1033
1034 /***********************************************************************
1035  *              ImmNotifyIME (IMM32.@)
1036  */
1037 BOOL WINAPI ImmNotifyIME(
1038   HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1039 {
1040     BOOL rc = FALSE;
1041   FIXME("(%p, %ld, %ld, %ld): stub\n",
1042         hIMC, dwAction, dwIndex, dwValue);
1043
1044     switch(dwAction)
1045     {
1046         case NI_CHANGECANDIDATELIST:
1047             FIXME("%s\n","NI_CHANGECANDIDATELIST");
1048             break;
1049         case NI_CLOSECANDIDATE:
1050             FIXME("%s\n","NI_CLOSECANDIDATE");
1051             break;
1052         case NI_COMPOSITIONSTR:
1053             switch (dwIndex)
1054             {
1055                 case CPS_CANCEL:
1056                     TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_CANCEL");
1057                     if (pX11DRV_ForceXIMReset)
1058                         pX11DRV_ForceXIMReset(root_context->hwnd);
1059                     if (root_context->dwCompStringSize)
1060                     {
1061                         HeapFree(GetProcessHeap(),0,
1062                                  root_context->CompositionString);
1063                         root_context->dwCompStringSize = 0;
1064                         root_context->dwCompStringLength = 0;
1065                         root_context->CompositionString = NULL;
1066                         ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1067                                                   GCS_COMPSTR);
1068                     }
1069                     rc = TRUE;
1070                     break;
1071                 case CPS_COMPLETE:
1072                     TRACE("%s - %s\n","NI_COMPOSITIONSTR","CPS_COMPLETE");
1073                     if (hIMC != (HIMC)FROM_IME && pX11DRV_ForceXIMReset)
1074                         pX11DRV_ForceXIMReset(root_context->hwnd);
1075
1076                     if (root_context->dwResultStringSize)
1077                     {
1078                         HeapFree(GetProcessHeap(),0,root_context->ResultString);
1079                         root_context->dwResultStringSize = 0;
1080                         root_context->ResultString = NULL;
1081                     }
1082                     if (root_context->dwCompStringLength)
1083                     {
1084                         root_context->ResultString = HeapAlloc(
1085                         GetProcessHeap(), 0, root_context->dwCompStringLength);
1086                         root_context->dwResultStringSize =
1087                                         root_context->dwCompStringLength;
1088
1089                         memcpy(root_context->ResultString,
1090                                root_context->CompositionString,
1091                                root_context->dwCompStringLength);
1092
1093                         HeapFree(GetProcessHeap(),0,
1094                                  root_context->CompositionString);
1095
1096                         root_context->dwCompStringSize = 0;
1097                         root_context->dwCompStringLength = 0;
1098                         root_context->CompositionString = NULL;
1099                         root_context->bRead = FALSE;
1100
1101                         ImmInternalPostIMEMessage(WM_IME_COMPOSITION, 0,
1102                                                   GCS_COMPSTR);
1103
1104                         ImmInternalPostIMEMessage(WM_IME_COMPOSITION,
1105                                             root_context->ResultString[0],
1106                                             GCS_RESULTSTR|GCS_RESULTCLAUSE);
1107                     }
1108                     break;
1109                 case CPS_CONVERT:
1110                     FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_CONVERT");
1111                     break;
1112                 case CPS_REVERT:
1113                     FIXME("%s - %s\n","NI_COMPOSITIONSTR","CPS_REVERT");
1114                     break;
1115                 default:
1116                     ERR("%s - %s (%li)\n","NI_COMPOSITIONSTR","UNKNOWN",dwIndex);
1117                     break;
1118             }
1119             break;
1120         case NI_IMEMENUSELECTED:
1121             FIXME("%s\n", "NI_IMEMENUSELECTED");
1122             break;
1123         case NI_OPENCANDIDATE:
1124             FIXME("%s\n", "NI_OPENCANDIDATE");
1125             break;
1126         case NI_SELECTCANDIDATESTR:
1127             FIXME("%s\n", "NI_SELECTCANDIDATESTR");
1128             break;
1129         case NI_SETCANDIDATE_PAGESIZE:
1130             FIXME("%s\n", "NI_SETCANDIDATE_PAGESIZE");
1131             break;
1132         case NI_SETCANDIDATE_PAGESTART:
1133             FIXME("%s\n", "NI_SETCANDIDATE_PAGESTART");
1134             break;
1135         default:
1136             ERR("Unknown\n");
1137     }
1138   
1139     return rc;
1140 }
1141
1142 /***********************************************************************
1143  *              ImmRegisterWordA (IMM32.@)
1144  */
1145 BOOL WINAPI ImmRegisterWordA(
1146   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1147 {
1148   FIXME("(%p, %s, %ld, %s): stub\n",
1149     hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister)
1150   );
1151   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1152   return FALSE;
1153 }
1154
1155 /***********************************************************************
1156  *              ImmRegisterWordW (IMM32.@)
1157  */
1158 BOOL WINAPI ImmRegisterWordW(
1159   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1160 {
1161   FIXME("(%p, %s, %ld, %s): stub\n",
1162     hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister)
1163   );
1164   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1165   return FALSE;
1166 }
1167
1168 /***********************************************************************
1169  *              ImmReleaseContext (IMM32.@)
1170  */
1171 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1172 {
1173   FIXME("(%p, %p): stub\n", hWnd, hIMC);
1174
1175     return TRUE;
1176 }
1177
1178 /***********************************************************************
1179  *              ImmSetCandidateWindow (IMM32.@)
1180  */
1181 BOOL WINAPI ImmSetCandidateWindow(
1182   HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1183 {
1184   FIXME("(%p, %p): stub\n", hIMC, lpCandidate);
1185   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1186   return FALSE;
1187 }
1188
1189 /***********************************************************************
1190  *              ImmSetCompositionFontA (IMM32.@)
1191  */
1192 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1193 {
1194     InputContextData *data = (InputContextData*)hIMC;
1195     TRACE("(%p, %p)\n", hIMC, lplf);
1196
1197     if (!data)
1198         return FALSE;
1199
1200     memcpy(&data->font,lplf,sizeof(LOGFONTA));
1201     MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->font.lfFaceName,
1202                         LF_FACESIZE);
1203
1204     SendMessageW(root_context->hwnd, WM_IME_NOTIFY, IMN_SETCOMPOSITIONFONT, 0);
1205
1206     if (data->textfont)
1207     {
1208         DeleteObject(data->textfont);
1209         data->textfont = NULL;
1210     }
1211
1212     data->textfont = CreateFontIndirectW(&data->font); 
1213     return TRUE;
1214 }
1215
1216 /***********************************************************************
1217  *              ImmSetCompositionFontW (IMM32.@)
1218  */
1219 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1220 {
1221     InputContextData *data = (InputContextData*)hIMC;
1222     TRACE("(%p, %p)\n", hIMC, lplf);
1223
1224     if (!data)
1225         return FALSE;
1226
1227     memcpy(&data->font,lplf,sizeof(LOGFONTW));
1228     SendMessageW(root_context->hwnd, WM_IME_NOTIFY, IMN_SETCOMPOSITIONFONT, 0);
1229
1230     if (data->textfont)
1231     {
1232         DeleteObject(data->textfont);
1233         data->textfont = NULL;
1234     }
1235     data->textfont = CreateFontIndirectW(&data->font); 
1236     return TRUE;
1237 }
1238
1239 /***********************************************************************
1240  *              ImmSetCompositionStringA (IMM32.@)
1241  */
1242 BOOL WINAPI ImmSetCompositionStringA(
1243   HIMC hIMC, DWORD dwIndex,
1244   LPCVOID lpComp, DWORD dwCompLen,
1245   LPCVOID lpRead, DWORD dwReadLen)
1246 {
1247     DWORD comp_len;
1248     DWORD read_len;
1249     WCHAR *CompBuffer = NULL;
1250     WCHAR *ReadBuffer = NULL;
1251     BOOL rc;
1252
1253     TRACE("(%p, %ld, %p, %ld, %p, %ld): stub\n",
1254             hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1255
1256     comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
1257     if (comp_len)
1258     {
1259         CompBuffer = (WCHAR*)HeapAlloc(GetProcessHeap(),0,comp_len);
1260         MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
1261     }
1262
1263     read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
1264     if (read_len)
1265     {
1266         ReadBuffer = (WCHAR*)HeapAlloc(GetProcessHeap(),0,read_len);
1267         MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
1268     }
1269
1270     rc =  ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
1271                                    ReadBuffer, read_len);
1272
1273     if (CompBuffer)
1274         HeapFree(GetProcessHeap(), 0, CompBuffer);
1275
1276     if (ReadBuffer)
1277         HeapFree(GetProcessHeap(), 0, ReadBuffer);
1278
1279     return rc;
1280 }
1281
1282 /***********************************************************************
1283  *              ImmSetCompositionStringW (IMM32.@)
1284  */
1285 BOOL WINAPI ImmSetCompositionStringW(
1286         HIMC hIMC, DWORD dwIndex,
1287         LPCVOID lpComp, DWORD dwCompLen,
1288         LPCVOID lpRead, DWORD dwReadLen)
1289 {
1290      DWORD flags = 0;
1291      WCHAR wParam  = 0;
1292
1293      TRACE("(%p, %ld, %p, %ld, %p, %ld): stub\n",
1294              hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
1295
1296
1297      if (hIMC != (HIMC)FROM_IME)
1298          FIXME("PROBLEM: This only sets the wine level string\n");
1299
1300      /*
1301       * Explanation:
1302       *  this sets the composition string in the imm32.dll level
1303       *  of the composition buffer. we cannot manipulate the xim level
1304       *  buffer, which means that once the xim level buffer changes again
1305       *  any call to this function from the application will be lost
1306       */
1307
1308      if (lpRead && dwReadLen)
1309          FIXME("Reading string unimplemented\n");
1310
1311      /*
1312       * app operating this api to also receive the message from xim
1313       */
1314
1315     if (dwIndex == SCS_SETSTR)
1316     {
1317          flags = GCS_COMPSTR;
1318
1319          if (root_context->dwCompStringLength)
1320              HeapFree(GetProcessHeap(),0,root_context->CompositionString);
1321
1322          root_context->dwCompStringLength = dwCompLen;
1323          root_context->dwCompStringSize = dwCompLen;
1324
1325          if (dwCompLen && lpComp)
1326          {
1327              root_context->CompositionString = HeapAlloc(GetProcessHeap(), 0,
1328                                                      dwCompLen);
1329              memcpy(root_context->CompositionString,lpComp,dwCompLen);
1330
1331              wParam = ((WCHAR*)lpComp)[0];
1332              flags |= GCS_COMPCLAUSE | GCS_COMPATTR;
1333          }
1334          else
1335              root_context->CompositionString = NULL;
1336
1337     }
1338
1339      UpdateDataInDefaultIMEWindow(hwndDefault);
1340
1341      ImmInternalPostIMEMessage(WM_IME_COMPOSITION, wParam, flags);
1342
1343      return TRUE;
1344 }
1345
1346 /***********************************************************************
1347  *              ImmSetCompositionWindow (IMM32.@)
1348  */
1349 BOOL WINAPI ImmSetCompositionWindow(
1350   HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1351 {
1352     BOOL reshow = FALSE;
1353     InputContextData *data = (InputContextData*)hIMC;
1354
1355     TRACE("(%p, %p)\n", hIMC, lpCompForm);
1356     TRACE("\t%lx, (%li,%li), (%li,%li - %li,%li)\n",lpCompForm->dwStyle,
1357           lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
1358           lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
1359
1360     if (!data)
1361         return FALSE;
1362
1363     memcpy(&data->CompForm,lpCompForm,sizeof(COMPOSITIONFORM));
1364
1365     if (IsWindowVisible(hwndDefault))
1366     {
1367         reshow = TRUE;
1368         ShowWindow(hwndDefault,SW_HIDE);
1369     }
1370
1371     FIXME("STUB\n");
1372
1373     if (reshow)
1374         ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1375
1376     SendMessageW(root_context->hwnd, WM_IME_NOTIFY,IMN_SETCOMPOSITIONWINDOW, 0);
1377     return TRUE;
1378 }
1379
1380 /***********************************************************************
1381  *              ImmSetConversionStatus (IMM32.@)
1382  */
1383 BOOL WINAPI ImmSetConversionStatus(
1384   HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
1385 {
1386   FIXME("(%p, %ld, %ld): stub\n",
1387     hIMC, fdwConversion, fdwSentence
1388   );
1389   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1390   return FALSE;
1391 }
1392
1393 /***********************************************************************
1394  *              ImmSetOpenStatus (IMM32.@)
1395  */
1396 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
1397 {
1398     InputContextData *data = (InputContextData*)hIMC;
1399     FIXME("Semi-Stub\n");
1400
1401     if (hIMC == (HIMC)FROM_IME)
1402     {
1403         if (fOpen)
1404             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION, 0, 0);
1405
1406         ImmInternalSetOpenStatus(fOpen);
1407
1408         if (!fOpen)
1409             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION, 0, 0);
1410
1411         return TRUE;
1412     }
1413
1414     if (!data)
1415         return FALSE;
1416
1417     if (fOpen != data->bInternalState)
1418     {
1419         if (fOpen == FALSE && pX11DRV_ForceXIMReset)
1420             pX11DRV_ForceXIMReset(data->hwnd);
1421
1422         if (fOpen == FALSE)
1423             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1424         else
1425             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1426
1427         ImmInternalSetOpenStatus(fOpen);
1428         ImmInternalSetOpenStatus(!fOpen);
1429
1430         if (data->bOpen == FALSE)
1431             ImmInternalPostIMEMessage(WM_IME_ENDCOMPOSITION,0,0);
1432         else
1433             ImmInternalPostIMEMessage(WM_IME_STARTCOMPOSITION,0,0);
1434
1435         return FALSE;
1436     }
1437     return TRUE;
1438 }
1439
1440 /***********************************************************************
1441  *              ImmSetStatusWindowPos (IMM32.@)
1442  */
1443 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1444 {
1445   FIXME("(%p, %p): stub\n", hIMC, lpptPos);
1446   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1447   return FALSE;
1448 }
1449
1450 /***********************************************************************
1451  *              ImmSimulateHotKey (IMM32.@)
1452  */
1453 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
1454 {
1455   FIXME("(%p, %ld): stub\n", hWnd, dwHotKeyID);
1456   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1457   return FALSE;
1458 }
1459
1460 /***********************************************************************
1461  *              ImmUnregisterWordA (IMM32.@)
1462  */
1463 BOOL WINAPI ImmUnregisterWordA(
1464   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
1465 {
1466   FIXME("(%p, %s, %ld, %s): stub\n",
1467     hKL, debugstr_a(lpszReading), dwStyle, debugstr_a(lpszUnregister)
1468   );
1469   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1470   return FALSE;
1471 }
1472
1473 /***********************************************************************
1474  *              ImmUnregisterWordW (IMM32.@)
1475  */
1476 BOOL WINAPI ImmUnregisterWordW(
1477   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
1478 {
1479   FIXME("(%p, %s, %ld, %s): stub\n",
1480     hKL, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszUnregister)
1481   );
1482   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1483   return FALSE;
1484 }
1485
1486
1487 /*****
1488  * Internal functions to help with IME window management
1489  */
1490 static void PaintDefaultIMEWnd(HWND hwnd)
1491 {
1492     PAINTSTRUCT ps;
1493     RECT rect;
1494     HDC hdc = BeginPaint(hwnd,&ps);
1495     GetClientRect(hwnd,&rect);
1496
1497     if (root_context->dwCompStringLength && root_context->CompositionString)
1498     {
1499         SIZE size;
1500         POINT pt;
1501         HFONT oldfont = NULL;
1502
1503         if (root_context->textfont)
1504             oldfont = SelectObject(hdc,root_context->textfont);
1505
1506         TextOutW(hdc, 0,0,(LPWSTR)root_context->CompositionString,
1507                  root_context->dwCompStringLength / sizeof(WCHAR));
1508
1509         GetTextExtentPoint32W(hdc, (LPWSTR)root_context->CompositionString,
1510                               root_context->dwCompStringLength / sizeof(WCHAR),
1511                               &size);
1512         pt.x = size.cx;
1513         pt.y = size.cy;
1514         LPtoDP(hdc,&pt,1);
1515         rect.left = pt.x;
1516
1517         if (oldfont)
1518             SelectObject(hdc,oldfont);
1519     }
1520     FillRect(hdc,&rect, (HBRUSH) (COLOR_WINDOW+1));
1521     EndPaint(hwnd,&ps);
1522 }
1523
1524 static void UpdateDataInDefaultIMEWindow(HWND hwnd)
1525 {
1526     RedrawWindow(hwnd,NULL,NULL,RDW_ERASENOW|RDW_INVALIDATE);
1527 }
1528
1529 /*
1530  * The window proc for the default IME window
1531  */
1532 static LRESULT WINAPI IME_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
1533                                           LPARAM lParam)
1534 {
1535     LRESULT rc = 0;
1536
1537     TRACE("Incoming Message 0x%x  (0x%08x, 0x%08x)\n", msg, (UINT)wParam,
1538            (UINT)lParam);
1539
1540     switch(msg)
1541     {
1542         case WM_PAINT:
1543             PaintDefaultIMEWnd(hwnd);
1544             return FALSE;
1545
1546         case WM_NCCREATE:
1547             return TRUE;
1548
1549         case WM_CREATE:
1550             SetWindowTextA(hwnd,"Wine Ime Active");
1551             return TRUE;
1552
1553         case WM_SETFOCUS:
1554             if (wParam)
1555                 SetFocus((HWND)wParam);
1556             else
1557                 FIXME("Received focus, should never have focus\n");
1558             break;
1559         case WM_IME_COMPOSITION:
1560             TRACE("IME message %s, 0x%x, 0x%x (%i)\n",
1561                     "WM_IME_COMPOSITION", (UINT)wParam, (UINT)lParam,
1562                      root_context->bRead);
1563             if ((lParam & GCS_RESULTSTR) && (!root_context->bRead))
1564                     IMM_PostResult(root_context);
1565             else
1566                  UpdateDataInDefaultIMEWindow(hwnd);
1567             break;
1568         case WM_IME_STARTCOMPOSITION:
1569             TRACE("IME message %s, 0x%x, 0x%x\n",
1570                     "WM_IME_STARTCOMPOSITION", (UINT)wParam, (UINT)lParam);
1571             root_context->hwnd = GetFocus();
1572             ShowWindow(hwndDefault,SW_SHOWNOACTIVATE);
1573             break;
1574         case WM_IME_ENDCOMPOSITION:
1575             TRACE("IME message %s, 0x%x, 0x%x\n",
1576                     "WM_IME_ENDCOMPOSITION", (UINT)wParam, (UINT)lParam);
1577             ShowWindow(hwndDefault,SW_HIDE);
1578             break;
1579         case WM_IME_SELECT:
1580             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_SELECT",
1581                 (UINT)wParam, (UINT)lParam);
1582             break;
1583         case WM_IME_CONTROL:
1584             TRACE("IME message %s, 0x%x, 0x%x\n","WM_IME_CONTROL",
1585                 (UINT)wParam, (UINT)lParam);
1586             rc = 1; 
1587             break;
1588         case WM_IME_NOTIFY:
1589             TRACE("!! IME NOTIFY\n");
1590             break;
1591        default:
1592             TRACE("Non-standard message 0x%x\n",msg);
1593     }
1594     /* check the MSIME messages */
1595     if (msg == WM_MSIME_SERVICE)
1596     {
1597             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_SERVICE",
1598                 (UINT)wParam, (UINT)lParam);
1599             rc = FALSE;
1600     }
1601     else if (msg == WM_MSIME_RECONVERTOPTIONS)
1602     {
1603             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTOPTIONS",
1604                 (UINT)wParam, (UINT)lParam);
1605     }
1606     else if (msg == WM_MSIME_MOUSE)
1607     {
1608             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_MOUSE",
1609                 (UINT)wParam, (UINT)lParam);
1610     }
1611     else if (msg == WM_MSIME_RECONVERTREQUEST)
1612     {
1613             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERTREQUEST",
1614                 (UINT)wParam, (UINT)lParam);
1615     }
1616     else if (msg == WM_MSIME_RECONVERT)
1617     {
1618             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_RECONVERT",
1619                 (UINT)wParam, (UINT)lParam);
1620     }
1621     else if (msg == WM_MSIME_QUERYPOSITION)
1622     {
1623             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_QUERYPOSITION",
1624                 (UINT)wParam, (UINT)lParam);
1625     }
1626     else if (msg == WM_MSIME_DOCUMENTFEED)
1627     {
1628             TRACE("IME message %s, 0x%x, 0x%x\n","WM_MSIME_DOCUMENTFEED",
1629                 (UINT)wParam, (UINT)lParam);
1630     }
1631     /* DefWndProc if not an IME message */
1632     else if (!rc && !((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1633                       (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP)))
1634         rc = DefWindowProcW(hwnd,msg,wParam,lParam);
1635
1636     return rc;
1637 }