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