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