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