imm32: Avoid null pointer dereference in trace.
[wine.git] / dlls / imm32 / imm.c
blob85b104534002d0b7912e3944837a5a59b6a8c5b2
1 /*
2 * IMM32 library
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
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.
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.
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
22 #include <stdarg.h>
23 #include <stdio.h>
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 #include "wine/unicode.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(imm);
40 #define IMM_INIT_MAGIC 0x19650412
41 BOOL WINAPI User32InitializeImmEntryTable(DWORD);
43 #define MAKE_FUNCPTR(f) typeof(f) * p##f
44 typedef struct _tagImmHkl{
45 struct list entry;
46 HKL hkl;
47 HMODULE hIME;
48 IMEINFO imeInfo;
49 WCHAR imeClassName[17]; /* 16 character max */
50 ULONG uSelected;
51 HWND UIWnd;
53 /* Function Pointers */
54 MAKE_FUNCPTR(ImeInquire);
55 MAKE_FUNCPTR(ImeConfigure);
56 MAKE_FUNCPTR(ImeDestroy);
57 MAKE_FUNCPTR(ImeEscape);
58 MAKE_FUNCPTR(ImeSelect);
59 MAKE_FUNCPTR(ImeSetActiveContext);
60 MAKE_FUNCPTR(ImeToAsciiEx);
61 MAKE_FUNCPTR(NotifyIME);
62 MAKE_FUNCPTR(ImeRegisterWord);
63 MAKE_FUNCPTR(ImeUnregisterWord);
64 MAKE_FUNCPTR(ImeEnumRegisterWord);
65 MAKE_FUNCPTR(ImeSetCompositionString);
66 MAKE_FUNCPTR(ImeConversionList);
67 MAKE_FUNCPTR(ImeProcessKey);
68 MAKE_FUNCPTR(ImeGetRegisterWordStyle);
69 MAKE_FUNCPTR(ImeGetImeMenuItems);
70 } ImmHkl;
71 #undef MAKE_FUNCPTR
73 typedef struct tagInputContextData
75 DWORD dwLock;
76 INPUTCONTEXT IMC;
77 DWORD threadID;
79 ImmHkl *immKbd;
80 UINT lastVK;
81 BOOL threadDefault;
82 DWORD magic;
83 } InputContextData;
85 #define WINE_IMC_VALID_MAGIC 0x56434D49
87 typedef struct _tagTRANSMSG {
88 UINT message;
89 WPARAM wParam;
90 LPARAM lParam;
91 } TRANSMSG, *LPTRANSMSG;
93 typedef struct _tagIMMThreadData {
94 struct list entry;
95 DWORD threadID;
96 HIMC defaultContext;
97 HWND hwndDefault;
98 } IMMThreadData;
100 static struct list ImmHklList = LIST_INIT(ImmHklList);
101 static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList);
103 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
105 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
106 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
107 static const WCHAR szImeRegFmt[] = {'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','\\','%','0','8','l','x',0};
109 static const WCHAR szwIME[] = {'I','M','E',0};
111 static CRITICAL_SECTION threaddata_cs;
112 static CRITICAL_SECTION_DEBUG critsect_debug =
114 0, 0, &threaddata_cs,
115 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
116 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
118 static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
120 #define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
121 #define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
123 static BOOL IMM_DestroyContext(HIMC hIMC);
124 static InputContextData* get_imc_data(HIMC hIMC);
126 static inline WCHAR *strdupAtoW( const char *str )
128 WCHAR *ret = NULL;
129 if (str)
131 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
132 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
133 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
135 return ret;
138 static inline CHAR *strdupWtoA( const WCHAR *str )
140 CHAR *ret = NULL;
141 if (str)
143 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
144 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
145 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
147 return ret;
150 static DWORD convert_candidatelist_WtoA(
151 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
153 DWORD ret, i, len;
155 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
156 if ( lpDst && dwBufLen > 0 )
158 *lpDst = *lpSrc;
159 lpDst->dwOffset[0] = ret;
162 for ( i = 0; i < lpSrc->dwCount; i++)
164 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
166 if ( lpDst && dwBufLen > 0 )
168 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
170 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1,
171 (LPSTR)dest, dwBufLen, NULL, NULL);
173 if ( i + 1 < lpSrc->dwCount )
174 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
175 dwBufLen -= len * sizeof(char);
177 else
178 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL);
180 ret += len * sizeof(char);
183 if ( lpDst )
184 lpDst->dwSize = ret;
186 return ret;
189 static DWORD convert_candidatelist_AtoW(
190 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
192 DWORD ret, i, len;
194 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
195 if ( lpDst && dwBufLen > 0 )
197 *lpDst = *lpSrc;
198 lpDst->dwOffset[0] = ret;
201 for ( i = 0; i < lpSrc->dwCount; i++)
203 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
205 if ( lpDst && dwBufLen > 0 )
207 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
209 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1,
210 (LPWSTR)dest, dwBufLen);
212 if ( i + 1 < lpSrc->dwCount )
213 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
214 dwBufLen -= len * sizeof(WCHAR);
216 else
217 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
219 ret += len * sizeof(WCHAR);
222 if ( lpDst )
223 lpDst->dwSize = ret;
225 return ret;
228 static IMMThreadData *IMM_GetThreadData(HWND hwnd)
230 IMMThreadData *data;
231 DWORD process, thread;
233 if (hwnd)
235 if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL;
236 if (process != GetCurrentProcessId()) return NULL;
238 else thread = GetCurrentThreadId();
240 EnterCriticalSection(&threaddata_cs);
241 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
242 if (data->threadID == thread) return data;
244 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
245 data->threadID = thread;
246 list_add_head(&ImmThreadDataList,&data->entry);
247 TRACE("Thread Data Created (%x)\n",thread);
248 return data;
251 static BOOL IMM_IsDefaultContext(HIMC imc)
253 InputContextData *data = get_imc_data(imc);
255 if (!data)
256 return FALSE;
258 return data->threadDefault;
261 static void IMM_FreeThreadData(void)
263 IMMThreadData *data;
265 EnterCriticalSection(&threaddata_cs);
266 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
268 if (data->threadID == GetCurrentThreadId())
270 list_remove(&data->entry);
271 LeaveCriticalSection(&threaddata_cs);
272 IMM_DestroyContext(data->defaultContext);
273 HeapFree(GetProcessHeap(),0,data);
274 TRACE("Thread Data Destroyed\n");
275 return;
278 LeaveCriticalSection(&threaddata_cs);
281 static HMODULE load_graphics_driver(void)
283 static const WCHAR display_device_guid_propW[] = {
284 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
285 'd','e','v','i','c','e','_','g','u','i','d',0 };
286 static const WCHAR key_pathW[] = {
287 'S','y','s','t','e','m','\\',
288 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
289 'C','o','n','t','r','o','l','\\',
290 'V','i','d','e','o','\\','{',0};
291 static const WCHAR displayW[] = {'}','\\','0','0','0','0',0};
292 static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
294 HMODULE ret = 0;
295 HKEY hkey;
296 DWORD size;
297 WCHAR path[MAX_PATH];
298 WCHAR key[(sizeof(key_pathW) + sizeof(displayW)) / sizeof(WCHAR) + 40];
299 UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
301 if (!guid_atom) return 0;
302 memcpy( key, key_pathW, sizeof(key_pathW) );
303 if (!GlobalGetAtomNameW( guid_atom, key + strlenW(key), 40 )) return 0;
304 strcatW( key, displayW );
305 if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
306 size = sizeof(path);
307 if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path );
308 RegCloseKey( hkey );
309 TRACE( "%s %p\n", debugstr_w(path), ret );
310 return ret;
313 /* ImmHkl loading and freeing */
314 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
315 static ImmHkl *IMM_GetImmHkl(HKL hkl)
317 ImmHkl *ptr;
318 WCHAR filename[MAX_PATH];
320 TRACE("Seeking ime for keyboard %p\n",hkl);
322 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
324 if (ptr->hkl == hkl)
325 return ptr;
327 /* not found... create it */
329 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
331 ptr->hkl = hkl;
332 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
333 if (!ptr->hIME) ptr->hIME = load_graphics_driver();
334 if (ptr->hIME)
336 LOAD_FUNCPTR(ImeInquire);
337 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
339 FreeLibrary(ptr->hIME);
340 ptr->hIME = NULL;
342 else
344 LOAD_FUNCPTR(ImeDestroy);
345 LOAD_FUNCPTR(ImeSelect);
346 if (!ptr->pImeSelect || !ptr->pImeDestroy)
348 FreeLibrary(ptr->hIME);
349 ptr->hIME = NULL;
351 else
353 LOAD_FUNCPTR(ImeConfigure);
354 LOAD_FUNCPTR(ImeEscape);
355 LOAD_FUNCPTR(ImeSetActiveContext);
356 LOAD_FUNCPTR(ImeToAsciiEx);
357 LOAD_FUNCPTR(NotifyIME);
358 LOAD_FUNCPTR(ImeRegisterWord);
359 LOAD_FUNCPTR(ImeUnregisterWord);
360 LOAD_FUNCPTR(ImeEnumRegisterWord);
361 LOAD_FUNCPTR(ImeSetCompositionString);
362 LOAD_FUNCPTR(ImeConversionList);
363 LOAD_FUNCPTR(ImeProcessKey);
364 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
365 LOAD_FUNCPTR(ImeGetImeMenuItems);
366 /* make sure our classname is WCHAR */
367 if (!is_kbd_ime_unicode(ptr))
369 WCHAR bufW[17];
370 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
371 -1, bufW, 17);
372 lstrcpyW(ptr->imeClassName, bufW);
377 list_add_head(&ImmHklList,&ptr->entry);
379 return ptr;
381 #undef LOAD_FUNCPTR
383 HWND WINAPI __wine_get_ui_window(HKL hkl)
385 ImmHkl *immHkl = IMM_GetImmHkl(hkl);
386 return immHkl->UIWnd;
389 static void IMM_FreeAllImmHkl(void)
391 ImmHkl *ptr,*cursor2;
393 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
395 list_remove(&ptr->entry);
396 if (ptr->hIME)
398 ptr->pImeDestroy(1);
399 FreeLibrary(ptr->hIME);
401 if (ptr->UIWnd)
402 DestroyWindow(ptr->UIWnd);
403 HeapFree(GetProcessHeap(),0,ptr);
407 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
409 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
410 switch (fdwReason)
412 case DLL_PROCESS_ATTACH:
413 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
415 return FALSE;
417 break;
418 case DLL_THREAD_ATTACH:
419 break;
420 case DLL_THREAD_DETACH:
421 IMM_FreeThreadData();
422 break;
423 case DLL_PROCESS_DETACH:
424 if (lpReserved) break;
425 IMM_FreeThreadData();
426 IMM_FreeAllImmHkl();
427 break;
429 return TRUE;
432 /* for posting messages as the IME */
433 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
435 HWND target = GetFocus();
436 if (!target)
437 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
438 else
439 PostMessageW(target, msg, wParam, lParam);
442 /* for sending messages as the IME */
443 static void ImmInternalSendIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
445 HWND target = GetFocus();
446 if (!target)
447 SendMessageW(data->IMC.hWnd,msg,wParam,lParam);
448 else
449 SendMessageW(target, msg, wParam, lParam);
452 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
454 HWND target;
456 target = data->IMC.hWnd;
457 if (!target) target = GetFocus();
459 if (target)
460 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
462 return 0;
465 static HIMCC ImmCreateBlankCompStr(void)
467 HIMCC rc;
468 LPCOMPOSITIONSTRING ptr;
469 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
470 ptr = ImmLockIMCC(rc);
471 memset(ptr,0,sizeof(COMPOSITIONSTRING));
472 ptr->dwSize = sizeof(COMPOSITIONSTRING);
473 ImmUnlockIMCC(rc);
474 return rc;
477 static InputContextData* get_imc_data(HIMC hIMC)
479 InputContextData *data = hIMC;
481 if (hIMC == NULL)
482 return NULL;
484 if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
486 SetLastError(ERROR_INVALID_HANDLE);
487 return NULL;
489 return data;
492 static HIMC get_default_context( HWND hwnd )
494 HIMC ret;
495 IMMThreadData* thread_data = IMM_GetThreadData( hwnd );
497 if (!thread_data) return 0;
499 if (thread_data->defaultContext)
501 ret = thread_data->defaultContext;
502 LeaveCriticalSection(&threaddata_cs);
503 return ret;
506 /* can't create a default context in another thread */
507 if (thread_data->threadID != GetCurrentThreadId())
509 LeaveCriticalSection(&threaddata_cs);
510 return 0;
513 LeaveCriticalSection(&threaddata_cs);
515 ret = ImmCreateContext();
516 if (!ret) return 0;
517 ((InputContextData*)ret)->threadDefault = TRUE;
519 /* thread_data is in the current thread so we can assume it's still valid */
520 EnterCriticalSection(&threaddata_cs);
522 if (thread_data->defaultContext) /* someone beat us */
524 IMM_DestroyContext( ret );
525 ret = thread_data->defaultContext;
527 else thread_data->defaultContext = ret;
529 LeaveCriticalSection(&threaddata_cs);
530 return ret;
533 static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
535 InputContextData *data;
537 if (hWnd)
539 DWORD thread = GetWindowThreadProcessId(hWnd, NULL);
540 if (thread != GetCurrentThreadId()) return TRUE;
542 data = get_imc_data(hIMC);
543 if (data && data->threadID != GetCurrentThreadId())
544 return TRUE;
546 return FALSE;
549 /***********************************************************************
550 * ImmAssociateContext (IMM32.@)
552 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
554 HIMC old = NULL;
555 InputContextData *data = get_imc_data(hIMC);
557 TRACE("(%p, %p):\n", hWnd, hIMC);
559 if(hIMC && !data)
560 return NULL;
563 * If already associated just return
565 if (hIMC && data->IMC.hWnd == hWnd)
566 return hIMC;
568 if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
569 return NULL;
571 if (hWnd)
573 HIMC defaultContext = get_default_context( hWnd );
574 old = RemovePropW(hWnd,szwWineIMCProperty);
576 if (old == NULL)
577 old = defaultContext;
578 else if (old == (HIMC)-1)
579 old = NULL;
581 if (hIMC != defaultContext)
583 if (hIMC == NULL) /* Meaning disable imm for that window*/
584 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
585 else
586 SetPropW(hWnd,szwWineIMCProperty,hIMC);
589 if (old)
591 InputContextData *old_data = old;
592 if (old_data->IMC.hWnd == hWnd)
593 old_data->IMC.hWnd = NULL;
597 if (!hIMC)
598 return old;
600 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
601 data->IMC.hWnd = hWnd;
602 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
604 return old;
609 * Helper function for ImmAssociateContextEx
611 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
613 HIMC hImc = (HIMC)lParam;
614 ImmAssociateContext(hwnd,hImc);
615 return TRUE;
618 /***********************************************************************
619 * ImmAssociateContextEx (IMM32.@)
621 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
623 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
625 if (!hWnd)
626 return FALSE;
628 switch (dwFlags)
630 case 0:
631 ImmAssociateContext(hWnd,hIMC);
632 return TRUE;
633 case IACE_DEFAULT:
635 HIMC defaultContext = get_default_context( hWnd );
636 if (!defaultContext) return FALSE;
637 ImmAssociateContext(hWnd,defaultContext);
638 return TRUE;
640 case IACE_IGNORENOCONTEXT:
641 if (GetPropW(hWnd,szwWineIMCProperty))
642 ImmAssociateContext(hWnd,hIMC);
643 return TRUE;
644 case IACE_CHILDREN:
645 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC);
646 return TRUE;
647 default:
648 FIXME("Unknown dwFlags 0x%x\n",dwFlags);
649 return FALSE;
653 /***********************************************************************
654 * ImmConfigureIMEA (IMM32.@)
656 BOOL WINAPI ImmConfigureIMEA(
657 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
659 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
661 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
663 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
664 return FALSE;
666 if (immHkl->hIME && immHkl->pImeConfigure)
668 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
669 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
670 else
672 REGISTERWORDW rww;
673 REGISTERWORDA *rwa = lpData;
674 BOOL rc;
676 rww.lpReading = strdupAtoW(rwa->lpReading);
677 rww.lpWord = strdupAtoW(rwa->lpWord);
678 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
679 HeapFree(GetProcessHeap(),0,rww.lpReading);
680 HeapFree(GetProcessHeap(),0,rww.lpWord);
681 return rc;
684 else
685 return FALSE;
688 /***********************************************************************
689 * ImmConfigureIMEW (IMM32.@)
691 BOOL WINAPI ImmConfigureIMEW(
692 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
694 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
696 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
698 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
699 return FALSE;
701 if (immHkl->hIME && immHkl->pImeConfigure)
703 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
704 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
705 else
707 REGISTERWORDW *rww = lpData;
708 REGISTERWORDA rwa;
709 BOOL rc;
711 rwa.lpReading = strdupWtoA(rww->lpReading);
712 rwa.lpWord = strdupWtoA(rww->lpWord);
713 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
714 HeapFree(GetProcessHeap(),0,rwa.lpReading);
715 HeapFree(GetProcessHeap(),0,rwa.lpWord);
716 return rc;
719 else
720 return FALSE;
723 /***********************************************************************
724 * ImmCreateContext (IMM32.@)
726 HIMC WINAPI ImmCreateContext(void)
728 InputContextData *new_context;
729 LPGUIDELINE gl;
730 LPCANDIDATEINFO ci;
731 int i;
733 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
735 /* Load the IME */
736 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
738 if (!new_context->immKbd->hIME)
740 TRACE("IME dll could not be loaded\n");
741 HeapFree(GetProcessHeap(),0,new_context);
742 return 0;
745 /* the HIMCCs are never NULL */
746 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
747 new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
748 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
749 ci = ImmLockIMCC(new_context->IMC.hCandInfo);
750 memset(ci,0,sizeof(CANDIDATEINFO));
751 ci->dwSize = sizeof(CANDIDATEINFO);
752 ImmUnlockIMCC(new_context->IMC.hCandInfo);
753 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
754 gl = ImmLockIMCC(new_context->IMC.hGuideLine);
755 memset(gl,0,sizeof(GUIDELINE));
756 gl->dwSize = sizeof(GUIDELINE);
757 ImmUnlockIMCC(new_context->IMC.hGuideLine);
759 for (i = 0; i < sizeof(new_context->IMC.cfCandForm) / sizeof(CANDIDATEFORM); i++)
760 new_context->IMC.cfCandForm[i].dwIndex = ~0u;
762 /* Initialize the IME Private */
763 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
765 new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps;
766 new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps;
768 if (!new_context->immKbd->pImeSelect(new_context, TRUE))
770 TRACE("Selection of IME failed\n");
771 IMM_DestroyContext(new_context);
772 return 0;
774 new_context->threadID = GetCurrentThreadId();
775 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd);
777 new_context->immKbd->uSelected++;
778 TRACE("Created context %p\n",new_context);
780 new_context->magic = WINE_IMC_VALID_MAGIC;
781 return new_context;
784 static BOOL IMM_DestroyContext(HIMC hIMC)
786 InputContextData *data = get_imc_data(hIMC);
788 TRACE("Destroying %p\n",hIMC);
790 if (!data)
791 return FALSE;
793 data->immKbd->uSelected --;
794 data->immKbd->pImeSelect(hIMC, FALSE);
795 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd);
797 ImmDestroyIMCC(data->IMC.hCompStr);
798 ImmDestroyIMCC(data->IMC.hCandInfo);
799 ImmDestroyIMCC(data->IMC.hGuideLine);
800 ImmDestroyIMCC(data->IMC.hPrivate);
801 ImmDestroyIMCC(data->IMC.hMsgBuf);
803 data->magic = 0;
804 HeapFree(GetProcessHeap(),0,data);
806 return TRUE;
809 /***********************************************************************
810 * ImmDestroyContext (IMM32.@)
812 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
814 if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
815 return IMM_DestroyContext(hIMC);
816 else
817 return FALSE;
820 /***********************************************************************
821 * ImmDisableIME (IMM32.@)
823 BOOL WINAPI ImmDisableIME(DWORD idThread)
825 FIXME("(%d): stub\n", idThread);
826 return TRUE;
829 /***********************************************************************
830 * ImmEnumRegisterWordA (IMM32.@)
832 UINT WINAPI ImmEnumRegisterWordA(
833 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
834 LPCSTR lpszReading, DWORD dwStyle,
835 LPCSTR lpszRegister, LPVOID lpData)
837 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
838 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
839 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
840 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
842 if (!is_kbd_ime_unicode(immHkl))
843 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
844 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
845 else
847 LPWSTR lpszwReading = strdupAtoW(lpszReading);
848 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
849 BOOL rc;
851 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
852 lpszwReading, dwStyle, lpszwRegister,
853 lpData);
855 HeapFree(GetProcessHeap(),0,lpszwReading);
856 HeapFree(GetProcessHeap(),0,lpszwRegister);
857 return rc;
860 else
861 return 0;
864 /***********************************************************************
865 * ImmEnumRegisterWordW (IMM32.@)
867 UINT WINAPI ImmEnumRegisterWordW(
868 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
869 LPCWSTR lpszReading, DWORD dwStyle,
870 LPCWSTR lpszRegister, LPVOID lpData)
872 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
873 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
874 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
875 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
877 if (is_kbd_ime_unicode(immHkl))
878 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
879 lpszRegister, lpData);
880 else
882 LPSTR lpszaReading = strdupWtoA(lpszReading);
883 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
884 BOOL rc;
886 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
887 dwStyle, (LPCWSTR)lpszaRegister, lpData);
889 HeapFree(GetProcessHeap(),0,lpszaReading);
890 HeapFree(GetProcessHeap(),0,lpszaRegister);
891 return rc;
894 else
895 return 0;
898 static inline BOOL EscapeRequiresWA(UINT uEscape)
900 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
901 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
902 uEscape == IME_ESC_IME_NAME ||
903 uEscape == IME_ESC_GETHELPFILENAME)
904 return TRUE;
905 return FALSE;
908 /***********************************************************************
909 * ImmEscapeA (IMM32.@)
911 LRESULT WINAPI ImmEscapeA(
912 HKL hKL, HIMC hIMC,
913 UINT uEscape, LPVOID lpData)
915 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
916 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
918 if (immHkl->hIME && immHkl->pImeEscape)
920 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
921 return immHkl->pImeEscape(hIMC,uEscape,lpData);
922 else
924 WCHAR buffer[81]; /* largest required buffer should be 80 */
925 LRESULT rc;
926 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
928 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
929 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
931 else
933 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
934 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
936 return rc;
939 else
940 return 0;
943 /***********************************************************************
944 * ImmEscapeW (IMM32.@)
946 LRESULT WINAPI ImmEscapeW(
947 HKL hKL, HIMC hIMC,
948 UINT uEscape, LPVOID lpData)
950 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
951 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
953 if (immHkl->hIME && immHkl->pImeEscape)
955 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
956 return immHkl->pImeEscape(hIMC,uEscape,lpData);
957 else
959 CHAR buffer[81]; /* largest required buffer should be 80 */
960 LRESULT rc;
961 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
963 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
964 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
966 else
968 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
969 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
971 return rc;
974 else
975 return 0;
978 /***********************************************************************
979 * ImmGetCandidateListA (IMM32.@)
981 DWORD WINAPI ImmGetCandidateListA(
982 HIMC hIMC, DWORD dwIndex,
983 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
985 InputContextData *data = get_imc_data(hIMC);
986 LPCANDIDATEINFO candinfo;
987 LPCANDIDATELIST candlist;
988 DWORD ret = 0;
990 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
992 if (!data || !data->IMC.hCandInfo)
993 return 0;
995 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
996 if ( dwIndex >= candinfo->dwCount ||
997 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
998 goto done;
1000 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1001 if ( !candlist->dwSize || !candlist->dwCount )
1002 goto done;
1004 if ( !is_himc_ime_unicode(data) )
1006 ret = candlist->dwSize;
1007 if ( lpCandList && dwBufLen >= ret )
1008 memcpy(lpCandList, candlist, ret);
1010 else
1011 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
1013 done:
1014 ImmUnlockIMCC(data->IMC.hCandInfo);
1015 return ret;
1018 /***********************************************************************
1019 * ImmGetCandidateListCountA (IMM32.@)
1021 DWORD WINAPI ImmGetCandidateListCountA(
1022 HIMC hIMC, LPDWORD lpdwListCount)
1024 InputContextData *data = get_imc_data(hIMC);
1025 LPCANDIDATEINFO candinfo;
1026 DWORD ret, count;
1028 TRACE("%p, %p\n", hIMC, lpdwListCount);
1030 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
1031 return 0;
1033 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1035 *lpdwListCount = count = candinfo->dwCount;
1037 if ( !is_himc_ime_unicode(data) )
1038 ret = candinfo->dwSize;
1039 else
1041 ret = sizeof(CANDIDATEINFO);
1042 while ( count-- )
1043 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
1046 ImmUnlockIMCC(data->IMC.hCandInfo);
1047 return ret;
1050 /***********************************************************************
1051 * ImmGetCandidateListCountW (IMM32.@)
1053 DWORD WINAPI ImmGetCandidateListCountW(
1054 HIMC hIMC, LPDWORD lpdwListCount)
1056 InputContextData *data = get_imc_data(hIMC);
1057 LPCANDIDATEINFO candinfo;
1058 DWORD ret, count;
1060 TRACE("%p, %p\n", hIMC, lpdwListCount);
1062 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
1063 return 0;
1065 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1067 *lpdwListCount = count = candinfo->dwCount;
1069 if ( is_himc_ime_unicode(data) )
1070 ret = candinfo->dwSize;
1071 else
1073 ret = sizeof(CANDIDATEINFO);
1074 while ( count-- )
1075 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
1078 ImmUnlockIMCC(data->IMC.hCandInfo);
1079 return ret;
1082 /***********************************************************************
1083 * ImmGetCandidateListW (IMM32.@)
1085 DWORD WINAPI ImmGetCandidateListW(
1086 HIMC hIMC, DWORD dwIndex,
1087 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1089 InputContextData *data = get_imc_data(hIMC);
1090 LPCANDIDATEINFO candinfo;
1091 LPCANDIDATELIST candlist;
1092 DWORD ret = 0;
1094 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1096 if (!data || !data->IMC.hCandInfo)
1097 return 0;
1099 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1100 if ( dwIndex >= candinfo->dwCount ||
1101 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
1102 goto done;
1104 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1105 if ( !candlist->dwSize || !candlist->dwCount )
1106 goto done;
1108 if ( is_himc_ime_unicode(data) )
1110 ret = candlist->dwSize;
1111 if ( lpCandList && dwBufLen >= ret )
1112 memcpy(lpCandList, candlist, ret);
1114 else
1115 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1117 done:
1118 ImmUnlockIMCC(data->IMC.hCandInfo);
1119 return ret;
1122 /***********************************************************************
1123 * ImmGetCandidateWindow (IMM32.@)
1125 BOOL WINAPI ImmGetCandidateWindow(
1126 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1128 InputContextData *data = get_imc_data(hIMC);
1130 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1132 if (!data || !lpCandidate)
1133 return FALSE;
1135 if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1136 return FALSE;
1138 if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex)
1139 return FALSE;
1141 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1143 return TRUE;
1146 /***********************************************************************
1147 * ImmGetCompositionFontA (IMM32.@)
1149 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1151 LOGFONTW lfW;
1152 BOOL rc;
1154 TRACE("(%p, %p):\n", hIMC, lplf);
1156 rc = ImmGetCompositionFontW(hIMC,&lfW);
1157 if (!rc || !lplf)
1158 return FALSE;
1160 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1161 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1162 LF_FACESIZE, NULL, NULL);
1163 return TRUE;
1166 /***********************************************************************
1167 * ImmGetCompositionFontW (IMM32.@)
1169 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1171 InputContextData *data = get_imc_data(hIMC);
1173 TRACE("(%p, %p):\n", hIMC, lplf);
1175 if (!data || !lplf)
1176 return FALSE;
1178 *lplf = data->IMC.lfFont.W;
1180 return TRUE;
1184 /* Helpers for the GetCompositionString functions */
1186 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1187 BOOL unicode )
1189 INT rc;
1191 if (is_himc_ime_unicode(data) && !unicode)
1192 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1193 else if (!is_himc_ime_unicode(data) && unicode)
1194 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1195 else
1197 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1198 memcpy( target, source, min(slen,tlen)*dlen);
1199 rc = slen*dlen;
1202 return rc;
1205 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1206 LPBYTE target, INT tlen, BOOL unicode )
1208 INT rc;
1210 if (is_himc_ime_unicode(data) && !unicode)
1212 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1213 if (tlen)
1215 const BYTE *src = source;
1216 LPBYTE dst = target;
1217 int i, j = 0, k = 0;
1219 if (rc < tlen)
1220 tlen = rc;
1221 for (i = 0; i < sslen; ++i)
1223 int len;
1225 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1226 NULL, 0, NULL, NULL);
1227 for (; len > 0; --len)
1229 dst[j++] = src[k];
1231 if (j >= tlen)
1232 goto end;
1234 ++k;
1236 end:
1237 rc = j;
1240 else if (!is_himc_ime_unicode(data) && unicode)
1242 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1243 if (tlen)
1245 const BYTE *src = source;
1246 LPBYTE dst = target;
1247 int i, j = 0;
1249 if (rc < tlen)
1250 tlen = rc;
1251 for (i = 0; i < sslen; ++i)
1253 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1254 continue;
1256 dst[j++] = src[i];
1258 if (j >= tlen)
1259 break;
1261 rc = j;
1264 else
1266 memcpy( target, source, min(slen,tlen));
1267 rc = slen;
1270 return rc;
1273 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
1274 LPBYTE target, INT tlen, BOOL unicode )
1276 INT rc;
1278 if (is_himc_ime_unicode(data) && !unicode)
1280 if (tlen)
1282 int i;
1284 if (slen < tlen)
1285 tlen = slen;
1286 tlen /= sizeof (DWORD);
1287 for (i = 0; i < tlen; ++i)
1289 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1290 ((DWORD *)source)[i],
1291 NULL, 0,
1292 NULL, NULL);
1294 rc = sizeof (DWORD) * i;
1296 else
1297 rc = slen;
1299 else if (!is_himc_ime_unicode(data) && unicode)
1301 if (tlen)
1303 int i;
1305 if (slen < tlen)
1306 tlen = slen;
1307 tlen /= sizeof (DWORD);
1308 for (i = 0; i < tlen; ++i)
1310 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1311 ((DWORD *)source)[i],
1312 NULL, 0);
1314 rc = sizeof (DWORD) * i;
1316 else
1317 rc = slen;
1319 else
1321 memcpy( target, source, min(slen,tlen));
1322 rc = slen;
1325 return rc;
1328 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1330 int rc;
1332 if (is_himc_ime_unicode(data) && !unicode)
1334 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1336 else if (!is_himc_ime_unicode(data) && unicode)
1338 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1340 else
1341 rc = offset;
1343 return rc;
1346 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1347 DWORD dwBufLen, BOOL unicode)
1349 LONG rc = 0;
1350 InputContextData *data = get_imc_data(hIMC);
1351 LPCOMPOSITIONSTRING compstr;
1352 LPBYTE compdata;
1354 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1356 if (!data)
1357 return FALSE;
1359 if (!data->IMC.hCompStr)
1360 return FALSE;
1362 compdata = ImmLockIMCC(data->IMC.hCompStr);
1363 compstr = (LPCOMPOSITIONSTRING)compdata;
1365 switch (dwIndex)
1367 case GCS_RESULTSTR:
1368 TRACE("GCS_RESULTSTR\n");
1369 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1370 break;
1371 case GCS_COMPSTR:
1372 TRACE("GCS_COMPSTR\n");
1373 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1374 break;
1375 case GCS_COMPATTR:
1376 TRACE("GCS_COMPATTR\n");
1377 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1378 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1379 lpBuf, dwBufLen, unicode);
1380 break;
1381 case GCS_COMPCLAUSE:
1382 TRACE("GCS_COMPCLAUSE\n");
1383 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1384 compdata + compstr->dwCompStrOffset,
1385 lpBuf, dwBufLen, unicode);
1386 break;
1387 case GCS_RESULTCLAUSE:
1388 TRACE("GCS_RESULTCLAUSE\n");
1389 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1390 compdata + compstr->dwResultStrOffset,
1391 lpBuf, dwBufLen, unicode);
1392 break;
1393 case GCS_RESULTREADSTR:
1394 TRACE("GCS_RESULTREADSTR\n");
1395 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1396 break;
1397 case GCS_RESULTREADCLAUSE:
1398 TRACE("GCS_RESULTREADCLAUSE\n");
1399 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1400 compdata + compstr->dwResultStrOffset,
1401 lpBuf, dwBufLen, unicode);
1402 break;
1403 case GCS_COMPREADSTR:
1404 TRACE("GCS_COMPREADSTR\n");
1405 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1406 break;
1407 case GCS_COMPREADATTR:
1408 TRACE("GCS_COMPREADATTR\n");
1409 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1410 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1411 lpBuf, dwBufLen, unicode);
1412 break;
1413 case GCS_COMPREADCLAUSE:
1414 TRACE("GCS_COMPREADCLAUSE\n");
1415 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1416 compdata + compstr->dwCompStrOffset,
1417 lpBuf, dwBufLen, unicode);
1418 break;
1419 case GCS_CURSORPOS:
1420 TRACE("GCS_CURSORPOS\n");
1421 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1422 break;
1423 case GCS_DELTASTART:
1424 TRACE("GCS_DELTASTART\n");
1425 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1426 break;
1427 default:
1428 FIXME("Unhandled index 0x%x\n",dwIndex);
1429 break;
1432 ImmUnlockIMCC(data->IMC.hCompStr);
1434 return rc;
1437 /***********************************************************************
1438 * ImmGetCompositionStringA (IMM32.@)
1440 LONG WINAPI ImmGetCompositionStringA(
1441 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1443 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1447 /***********************************************************************
1448 * ImmGetCompositionStringW (IMM32.@)
1450 LONG WINAPI ImmGetCompositionStringW(
1451 HIMC hIMC, DWORD dwIndex,
1452 LPVOID lpBuf, DWORD dwBufLen)
1454 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1457 /***********************************************************************
1458 * ImmGetCompositionWindow (IMM32.@)
1460 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1462 InputContextData *data = get_imc_data(hIMC);
1464 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1466 if (!data)
1467 return FALSE;
1469 *lpCompForm = data->IMC.cfCompForm;
1470 return TRUE;
1473 /***********************************************************************
1474 * ImmGetContext (IMM32.@)
1477 HIMC WINAPI ImmGetContext(HWND hWnd)
1479 HIMC rc;
1481 TRACE("%p\n", hWnd);
1483 if (!IsWindow(hWnd))
1485 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1486 return NULL;
1489 rc = GetPropW(hWnd,szwWineIMCProperty);
1490 if (rc == (HIMC)-1)
1491 rc = NULL;
1492 else if (rc == NULL)
1493 rc = get_default_context( hWnd );
1495 if (rc)
1497 InputContextData *data = rc;
1498 data->IMC.hWnd = hWnd;
1501 TRACE("returning %p\n", rc);
1503 return rc;
1506 /***********************************************************************
1507 * ImmGetConversionListA (IMM32.@)
1509 DWORD WINAPI ImmGetConversionListA(
1510 HKL hKL, HIMC hIMC,
1511 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1512 DWORD dwBufLen, UINT uFlag)
1514 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1515 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1516 dwBufLen, uFlag);
1517 if (immHkl->hIME && immHkl->pImeConversionList)
1519 if (!is_kbd_ime_unicode(immHkl))
1520 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1521 else
1523 LPCANDIDATELIST lpwDst;
1524 DWORD ret = 0, len;
1525 LPWSTR pwSrc = strdupAtoW(pSrc);
1527 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1528 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1529 if ( lpwDst )
1531 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1532 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1533 HeapFree(GetProcessHeap(), 0, lpwDst);
1535 HeapFree(GetProcessHeap(), 0, pwSrc);
1537 return ret;
1540 else
1541 return 0;
1544 /***********************************************************************
1545 * ImmGetConversionListW (IMM32.@)
1547 DWORD WINAPI ImmGetConversionListW(
1548 HKL hKL, HIMC hIMC,
1549 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1550 DWORD dwBufLen, UINT uFlag)
1552 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1553 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1554 dwBufLen, uFlag);
1555 if (immHkl->hIME && immHkl->pImeConversionList)
1557 if (is_kbd_ime_unicode(immHkl))
1558 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1559 else
1561 LPCANDIDATELIST lpaDst;
1562 DWORD ret = 0, len;
1563 LPSTR paSrc = strdupWtoA(pSrc);
1565 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1566 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1567 if ( lpaDst )
1569 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1570 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1571 HeapFree(GetProcessHeap(), 0, lpaDst);
1573 HeapFree(GetProcessHeap(), 0, paSrc);
1575 return ret;
1578 else
1579 return 0;
1582 /***********************************************************************
1583 * ImmGetConversionStatus (IMM32.@)
1585 BOOL WINAPI ImmGetConversionStatus(
1586 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1588 InputContextData *data = get_imc_data(hIMC);
1590 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1592 if (!data)
1593 return FALSE;
1595 if (lpfdwConversion)
1596 *lpfdwConversion = data->IMC.fdwConversion;
1597 if (lpfdwSentence)
1598 *lpfdwSentence = data->IMC.fdwSentence;
1600 return TRUE;
1603 /***********************************************************************
1604 * ImmGetDefaultIMEWnd (IMM32.@)
1606 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1608 HWND ret, new = NULL;
1609 IMMThreadData* thread_data = IMM_GetThreadData(hWnd);
1610 if (!thread_data)
1611 return NULL;
1612 if (thread_data->hwndDefault == NULL && thread_data->threadID == GetCurrentThreadId())
1614 /* Do not create the window inside of a critical section */
1615 LeaveCriticalSection(&threaddata_cs);
1616 new = CreateWindowExW( WS_EX_TOOLWINDOW,
1617 szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
1618 /* thread_data is in the current thread so we can assume it's still valid */
1619 EnterCriticalSection(&threaddata_cs);
1620 /* See if anyone beat us */
1621 if (thread_data->hwndDefault == NULL)
1623 thread_data->hwndDefault = new;
1624 new = NULL;
1627 ret = thread_data->hwndDefault;
1628 LeaveCriticalSection(&threaddata_cs);
1629 TRACE("Default is %p\n",ret);
1630 /* Clean up an unused new window outside of the critical section */
1631 if (new != NULL)
1633 DestroyWindow(new);
1635 TRACE("Default is %p\n",ret);
1636 return ret;
1639 /***********************************************************************
1640 * ImmGetDescriptionA (IMM32.@)
1642 UINT WINAPI ImmGetDescriptionA(
1643 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1645 WCHAR *buf;
1646 DWORD len;
1648 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1650 /* find out how many characters in the unicode buffer */
1651 len = ImmGetDescriptionW( hKL, NULL, 0 );
1652 if (!len)
1653 return 0;
1655 /* allocate a buffer of that size */
1656 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1657 if( !buf )
1658 return 0;
1660 /* fetch the unicode buffer */
1661 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1663 /* convert it back to ASCII */
1664 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1665 lpszDescription, uBufLen, NULL, NULL );
1667 HeapFree( GetProcessHeap(), 0, buf );
1669 if (len == 0)
1670 return 0;
1672 return len - 1;
1675 /***********************************************************************
1676 * ImmGetDescriptionW (IMM32.@)
1678 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1680 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1682 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1684 if (!hKL) return 0;
1685 if (!uBufLen) return lstrlenW( name );
1686 lstrcpynW( lpszDescription, name, uBufLen );
1687 return lstrlenW( lpszDescription );
1690 /***********************************************************************
1691 * ImmGetGuideLineA (IMM32.@)
1693 DWORD WINAPI ImmGetGuideLineA(
1694 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1696 FIXME("(%p, %d, %s, %d): stub\n",
1697 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1699 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1700 return 0;
1703 /***********************************************************************
1704 * ImmGetGuideLineW (IMM32.@)
1706 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1708 FIXME("(%p, %d, %s, %d): stub\n",
1709 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1711 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1712 return 0;
1715 /***********************************************************************
1716 * ImmGetIMEFileNameA (IMM32.@)
1718 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1720 LPWSTR bufW = NULL;
1721 UINT wBufLen = uBufLen;
1722 UINT rc;
1724 if (uBufLen && lpszFileName)
1725 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1726 else /* We need this to get the number of byte required */
1728 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1729 wBufLen = MAX_PATH;
1732 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1734 if (rc > 0)
1736 if (uBufLen && lpszFileName)
1737 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1738 uBufLen, NULL, NULL);
1739 else /* get the length */
1740 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1741 NULL);
1744 HeapFree(GetProcessHeap(),0,bufW);
1745 return rc;
1748 /***********************************************************************
1749 * ImmGetIMEFileNameW (IMM32.@)
1751 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1753 HKEY hkey;
1754 DWORD length;
1755 DWORD rc;
1756 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1758 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1759 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1760 if (rc != ERROR_SUCCESS)
1762 SetLastError(rc);
1763 return 0;
1766 length = 0;
1767 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1769 if (rc != ERROR_SUCCESS)
1771 RegCloseKey(hkey);
1772 SetLastError(rc);
1773 return 0;
1775 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1777 RegCloseKey(hkey);
1778 if (lpszFileName)
1780 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1781 return 0;
1783 else
1784 return length / sizeof(WCHAR);
1787 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1789 RegCloseKey(hkey);
1791 return length / sizeof(WCHAR);
1794 /***********************************************************************
1795 * ImmGetOpenStatus (IMM32.@)
1797 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1799 InputContextData *data = get_imc_data(hIMC);
1800 static int i;
1802 if (!data)
1803 return FALSE;
1805 TRACE("(%p): semi-stub\n", hIMC);
1807 if (!i++)
1808 FIXME("(%p): semi-stub\n", hIMC);
1810 return data->IMC.fOpen;
1813 /***********************************************************************
1814 * ImmGetProperty (IMM32.@)
1816 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1818 DWORD rc = 0;
1819 ImmHkl *kbd;
1821 TRACE("(%p, %d)\n", hKL, fdwIndex);
1822 kbd = IMM_GetImmHkl(hKL);
1824 if (kbd && kbd->hIME)
1826 switch (fdwIndex)
1828 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1829 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1830 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1831 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1832 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1833 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1834 case IGP_UI: rc = 0; break;
1835 default: rc = 0;
1838 return rc;
1841 /***********************************************************************
1842 * ImmGetRegisterWordStyleA (IMM32.@)
1844 UINT WINAPI ImmGetRegisterWordStyleA(
1845 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1847 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1848 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1849 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1851 if (!is_kbd_ime_unicode(immHkl))
1852 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1853 else
1855 STYLEBUFW sbw;
1856 UINT rc;
1858 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1859 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1860 lpStyleBuf->szDescription, 32, NULL, NULL);
1861 lpStyleBuf->dwStyle = sbw.dwStyle;
1862 return rc;
1865 else
1866 return 0;
1869 /***********************************************************************
1870 * ImmGetRegisterWordStyleW (IMM32.@)
1872 UINT WINAPI ImmGetRegisterWordStyleW(
1873 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1875 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1876 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1877 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1879 if (is_kbd_ime_unicode(immHkl))
1880 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1881 else
1883 STYLEBUFA sba;
1884 UINT rc;
1886 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1887 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1888 lpStyleBuf->szDescription, 32);
1889 lpStyleBuf->dwStyle = sba.dwStyle;
1890 return rc;
1893 else
1894 return 0;
1897 /***********************************************************************
1898 * ImmGetStatusWindowPos (IMM32.@)
1900 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1902 InputContextData *data = get_imc_data(hIMC);
1904 TRACE("(%p, %p)\n", hIMC, lpptPos);
1906 if (!data || !lpptPos)
1907 return FALSE;
1909 *lpptPos = data->IMC.ptStatusWndPos;
1911 return TRUE;
1914 /***********************************************************************
1915 * ImmGetVirtualKey (IMM32.@)
1917 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1919 OSVERSIONINFOA version;
1920 InputContextData *data = ImmGetContext( hWnd );
1921 TRACE("%p\n", hWnd);
1923 if ( data )
1924 return data->lastVK;
1926 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
1927 GetVersionExA( &version );
1928 switch(version.dwPlatformId)
1930 case VER_PLATFORM_WIN32_WINDOWS:
1931 return VK_PROCESSKEY;
1932 case VER_PLATFORM_WIN32_NT:
1933 return 0;
1934 default:
1935 FIXME("%d not supported\n",version.dwPlatformId);
1936 return VK_PROCESSKEY;
1940 /***********************************************************************
1941 * ImmInstallIMEA (IMM32.@)
1943 HKL WINAPI ImmInstallIMEA(
1944 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1946 LPWSTR lpszwIMEFileName;
1947 LPWSTR lpszwLayoutText;
1948 HKL hkl;
1950 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
1951 debugstr_a(lpszLayoutText));
1953 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
1954 lpszwLayoutText = strdupAtoW(lpszLayoutText);
1956 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
1958 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
1959 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
1960 return hkl;
1963 /***********************************************************************
1964 * ImmInstallIMEW (IMM32.@)
1966 HKL WINAPI ImmInstallIMEW(
1967 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1969 INT lcid = GetUserDefaultLCID();
1970 INT count;
1971 HKL hkl;
1972 DWORD rc;
1973 HKEY hkey;
1974 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1976 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
1977 debugstr_w(lpszLayoutText));
1979 /* Start with 2. e001 will be blank and so default to the wine internal IME */
1980 count = 2;
1982 while (count < 0xfff)
1984 DWORD disposition = 0;
1986 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
1987 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
1989 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
1990 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
1991 break;
1992 else if (rc == ERROR_SUCCESS)
1993 RegCloseKey(hkey);
1995 count++;
1998 if (count == 0xfff)
2000 WARN("Unable to find slot to install IME\n");
2001 return 0;
2004 if (rc == ERROR_SUCCESS)
2006 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
2007 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
2008 if (rc == ERROR_SUCCESS)
2009 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
2010 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
2011 RegCloseKey(hkey);
2012 return hkl;
2014 else
2016 WARN("Unable to set IME registry values\n");
2017 return 0;
2021 /***********************************************************************
2022 * ImmIsIME (IMM32.@)
2024 BOOL WINAPI ImmIsIME(HKL hKL)
2026 ImmHkl *ptr;
2027 TRACE("(%p):\n", hKL);
2028 ptr = IMM_GetImmHkl(hKL);
2029 return (ptr && ptr->hIME);
2032 /***********************************************************************
2033 * ImmIsUIMessageA (IMM32.@)
2035 BOOL WINAPI ImmIsUIMessageA(
2036 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2038 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2039 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2040 (msg == WM_IME_SETCONTEXT) ||
2041 (msg == WM_IME_NOTIFY) ||
2042 (msg == WM_IME_COMPOSITIONFULL) ||
2043 (msg == WM_IME_SELECT) ||
2044 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2046 if (hWndIME)
2047 SendMessageA(hWndIME, msg, wParam, lParam);
2049 return TRUE;
2051 return FALSE;
2054 /***********************************************************************
2055 * ImmIsUIMessageW (IMM32.@)
2057 BOOL WINAPI ImmIsUIMessageW(
2058 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2060 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2061 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2062 (msg == WM_IME_SETCONTEXT) ||
2063 (msg == WM_IME_NOTIFY) ||
2064 (msg == WM_IME_COMPOSITIONFULL) ||
2065 (msg == WM_IME_SELECT) ||
2066 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2068 if (hWndIME)
2069 SendMessageW(hWndIME, msg, wParam, lParam);
2071 return TRUE;
2073 return FALSE;
2076 /***********************************************************************
2077 * ImmNotifyIME (IMM32.@)
2079 BOOL WINAPI ImmNotifyIME(
2080 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
2082 InputContextData *data = get_imc_data(hIMC);
2084 TRACE("(%p, %d, %d, %d)\n",
2085 hIMC, dwAction, dwIndex, dwValue);
2087 if (hIMC == NULL)
2089 SetLastError(ERROR_SUCCESS);
2090 return FALSE;
2093 if (!data || ! data->immKbd->pNotifyIME)
2095 return FALSE;
2098 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
2101 /***********************************************************************
2102 * ImmRegisterWordA (IMM32.@)
2104 BOOL WINAPI ImmRegisterWordA(
2105 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
2107 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2108 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2109 debugstr_a(lpszRegister));
2110 if (immHkl->hIME && immHkl->pImeRegisterWord)
2112 if (!is_kbd_ime_unicode(immHkl))
2113 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
2114 (LPCWSTR)lpszRegister);
2115 else
2117 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2118 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
2119 BOOL rc;
2121 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
2122 HeapFree(GetProcessHeap(),0,lpszwReading);
2123 HeapFree(GetProcessHeap(),0,lpszwRegister);
2124 return rc;
2127 else
2128 return FALSE;
2131 /***********************************************************************
2132 * ImmRegisterWordW (IMM32.@)
2134 BOOL WINAPI ImmRegisterWordW(
2135 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
2137 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2138 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2139 debugstr_w(lpszRegister));
2140 if (immHkl->hIME && immHkl->pImeRegisterWord)
2142 if (is_kbd_ime_unicode(immHkl))
2143 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
2144 else
2146 LPSTR lpszaReading = strdupWtoA(lpszReading);
2147 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
2148 BOOL rc;
2150 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
2151 (LPCWSTR)lpszaRegister);
2152 HeapFree(GetProcessHeap(),0,lpszaReading);
2153 HeapFree(GetProcessHeap(),0,lpszaRegister);
2154 return rc;
2157 else
2158 return FALSE;
2161 /***********************************************************************
2162 * ImmReleaseContext (IMM32.@)
2164 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2166 static BOOL shown = FALSE;
2168 if (!shown) {
2169 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2170 shown = TRUE;
2172 return TRUE;
2175 /***********************************************************************
2176 * ImmRequestMessageA(IMM32.@)
2178 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2180 InputContextData *data = get_imc_data(hIMC);
2182 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2184 if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2186 SetLastError(ERROR_INVALID_HANDLE);
2187 return 0;
2190 /***********************************************************************
2191 * ImmRequestMessageW(IMM32.@)
2193 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2195 InputContextData *data = get_imc_data(hIMC);
2197 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2199 if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2201 SetLastError(ERROR_INVALID_HANDLE);
2202 return 0;
2205 /***********************************************************************
2206 * ImmSetCandidateWindow (IMM32.@)
2208 BOOL WINAPI ImmSetCandidateWindow(
2209 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2211 InputContextData *data = get_imc_data(hIMC);
2213 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2215 if (!data || !lpCandidate)
2216 return FALSE;
2218 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2219 return FALSE;
2221 TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
2222 lpCandidate->dwIndex, lpCandidate->dwStyle,
2223 lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
2224 lpCandidate->rcArea.top, lpCandidate->rcArea.left,
2225 lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
2227 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
2228 return FALSE;
2230 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2231 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2232 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2234 return TRUE;
2237 /***********************************************************************
2238 * ImmSetCompositionFontA (IMM32.@)
2240 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2242 InputContextData *data = get_imc_data(hIMC);
2243 TRACE("(%p, %p)\n", hIMC, lplf);
2245 if (!data || !lplf)
2247 SetLastError(ERROR_INVALID_HANDLE);
2248 return FALSE;
2251 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2252 return FALSE;
2254 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2255 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2256 LF_FACESIZE);
2257 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2258 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2260 return TRUE;
2263 /***********************************************************************
2264 * ImmSetCompositionFontW (IMM32.@)
2266 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2268 InputContextData *data = get_imc_data(hIMC);
2269 TRACE("(%p, %p)\n", hIMC, lplf);
2271 if (!data || !lplf)
2273 SetLastError(ERROR_INVALID_HANDLE);
2274 return FALSE;
2277 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2278 return FALSE;
2280 data->IMC.lfFont.W = *lplf;
2281 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2282 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2284 return TRUE;
2287 /***********************************************************************
2288 * ImmSetCompositionStringA (IMM32.@)
2290 BOOL WINAPI ImmSetCompositionStringA(
2291 HIMC hIMC, DWORD dwIndex,
2292 LPCVOID lpComp, DWORD dwCompLen,
2293 LPCVOID lpRead, DWORD dwReadLen)
2295 DWORD comp_len;
2296 DWORD read_len;
2297 WCHAR *CompBuffer = NULL;
2298 WCHAR *ReadBuffer = NULL;
2299 BOOL rc;
2300 InputContextData *data = get_imc_data(hIMC);
2302 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2303 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2305 if (!data)
2306 return FALSE;
2308 if (!(dwIndex == SCS_SETSTR ||
2309 dwIndex == SCS_CHANGEATTR ||
2310 dwIndex == SCS_CHANGECLAUSE ||
2311 dwIndex == SCS_SETRECONVERTSTRING ||
2312 dwIndex == SCS_QUERYRECONVERTSTRING))
2313 return FALSE;
2315 if (!is_himc_ime_unicode(data))
2316 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2317 dwCompLen, lpRead, dwReadLen);
2319 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2320 if (comp_len)
2322 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2323 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2326 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2327 if (read_len)
2329 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2330 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2333 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2334 ReadBuffer, read_len);
2336 HeapFree(GetProcessHeap(), 0, CompBuffer);
2337 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2339 return rc;
2342 /***********************************************************************
2343 * ImmSetCompositionStringW (IMM32.@)
2345 BOOL WINAPI ImmSetCompositionStringW(
2346 HIMC hIMC, DWORD dwIndex,
2347 LPCVOID lpComp, DWORD dwCompLen,
2348 LPCVOID lpRead, DWORD dwReadLen)
2350 DWORD comp_len;
2351 DWORD read_len;
2352 CHAR *CompBuffer = NULL;
2353 CHAR *ReadBuffer = NULL;
2354 BOOL rc;
2355 InputContextData *data = get_imc_data(hIMC);
2357 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2358 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2360 if (!data)
2361 return FALSE;
2363 if (!(dwIndex == SCS_SETSTR ||
2364 dwIndex == SCS_CHANGEATTR ||
2365 dwIndex == SCS_CHANGECLAUSE ||
2366 dwIndex == SCS_SETRECONVERTSTRING ||
2367 dwIndex == SCS_QUERYRECONVERTSTRING))
2368 return FALSE;
2370 if (is_himc_ime_unicode(data))
2371 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2372 dwCompLen, lpRead, dwReadLen);
2374 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2375 NULL);
2376 if (comp_len)
2378 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2379 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2380 NULL, NULL);
2383 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2384 NULL);
2385 if (read_len)
2387 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2388 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2389 NULL, NULL);
2392 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2393 ReadBuffer, read_len);
2395 HeapFree(GetProcessHeap(), 0, CompBuffer);
2396 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2398 return rc;
2401 /***********************************************************************
2402 * ImmSetCompositionWindow (IMM32.@)
2404 BOOL WINAPI ImmSetCompositionWindow(
2405 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2407 BOOL reshow = FALSE;
2408 InputContextData *data = get_imc_data(hIMC);
2410 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2411 if (lpCompForm)
2412 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2413 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2414 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2416 if (!data)
2418 SetLastError(ERROR_INVALID_HANDLE);
2419 return FALSE;
2422 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2423 return FALSE;
2425 data->IMC.cfCompForm = *lpCompForm;
2427 if (IsWindowVisible(data->immKbd->UIWnd))
2429 reshow = TRUE;
2430 ShowWindow(data->immKbd->UIWnd,SW_HIDE);
2433 /* FIXME: this is a partial stub */
2435 if (reshow)
2436 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE);
2438 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2439 return TRUE;
2442 /***********************************************************************
2443 * ImmSetConversionStatus (IMM32.@)
2445 BOOL WINAPI ImmSetConversionStatus(
2446 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2448 DWORD oldConversion, oldSentence;
2449 InputContextData *data = get_imc_data(hIMC);
2451 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2453 if (!data)
2455 SetLastError(ERROR_INVALID_HANDLE);
2456 return FALSE;
2459 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2460 return FALSE;
2462 if ( fdwConversion != data->IMC.fdwConversion )
2464 oldConversion = data->IMC.fdwConversion;
2465 data->IMC.fdwConversion = fdwConversion;
2466 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2467 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2469 if ( fdwSentence != data->IMC.fdwSentence )
2471 oldSentence = data->IMC.fdwSentence;
2472 data->IMC.fdwSentence = fdwSentence;
2473 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2474 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2477 return TRUE;
2480 /***********************************************************************
2481 * ImmSetOpenStatus (IMM32.@)
2483 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2485 InputContextData *data = get_imc_data(hIMC);
2487 TRACE("%p %d\n", hIMC, fOpen);
2489 if (!data)
2491 SetLastError(ERROR_INVALID_HANDLE);
2492 return FALSE;
2495 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2496 return FALSE;
2498 if (data->immKbd->UIWnd == NULL)
2500 /* create the ime window */
2501 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2502 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2503 0, data->immKbd->hIME, 0);
2504 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2506 else if (fOpen)
2507 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2509 if (!fOpen != !data->IMC.fOpen)
2511 data->IMC.fOpen = fOpen;
2512 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2513 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2516 return TRUE;
2519 /***********************************************************************
2520 * ImmSetStatusWindowPos (IMM32.@)
2522 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2524 InputContextData *data = get_imc_data(hIMC);
2526 TRACE("(%p, %p)\n", hIMC, lpptPos);
2528 if (!data || !lpptPos)
2530 SetLastError(ERROR_INVALID_HANDLE);
2531 return FALSE;
2534 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2535 return FALSE;
2537 TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2539 data->IMC.ptStatusWndPos = *lpptPos;
2540 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2541 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2543 return TRUE;
2546 /***********************************************************************
2547 * ImmCreateSoftKeyboard(IMM32.@)
2549 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2551 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2552 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2553 return 0;
2556 /***********************************************************************
2557 * ImmDestroySoftKeyboard(IMM32.@)
2559 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2561 FIXME("(%p): stub\n", hSoftWnd);
2562 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2563 return FALSE;
2566 /***********************************************************************
2567 * ImmShowSoftKeyboard(IMM32.@)
2569 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2571 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2572 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2573 return FALSE;
2576 /***********************************************************************
2577 * ImmSimulateHotKey (IMM32.@)
2579 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2581 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2582 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2583 return FALSE;
2586 /***********************************************************************
2587 * ImmUnregisterWordA (IMM32.@)
2589 BOOL WINAPI ImmUnregisterWordA(
2590 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2592 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2593 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2594 debugstr_a(lpszUnregister));
2595 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2597 if (!is_kbd_ime_unicode(immHkl))
2598 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2599 (LPCWSTR)lpszUnregister);
2600 else
2602 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2603 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2604 BOOL rc;
2606 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2607 HeapFree(GetProcessHeap(),0,lpszwReading);
2608 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2609 return rc;
2612 else
2613 return FALSE;
2616 /***********************************************************************
2617 * ImmUnregisterWordW (IMM32.@)
2619 BOOL WINAPI ImmUnregisterWordW(
2620 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2622 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2623 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2624 debugstr_w(lpszUnregister));
2625 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2627 if (is_kbd_ime_unicode(immHkl))
2628 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2629 else
2631 LPSTR lpszaReading = strdupWtoA(lpszReading);
2632 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2633 BOOL rc;
2635 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2636 (LPCWSTR)lpszaUnregister);
2637 HeapFree(GetProcessHeap(),0,lpszaReading);
2638 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2639 return rc;
2642 else
2643 return FALSE;
2646 /***********************************************************************
2647 * ImmGetImeMenuItemsA (IMM32.@)
2649 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2650 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2651 DWORD dwSize)
2653 InputContextData *data = get_imc_data(hIMC);
2654 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2655 lpImeParentMenu, lpImeMenu, dwSize);
2657 if (!data)
2659 SetLastError(ERROR_INVALID_HANDLE);
2660 return 0;
2663 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2665 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2666 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2667 (IMEMENUITEMINFOW*)lpImeParentMenu,
2668 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2669 else
2671 IMEMENUITEMINFOW lpImeParentMenuW;
2672 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2673 DWORD rc;
2675 if (lpImeParentMenu)
2676 parent = &lpImeParentMenuW;
2677 if (lpImeMenu)
2679 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2680 dwSize = count * sizeof(IMEMENUITEMINFOW);
2681 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2683 else
2684 lpImeMenuW = NULL;
2686 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2687 parent, lpImeMenuW, dwSize);
2689 if (lpImeParentMenu)
2691 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2692 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2693 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2694 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2695 NULL, NULL);
2697 if (lpImeMenu && rc)
2699 unsigned int i;
2700 for (i = 0; i < rc; i++)
2702 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2703 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2704 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2705 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2706 NULL, NULL);
2709 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2710 return rc;
2713 else
2714 return 0;
2717 /***********************************************************************
2718 * ImmGetImeMenuItemsW (IMM32.@)
2720 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2721 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2722 DWORD dwSize)
2724 InputContextData *data = get_imc_data(hIMC);
2725 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2726 lpImeParentMenu, lpImeMenu, dwSize);
2728 if (!data)
2730 SetLastError(ERROR_INVALID_HANDLE);
2731 return 0;
2734 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2736 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2737 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2738 lpImeParentMenu, lpImeMenu, dwSize);
2739 else
2741 IMEMENUITEMINFOA lpImeParentMenuA;
2742 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2743 DWORD rc;
2745 if (lpImeParentMenu)
2746 parent = &lpImeParentMenuA;
2747 if (lpImeMenu)
2749 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2750 dwSize = count * sizeof(IMEMENUITEMINFOA);
2751 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2753 else
2754 lpImeMenuA = NULL;
2756 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2757 (IMEMENUITEMINFOW*)parent,
2758 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2760 if (lpImeParentMenu)
2762 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2763 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2764 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2765 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2767 if (lpImeMenu && rc)
2769 unsigned int i;
2770 for (i = 0; i < rc; i++)
2772 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2773 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2774 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2775 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2778 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2779 return rc;
2782 else
2783 return 0;
2786 /***********************************************************************
2787 * ImmLockIMC(IMM32.@)
2789 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2791 InputContextData *data = get_imc_data(hIMC);
2793 if (!data)
2794 return NULL;
2795 data->dwLock++;
2796 return &data->IMC;
2799 /***********************************************************************
2800 * ImmUnlockIMC(IMM32.@)
2802 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2804 InputContextData *data = get_imc_data(hIMC);
2806 if (!data)
2807 return FALSE;
2808 if (data->dwLock)
2809 data->dwLock--;
2810 return TRUE;
2813 /***********************************************************************
2814 * ImmGetIMCLockCount(IMM32.@)
2816 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2818 InputContextData *data = get_imc_data(hIMC);
2819 if (!data)
2820 return 0;
2821 return data->dwLock;
2824 /***********************************************************************
2825 * ImmCreateIMCC(IMM32.@)
2827 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2829 return GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, size);
2832 /***********************************************************************
2833 * ImmDestroyIMCC(IMM32.@)
2835 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2837 return GlobalFree(block);
2840 /***********************************************************************
2841 * ImmLockIMCC(IMM32.@)
2843 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2845 return GlobalLock(imcc);
2848 /***********************************************************************
2849 * ImmUnlockIMCC(IMM32.@)
2851 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2853 return GlobalUnlock(imcc);
2856 /***********************************************************************
2857 * ImmGetIMCCLockCount(IMM32.@)
2859 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2861 return GlobalFlags(imcc) & GMEM_LOCKCOUNT;
2864 /***********************************************************************
2865 * ImmReSizeIMCC(IMM32.@)
2867 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2869 return GlobalReAlloc(imcc, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
2872 /***********************************************************************
2873 * ImmGetIMCCSize(IMM32.@)
2875 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2877 return GlobalSize(imcc);
2880 /***********************************************************************
2881 * ImmGenerateMessage(IMM32.@)
2883 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2885 InputContextData *data = get_imc_data(hIMC);
2887 if (!data)
2889 SetLastError(ERROR_INVALID_HANDLE);
2890 return FALSE;
2893 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2894 if (data->IMC.dwNumMsgBuf > 0)
2896 LPTRANSMSG lpTransMsg;
2897 HIMCC hMsgBuf;
2898 DWORD i, dwNumMsgBuf;
2900 /* We are going to detach our hMsgBuff so that if processing messages
2901 generates new messages they go into a new buffer */
2902 hMsgBuf = data->IMC.hMsgBuf;
2903 dwNumMsgBuf = data->IMC.dwNumMsgBuf;
2905 data->IMC.hMsgBuf = ImmCreateIMCC(0);
2906 data->IMC.dwNumMsgBuf = 0;
2908 lpTransMsg = ImmLockIMCC(hMsgBuf);
2909 for (i = 0; i < dwNumMsgBuf; i++)
2910 ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2912 ImmUnlockIMCC(hMsgBuf);
2913 ImmDestroyIMCC(hMsgBuf);
2916 return TRUE;
2919 /***********************************************************************
2920 * ImmTranslateMessage(IMM32.@)
2921 * ( Undocumented, call internally and from user32.dll )
2923 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2925 InputContextData *data;
2926 HIMC imc = ImmGetContext(hwnd);
2927 BYTE state[256];
2928 UINT scancode;
2929 LPVOID list = 0;
2930 UINT msg_count;
2931 UINT uVirtKey;
2932 static const DWORD list_count = 10;
2934 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2936 if (imc)
2937 data = imc;
2938 else
2939 return FALSE;
2941 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2942 return FALSE;
2944 GetKeyboardState(state);
2945 scancode = lKeyData >> 0x10 & 0xff;
2947 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2948 ((DWORD*)list)[0] = list_count;
2950 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2952 WCHAR chr;
2954 if (!is_himc_ime_unicode(data))
2955 ToAscii(data->lastVK, scancode, state, &chr, 0);
2956 else
2957 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2958 uVirtKey = MAKELONG(data->lastVK,chr);
2960 else
2961 uVirtKey = data->lastVK;
2963 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2964 TRACE("%i messages generated\n",msg_count);
2965 if (msg_count && msg_count <= list_count)
2967 UINT i;
2968 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2970 for (i = 0; i < msg_count; i++)
2971 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2973 else if (msg_count > list_count)
2974 ImmGenerateMessage(imc);
2976 HeapFree(GetProcessHeap(),0,list);
2978 data->lastVK = VK_PROCESSKEY;
2980 return (msg_count > 0);
2983 /***********************************************************************
2984 * ImmProcessKey(IMM32.@)
2985 * ( Undocumented, called from user32.dll )
2987 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2989 InputContextData *data;
2990 HIMC imc = ImmGetContext(hwnd);
2991 BYTE state[256];
2993 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2995 if (imc)
2996 data = imc;
2997 else
2998 return FALSE;
3000 /* Make sure we are inputting to the correct keyboard */
3001 if (data->immKbd->hkl != hKL)
3003 ImmHkl *new_hkl = IMM_GetImmHkl(hKL);
3004 if (new_hkl)
3006 data->immKbd->pImeSelect(imc, FALSE);
3007 data->immKbd->uSelected--;
3008 data->immKbd = new_hkl;
3009 data->immKbd->pImeSelect(imc, TRUE);
3010 data->immKbd->uSelected++;
3012 else
3013 return FALSE;
3016 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
3017 return FALSE;
3019 GetKeyboardState(state);
3020 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
3022 data->lastVK = vKey;
3023 return TRUE;
3026 data->lastVK = VK_PROCESSKEY;
3027 return FALSE;
3030 /***********************************************************************
3031 * ImmDisableTextFrameService(IMM32.@)
3033 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread)
3035 FIXME("Stub\n");
3036 return FALSE;
3039 /***********************************************************************
3040 * ImmEnumInputContext(IMM32.@)
3043 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam)
3045 FIXME("Stub\n");
3046 return FALSE;
3049 /***********************************************************************
3050 * ImmGetHotKey(IMM32.@)
3053 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl)
3055 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl);
3056 return FALSE;