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