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