~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/imm32/imm.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * IMM32 library
  3  *
  4  * Copyright 1998 Patrik Stridvall
  5  * Copyright 2002, 2003, 2007 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 #include <stdio.h>
 24 
 25 #include "windef.h"
 26 #include "winbase.h"
 27 #include "wingdi.h"
 28 #include "winuser.h"
 29 #include "winerror.h"
 30 #include "wine/debug.h"
 31 #include "imm.h"
 32 #include "ddk/imm.h"
 33 #include "winnls.h"
 34 #include "winreg.h"
 35 #include "wine/list.h"
 36 
 37 WINE_DEFAULT_DEBUG_CHANNEL(imm);
 38 
 39 typedef struct tagIMCCInternal
 40 {
 41     DWORD dwLock;
 42     DWORD dwSize;
 43 } IMCCInternal;
 44 
 45 #define MAKE_FUNCPTR(f) typeof(f) * p##f
 46 typedef struct _tagImmHkl{
 47     struct list entry;
 48     HKL         hkl;
 49     HMODULE     hIME;
 50     IMEINFO     imeInfo;
 51     WCHAR       imeClassName[17]; /* 16 character max */
 52     ULONG       uSelected;
 53 
 54     /* Function Pointers */
 55     MAKE_FUNCPTR(ImeInquire);
 56     MAKE_FUNCPTR(ImeConfigure);
 57     MAKE_FUNCPTR(ImeDestroy);
 58     MAKE_FUNCPTR(ImeEscape);
 59     MAKE_FUNCPTR(ImeSelect);
 60     MAKE_FUNCPTR(ImeSetActiveContext);
 61     MAKE_FUNCPTR(ImeToAsciiEx);
 62     MAKE_FUNCPTR(NotifyIME);
 63     MAKE_FUNCPTR(ImeRegisterWord);
 64     MAKE_FUNCPTR(ImeUnregisterWord);
 65     MAKE_FUNCPTR(ImeEnumRegisterWord);
 66     MAKE_FUNCPTR(ImeSetCompositionString);
 67     MAKE_FUNCPTR(ImeConversionList);
 68     MAKE_FUNCPTR(ImeProcessKey);
 69     MAKE_FUNCPTR(ImeGetRegisterWordStyle);
 70     MAKE_FUNCPTR(ImeGetImeMenuItems);
 71 } ImmHkl;
 72 #undef MAKE_FUNCPTR
 73 
 74 typedef struct tagInputContextData
 75 {
 76         DWORD           dwLock;
 77         INPUTCONTEXT    IMC;
 78 
 79         ImmHkl          *immKbd;
 80         HWND            imeWnd;
 81         UINT            lastVK;
 82 } InputContextData;
 83 
 84 typedef struct _tagTRANSMSG {
 85     UINT message;
 86     WPARAM wParam;
 87     LPARAM lParam;
 88 } TRANSMSG, *LPTRANSMSG;
 89 
 90 typedef struct _tagIMMThreadData {
 91     HIMC defaultContext;
 92     HWND hwndDefault;
 93 } IMMThreadData;
 94 
 95 static DWORD tlsIndex = 0;
 96 static struct list ImmHklList = LIST_INIT(ImmHklList);
 97 
 98 /* MSIME messages */
 99 static UINT WM_MSIME_SERVICE;
100 static UINT WM_MSIME_RECONVERTOPTIONS;
101 static UINT WM_MSIME_MOUSE;
102 static UINT WM_MSIME_RECONVERTREQUEST;
103 static UINT WM_MSIME_RECONVERT;
104 static UINT WM_MSIME_QUERYPOSITION;
105 static UINT WM_MSIME_DOCUMENTFEED;
106 
107 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
108 
109 #define is_himc_ime_unicode(p)  (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
110 #define is_kbd_ime_unicode(p)  (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
111 
112 static BOOL IMM_DestroyContext(HIMC hIMC);
113 
114 static inline WCHAR *strdupAtoW( const char *str )
115 {
116     WCHAR *ret = NULL;
117     if (str)
118     {
119         DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
120         if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
121             MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
122     }
123     return ret;
124 }
125 
126 static inline CHAR *strdupWtoA( const WCHAR *str )
127 {
128     CHAR *ret = NULL;
129     if (str)
130     {
131         DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
132         if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
133             WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
134     }
135     return ret;
136 }
137 
138 static DWORD convert_candidatelist_WtoA(
139         LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
140 {
141     DWORD ret, i, len;
142 
143     ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
144     if ( lpDst && dwBufLen > 0 )
145     {
146         *lpDst = *lpSrc;
147         lpDst->dwOffset[0] = ret;
148     }
149 
150     for ( i = 0; i < lpSrc->dwCount; i++)
151     {
152         LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
153 
154         if ( lpDst && dwBufLen > 0 )
155         {
156             LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
157 
158             len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1,
159                                       (LPSTR)dest, dwBufLen, NULL, NULL);
160 
161             if ( i + 1 < lpSrc->dwCount )
162                 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
163             dwBufLen -= len * sizeof(char);
164         }
165         else
166             len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL);
167 
168         ret += len * sizeof(char);
169     }
170 
171     if ( lpDst )
172         lpDst->dwSize = ret;
173 
174     return ret;
175 }
176 
177 static DWORD convert_candidatelist_AtoW(
178         LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
179 {
180     DWORD ret, i, len;
181 
182     ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
183     if ( lpDst && dwBufLen > 0 )
184     {
185         *lpDst = *lpSrc;
186         lpDst->dwOffset[0] = ret;
187     }
188 
189     for ( i = 0; i < lpSrc->dwCount; i++)
190     {
191         LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
192 
193         if ( lpDst && dwBufLen > 0 )
194         {
195             LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
196 
197             len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1,
198                                       (LPWSTR)dest, dwBufLen);
199 
200             if ( i + 1 < lpSrc->dwCount )
201                 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
202             dwBufLen -= len * sizeof(WCHAR);
203         }
204         else
205             len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
206 
207         ret += len * sizeof(WCHAR);
208     }
209 
210     if ( lpDst )
211         lpDst->dwSize = ret;
212 
213     return ret;
214 }
215 
216 static IMMThreadData* IMM_GetThreadData(void)
217 {
218     return (IMMThreadData*)TlsGetValue(tlsIndex);
219 }
220 
221 static void IMM_InitThreadData(void)
222 {
223     IMMThreadData* data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
224                                     sizeof(IMMThreadData));
225     TlsSetValue(tlsIndex,data);
226 
227     TRACE("Thread Data Created\n");
228 }
229 
230 static void IMM_FreeThreadData(void)
231 {
232     IMMThreadData* data = TlsGetValue(tlsIndex);
233     IMM_DestroyContext(data->defaultContext);
234     DestroyWindow(data->hwndDefault);
235     HeapFree(GetProcessHeap(),0,data);
236     TRACE("Thread Data Destroyed\n");
237 }
238 
239 static HMODULE LoadDefaultWineIME(void)
240 {
241     char buffer[MAX_PATH], libname[32], *name, *next;
242     HMODULE module = 0;
243     HKEY hkey;
244 
245     TRACE("Attempting to fall back to wine default IME\n");
246 
247     strcpy( buffer, "x11" );  /* default value */
248     /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
249     if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
250     {
251         DWORD type, count = sizeof(buffer);
252         RegQueryValueExA( hkey, "Ime", 0, &type, (LPBYTE) buffer, &count );
253         RegCloseKey( hkey );
254     }
255 
256     name = buffer;
257     while (name)
258     {
259         next = strchr( name, ',' );
260         if (next) *next++ = 0;
261 
262         snprintf( libname, sizeof(libname), "wine%s.drv", name );
263         if ((module = LoadLibraryA( libname )) != 0) break;
264         name = next;
265     }
266 
267     return module;
268 }
269 
270 /* ImmHkl loading and freeing */
271 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
272 static ImmHkl *IMM_GetImmHkl(HKL hkl)
273 {
274     ImmHkl *ptr;
275     WCHAR filename[MAX_PATH];
276 
277     TRACE("Seeking ime for keyboard 0x%x\n",(unsigned)hkl);
278 
279     LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
280     {
281         if (ptr->hkl == hkl)
282             return ptr;
283     }
284     /* not found... create it */
285 
286     ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
287 
288     ptr->hkl = hkl;
289     if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
290     if (!ptr->hIME)
291         ptr->hIME = LoadDefaultWineIME();
292     if (ptr->hIME)
293     {
294         LOAD_FUNCPTR(ImeInquire);
295         if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
296         {
297             FreeLibrary(ptr->hIME);
298             ptr->hIME = NULL;
299         }
300         else
301         {
302             LOAD_FUNCPTR(ImeDestroy);
303             LOAD_FUNCPTR(ImeSelect);
304             if (!ptr->pImeSelect || !ptr->pImeDestroy)
305             {
306                 FreeLibrary(ptr->hIME);
307                 ptr->hIME = NULL;
308             }
309             else
310             {
311                 LOAD_FUNCPTR(ImeConfigure);
312                 LOAD_FUNCPTR(ImeEscape);
313                 LOAD_FUNCPTR(ImeSetActiveContext);
314                 LOAD_FUNCPTR(ImeToAsciiEx);
315                 LOAD_FUNCPTR(NotifyIME);
316                 LOAD_FUNCPTR(ImeRegisterWord);
317                 LOAD_FUNCPTR(ImeUnregisterWord);
318                 LOAD_FUNCPTR(ImeEnumRegisterWord);
319                 LOAD_FUNCPTR(ImeSetCompositionString);
320                 LOAD_FUNCPTR(ImeConversionList);
321                 LOAD_FUNCPTR(ImeProcessKey);
322                 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
323                 LOAD_FUNCPTR(ImeGetImeMenuItems);
324                 /* make sure our classname is WCHAR */
325                 if (!is_kbd_ime_unicode(ptr))
326                 {
327                     WCHAR bufW[17];
328                     MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
329                                         -1, bufW, 17);
330                     lstrcpyW(ptr->imeClassName, bufW);
331                 }
332             }
333         }
334     }
335     list_add_head(&ImmHklList,&ptr->entry);
336 
337     return ptr;
338 }
339 #undef LOAD_FUNCPTR
340 
341 static void IMM_FreeAllImmHkl(void)
342 {
343     ImmHkl *ptr,*cursor2;
344 
345     LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
346     {
347         list_remove(&ptr->entry);
348         if (ptr->hIME)
349         {
350             ptr->pImeDestroy(1);
351             FreeLibrary(ptr->hIME);
352         }
353         HeapFree(GetProcessHeap(),0,ptr);
354     }
355 }
356 
357 static void IMM_RegisterMessages(void)
358 {
359     WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
360     WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
361     WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
362     WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
363     WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
364     WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
365     WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
366 }
367 
368 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
369 {
370     TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
371     switch (fdwReason)
372     {
373         case DLL_PROCESS_ATTACH:
374             IMM_RegisterMessages();
375             tlsIndex = TlsAlloc();
376             IMM_InitThreadData();
377             break;
378         case DLL_THREAD_ATTACH:
379             IMM_InitThreadData();
380             break;
381         case DLL_THREAD_DETACH:
382             IMM_FreeThreadData();
383             break;
384         case DLL_PROCESS_DETACH:
385             IMM_FreeThreadData();
386             IMM_FreeAllImmHkl();
387             TlsFree(tlsIndex);
388             break;
389     }
390     return TRUE;
391 }
392 
393 /* for posting messages as the IME */
394 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
395 {
396     HWND target = GetFocus();
397     if (!target)
398        PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
399     else
400        PostMessageW(target, msg, wParam, lParam);
401 }
402 
403 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
404 {
405     HWND target;
406 
407     target = data->IMC.hWnd;
408     if (!target) target = GetFocus();
409 
410     if (target)
411        return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
412 
413     return 0;
414 }
415 
416 static HIMCC ImmCreateBlankCompStr(void)
417 {
418     HIMCC rc;
419     LPCOMPOSITIONSTRING ptr;
420     rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
421     ptr = (LPCOMPOSITIONSTRING)ImmLockIMCC(rc);
422     memset(ptr,0,sizeof(COMPOSITIONSTRING));
423     ptr->dwSize = sizeof(COMPOSITIONSTRING);
424     ImmUnlockIMCC(rc);
425     return rc;
426 }
427 
428 /***********************************************************************
429  *              ImmAssociateContext (IMM32.@)
430  */
431 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
432 {
433     HIMC old = NULL;
434     InputContextData *data = (InputContextData*)hIMC;
435 
436     TRACE("(%p, %p):\n", hWnd, hIMC);
437 
438     if (!IMM_GetThreadData()->defaultContext)
439         IMM_GetThreadData()->defaultContext = ImmCreateContext();
440 
441     /*
442      * If already associated just return
443      */
444     if (hIMC && data->IMC.hWnd == hWnd)
445         return hIMC;
446 
447     if (hWnd)
448     {
449         old = (HIMC)RemovePropW(hWnd,szwWineIMCProperty);
450 
451         if (old == NULL)
452             old = IMM_GetThreadData()->defaultContext;
453         else if (old == (HIMC)-1)
454             old = NULL;
455 
456         if (hIMC != IMM_GetThreadData()->defaultContext)
457         {
458             if (hIMC == NULL) /* Meaning disable imm for that window*/
459                 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
460             else
461                 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)hIMC);
462         }
463 
464         if (old)
465         {
466             InputContextData *old_data = (InputContextData*)old;
467             if (old_data->IMC.hWnd == hWnd)
468                 old_data->IMC.hWnd = NULL;
469         }
470     }
471 
472     if (!hIMC)
473         return old;
474 
475     if (IsWindow(data->IMC.hWnd))
476     {
477         /*
478          * Post a message that your context is switching
479          */
480         SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
481     }
482 
483     data->IMC.hWnd = hWnd;
484 
485     if (IsWindow(data->IMC.hWnd))
486     {
487         /*
488          * Post a message that your context is switching
489          */
490         SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
491     }
492 
493     return old;
494 }
495 
496 /***********************************************************************
497  *              ImmAssociateContextEx (IMM32.@)
498  */
499 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
500 {
501     FIXME("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
502     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
503     return FALSE;
504 }
505 
506 /***********************************************************************
507  *              ImmConfigureIMEA (IMM32.@)
508  */
509 BOOL WINAPI ImmConfigureIMEA(
510   HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
511 {
512     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
513 
514     TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
515 
516     if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
517         return FALSE;
518 
519     if (immHkl->hIME && immHkl->pImeConfigure)
520     {
521         if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
522             return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
523         else
524         {
525             REGISTERWORDW rww;
526             REGISTERWORDA *rwa = (REGISTERWORDA*)lpData;
527             BOOL rc;
528 
529             rww.lpReading = strdupAtoW(rwa->lpReading);
530             rww.lpWord = strdupAtoW(rwa->lpWord);
531             rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
532             HeapFree(GetProcessHeap(),0,rww.lpReading);
533             HeapFree(GetProcessHeap(),0,rww.lpWord);
534             return rc;
535         }
536     }
537     else
538         return FALSE;
539 }
540 
541 /***********************************************************************
542  *              ImmConfigureIMEW (IMM32.@)
543  */
544 BOOL WINAPI ImmConfigureIMEW(
545   HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
546 {
547     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
548 
549     TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
550 
551     if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
552         return FALSE;
553 
554     if (immHkl->hIME && immHkl->pImeConfigure)
555     {
556         if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
557             return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
558         else
559         {
560             REGISTERWORDW *rww = (REGISTERWORDW*)lpData;
561             REGISTERWORDA rwa;
562             BOOL rc;
563 
564             rwa.lpReading = strdupWtoA(rww->lpReading);
565             rwa.lpWord = strdupWtoA(rww->lpWord);
566             rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
567             HeapFree(GetProcessHeap(),0,rwa.lpReading);
568             HeapFree(GetProcessHeap(),0,rwa.lpWord);
569             return rc;
570         }
571     }
572     else
573         return FALSE;
574 }
575 
576 /***********************************************************************
577  *              ImmCreateContext (IMM32.@)
578  */
579 HIMC WINAPI ImmCreateContext(void)
580 {
581     InputContextData *new_context;
582     LPGUIDELINE gl;
583     LPCANDIDATEINFO ci;
584 
585     new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
586 
587     /* Load the IME */
588     new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
589 
590     if (!new_context->immKbd->hIME)
591     {
592         TRACE("IME dll could not be loaded\n");
593         HeapFree(GetProcessHeap(),0,new_context);
594         return 0;
595     }
596 
597     /* the HIMCCs are never NULL */
598     new_context->IMC.hCompStr = ImmCreateBlankCompStr();
599     new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
600     new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
601     ci = ImmLockIMCC(new_context->IMC.hCandInfo);
602     memset(ci,0,sizeof(CANDIDATEINFO));
603     ci->dwSize = sizeof(CANDIDATEINFO);
604     ImmUnlockIMCC(new_context->IMC.hCandInfo);
605     new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
606     gl = ImmLockIMCC(new_context->IMC.hGuideLine);
607     memset(gl,0,sizeof(GUIDELINE));
608     gl->dwSize = sizeof(GUIDELINE);
609     ImmUnlockIMCC(new_context->IMC.hGuideLine);
610 
611     /* Initialize the IME Private */
612     new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
613 
614     if (!new_context->immKbd->pImeSelect(new_context, TRUE))
615     {
616         TRACE("Selection of IME failed\n");
617         IMM_DestroyContext(new_context);
618         return 0;
619     }
620 
621     new_context->immKbd->uSelected++;
622     TRACE("Created context 0x%x\n",(UINT)new_context);
623 
624     return (HIMC)new_context;
625 }
626 
627 static BOOL IMM_DestroyContext(HIMC hIMC)
628 {
629     InputContextData *data = (InputContextData*)hIMC;
630 
631     TRACE("Destroying %p\n",hIMC);
632 
633     if (hIMC)
634     {
635         data->immKbd->uSelected --;
636         data->immKbd->pImeSelect(hIMC, FALSE);
637 
638         if (IMM_GetThreadData()->hwndDefault == data->imeWnd)
639             IMM_GetThreadData()->hwndDefault = NULL;
640         DestroyWindow(data->imeWnd);
641 
642         ImmDestroyIMCC(data->IMC.hCompStr);
643         ImmDestroyIMCC(data->IMC.hCandInfo);
644         ImmDestroyIMCC(data->IMC.hGuideLine);
645         ImmDestroyIMCC(data->IMC.hPrivate);
646         ImmDestroyIMCC(data->IMC.hMsgBuf);
647 
648         HeapFree(GetProcessHeap(),0,data);
649     }
650     return TRUE;
651 }
652 
653 /***********************************************************************
654  *              ImmDestroyContext (IMM32.@)
655  */
656 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
657 {
658     if (hIMC != IMM_GetThreadData()->defaultContext)
659         return IMM_DestroyContext(hIMC);
660     else
661         return FALSE;
662 }
663 
664 /***********************************************************************
665  *              ImmDisableIME (IMM32.@)
666  */
667 BOOL WINAPI ImmDisableIME(DWORD idThread)
668 {
669     FIXME("(%d): stub\n", idThread);
670     return TRUE;
671 }
672 
673 /***********************************************************************
674  *              ImmEnumRegisterWordA (IMM32.@)
675  */
676 UINT WINAPI ImmEnumRegisterWordA(
677   HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
678   LPCSTR lpszReading, DWORD dwStyle,
679   LPCSTR lpszRegister, LPVOID lpData)
680 {
681     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
682     TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
683         debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
684     if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
685     {
686         if (!is_kbd_ime_unicode(immHkl))
687             return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
688                 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
689         else
690         {
691             LPWSTR lpszwReading = strdupAtoW(lpszReading);
692             LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
693             BOOL rc;
694 
695             rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
696                                               lpszwReading, dwStyle, lpszwRegister,
697                                               lpData);
698 
699             HeapFree(GetProcessHeap(),0,lpszwReading);
700             HeapFree(GetProcessHeap(),0,lpszwRegister);
701             return rc;
702         }
703     }
704     else
705         return 0;
706 }
707 
708 /***********************************************************************
709  *              ImmEnumRegisterWordW (IMM32.@)
710  */
711 UINT WINAPI ImmEnumRegisterWordW(
712   HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
713   LPCWSTR lpszReading, DWORD dwStyle,
714   LPCWSTR lpszRegister, LPVOID lpData)
715 {
716     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
717     TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
718         debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
719     if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
720     {
721         if (is_kbd_ime_unicode(immHkl))
722             return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
723                                             lpszRegister, lpData);
724         else
725         {
726             LPSTR lpszaReading = strdupWtoA(lpszReading);
727             LPSTR lpszaRegister = strdupWtoA(lpszRegister);
728             BOOL rc;
729 
730             rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
731                                               dwStyle, (LPCWSTR)lpszaRegister, lpData);
732 
733             HeapFree(GetProcessHeap(),0,lpszaReading);
734             HeapFree(GetProcessHeap(),0,lpszaRegister);
735             return rc;
736         }
737     }
738     else
739         return 0;
740 }
741 
742 /***********************************************************************
743  *              ImmEscapeA (IMM32.@)
744  */
745 LRESULT WINAPI ImmEscapeA(
746   HKL hKL, HIMC hIMC,
747   UINT uEscape, LPVOID lpData)
748 {
749     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
750     TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
751 
752     if (immHkl->hIME && immHkl->pImeEscape)
753     {
754         if (!is_kbd_ime_unicode(immHkl))
755             return immHkl->pImeEscape(hIMC,uEscape,lpData);
756         else
757         {
758             FIXME("A procedure called with W ime back end\n");
759             SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
760             return 0;
761         }
762     }
763     else
764         return 0;
765 }
766 
767 /***********************************************************************
768  *              ImmEscapeW (IMM32.@)
769  */
770 LRESULT WINAPI ImmEscapeW(
771   HKL hKL, HIMC hIMC,
772   UINT uEscape, LPVOID lpData)
773 {
774     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
775     TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
776 
777     if (immHkl->hIME && immHkl->pImeEscape)
778     {
779         if (is_kbd_ime_unicode(immHkl))
780             return immHkl->pImeEscape(hIMC,uEscape,lpData);
781         else
782         {
783             FIXME("W procedure called with A ime back end\n");
784             SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
785             return 0;
786         }
787     }
788     else
789         return 0;
790 }
791 
792 /***********************************************************************
793  *              ImmGetCandidateListA (IMM32.@)
794  */
795 DWORD WINAPI ImmGetCandidateListA(
796   HIMC hIMC, DWORD dwIndex,
797   LPCANDIDATELIST lpCandList, DWORD dwBufLen)
798 {
799     InputContextData *data = (InputContextData *)hIMC;
800     LPCANDIDATEINFO candinfo;
801     LPCANDIDATELIST candlist;
802     DWORD ret = 0;
803 
804     TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
805 
806     if (!data || !data->IMC.hCandInfo)
807        return 0;
808 
809     candinfo = ImmLockIMCC(data->IMC.hCandInfo);
810     if ( dwIndex >= candinfo->dwCount ||
811          dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
812         goto done;
813 
814     candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
815     if ( !candlist->dwSize || !candlist->dwCount )
816         goto done;
817 
818     if ( !is_himc_ime_unicode(data) )
819     {
820         ret = candlist->dwSize;
821         if ( lpCandList && dwBufLen >= ret )
822             memcpy(lpCandList, candlist, ret);
823     }
824     else
825         ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
826 
827 done:
828     ImmUnlockIMCC(data->IMC.hCandInfo);
829     return ret;
830 }
831 
832 /***********************************************************************
833  *              ImmGetCandidateListCountA (IMM32.@)
834  */
835 DWORD WINAPI ImmGetCandidateListCountA(
836   HIMC hIMC, LPDWORD lpdwListCount)
837 {
838     InputContextData *data = (InputContextData *)hIMC;
839     LPCANDIDATEINFO candinfo;
840     DWORD ret, count;
841 
842     TRACE("%p, %p\n", hIMC, lpdwListCount);
843 
844     if (!data || !lpdwListCount || !data->IMC.hCandInfo)
845        return 0;
846 
847     candinfo = ImmLockIMCC(data->IMC.hCandInfo);
848 
849     *lpdwListCount = count = candinfo->dwCount;
850 
851     if ( !is_himc_ime_unicode(data) )
852         ret = candinfo->dwSize;
853     else
854     {
855         ret = sizeof(CANDIDATEINFO);
856         while ( count-- )
857             ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
858     }
859 
860     ImmUnlockIMCC(data->IMC.hCandInfo);
861     return ret;
862 }
863 
864 /***********************************************************************
865  *              ImmGetCandidateListCountW (IMM32.@)
866  */
867 DWORD WINAPI ImmGetCandidateListCountW(
868   HIMC hIMC, LPDWORD lpdwListCount)
869 {
870     InputContextData *data = (InputContextData *)hIMC;
871     LPCANDIDATEINFO candinfo;
872     DWORD ret, count;
873 
874     TRACE("%p, %p\n", hIMC, lpdwListCount);
875 
876     if (!data || !lpdwListCount || !data->IMC.hCandInfo)
877        return 0;
878 
879     candinfo = ImmLockIMCC(data->IMC.hCandInfo);
880 
881     *lpdwListCount = count = candinfo->dwCount;
882 
883     if ( is_himc_ime_unicode(data) )
884         ret = candinfo->dwSize;
885     else
886     {
887         ret = sizeof(CANDIDATEINFO);
888         while ( count-- )
889             ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
890     }
891 
892     ImmUnlockIMCC(data->IMC.hCandInfo);
893     return ret;
894 }
895 
896 /***********************************************************************
897  *              ImmGetCandidateListW (IMM32.@)
898  */
899 DWORD WINAPI ImmGetCandidateListW(
900   HIMC hIMC, DWORD dwIndex,
901   LPCANDIDATELIST lpCandList, DWORD dwBufLen)
902 {
903     InputContextData *data = (InputContextData *)hIMC;
904     LPCANDIDATEINFO candinfo;
905     LPCANDIDATELIST candlist;
906     DWORD ret = 0;
907 
908     TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
909 
910     if (!data || !data->IMC.hCandInfo)
911        return 0;
912 
913     candinfo = ImmLockIMCC(data->IMC.hCandInfo);
914     if ( dwIndex >= candinfo->dwCount ||
915          dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
916         goto done;
917 
918     candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
919     if ( !candlist->dwSize || !candlist->dwCount )
920         goto done;
921 
922     if ( is_himc_ime_unicode(data) )
923     {
924         ret = candlist->dwSize;
925         if ( lpCandList && dwBufLen >= ret )
926             memcpy(lpCandList, candlist, ret);
927     }
928     else
929         ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
930 
931 done:
932     ImmUnlockIMCC(data->IMC.hCandInfo);
933     return ret;
934 }
935 
936 /***********************************************************************
937  *              ImmGetCandidateWindow (IMM32.@)
938  */
939 BOOL WINAPI ImmGetCandidateWindow(
940   HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
941 {
942     InputContextData *data = (InputContextData*)hIMC;
943 
944     TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
945 
946     if (!data || !lpCandidate)
947         return FALSE;
948 
949     if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
950         return FALSE;
951 
952     *lpCandidate = data->IMC.cfCandForm[dwIndex];
953 
954     return TRUE;
955 }
956 
957 /***********************************************************************
958  *              ImmGetCompositionFontA (IMM32.@)
959  */
960 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
961 {
962     LOGFONTW lfW;
963     BOOL rc;
964 
965     TRACE("(%p, %p):\n", hIMC, lplf);
966 
967     rc = ImmGetCompositionFontW(hIMC,&lfW);
968     if (!rc || !lplf)
969         return FALSE;
970 
971     memcpy(lplf,&lfW,sizeof(LOGFONTA));
972     WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
973                         LF_FACESIZE, NULL, NULL);
974     return TRUE;
975 }
976 
977 /***********************************************************************
978  *              ImmGetCompositionFontW (IMM32.@)
979  */
980 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
981 {
982     InputContextData *data = (InputContextData*)hIMC;
983 
984     TRACE("(%p, %p):\n", hIMC, lplf);
985 
986     if (!data || !lplf)
987         return FALSE;
988 
989     *lplf = data->IMC.lfFont.W;
990 
991     return TRUE;
992 }
993 
994 
995 /* Helpers for the GetCompositionString functions */
996 
997 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
998                                      BOOL unicode )
999 {
1000     INT rc;
1001 
1002     if (is_himc_ime_unicode(data) && !unicode)
1003         rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1004     else if (!is_himc_ime_unicode(data) && unicode)
1005         rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1006     else
1007     {
1008         int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1009         memcpy( target, source, min(slen,tlen)*dlen);
1010         rc = slen*dlen;
1011     }
1012 
1013     return rc;
1014 }
1015 
1016 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1017                                    LPBYTE target, INT tlen, BOOL unicode )
1018 {
1019     INT rc;
1020 
1021     if (is_himc_ime_unicode(data) && !unicode)
1022     {
1023         rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1024         if (tlen)
1025         {
1026             const BYTE *src = source;
1027             LPBYTE dst = target;
1028             int i, j = 0, k = 0;
1029 
1030             if (rc < tlen)
1031                 tlen = rc;
1032             for (i = 0; i < sslen; ++i)
1033             {
1034                 int len;
1035 
1036                 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1037                                           NULL, 0, NULL, NULL);
1038                 for (; len > 0; --len)
1039                 {
1040                     dst[j++] = src[k];
1041 
1042                     if (j >= tlen)
1043                         goto end;
1044                 }
1045                 ++k;
1046             }
1047         end:
1048             rc = j;
1049         }
1050     }
1051     else if (!is_himc_ime_unicode(data) && unicode)
1052     {
1053         rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1054         if (tlen)
1055         {
1056             const BYTE *src = source;
1057             LPBYTE dst = target;
1058             int i, j = 0;
1059 
1060             if (rc < tlen)
1061                 tlen = rc;
1062             for (i = 0; i < sslen; ++i)
1063             {
1064                 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1065                     continue;
1066 
1067                 dst[j++] = src[i];
1068 
1069                 if (j >= tlen)
1070                     break;
1071             }
1072             rc = j;
1073         }
1074     }
1075     else
1076     {
1077         memcpy( target, source, min(slen,tlen));
1078         rc = slen;
1079     }
1080 
1081     return rc;
1082 }
1083 
1084 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1085                                      LPBYTE target, INT tlen, BOOL unicode )
1086 {
1087     INT rc;
1088 
1089     if (is_himc_ime_unicode(data) && !unicode)
1090     {
1091         if (tlen)
1092         {
1093             int i;
1094 
1095             if (slen < tlen)
1096                 tlen = slen;
1097             tlen /= sizeof (DWORD);
1098             for (i = 0; i < tlen; ++i)
1099             {
1100                 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1101                                                           ((DWORD *)source)[i],
1102                                                           NULL, 0,
1103                                                           NULL, NULL);
1104             }
1105             rc = sizeof (DWORD) * i;
1106         }
1107         else
1108             rc = slen;
1109     }
1110     else if (!is_himc_ime_unicode(data) && unicode)
1111     {
1112         if (tlen)
1113         {
1114             int i;
1115 
1116             if (slen < tlen)
1117                 tlen = slen;
1118             tlen /= sizeof (DWORD);
1119             for (i = 0; i < tlen; ++i)
1120             {
1121                 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1122                                                           ((DWORD *)source)[i],
1123                                                           NULL, 0);
1124             }
1125             rc = sizeof (DWORD) * i;
1126         }
1127         else
1128             rc = slen;
1129     }
1130     else
1131     {
1132         memcpy( target, source, min(slen,tlen));
1133         rc = slen;
1134     }
1135 
1136     return rc;
1137 }
1138 
1139 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1140 {
1141     int rc;
1142 
1143     if (is_himc_ime_unicode(data) && !unicode)
1144     {
1145         rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1146     }
1147     else if (!is_himc_ime_unicode(data) && unicode)
1148     {
1149         rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1150     }
1151     else
1152         rc = offset;
1153 
1154     return rc;
1155 }
1156 
1157 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1158                                       DWORD dwBufLen, BOOL unicode)
1159 {
1160     LONG rc = 0;
1161     InputContextData *data = (InputContextData*)hIMC;
1162     LPCOMPOSITIONSTRING compstr;
1163     LPBYTE compdata;
1164 
1165     TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1166 
1167     if (!data)
1168        return FALSE;
1169 
1170     if (!data->IMC.hCompStr)
1171        return FALSE;
1172 
1173     compdata = ImmLockIMCC(data->IMC.hCompStr);
1174     compstr = (LPCOMPOSITIONSTRING)compdata;
1175 
1176     switch (dwIndex)
1177     {
1178     case GCS_RESULTSTR:
1179         TRACE("GCS_RESULTSTR\n");
1180         rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1181         break;
1182     case GCS_COMPSTR:
1183         TRACE("GCS_COMPSTR\n");
1184         rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1185         break;
1186     case GCS_COMPATTR:
1187         TRACE("GCS_COMPATTR\n");
1188         rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1189                                      compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1190                                      lpBuf, dwBufLen, unicode);
1191         break;
1192     case GCS_COMPCLAUSE:
1193         TRACE("GCS_COMPCLAUSE\n");
1194         rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1195                                        compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1196                                        lpBuf, dwBufLen, unicode);
1197         break;
1198     case GCS_RESULTCLAUSE:
1199         TRACE("GCS_RESULTCLAUSE\n");
1200         rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1201                                        compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen,
1202                                        lpBuf, dwBufLen, unicode);
1203         break;
1204     case GCS_RESULTREADSTR:
1205         TRACE("GCS_RESULTREADSTR\n");
1206         rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1207         break;
1208     case GCS_RESULTREADCLAUSE:
1209         TRACE("GCS_RESULTREADCLAUSE\n");
1210         rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1211                                        compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen,
1212                                        lpBuf, dwBufLen, unicode);
1213         break;
1214     case GCS_COMPREADSTR:
1215         TRACE("GCS_COMPREADSTR\n");
1216         rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1217         break;
1218     case GCS_COMPREADATTR:
1219         TRACE("GCS_COMPREADATTR\n");
1220         rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1221                                      compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1222                                      lpBuf, dwBufLen, unicode);
1223         break;
1224     case GCS_COMPREADCLAUSE:
1225         TRACE("GCS_COMPREADCLAUSE\n");
1226         rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1227                                        compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1228                                        lpBuf, dwBufLen, unicode);
1229         break;
1230     case GCS_CURSORPOS:
1231         TRACE("GCS_CURSORPOS\n");
1232         rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1233         break;
1234     case GCS_DELTASTART:
1235         TRACE("GCS_DELTASTART\n");
1236         rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1237         break;
1238     default:
1239         FIXME("Unhandled index 0x%x\n",dwIndex);
1240         break;
1241     }
1242 
1243     ImmUnlockIMCC(data->IMC.hCompStr);
1244 
1245     return rc;
1246 }
1247 
1248 /***********************************************************************
1249  *              ImmGetCompositionStringA (IMM32.@)
1250  */
1251 LONG WINAPI ImmGetCompositionStringA(
1252   HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1253 {
1254     return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1255 }
1256 
1257 
1258 /***********************************************************************
1259  *              ImmGetCompositionStringW (IMM32.@)
1260  */
1261 LONG WINAPI ImmGetCompositionStringW(
1262   HIMC hIMC, DWORD dwIndex,
1263   LPVOID lpBuf, DWORD dwBufLen)
1264 {
1265     return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1266 }
1267 
1268 /***********************************************************************
1269  *              ImmGetCompositionWindow (IMM32.@)
1270  */
1271 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1272 {
1273     InputContextData *data = (InputContextData*)hIMC;
1274 
1275     TRACE("(%p, %p)\n", hIMC, lpCompForm);
1276 
1277     if (!data)
1278         return FALSE;
1279 
1280     *lpCompForm = data->IMC.cfCompForm;
1281     return 1;
1282 }
1283 
1284 /***********************************************************************
1285  *              ImmGetContext (IMM32.@)
1286  *
1287  */
1288 HIMC WINAPI ImmGetContext(HWND hWnd)
1289 {
1290     HIMC rc = NULL;
1291 
1292     TRACE("%p\n", hWnd);
1293     if (!IMM_GetThreadData()->defaultContext)
1294         IMM_GetThreadData()->defaultContext = ImmCreateContext();
1295 
1296     rc = (HIMC)GetPropW(hWnd,szwWineIMCProperty);
1297     if (rc == (HIMC)-1)
1298         rc = NULL;
1299     else if (rc == NULL)
1300         rc = IMM_GetThreadData()->defaultContext;
1301 
1302     if (rc)
1303     {
1304         InputContextData *data = (InputContextData*)rc;
1305         data->IMC.hWnd = hWnd;
1306     }
1307     TRACE("returning %p\n", rc);
1308 
1309     return rc;
1310 }
1311 
1312 /***********************************************************************
1313  *              ImmGetConversionListA (IMM32.@)
1314  */
1315 DWORD WINAPI ImmGetConversionListA(
1316   HKL hKL, HIMC hIMC,
1317   LPCSTR pSrc, LPCANDIDATELIST lpDst,
1318   DWORD dwBufLen, UINT uFlag)
1319 {
1320     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1321     TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1322                 dwBufLen, uFlag);
1323     if (immHkl->hIME && immHkl->pImeConversionList)
1324     {
1325         if (!is_kbd_ime_unicode(immHkl))
1326             return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1327         else
1328         {
1329             LPCANDIDATELIST lpwDst;
1330             DWORD ret = 0, len;
1331             LPWSTR pwSrc = strdupAtoW(pSrc);
1332 
1333             len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1334             lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1335             if ( lpwDst )
1336             {
1337                 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1338                 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1339                 HeapFree(GetProcessHeap(), 0, lpwDst);
1340             }
1341             HeapFree(GetProcessHeap(), 0, pwSrc);
1342 
1343             return ret;
1344         }
1345     }
1346     else
1347         return 0;
1348 }
1349 
1350 /***********************************************************************
1351  *              ImmGetConversionListW (IMM32.@)
1352  */
1353 DWORD WINAPI ImmGetConversionListW(
1354   HKL hKL, HIMC hIMC,
1355   LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1356   DWORD dwBufLen, UINT uFlag)
1357 {
1358     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1359     TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1360                 dwBufLen, uFlag);
1361     if (immHkl->hIME && immHkl->pImeConversionList)
1362     {
1363         if (is_kbd_ime_unicode(immHkl))
1364             return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1365         else
1366         {
1367             LPCANDIDATELIST lpaDst;
1368             DWORD ret = 0, len;
1369             LPSTR paSrc = strdupWtoA(pSrc);
1370 
1371             len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1372             lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1373             if ( lpaDst )
1374             {
1375                 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1376                 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1377                 HeapFree(GetProcessHeap(), 0, lpaDst);
1378             }
1379             HeapFree(GetProcessHeap(), 0, paSrc);
1380 
1381             return ret;
1382         }
1383     }
1384     else
1385         return 0;
1386 }
1387 
1388 /***********************************************************************
1389  *              ImmGetConversionStatus (IMM32.@)
1390  */
1391 BOOL WINAPI ImmGetConversionStatus(
1392   HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1393 {
1394     InputContextData *data = (InputContextData*)hIMC;
1395 
1396     TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1397 
1398     if (!data)
1399         return FALSE;
1400 
1401     if (lpfdwConversion)
1402         *lpfdwConversion = data->IMC.fdwConversion;
1403     if (lpfdwSentence)
1404         *lpfdwSentence = data->IMC.fdwSentence;
1405 
1406     return TRUE;
1407 }
1408 
1409 /***********************************************************************
1410  *              ImmGetDefaultIMEWnd (IMM32.@)
1411  */
1412 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1413 {
1414     TRACE("Default is %x\n",(unsigned)IMM_GetThreadData()->hwndDefault);
1415     return IMM_GetThreadData()->hwndDefault;
1416 }
1417 
1418 /***********************************************************************
1419  *              ImmGetDescriptionA (IMM32.@)
1420  */
1421 UINT WINAPI ImmGetDescriptionA(
1422   HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1423 {
1424   WCHAR *buf;
1425   DWORD len;
1426 
1427   TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1428 
1429   /* find out how many characters in the unicode buffer */
1430   len = ImmGetDescriptionW( hKL, NULL, 0 );
1431 
1432   /* allocate a buffer of that size */
1433   buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1434   if( !buf )
1435   return 0;
1436 
1437   /* fetch the unicode buffer */
1438   len = ImmGetDescriptionW( hKL, buf, len + 1 );
1439 
1440   /* convert it back to ASCII */
1441   len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1442                              lpszDescription, uBufLen, NULL, NULL );
1443 
1444   HeapFree( GetProcessHeap(), 0, buf );
1445 
1446   return len;
1447 }
1448 
1449 /***********************************************************************
1450  *              ImmGetDescriptionW (IMM32.@)
1451  */
1452 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1453 {
1454   static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1455 
1456   FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1457 
1458   if (!uBufLen) return lstrlenW( name );
1459   lstrcpynW( lpszDescription, name, uBufLen );
1460   return lstrlenW( lpszDescription );
1461 }
1462 
1463 /***********************************************************************
1464  *              ImmGetGuideLineA (IMM32.@)
1465  */
1466 DWORD WINAPI ImmGetGuideLineA(
1467   HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1468 {
1469   FIXME("(%p, %d, %s, %d): stub\n",
1470     hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1471   );
1472   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1473   return 0;
1474 }
1475 
1476 /***********************************************************************
1477  *              ImmGetGuideLineW (IMM32.@)
1478  */
1479 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1480 {
1481   FIXME("(%p, %d, %s, %d): stub\n",
1482     hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1483   );
1484   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1485   return 0;
1486 }
1487 
1488 /***********************************************************************
1489  *              ImmGetIMEFileNameA (IMM32.@)
1490  */
1491 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1492 {
1493     LPWSTR bufW = NULL;
1494     UINT wBufLen = uBufLen;
1495     UINT rc;
1496 
1497     if (uBufLen && lpszFileName)
1498         bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1499     else /* We need this to get the number of byte required */
1500     {
1501         bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1502         wBufLen = MAX_PATH;
1503     }
1504 
1505     rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1506 
1507     if (rc > 0)
1508     {
1509         if (uBufLen && lpszFileName)
1510             rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1511                                  uBufLen, NULL, NULL);
1512         else /* get the length */
1513             rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1514                                      NULL);
1515     }
1516 
1517     HeapFree(GetProcessHeap(),0,bufW);
1518     return rc;
1519 }
1520 
1521 /***********************************************************************
1522  *              ImmGetIMEFileNameW (IMM32.@)
1523  */
1524 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1525 {
1526     static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
1527     static const WCHAR fmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','','8','x',0};
1528 
1529     HKEY hkey;
1530     DWORD length;
1531     DWORD rc;
1532     WCHAR regKey[sizeof(fmt)/sizeof(WCHAR)+8];
1533 
1534     wsprintfW( regKey, fmt, (unsigned)hKL );
1535     rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1536     if (rc != ERROR_SUCCESS)
1537     {
1538         SetLastError(rc);
1539         return 0;
1540     }
1541 
1542     length = 0;
1543     rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1544 
1545     if (rc != ERROR_SUCCESS)
1546     {
1547         RegCloseKey(hkey);
1548         SetLastError(rc);
1549         return 0;
1550     }
1551     if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1552     {
1553         RegCloseKey(hkey);
1554         if (lpszFileName)
1555         {
1556             SetLastError(ERROR_INSUFFICIENT_BUFFER);
1557             return 0;
1558         }
1559         else
1560             return length / sizeof(WCHAR);
1561     }
1562 
1563     RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1564 
1565     RegCloseKey(hkey);
1566 
1567     return length / sizeof(WCHAR);
1568 }
1569 
1570 /***********************************************************************
1571  *              ImmGetOpenStatus (IMM32.@)
1572  */
1573 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1574 {
1575   InputContextData *data = (InputContextData*)hIMC;
1576 
1577     if (!data)
1578         return FALSE;
1579   FIXME("(%p): semi-stub\n", hIMC);
1580 
1581   return data->IMC.fOpen;
1582 }
1583 
1584 /***********************************************************************
1585  *              ImmGetProperty (IMM32.@)
1586  */
1587 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1588 {
1589     DWORD rc = 0;
1590     ImmHkl *kbd;
1591 
1592     TRACE("(%p, %d)\n", hKL, fdwIndex);
1593     kbd = IMM_GetImmHkl(hKL);
1594 
1595     if (kbd && kbd->hIME)
1596     {
1597         switch (fdwIndex)
1598         {
1599             case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1600             case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1601             case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1602             case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1603             case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1604             case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1605             case IGP_UI: rc = 0; break;
1606             default: rc = 0;
1607         }
1608     }
1609     return rc;
1610 }
1611 
1612 /***********************************************************************
1613  *              ImmGetRegisterWordStyleA (IMM32.@)
1614  */
1615 UINT WINAPI ImmGetRegisterWordStyleA(
1616   HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1617 {
1618     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1619     TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1620     if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1621     {
1622         if (!is_kbd_ime_unicode(immHkl))
1623             return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1624         else
1625         {
1626             STYLEBUFW sbw;
1627             UINT rc;
1628 
1629             rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1630             WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1631                 lpStyleBuf->szDescription, 32, NULL, NULL);
1632             lpStyleBuf->dwStyle = sbw.dwStyle;
1633             return rc;
1634         }
1635     }
1636     else
1637         return 0;
1638 }
1639 
1640 /***********************************************************************
1641  *              ImmGetRegisterWordStyleW (IMM32.@)
1642  */
1643 UINT WINAPI ImmGetRegisterWordStyleW(
1644   HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1645 {
1646     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1647     TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1648     if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1649     {
1650         if (is_kbd_ime_unicode(immHkl))
1651             return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1652         else
1653         {
1654             STYLEBUFA sba;
1655             UINT rc;
1656 
1657             rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1658             MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1659                 lpStyleBuf->szDescription, 32);
1660             lpStyleBuf->dwStyle = sba.dwStyle;
1661             return rc;
1662         }
1663     }
1664     else
1665         return 0;
1666 }
1667 
1668 /***********************************************************************
1669  *              ImmGetStatusWindowPos (IMM32.@)
1670  */
1671 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1672 {
1673     InputContextData *data = (InputContextData*)hIMC;
1674 
1675     TRACE("(%p, %p)\n", hIMC, lpptPos);
1676 
1677     if (!data || !lpptPos)
1678         return FALSE;
1679 
1680     *lpptPos = data->IMC.ptStatusWndPos;
1681 
1682     return TRUE;
1683 }
1684 
1685 /***********************************************************************
1686  *              ImmGetVirtualKey (IMM32.@)
1687  */
1688 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1689 {
1690   OSVERSIONINFOA version;
1691   InputContextData *data = (InputContextData *)ImmGetContext( hWnd );
1692   TRACE("%p\n", hWnd);
1693 
1694   if ( data )
1695       return data->lastVK;
1696 
1697   GetVersionExA( &version );
1698   switch(version.dwPlatformId)
1699   {
1700   case VER_PLATFORM_WIN32_WINDOWS:
1701       return VK_PROCESSKEY;
1702   case VER_PLATFORM_WIN32_NT:
1703       return 0;
1704   default:
1705       FIXME("%d not supported\n",version.dwPlatformId);
1706       return VK_PROCESSKEY;
1707   }
1708 }
1709 
1710 /***********************************************************************
1711  *              ImmInstallIMEA (IMM32.@)
1712  */
1713 HKL WINAPI ImmInstallIMEA(
1714   LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1715 {
1716   FIXME("(%s, %s): stub\n",
1717     debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1718   );
1719   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1720   return NULL;
1721 }
1722 
1723 /***********************************************************************
1724  *              ImmInstallIMEW (IMM32.@)
1725  */
1726 HKL WINAPI ImmInstallIMEW(
1727   LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1728 {
1729   FIXME("(%s, %s): stub\n",
1730     debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1731   );
1732   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1733   return NULL;
1734 }
1735 
1736 /***********************************************************************
1737  *              ImmIsIME (IMM32.@)
1738  */
1739 BOOL WINAPI ImmIsIME(HKL hKL)
1740 {
1741     ImmHkl *ptr;
1742     TRACE("(%p):\n", hKL);
1743     ptr = IMM_GetImmHkl(hKL);
1744     return (ptr && ptr->hIME);
1745 }
1746 
1747 /***********************************************************************
1748  *              ImmIsUIMessageA (IMM32.@)
1749  */
1750 BOOL WINAPI ImmIsUIMessageA(
1751   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1752 {
1753     BOOL rc = FALSE;
1754 
1755     TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1756     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1757         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1758         (msg == WM_MSIME_SERVICE) ||
1759         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1760         (msg == WM_MSIME_MOUSE) ||
1761         (msg == WM_MSIME_RECONVERTREQUEST) ||
1762         (msg == WM_MSIME_RECONVERT) ||
1763         (msg == WM_MSIME_QUERYPOSITION) ||
1764         (msg == WM_MSIME_DOCUMENTFEED))
1765 
1766     {
1767         if (!IMM_GetThreadData()->hwndDefault)
1768             ImmGetDefaultIMEWnd(NULL);
1769 
1770         if (hWndIME == NULL)
1771             PostMessageA(IMM_GetThreadData()->hwndDefault, msg, wParam, lParam);
1772 
1773         rc = TRUE;
1774     }
1775     return rc;
1776 }
1777 
1778 /***********************************************************************
1779  *              ImmIsUIMessageW (IMM32.@)
1780  */
1781 BOOL WINAPI ImmIsUIMessageW(
1782   HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1783 {
1784     BOOL rc = FALSE;
1785     TRACE("(%p, %d, %ld, %ld):\n", hWndIME, msg, wParam, lParam);
1786     if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1787         (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1788         (msg == WM_MSIME_SERVICE) ||
1789         (msg == WM_MSIME_RECONVERTOPTIONS) ||
1790         (msg == WM_MSIME_MOUSE) ||
1791         (msg == WM_MSIME_RECONVERTREQUEST) ||
1792         (msg == WM_MSIME_RECONVERT) ||
1793         (msg == WM_MSIME_QUERYPOSITION) ||
1794         (msg == WM_MSIME_DOCUMENTFEED))
1795         rc = TRUE;
1796     return rc;
1797 }
1798 
1799 /***********************************************************************
1800  *              ImmNotifyIME (IMM32.@)
1801  */
1802 BOOL WINAPI ImmNotifyIME(
1803   HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1804 {
1805     InputContextData *data = (InputContextData*)hIMC;
1806 
1807     TRACE("(%p, %d, %d, %d)\n",
1808         hIMC, dwAction, dwIndex, dwValue);
1809 
1810     if (!data || ! data->immKbd->pNotifyIME)
1811         return FALSE;
1812 
1813     return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
1814 }
1815 
1816 /***********************************************************************
1817  *              ImmRegisterWordA (IMM32.@)
1818  */
1819 BOOL WINAPI ImmRegisterWordA(
1820   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1821 {
1822     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1823     TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
1824                     debugstr_a(lpszRegister));
1825     if (immHkl->hIME && immHkl->pImeRegisterWord)
1826     {
1827         if (!is_kbd_ime_unicode(immHkl))
1828             return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
1829                                             (LPCWSTR)lpszRegister);
1830         else
1831         {
1832             LPWSTR lpszwReading = strdupAtoW(lpszReading);
1833             LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
1834             BOOL rc;
1835 
1836             rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
1837             HeapFree(GetProcessHeap(),0,lpszwReading);
1838             HeapFree(GetProcessHeap(),0,lpszwRegister);
1839             return rc;
1840         }
1841     }
1842     else
1843         return FALSE;
1844 }
1845 
1846 /***********************************************************************
1847  *              ImmRegisterWordW (IMM32.@)
1848  */
1849 BOOL WINAPI ImmRegisterWordW(
1850   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1851 {
1852     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1853     TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
1854                     debugstr_w(lpszRegister));
1855     if (immHkl->hIME && immHkl->pImeRegisterWord)
1856     {
1857         if (is_kbd_ime_unicode(immHkl))
1858             return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
1859         else
1860         {
1861             LPSTR lpszaReading = strdupWtoA(lpszReading);
1862             LPSTR lpszaRegister = strdupWtoA(lpszRegister);
1863             BOOL rc;
1864 
1865             rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
1866                                           (LPCWSTR)lpszaRegister);
1867             HeapFree(GetProcessHeap(),0,lpszaReading);
1868             HeapFree(GetProcessHeap(),0,lpszaRegister);
1869             return rc;
1870         }
1871     }
1872     else
1873         return FALSE;
1874 }
1875 
1876 /***********************************************************************
1877  *              ImmReleaseContext (IMM32.@)
1878  */
1879 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1880 {
1881   static int shown = 0;
1882 
1883   if (!shown) {
1884      FIXME("(%p, %p): stub\n", hWnd, hIMC);
1885      shown = 1;
1886   }
1887   return TRUE;
1888 }
1889 
1890 /***********************************************************************
1891 *              ImmRequestMessageA(IMM32.@)
1892 */
1893 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
1894 {
1895     InputContextData *data = (InputContextData*)hIMC;
1896 
1897     TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
1898 
1899     if (data && IsWindow(data->IMC.hWnd))
1900         return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
1901 
1902      return 0;
1903 }
1904 
1905 /***********************************************************************
1906 *              ImmRequestMessageW(IMM32.@)
1907 */
1908 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
1909 {
1910     InputContextData *data = (InputContextData*)hIMC;
1911 
1912     TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
1913 
1914     if (data && IsWindow(data->IMC.hWnd))
1915         return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
1916 
1917      return 0;
1918 }
1919 
1920 /***********************************************************************
1921  *              ImmSetCandidateWindow (IMM32.@)
1922  */
1923 BOOL WINAPI ImmSetCandidateWindow(
1924   HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1925 {
1926     InputContextData *data = (InputContextData*)hIMC;
1927 
1928     TRACE("(%p, %p)\n", hIMC, lpCandidate);
1929 
1930     if (!data || !lpCandidate)
1931         return FALSE;
1932 
1933     TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
1934             lpCandidate->dwIndex, lpCandidate->dwStyle,
1935             lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
1936             lpCandidate->rcArea.top, lpCandidate->rcArea.left,
1937             lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
1938 
1939     if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1940         return FALSE;
1941 
1942     data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
1943     ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
1944     ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
1945 
1946     return TRUE;
1947 }
1948 
1949 /***********************************************************************
1950  *              ImmSetCompositionFontA (IMM32.@)
1951  */
1952 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1953 {
1954     InputContextData *data = (InputContextData*)hIMC;
1955     TRACE("(%p, %p)\n", hIMC, lplf);
1956 
1957     if (!data || !lplf)
1958         return FALSE;
1959 
1960     memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1961     MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1962                         LF_FACESIZE);
1963     ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
1964     ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1965 
1966     return TRUE;
1967 }
1968 
1969 /***********************************************************************
1970  *              ImmSetCompositionFontW (IMM32.@)
1971  */
1972 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1973 {
1974     InputContextData *data = (InputContextData*)hIMC;
1975     TRACE("(%p, %p)\n", hIMC, lplf);
1976 
1977     if (!data || !lplf)
1978         return FALSE;
1979 
1980     data->IMC.lfFont.W = *lplf;
1981     ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
1982     ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1983 
1984     return TRUE;
1985 }
1986 
1987 /***********************************************************************
1988  *              ImmSetCompositionStringA (IMM32.@)
1989  */
1990 BOOL WINAPI ImmSetCompositionStringA(
1991   HIMC hIMC, DWORD dwIndex,
1992   LPCVOID lpComp, DWORD dwCompLen,
1993   LPCVOID lpRead, DWORD dwReadLen)
1994 {
1995     DWORD comp_len;
1996     DWORD read_len;
1997     WCHAR *CompBuffer = NULL;
1998     WCHAR *ReadBuffer = NULL;
1999     BOOL rc;
2000     InputContextData *data = (InputContextData*)hIMC;
2001 
2002     TRACE("(%p, %d, %p, %d, %p, %d):\n",
2003             hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2004 
2005     if (!data)
2006         return FALSE;
2007 
2008     if (!is_himc_ime_unicode(data))
2009         return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2010                         dwCompLen, lpRead, dwReadLen);
2011 
2012     comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2013     if (comp_len)
2014     {
2015         CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2016         MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2017     }
2018 
2019     read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2020     if (read_len)
2021     {
2022         ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2023         MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2024     }
2025 
2026     rc =  ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2027                                    ReadBuffer, read_len);
2028 
2029     HeapFree(GetProcessHeap(), 0, CompBuffer);
2030     HeapFree(GetProcessHeap(), 0, ReadBuffer);
2031 
2032     return rc;
2033 }
2034 
2035 /***********************************************************************
2036  *              ImmSetCompositionStringW (IMM32.@)
2037  */
2038 BOOL WINAPI ImmSetCompositionStringW(
2039         HIMC hIMC, DWORD dwIndex,
2040         LPCVOID lpComp, DWORD dwCompLen,
2041         LPCVOID lpRead, DWORD dwReadLen)
2042 {
2043     DWORD comp_len;
2044     DWORD read_len;
2045     CHAR *CompBuffer = NULL;
2046     CHAR *ReadBuffer = NULL;
2047     BOOL rc;
2048     InputContextData *data = (InputContextData*)hIMC;
2049 
2050     TRACE("(%p, %d, %p, %d, %p, %d):\n",
2051             hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2052 
2053     if (!data)
2054         return FALSE;
2055 
2056     if (is_himc_ime_unicode(data))
2057         return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2058                         dwCompLen, lpRead, dwReadLen);
2059 
2060     comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2061                                    NULL);
2062     if (comp_len)
2063     {
2064         CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2065         WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2066                             NULL, NULL);
2067     }
2068 
2069     read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2070                                    NULL);
2071     if (read_len)
2072     {
2073         ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2074         WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2075                             NULL, NULL);
2076     }
2077 
2078     rc =  ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2079                                    ReadBuffer, read_len);
2080 
2081     HeapFree(GetProcessHeap(), 0, CompBuffer);
2082     HeapFree(GetProcessHeap(), 0, ReadBuffer);
2083 
2084     return rc;
2085 }
2086 
2087 /***********************************************************************
2088  *              ImmSetCompositionWindow (IMM32.@)
2089  */
2090 BOOL WINAPI ImmSetCompositionWindow(
2091   HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2092 {
2093     BOOL reshow = FALSE;
2094     InputContextData *data = (InputContextData*)hIMC;
2095 
2096     TRACE("(%p, %p)\n", hIMC, lpCompForm);
2097     TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2098           lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2099           lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2100 
2101     if (!data)
2102         return FALSE;
2103 
2104     data->IMC.cfCompForm = *lpCompForm;
2105 
2106     if (IsWindowVisible(IMM_GetThreadData()->hwndDefault))
2107     {
2108         reshow = TRUE;
2109         ShowWindow(IMM_GetThreadData()->hwndDefault,SW_HIDE);
2110     }
2111 
2112     /* FIXME: this is a partial stub */
2113 
2114     if (reshow)
2115         ShowWindow(IMM_GetThreadData()->hwndDefault,SW_SHOWNOACTIVATE);
2116 
2117     ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2118     return TRUE;
2119 }
2120 
2121 /***********************************************************************
2122  *              ImmSetConversionStatus (IMM32.@)
2123  */
2124 BOOL WINAPI ImmSetConversionStatus(
2125   HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2126 {
2127     DWORD oldConversion, oldSentence;
2128     InputContextData *data = (InputContextData*)hIMC;
2129 
2130     TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2131 
2132     if (!data)
2133         return FALSE;
2134 
2135     if ( fdwConversion != data->IMC.fdwConversion )
2136     {
2137         oldConversion = data->IMC.fdwConversion;
2138         data->IMC.fdwConversion = fdwConversion;
2139         ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2140         ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2141     }
2142     if ( fdwSentence != data->IMC.fdwSentence )
2143     {
2144         oldSentence = data->IMC.fdwSentence;
2145         data->IMC.fdwSentence = fdwSentence;
2146         ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2147         ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2148     }
2149 
2150     return TRUE;
2151 }
2152 
2153 /***********************************************************************
2154  *              ImmSetOpenStatus (IMM32.@)
2155  */
2156 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2157 {
2158     InputContextData *data = (InputContextData*)hIMC;
2159 
2160     TRACE("%p %d\n", hIMC, fOpen);
2161 
2162     if (!data)
2163         return FALSE;
2164 
2165     if (data->imeWnd == NULL)
2166     {
2167         /* create the ime window */
2168         data->imeWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2169                     data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2170                     0, data->immKbd->hIME, 0);
2171         SetWindowLongW(data->imeWnd, IMMGWL_IMC, (LONG)data);
2172         IMM_GetThreadData()->hwndDefault = data->imeWnd;
2173     }
2174 
2175     if (!fOpen != !data->IMC.fOpen)
2176     {
2177         data->IMC.fOpen = fOpen;
2178         ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2179         ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2180     }
2181 
2182     return TRUE;
2183 }
2184 
2185 /***********************************************************************
2186  *              ImmSetStatusWindowPos (IMM32.@)
2187  */
2188 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2189 {
2190     InputContextData *data = (InputContextData*)hIMC;
2191 
2192     TRACE("(%p, %p)\n", hIMC, lpptPos);
2193 
2194     if (!data || !lpptPos)
2195         return FALSE;
2196 
2197     TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2198 
2199     data->IMC.ptStatusWndPos = *lpptPos;
2200     ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2201     ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2202 
2203     return TRUE;
2204 }
2205 
2206 /***********************************************************************
2207  *              ImmCreateSoftKeyboard(IMM32.@)
2208  */
2209 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2210 {
2211     FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2212     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2213     return 0;
2214 }
2215 
2216 /***********************************************************************
2217  *              ImmDestroySoftKeyboard(IMM32.@)
2218  */
2219 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2220 {
2221     FIXME("(%p): stub\n", hSoftWnd);
2222     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2223     return FALSE;
2224 }
2225 
2226 /***********************************************************************
2227  *              ImmShowSoftKeyboard(IMM32.@)
2228  */
2229 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2230 {
2231     FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2232     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2233     return FALSE;
2234 }
2235 
2236 /***********************************************************************
2237  *              ImmSimulateHotKey (IMM32.@)
2238  */
2239 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2240 {
2241   FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2242   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2243   return FALSE;
2244 }
2245 
2246 /***********************************************************************
2247  *              ImmUnregisterWordA (IMM32.@)
2248  */
2249 BOOL WINAPI ImmUnregisterWordA(
2250   HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2251 {
2252     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2253     TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2254             debugstr_a(lpszUnregister));
2255     if (immHkl->hIME && immHkl->pImeUnregisterWord)
2256     {
2257         if (!is_kbd_ime_unicode(immHkl))
2258             return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2259                                               (LPCWSTR)lpszUnregister);
2260         else
2261         {
2262             LPWSTR lpszwReading = strdupAtoW(lpszReading);
2263             LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2264             BOOL rc;
2265 
2266             rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2267             HeapFree(GetProcessHeap(),0,lpszwReading);
2268             HeapFree(GetProcessHeap(),0,lpszwUnregister);
2269             return rc;
2270         }
2271     }
2272     else
2273         return FALSE;
2274 }
2275 
2276 /***********************************************************************
2277  *              ImmUnregisterWordW (IMM32.@)
2278  */
2279 BOOL WINAPI ImmUnregisterWordW(
2280   HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2281 {
2282     ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2283     TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2284             debugstr_w(lpszUnregister));
2285     if (immHkl->hIME && immHkl->pImeUnregisterWord)
2286     {
2287         if (is_kbd_ime_unicode(immHkl))
2288             return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2289         else
2290         {
2291             LPSTR lpszaReading = strdupWtoA(lpszReading);
2292             LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2293             BOOL rc;
2294 
2295             rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2296                                             (LPCWSTR)lpszaUnregister);
2297             HeapFree(GetProcessHeap(),0,lpszaReading);
2298             HeapFree(GetProcessHeap(),0,lpszaUnregister);
2299             return rc;
2300         }
2301     }
2302     else
2303         return FALSE;
2304 }
2305 
2306 /***********************************************************************
2307  *              ImmGetImeMenuItemsA (IMM32.@)
2308  */
2309 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2310    LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2311     DWORD dwSize)
2312 {
2313     InputContextData *data = (InputContextData*)hIMC;
2314     TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2315         lpImeParentMenu, lpImeMenu, dwSize);
2316     if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2317     {
2318         if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2319             return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2320                                 (IMEMENUITEMINFOW*)lpImeParentMenu,
2321                                 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2322         else
2323         {
2324             IMEMENUITEMINFOW lpImeParentMenuW;
2325             IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2326             DWORD rc;
2327 
2328             if (lpImeParentMenu)
2329                 parent = &lpImeParentMenuW;
2330             if (lpImeMenu)
2331             {
2332                 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2333                 dwSize = count * sizeof(IMEMENUITEMINFOW);
2334                 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2335             }
2336             else
2337                 lpImeMenuW = NULL;
2338 
2339             rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2340                                 parent, lpImeMenuW, dwSize);
2341 
2342             if (lpImeParentMenu)
2343             {
2344                 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2345                 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2346                 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2347                     -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2348                     NULL, NULL);
2349             }
2350             if (lpImeMenu && rc)
2351             {
2352                 unsigned int i;
2353                 for (i = 0; i < rc; i++)
2354                 {
2355                     memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2356                     lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2357                     WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2358                         -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2359                         NULL, NULL);
2360                 }
2361             }
2362             HeapFree(GetProcessHeap(),0,lpImeMenuW);
2363             return rc;
2364         }
2365     }
2366     else
2367         return 0;
2368 }
2369 
2370 /***********************************************************************
2371 *               ImmGetImeMenuItemsW (IMM32.@)
2372 */
2373 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2374    LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2375    DWORD dwSize)
2376 {
2377     InputContextData *data = (InputContextData*)hIMC;
2378     TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2379         lpImeParentMenu, lpImeMenu, dwSize);
2380     if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2381     {
2382         if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2383             return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2384                                 lpImeParentMenu, lpImeMenu, dwSize);
2385         else
2386         {
2387             IMEMENUITEMINFOA lpImeParentMenuA;
2388             IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2389             DWORD rc;
2390 
2391             if (lpImeParentMenu)
2392                 parent = &lpImeParentMenuA;
2393             if (lpImeMenu)
2394             {
2395                 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2396                 dwSize = count * sizeof(IMEMENUITEMINFOA);
2397                 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2398             }
2399             else
2400                 lpImeMenuA = NULL;
2401 
2402             rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2403                                 (IMEMENUITEMINFOW*)parent,
2404                                 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2405 
2406             if (lpImeParentMenu)
2407             {
2408                 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2409                 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2410                 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2411                     -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2412             }
2413             if (lpImeMenu && rc)
2414             {
2415                 unsigned int i;
2416                 for (i = 0; i < rc; i++)
2417                 {
2418                     memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2419                     lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2420                     MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2421                         -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2422                 }
2423             }
2424             HeapFree(GetProcessHeap(),0,lpImeMenuA);
2425             return rc;
2426         }
2427     }
2428     else
2429         return 0;
2430 }
2431 
2432 /***********************************************************************
2433 *               ImmLockIMC(IMM32.@)
2434 */
2435 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2436 {
2437     InputContextData *data = (InputContextData*)hIMC;
2438 
2439     if (!data)
2440         return NULL;
2441     data->dwLock++;
2442     return &data->IMC;
2443 }
2444 
2445 /***********************************************************************
2446 *               ImmUnlockIMC(IMM32.@)
2447 */
2448 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2449 {
2450     InputContextData *data = (InputContextData*)hIMC;
2451     data->dwLock--;
2452     return (data->dwLock!=0);
2453 }
2454 
2455 /***********************************************************************
2456 *               ImmGetIMCLockCount(IMM32.@)
2457 */
2458 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2459 {
2460     InputContextData *data = (InputContextData*)hIMC;
2461     return data->dwLock;
2462 }
2463 
2464 /***********************************************************************
2465 *               ImmCreateIMCC(IMM32.@)
2466 */
2467 HIMCC  WINAPI ImmCreateIMCC(DWORD size)
2468 {
2469     IMCCInternal *internal;
2470     int real_size = size + sizeof(IMCCInternal);
2471 
2472     internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2473     if (internal == NULL)
2474         return NULL;
2475 
2476     internal->dwSize = size;
2477     return  (HIMCC)internal;
2478 }
2479 
2480 /***********************************************************************
2481 *       ImmDestroyIMCC(IMM32.@)
2482 */
2483 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2484 {
2485     HeapFree(GetProcessHeap(),0,block);
2486     return NULL;
2487 }
2488 
2489 /***********************************************************************
2490 *               ImmLockIMCC(IMM32.@)
2491 */
2492 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2493 {
2494     IMCCInternal *internal;
2495     internal = (IMCCInternal*) imcc;
2496 
2497     internal->dwLock ++;
2498     return internal + 1;
2499 }
2500 
2501 /***********************************************************************
2502 *               ImmUnlockIMCC(IMM32.@)
2503 */
2504 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2505 {
2506     IMCCInternal *internal;
2507     internal = (IMCCInternal*) imcc;
2508 
2509     internal->dwLock --;
2510     return (internal->dwLock!=0);
2511 }
2512 
2513 /***********************************************************************
2514 *               ImmGetIMCCLockCount(IMM32.@)
2515 */
2516 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2517 {
2518     IMCCInternal *internal;
2519     internal = (IMCCInternal*) imcc;
2520 
2521     return internal->dwLock;
2522 }
2523 
2524 /***********************************************************************
2525 *               ImmReSizeIMCC(IMM32.@)
2526 */
2527 HIMCC  WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2528 {
2529     IMCCInternal *internal,*newone;
2530     int real_size = size + sizeof(IMCCInternal);
2531 
2532     internal = (IMCCInternal*) imcc;
2533 
2534     newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2535     newone->dwSize = size;
2536 
2537     return newone;
2538 }
2539 
2540 /***********************************************************************
2541 *               ImmGetIMCCSize(IMM32.@)
2542 */
2543 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2544 {
2545     IMCCInternal *internal;
2546     internal = (IMCCInternal*) imcc;
2547 
2548     return internal->dwSize;
2549 }
2550 
2551 /***********************************************************************
2552 *               ImmGenerateMessage(IMM32.@)
2553 */
2554 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2555 {
2556     InputContextData *data = (InputContextData*)hIMC;
2557 
2558     TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2559     if (data->IMC.dwNumMsgBuf > 0)
2560     {
2561         LPTRANSMSG lpTransMsg;
2562         DWORD i;
2563 
2564         lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
2565         for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2566             ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2567 
2568         ImmUnlockIMCC(data->IMC.hMsgBuf);
2569 
2570         data->IMC.dwNumMsgBuf = 0;
2571     }
2572 
2573     return TRUE;
2574 }
2575 
2576 /***********************************************************************
2577 *       ImmTranslateMessage(IMM32.@)
2578 *       ( Undocumented, call internally and from user32.dll )
2579 */
2580 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2581 {
2582     InputContextData *data;
2583     HIMC imc = ImmGetContext(hwnd);
2584     BYTE state[256];
2585     UINT scancode;
2586     LPVOID list = 0;
2587     UINT msg_count;
2588     UINT uVirtKey;
2589     static const DWORD list_count = 10;
2590 
2591     TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2592 
2593     if (imc)
2594         data = (InputContextData*)imc;
2595     else
2596         return FALSE;
2597 
2598     if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2599         return FALSE;
2600 
2601     GetKeyboardState(state);
2602     scancode = lKeyData >> 0x10 & 0xff;
2603 
2604     list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2605     ((DWORD*)list)[0] = list_count;
2606 
2607     if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2608     {
2609         WCHAR chr;
2610 
2611         if (!is_himc_ime_unicode(data))
2612             ToAscii(data->lastVK, scancode, state, &chr, 0);
2613         else
2614             ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2615         uVirtKey = MAKELONG(data->lastVK,chr);
2616     }
2617     else
2618         uVirtKey = data->lastVK;
2619 
2620     msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2621     TRACE("%i messages generated\n",msg_count);
2622     if (msg_count && msg_count <= list_count)
2623     {
2624         UINT i;
2625         LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2626 
2627         for (i = 0; i < msg_count; i++)
2628             ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2629     }
2630     else if (msg_count > list_count)
2631         ImmGenerateMessage(imc);
2632 
2633     HeapFree(GetProcessHeap(),0,list);
2634 
2635     data->lastVK = VK_PROCESSKEY;
2636 
2637     return (msg_count > 0);
2638 }
2639 
2640 /***********************************************************************
2641 *               ImmProcessKey(IMM32.@)
2642 *       ( Undocumented, called from user32.dll )
2643 */
2644 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2645 {
2646     InputContextData *data;
2647     HIMC imc = ImmGetContext(hwnd);
2648     BYTE state[256];
2649 
2650     TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2651 
2652     if (imc)
2653         data = (InputContextData*)imc;
2654     else
2655         return FALSE;
2656 
2657     if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
2658         return FALSE;
2659 
2660     GetKeyboardState(state);
2661     if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
2662     {
2663         data->lastVK = vKey;
2664         return TRUE;
2665     }
2666 
2667     data->lastVK = VK_PROCESSKEY;
2668     return FALSE;
2669 }
2670 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.