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