Release 1.9.16.
[wine.git] / dlls / imm32 / imm.c
blobd9c9782e2a54a5d28cf14a0d8417da16989daa78
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 BOOL disableIME;
99 } IMMThreadData;
101 static struct list ImmHklList = LIST_INIT(ImmHklList);
102 static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList);
104 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
106 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
107 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
108 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};
110 static const WCHAR szwIME[] = {'I','M','E',0};
112 static CRITICAL_SECTION threaddata_cs;
113 static CRITICAL_SECTION_DEBUG critsect_debug =
115 0, 0, &threaddata_cs,
116 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
117 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
119 static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
120 static BOOL disable_ime;
122 #define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
123 #define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
125 static BOOL IMM_DestroyContext(HIMC hIMC);
126 static InputContextData* get_imc_data(HIMC hIMC);
128 static inline WCHAR *strdupAtoW( const char *str )
130 WCHAR *ret = NULL;
131 if (str)
133 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
134 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
135 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
137 return ret;
140 static inline CHAR *strdupWtoA( const WCHAR *str )
142 CHAR *ret = NULL;
143 if (str)
145 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
146 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
147 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
149 return ret;
152 static DWORD convert_candidatelist_WtoA(
153 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
155 DWORD ret, i, len;
157 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
158 if ( lpDst && dwBufLen > 0 )
160 *lpDst = *lpSrc;
161 lpDst->dwOffset[0] = ret;
164 for ( i = 0; i < lpSrc->dwCount; i++)
166 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
168 if ( lpDst && dwBufLen > 0 )
170 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
172 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1,
173 (LPSTR)dest, dwBufLen, NULL, NULL);
175 if ( i + 1 < lpSrc->dwCount )
176 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
177 dwBufLen -= len * sizeof(char);
179 else
180 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL);
182 ret += len * sizeof(char);
185 if ( lpDst )
186 lpDst->dwSize = ret;
188 return ret;
191 static DWORD convert_candidatelist_AtoW(
192 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
194 DWORD ret, i, len;
196 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
197 if ( lpDst && dwBufLen > 0 )
199 *lpDst = *lpSrc;
200 lpDst->dwOffset[0] = ret;
203 for ( i = 0; i < lpSrc->dwCount; i++)
205 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
207 if ( lpDst && dwBufLen > 0 )
209 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
211 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1,
212 (LPWSTR)dest, dwBufLen);
214 if ( i + 1 < lpSrc->dwCount )
215 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
216 dwBufLen -= len * sizeof(WCHAR);
218 else
219 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
221 ret += len * sizeof(WCHAR);
224 if ( lpDst )
225 lpDst->dwSize = ret;
227 return ret;
230 static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD thread)
232 IMMThreadData *data;
233 DWORD process;
235 if (hwnd)
237 if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL;
238 if (process != GetCurrentProcessId()) return NULL;
240 else if (thread)
242 HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, FALSE, thread);
243 if (!h) return NULL;
244 process = GetProcessIdOfThread(h);
245 CloseHandle(h);
246 if (process != GetCurrentProcessId()) return NULL;
248 else
249 thread = GetCurrentThreadId();
251 EnterCriticalSection(&threaddata_cs);
252 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
253 if (data->threadID == thread) return data;
255 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
256 data->threadID = thread;
257 list_add_head(&ImmThreadDataList,&data->entry);
258 TRACE("Thread Data Created (%x)\n",thread);
259 return data;
262 static BOOL IMM_IsDefaultContext(HIMC imc)
264 InputContextData *data = get_imc_data(imc);
266 if (!data)
267 return FALSE;
269 return data->threadDefault;
272 static void IMM_FreeThreadData(void)
274 IMMThreadData *data;
276 EnterCriticalSection(&threaddata_cs);
277 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
279 if (data->threadID == GetCurrentThreadId())
281 list_remove(&data->entry);
282 LeaveCriticalSection(&threaddata_cs);
283 IMM_DestroyContext(data->defaultContext);
284 HeapFree(GetProcessHeap(),0,data);
285 TRACE("Thread Data Destroyed\n");
286 return;
289 LeaveCriticalSection(&threaddata_cs);
292 static HMODULE load_graphics_driver(void)
294 static const WCHAR display_device_guid_propW[] = {
295 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
296 'd','e','v','i','c','e','_','g','u','i','d',0 };
297 static const WCHAR key_pathW[] = {
298 'S','y','s','t','e','m','\\',
299 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
300 'C','o','n','t','r','o','l','\\',
301 'V','i','d','e','o','\\','{',0};
302 static const WCHAR displayW[] = {'}','\\','0','0','0','0',0};
303 static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
305 HMODULE ret = 0;
306 HKEY hkey;
307 DWORD size;
308 WCHAR path[MAX_PATH];
309 WCHAR key[(sizeof(key_pathW) + sizeof(displayW)) / sizeof(WCHAR) + 40];
310 UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
312 if (!guid_atom) return 0;
313 memcpy( key, key_pathW, sizeof(key_pathW) );
314 if (!GlobalGetAtomNameW( guid_atom, key + strlenW(key), 40 )) return 0;
315 strcatW( key, displayW );
316 if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
317 size = sizeof(path);
318 if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path );
319 RegCloseKey( hkey );
320 TRACE( "%s %p\n", debugstr_w(path), ret );
321 return ret;
324 /* ImmHkl loading and freeing */
325 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
326 static ImmHkl *IMM_GetImmHkl(HKL hkl)
328 ImmHkl *ptr;
329 WCHAR filename[MAX_PATH];
331 TRACE("Seeking ime for keyboard %p\n",hkl);
333 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
335 if (ptr->hkl == hkl)
336 return ptr;
338 /* not found... create it */
340 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
342 ptr->hkl = hkl;
343 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
344 if (!ptr->hIME) ptr->hIME = load_graphics_driver();
345 if (ptr->hIME)
347 LOAD_FUNCPTR(ImeInquire);
348 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
350 FreeLibrary(ptr->hIME);
351 ptr->hIME = NULL;
353 else
355 LOAD_FUNCPTR(ImeDestroy);
356 LOAD_FUNCPTR(ImeSelect);
357 if (!ptr->pImeSelect || !ptr->pImeDestroy)
359 FreeLibrary(ptr->hIME);
360 ptr->hIME = NULL;
362 else
364 LOAD_FUNCPTR(ImeConfigure);
365 LOAD_FUNCPTR(ImeEscape);
366 LOAD_FUNCPTR(ImeSetActiveContext);
367 LOAD_FUNCPTR(ImeToAsciiEx);
368 LOAD_FUNCPTR(NotifyIME);
369 LOAD_FUNCPTR(ImeRegisterWord);
370 LOAD_FUNCPTR(ImeUnregisterWord);
371 LOAD_FUNCPTR(ImeEnumRegisterWord);
372 LOAD_FUNCPTR(ImeSetCompositionString);
373 LOAD_FUNCPTR(ImeConversionList);
374 LOAD_FUNCPTR(ImeProcessKey);
375 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
376 LOAD_FUNCPTR(ImeGetImeMenuItems);
377 /* make sure our classname is WCHAR */
378 if (!is_kbd_ime_unicode(ptr))
380 WCHAR bufW[17];
381 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
382 -1, bufW, 17);
383 lstrcpyW(ptr->imeClassName, bufW);
388 list_add_head(&ImmHklList,&ptr->entry);
390 return ptr;
392 #undef LOAD_FUNCPTR
394 HWND WINAPI __wine_get_ui_window(HKL hkl)
396 ImmHkl *immHkl = IMM_GetImmHkl(hkl);
397 return immHkl->UIWnd;
400 static void IMM_FreeAllImmHkl(void)
402 ImmHkl *ptr,*cursor2;
404 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
406 list_remove(&ptr->entry);
407 if (ptr->hIME)
409 ptr->pImeDestroy(1);
410 FreeLibrary(ptr->hIME);
412 if (ptr->UIWnd)
413 DestroyWindow(ptr->UIWnd);
414 HeapFree(GetProcessHeap(),0,ptr);
418 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
420 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
421 switch (fdwReason)
423 case DLL_PROCESS_ATTACH:
424 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
426 return FALSE;
428 break;
429 case DLL_THREAD_ATTACH:
430 break;
431 case DLL_THREAD_DETACH:
432 IMM_FreeThreadData();
433 break;
434 case DLL_PROCESS_DETACH:
435 if (lpReserved) break;
436 IMM_FreeThreadData();
437 IMM_FreeAllImmHkl();
438 break;
440 return TRUE;
443 /* for posting messages as the IME */
444 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
446 HWND target = GetFocus();
447 if (!target)
448 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
449 else
450 PostMessageW(target, msg, wParam, lParam);
453 /* for sending messages as the IME */
454 static void ImmInternalSendIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
456 HWND target = GetFocus();
457 if (!target)
458 SendMessageW(data->IMC.hWnd,msg,wParam,lParam);
459 else
460 SendMessageW(target, msg, wParam, lParam);
463 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
465 HWND target;
467 target = data->IMC.hWnd;
468 if (!target) target = GetFocus();
470 if (target)
471 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
473 return 0;
476 static HIMCC ImmCreateBlankCompStr(void)
478 HIMCC rc;
479 LPCOMPOSITIONSTRING ptr;
480 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
481 ptr = ImmLockIMCC(rc);
482 memset(ptr,0,sizeof(COMPOSITIONSTRING));
483 ptr->dwSize = sizeof(COMPOSITIONSTRING);
484 ImmUnlockIMCC(rc);
485 return rc;
488 static InputContextData* get_imc_data(HIMC hIMC)
490 InputContextData *data = hIMC;
492 if (hIMC == NULL)
493 return NULL;
495 if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
497 SetLastError(ERROR_INVALID_HANDLE);
498 return NULL;
500 return data;
503 static HIMC get_default_context( HWND hwnd )
505 HIMC ret;
506 IMMThreadData* thread_data = IMM_GetThreadData( hwnd, 0 );
508 if (!thread_data) return 0;
510 if (thread_data->defaultContext)
512 ret = thread_data->defaultContext;
513 LeaveCriticalSection(&threaddata_cs);
514 return ret;
517 /* can't create a default context in another thread */
518 if (thread_data->threadID != GetCurrentThreadId())
520 LeaveCriticalSection(&threaddata_cs);
521 return 0;
524 LeaveCriticalSection(&threaddata_cs);
526 ret = ImmCreateContext();
527 if (!ret) return 0;
528 ((InputContextData*)ret)->threadDefault = TRUE;
530 /* thread_data is in the current thread so we can assume it's still valid */
531 EnterCriticalSection(&threaddata_cs);
533 if (thread_data->defaultContext) /* someone beat us */
535 IMM_DestroyContext( ret );
536 ret = thread_data->defaultContext;
538 else thread_data->defaultContext = ret;
540 LeaveCriticalSection(&threaddata_cs);
541 return ret;
544 static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
546 InputContextData *data;
548 if (hWnd)
550 DWORD thread = GetWindowThreadProcessId(hWnd, NULL);
551 if (thread != GetCurrentThreadId()) return TRUE;
553 data = get_imc_data(hIMC);
554 if (data && data->threadID != GetCurrentThreadId())
555 return TRUE;
557 return FALSE;
560 /***********************************************************************
561 * ImmAssociateContext (IMM32.@)
563 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
565 HIMC old = NULL;
566 InputContextData *data = get_imc_data(hIMC);
568 TRACE("(%p, %p):\n", hWnd, hIMC);
570 if(hIMC && !data)
571 return NULL;
574 * If already associated just return
576 if (hIMC && data->IMC.hWnd == hWnd)
577 return hIMC;
579 if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
580 return NULL;
582 if (hWnd)
584 HIMC defaultContext = get_default_context( hWnd );
585 old = RemovePropW(hWnd,szwWineIMCProperty);
587 if (old == NULL)
588 old = defaultContext;
589 else if (old == (HIMC)-1)
590 old = NULL;
592 if (hIMC != defaultContext)
594 if (hIMC == NULL) /* Meaning disable imm for that window*/
595 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
596 else
597 SetPropW(hWnd,szwWineIMCProperty,hIMC);
600 if (old)
602 InputContextData *old_data = old;
603 if (old_data->IMC.hWnd == hWnd)
604 old_data->IMC.hWnd = NULL;
608 if (!hIMC)
609 return old;
611 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
612 data->IMC.hWnd = hWnd;
613 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
615 return old;
620 * Helper function for ImmAssociateContextEx
622 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
624 HIMC hImc = (HIMC)lParam;
625 ImmAssociateContext(hwnd,hImc);
626 return TRUE;
629 /***********************************************************************
630 * ImmAssociateContextEx (IMM32.@)
632 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
634 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
636 if (!hWnd)
637 return FALSE;
639 switch (dwFlags)
641 case 0:
642 ImmAssociateContext(hWnd,hIMC);
643 return TRUE;
644 case IACE_DEFAULT:
646 HIMC defaultContext = get_default_context( hWnd );
647 if (!defaultContext) return FALSE;
648 ImmAssociateContext(hWnd,defaultContext);
649 return TRUE;
651 case IACE_IGNORENOCONTEXT:
652 if (GetPropW(hWnd,szwWineIMCProperty))
653 ImmAssociateContext(hWnd,hIMC);
654 return TRUE;
655 case IACE_CHILDREN:
656 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC);
657 return TRUE;
658 default:
659 FIXME("Unknown dwFlags 0x%x\n",dwFlags);
660 return FALSE;
664 /***********************************************************************
665 * ImmConfigureIMEA (IMM32.@)
667 BOOL WINAPI ImmConfigureIMEA(
668 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
670 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
672 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
674 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
675 return FALSE;
677 if (immHkl->hIME && immHkl->pImeConfigure)
679 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
680 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
681 else
683 REGISTERWORDW rww;
684 REGISTERWORDA *rwa = lpData;
685 BOOL rc;
687 rww.lpReading = strdupAtoW(rwa->lpReading);
688 rww.lpWord = strdupAtoW(rwa->lpWord);
689 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
690 HeapFree(GetProcessHeap(),0,rww.lpReading);
691 HeapFree(GetProcessHeap(),0,rww.lpWord);
692 return rc;
695 else
696 return FALSE;
699 /***********************************************************************
700 * ImmConfigureIMEW (IMM32.@)
702 BOOL WINAPI ImmConfigureIMEW(
703 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
705 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
707 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
709 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
710 return FALSE;
712 if (immHkl->hIME && immHkl->pImeConfigure)
714 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
715 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
716 else
718 REGISTERWORDW *rww = lpData;
719 REGISTERWORDA rwa;
720 BOOL rc;
722 rwa.lpReading = strdupWtoA(rww->lpReading);
723 rwa.lpWord = strdupWtoA(rww->lpWord);
724 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
725 HeapFree(GetProcessHeap(),0,rwa.lpReading);
726 HeapFree(GetProcessHeap(),0,rwa.lpWord);
727 return rc;
730 else
731 return FALSE;
734 /***********************************************************************
735 * ImmCreateContext (IMM32.@)
737 HIMC WINAPI ImmCreateContext(void)
739 InputContextData *new_context;
740 LPGUIDELINE gl;
741 LPCANDIDATEINFO ci;
742 int i;
744 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
746 /* Load the IME */
747 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
749 if (!new_context->immKbd->hIME)
751 TRACE("IME dll could not be loaded\n");
752 HeapFree(GetProcessHeap(),0,new_context);
753 return 0;
756 /* the HIMCCs are never NULL */
757 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
758 new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
759 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
760 ci = ImmLockIMCC(new_context->IMC.hCandInfo);
761 memset(ci,0,sizeof(CANDIDATEINFO));
762 ci->dwSize = sizeof(CANDIDATEINFO);
763 ImmUnlockIMCC(new_context->IMC.hCandInfo);
764 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
765 gl = ImmLockIMCC(new_context->IMC.hGuideLine);
766 memset(gl,0,sizeof(GUIDELINE));
767 gl->dwSize = sizeof(GUIDELINE);
768 ImmUnlockIMCC(new_context->IMC.hGuideLine);
770 for (i = 0; i < sizeof(new_context->IMC.cfCandForm) / sizeof(CANDIDATEFORM); i++)
771 new_context->IMC.cfCandForm[i].dwIndex = ~0u;
773 /* Initialize the IME Private */
774 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
776 new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps;
777 new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps;
779 if (!new_context->immKbd->pImeSelect(new_context, TRUE))
781 TRACE("Selection of IME failed\n");
782 IMM_DestroyContext(new_context);
783 return 0;
785 new_context->threadID = GetCurrentThreadId();
786 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd);
788 new_context->immKbd->uSelected++;
789 TRACE("Created context %p\n",new_context);
791 new_context->magic = WINE_IMC_VALID_MAGIC;
792 return new_context;
795 static BOOL IMM_DestroyContext(HIMC hIMC)
797 InputContextData *data = get_imc_data(hIMC);
799 TRACE("Destroying %p\n",hIMC);
801 if (!data)
802 return FALSE;
804 data->immKbd->uSelected --;
805 data->immKbd->pImeSelect(hIMC, FALSE);
806 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd);
808 ImmDestroyIMCC(data->IMC.hCompStr);
809 ImmDestroyIMCC(data->IMC.hCandInfo);
810 ImmDestroyIMCC(data->IMC.hGuideLine);
811 ImmDestroyIMCC(data->IMC.hPrivate);
812 ImmDestroyIMCC(data->IMC.hMsgBuf);
814 data->magic = 0;
815 HeapFree(GetProcessHeap(),0,data);
817 return TRUE;
820 /***********************************************************************
821 * ImmDestroyContext (IMM32.@)
823 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
825 if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
826 return IMM_DestroyContext(hIMC);
827 else
828 return FALSE;
831 /***********************************************************************
832 * ImmDisableIME (IMM32.@)
834 BOOL WINAPI ImmDisableIME(DWORD idThread)
836 if (idThread == (DWORD)-1)
837 disable_ime = TRUE;
838 else {
839 IMMThreadData *thread_data = IMM_GetThreadData(NULL, idThread);
840 if (!thread_data) return FALSE;
841 thread_data->disableIME = TRUE;
842 LeaveCriticalSection(&threaddata_cs);
844 return TRUE;
847 /***********************************************************************
848 * ImmEnumRegisterWordA (IMM32.@)
850 UINT WINAPI ImmEnumRegisterWordA(
851 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
852 LPCSTR lpszReading, DWORD dwStyle,
853 LPCSTR lpszRegister, LPVOID lpData)
855 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
856 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
857 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
858 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
860 if (!is_kbd_ime_unicode(immHkl))
861 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
862 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
863 else
865 LPWSTR lpszwReading = strdupAtoW(lpszReading);
866 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
867 BOOL rc;
869 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
870 lpszwReading, dwStyle, lpszwRegister,
871 lpData);
873 HeapFree(GetProcessHeap(),0,lpszwReading);
874 HeapFree(GetProcessHeap(),0,lpszwRegister);
875 return rc;
878 else
879 return 0;
882 /***********************************************************************
883 * ImmEnumRegisterWordW (IMM32.@)
885 UINT WINAPI ImmEnumRegisterWordW(
886 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
887 LPCWSTR lpszReading, DWORD dwStyle,
888 LPCWSTR lpszRegister, LPVOID lpData)
890 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
891 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
892 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
893 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
895 if (is_kbd_ime_unicode(immHkl))
896 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
897 lpszRegister, lpData);
898 else
900 LPSTR lpszaReading = strdupWtoA(lpszReading);
901 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
902 BOOL rc;
904 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
905 dwStyle, (LPCWSTR)lpszaRegister, lpData);
907 HeapFree(GetProcessHeap(),0,lpszaReading);
908 HeapFree(GetProcessHeap(),0,lpszaRegister);
909 return rc;
912 else
913 return 0;
916 static inline BOOL EscapeRequiresWA(UINT uEscape)
918 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
919 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
920 uEscape == IME_ESC_IME_NAME ||
921 uEscape == IME_ESC_GETHELPFILENAME)
922 return TRUE;
923 return FALSE;
926 /***********************************************************************
927 * ImmEscapeA (IMM32.@)
929 LRESULT WINAPI ImmEscapeA(
930 HKL hKL, HIMC hIMC,
931 UINT uEscape, LPVOID lpData)
933 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
934 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
936 if (immHkl->hIME && immHkl->pImeEscape)
938 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
939 return immHkl->pImeEscape(hIMC,uEscape,lpData);
940 else
942 WCHAR buffer[81]; /* largest required buffer should be 80 */
943 LRESULT rc;
944 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
946 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
947 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
949 else
951 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
952 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
954 return rc;
957 else
958 return 0;
961 /***********************************************************************
962 * ImmEscapeW (IMM32.@)
964 LRESULT WINAPI ImmEscapeW(
965 HKL hKL, HIMC hIMC,
966 UINT uEscape, LPVOID lpData)
968 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
969 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
971 if (immHkl->hIME && immHkl->pImeEscape)
973 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
974 return immHkl->pImeEscape(hIMC,uEscape,lpData);
975 else
977 CHAR buffer[81]; /* largest required buffer should be 80 */
978 LRESULT rc;
979 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
981 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
982 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
984 else
986 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
987 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
989 return rc;
992 else
993 return 0;
996 /***********************************************************************
997 * ImmGetCandidateListA (IMM32.@)
999 DWORD WINAPI ImmGetCandidateListA(
1000 HIMC hIMC, DWORD dwIndex,
1001 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1003 InputContextData *data = get_imc_data(hIMC);
1004 LPCANDIDATEINFO candinfo;
1005 LPCANDIDATELIST candlist;
1006 DWORD ret = 0;
1008 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1010 if (!data || !data->IMC.hCandInfo)
1011 return 0;
1013 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1014 if ( dwIndex >= candinfo->dwCount ||
1015 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
1016 goto done;
1018 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1019 if ( !candlist->dwSize || !candlist->dwCount )
1020 goto done;
1022 if ( !is_himc_ime_unicode(data) )
1024 ret = candlist->dwSize;
1025 if ( lpCandList && dwBufLen >= ret )
1026 memcpy(lpCandList, candlist, ret);
1028 else
1029 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
1031 done:
1032 ImmUnlockIMCC(data->IMC.hCandInfo);
1033 return ret;
1036 /***********************************************************************
1037 * ImmGetCandidateListCountA (IMM32.@)
1039 DWORD WINAPI ImmGetCandidateListCountA(
1040 HIMC hIMC, LPDWORD lpdwListCount)
1042 InputContextData *data = get_imc_data(hIMC);
1043 LPCANDIDATEINFO candinfo;
1044 DWORD ret, count;
1046 TRACE("%p, %p\n", hIMC, lpdwListCount);
1048 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
1049 return 0;
1051 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1053 *lpdwListCount = count = candinfo->dwCount;
1055 if ( !is_himc_ime_unicode(data) )
1056 ret = candinfo->dwSize;
1057 else
1059 ret = sizeof(CANDIDATEINFO);
1060 while ( count-- )
1061 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
1064 ImmUnlockIMCC(data->IMC.hCandInfo);
1065 return ret;
1068 /***********************************************************************
1069 * ImmGetCandidateListCountW (IMM32.@)
1071 DWORD WINAPI ImmGetCandidateListCountW(
1072 HIMC hIMC, LPDWORD lpdwListCount)
1074 InputContextData *data = get_imc_data(hIMC);
1075 LPCANDIDATEINFO candinfo;
1076 DWORD ret, count;
1078 TRACE("%p, %p\n", hIMC, lpdwListCount);
1080 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
1081 return 0;
1083 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1085 *lpdwListCount = count = candinfo->dwCount;
1087 if ( is_himc_ime_unicode(data) )
1088 ret = candinfo->dwSize;
1089 else
1091 ret = sizeof(CANDIDATEINFO);
1092 while ( count-- )
1093 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
1096 ImmUnlockIMCC(data->IMC.hCandInfo);
1097 return ret;
1100 /***********************************************************************
1101 * ImmGetCandidateListW (IMM32.@)
1103 DWORD WINAPI ImmGetCandidateListW(
1104 HIMC hIMC, DWORD dwIndex,
1105 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1107 InputContextData *data = get_imc_data(hIMC);
1108 LPCANDIDATEINFO candinfo;
1109 LPCANDIDATELIST candlist;
1110 DWORD ret = 0;
1112 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1114 if (!data || !data->IMC.hCandInfo)
1115 return 0;
1117 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1118 if ( dwIndex >= candinfo->dwCount ||
1119 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
1120 goto done;
1122 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1123 if ( !candlist->dwSize || !candlist->dwCount )
1124 goto done;
1126 if ( is_himc_ime_unicode(data) )
1128 ret = candlist->dwSize;
1129 if ( lpCandList && dwBufLen >= ret )
1130 memcpy(lpCandList, candlist, ret);
1132 else
1133 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1135 done:
1136 ImmUnlockIMCC(data->IMC.hCandInfo);
1137 return ret;
1140 /***********************************************************************
1141 * ImmGetCandidateWindow (IMM32.@)
1143 BOOL WINAPI ImmGetCandidateWindow(
1144 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1146 InputContextData *data = get_imc_data(hIMC);
1148 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1150 if (!data || !lpCandidate)
1151 return FALSE;
1153 if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1154 return FALSE;
1156 if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex)
1157 return FALSE;
1159 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1161 return TRUE;
1164 /***********************************************************************
1165 * ImmGetCompositionFontA (IMM32.@)
1167 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1169 LOGFONTW lfW;
1170 BOOL rc;
1172 TRACE("(%p, %p):\n", hIMC, lplf);
1174 rc = ImmGetCompositionFontW(hIMC,&lfW);
1175 if (!rc || !lplf)
1176 return FALSE;
1178 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1179 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1180 LF_FACESIZE, NULL, NULL);
1181 return TRUE;
1184 /***********************************************************************
1185 * ImmGetCompositionFontW (IMM32.@)
1187 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1189 InputContextData *data = get_imc_data(hIMC);
1191 TRACE("(%p, %p):\n", hIMC, lplf);
1193 if (!data || !lplf)
1194 return FALSE;
1196 *lplf = data->IMC.lfFont.W;
1198 return TRUE;
1202 /* Helpers for the GetCompositionString functions */
1204 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1205 BOOL unicode )
1207 INT rc;
1209 if (is_himc_ime_unicode(data) && !unicode)
1210 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1211 else if (!is_himc_ime_unicode(data) && unicode)
1212 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1213 else
1215 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1216 memcpy( target, source, min(slen,tlen)*dlen);
1217 rc = slen*dlen;
1220 return rc;
1223 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1224 LPBYTE target, INT tlen, BOOL unicode )
1226 INT rc;
1228 if (is_himc_ime_unicode(data) && !unicode)
1230 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1231 if (tlen)
1233 const BYTE *src = source;
1234 LPBYTE dst = target;
1235 int i, j = 0, k = 0;
1237 if (rc < tlen)
1238 tlen = rc;
1239 for (i = 0; i < sslen; ++i)
1241 int len;
1243 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1244 NULL, 0, NULL, NULL);
1245 for (; len > 0; --len)
1247 dst[j++] = src[k];
1249 if (j >= tlen)
1250 goto end;
1252 ++k;
1254 end:
1255 rc = j;
1258 else if (!is_himc_ime_unicode(data) && unicode)
1260 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1261 if (tlen)
1263 const BYTE *src = source;
1264 LPBYTE dst = target;
1265 int i, j = 0;
1267 if (rc < tlen)
1268 tlen = rc;
1269 for (i = 0; i < sslen; ++i)
1271 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1272 continue;
1274 dst[j++] = src[i];
1276 if (j >= tlen)
1277 break;
1279 rc = j;
1282 else
1284 memcpy( target, source, min(slen,tlen));
1285 rc = slen;
1288 return rc;
1291 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
1292 LPBYTE target, INT tlen, BOOL unicode )
1294 INT rc;
1296 if (is_himc_ime_unicode(data) && !unicode)
1298 if (tlen)
1300 int i;
1302 if (slen < tlen)
1303 tlen = slen;
1304 tlen /= sizeof (DWORD);
1305 for (i = 0; i < tlen; ++i)
1307 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1308 ((DWORD *)source)[i],
1309 NULL, 0,
1310 NULL, NULL);
1312 rc = sizeof (DWORD) * i;
1314 else
1315 rc = slen;
1317 else if (!is_himc_ime_unicode(data) && unicode)
1319 if (tlen)
1321 int i;
1323 if (slen < tlen)
1324 tlen = slen;
1325 tlen /= sizeof (DWORD);
1326 for (i = 0; i < tlen; ++i)
1328 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1329 ((DWORD *)source)[i],
1330 NULL, 0);
1332 rc = sizeof (DWORD) * i;
1334 else
1335 rc = slen;
1337 else
1339 memcpy( target, source, min(slen,tlen));
1340 rc = slen;
1343 return rc;
1346 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1348 int rc;
1350 if (is_himc_ime_unicode(data) && !unicode)
1352 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1354 else if (!is_himc_ime_unicode(data) && unicode)
1356 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1358 else
1359 rc = offset;
1361 return rc;
1364 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1365 DWORD dwBufLen, BOOL unicode)
1367 LONG rc = 0;
1368 InputContextData *data = get_imc_data(hIMC);
1369 LPCOMPOSITIONSTRING compstr;
1370 LPBYTE compdata;
1372 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1374 if (!data)
1375 return FALSE;
1377 if (!data->IMC.hCompStr)
1378 return FALSE;
1380 compdata = ImmLockIMCC(data->IMC.hCompStr);
1381 compstr = (LPCOMPOSITIONSTRING)compdata;
1383 switch (dwIndex)
1385 case GCS_RESULTSTR:
1386 TRACE("GCS_RESULTSTR\n");
1387 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1388 break;
1389 case GCS_COMPSTR:
1390 TRACE("GCS_COMPSTR\n");
1391 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1392 break;
1393 case GCS_COMPATTR:
1394 TRACE("GCS_COMPATTR\n");
1395 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1396 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1397 lpBuf, dwBufLen, unicode);
1398 break;
1399 case GCS_COMPCLAUSE:
1400 TRACE("GCS_COMPCLAUSE\n");
1401 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1402 compdata + compstr->dwCompStrOffset,
1403 lpBuf, dwBufLen, unicode);
1404 break;
1405 case GCS_RESULTCLAUSE:
1406 TRACE("GCS_RESULTCLAUSE\n");
1407 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1408 compdata + compstr->dwResultStrOffset,
1409 lpBuf, dwBufLen, unicode);
1410 break;
1411 case GCS_RESULTREADSTR:
1412 TRACE("GCS_RESULTREADSTR\n");
1413 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1414 break;
1415 case GCS_RESULTREADCLAUSE:
1416 TRACE("GCS_RESULTREADCLAUSE\n");
1417 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1418 compdata + compstr->dwResultStrOffset,
1419 lpBuf, dwBufLen, unicode);
1420 break;
1421 case GCS_COMPREADSTR:
1422 TRACE("GCS_COMPREADSTR\n");
1423 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1424 break;
1425 case GCS_COMPREADATTR:
1426 TRACE("GCS_COMPREADATTR\n");
1427 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1428 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1429 lpBuf, dwBufLen, unicode);
1430 break;
1431 case GCS_COMPREADCLAUSE:
1432 TRACE("GCS_COMPREADCLAUSE\n");
1433 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1434 compdata + compstr->dwCompStrOffset,
1435 lpBuf, dwBufLen, unicode);
1436 break;
1437 case GCS_CURSORPOS:
1438 TRACE("GCS_CURSORPOS\n");
1439 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1440 break;
1441 case GCS_DELTASTART:
1442 TRACE("GCS_DELTASTART\n");
1443 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1444 break;
1445 default:
1446 FIXME("Unhandled index 0x%x\n",dwIndex);
1447 break;
1450 ImmUnlockIMCC(data->IMC.hCompStr);
1452 return rc;
1455 /***********************************************************************
1456 * ImmGetCompositionStringA (IMM32.@)
1458 LONG WINAPI ImmGetCompositionStringA(
1459 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1461 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1465 /***********************************************************************
1466 * ImmGetCompositionStringW (IMM32.@)
1468 LONG WINAPI ImmGetCompositionStringW(
1469 HIMC hIMC, DWORD dwIndex,
1470 LPVOID lpBuf, DWORD dwBufLen)
1472 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1475 /***********************************************************************
1476 * ImmGetCompositionWindow (IMM32.@)
1478 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1480 InputContextData *data = get_imc_data(hIMC);
1482 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1484 if (!data)
1485 return FALSE;
1487 *lpCompForm = data->IMC.cfCompForm;
1488 return TRUE;
1491 /***********************************************************************
1492 * ImmGetContext (IMM32.@)
1495 HIMC WINAPI ImmGetContext(HWND hWnd)
1497 HIMC rc;
1499 TRACE("%p\n", hWnd);
1501 if (!IsWindow(hWnd))
1503 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1504 return NULL;
1507 rc = GetPropW(hWnd,szwWineIMCProperty);
1508 if (rc == (HIMC)-1)
1509 rc = NULL;
1510 else if (rc == NULL)
1511 rc = get_default_context( hWnd );
1513 if (rc)
1515 InputContextData *data = rc;
1516 data->IMC.hWnd = hWnd;
1519 TRACE("returning %p\n", rc);
1521 return rc;
1524 /***********************************************************************
1525 * ImmGetConversionListA (IMM32.@)
1527 DWORD WINAPI ImmGetConversionListA(
1528 HKL hKL, HIMC hIMC,
1529 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1530 DWORD dwBufLen, UINT uFlag)
1532 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1533 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1534 dwBufLen, uFlag);
1535 if (immHkl->hIME && immHkl->pImeConversionList)
1537 if (!is_kbd_ime_unicode(immHkl))
1538 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1539 else
1541 LPCANDIDATELIST lpwDst;
1542 DWORD ret = 0, len;
1543 LPWSTR pwSrc = strdupAtoW(pSrc);
1545 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1546 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1547 if ( lpwDst )
1549 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1550 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1551 HeapFree(GetProcessHeap(), 0, lpwDst);
1553 HeapFree(GetProcessHeap(), 0, pwSrc);
1555 return ret;
1558 else
1559 return 0;
1562 /***********************************************************************
1563 * ImmGetConversionListW (IMM32.@)
1565 DWORD WINAPI ImmGetConversionListW(
1566 HKL hKL, HIMC hIMC,
1567 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1568 DWORD dwBufLen, UINT uFlag)
1570 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1571 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1572 dwBufLen, uFlag);
1573 if (immHkl->hIME && immHkl->pImeConversionList)
1575 if (is_kbd_ime_unicode(immHkl))
1576 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1577 else
1579 LPCANDIDATELIST lpaDst;
1580 DWORD ret = 0, len;
1581 LPSTR paSrc = strdupWtoA(pSrc);
1583 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1584 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1585 if ( lpaDst )
1587 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1588 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1589 HeapFree(GetProcessHeap(), 0, lpaDst);
1591 HeapFree(GetProcessHeap(), 0, paSrc);
1593 return ret;
1596 else
1597 return 0;
1600 /***********************************************************************
1601 * ImmGetConversionStatus (IMM32.@)
1603 BOOL WINAPI ImmGetConversionStatus(
1604 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1606 InputContextData *data = get_imc_data(hIMC);
1608 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1610 if (!data)
1611 return FALSE;
1613 if (lpfdwConversion)
1614 *lpfdwConversion = data->IMC.fdwConversion;
1615 if (lpfdwSentence)
1616 *lpfdwSentence = data->IMC.fdwSentence;
1618 return TRUE;
1621 /***********************************************************************
1622 * ImmGetDefaultIMEWnd (IMM32.@)
1624 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1626 HWND ret, new = NULL;
1627 IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0);
1628 if (!thread_data)
1629 return NULL;
1630 if (thread_data->hwndDefault == NULL && thread_data->threadID == GetCurrentThreadId())
1632 if (thread_data->disableIME || disable_ime)
1634 TRACE("IME for this thread is disabled\n");
1635 LeaveCriticalSection(&threaddata_cs);
1636 return NULL;
1638 /* Do not create the window inside of a critical section */
1639 LeaveCriticalSection(&threaddata_cs);
1640 new = CreateWindowExW( WS_EX_TOOLWINDOW,
1641 szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
1642 /* thread_data is in the current thread so we can assume it's still valid */
1643 EnterCriticalSection(&threaddata_cs);
1644 /* See if anyone beat us */
1645 if (thread_data->hwndDefault == NULL)
1647 thread_data->hwndDefault = new;
1648 new = NULL;
1651 ret = thread_data->hwndDefault;
1652 LeaveCriticalSection(&threaddata_cs);
1653 TRACE("Default is %p\n",ret);
1654 /* Clean up an unused new window outside of the critical section */
1655 if (new != NULL)
1657 DestroyWindow(new);
1659 TRACE("Default is %p\n",ret);
1660 return ret;
1663 /***********************************************************************
1664 * ImmGetDescriptionA (IMM32.@)
1666 UINT WINAPI ImmGetDescriptionA(
1667 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1669 WCHAR *buf;
1670 DWORD len;
1672 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1674 /* find out how many characters in the unicode buffer */
1675 len = ImmGetDescriptionW( hKL, NULL, 0 );
1676 if (!len)
1677 return 0;
1679 /* allocate a buffer of that size */
1680 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1681 if( !buf )
1682 return 0;
1684 /* fetch the unicode buffer */
1685 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1687 /* convert it back to ASCII */
1688 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1689 lpszDescription, uBufLen, NULL, NULL );
1691 HeapFree( GetProcessHeap(), 0, buf );
1693 if (len == 0)
1694 return 0;
1696 return len - 1;
1699 /***********************************************************************
1700 * ImmGetDescriptionW (IMM32.@)
1702 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1704 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1706 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1708 if (!hKL) return 0;
1709 if (!uBufLen) return lstrlenW( name );
1710 lstrcpynW( lpszDescription, name, uBufLen );
1711 return lstrlenW( lpszDescription );
1714 /***********************************************************************
1715 * ImmGetGuideLineA (IMM32.@)
1717 DWORD WINAPI ImmGetGuideLineA(
1718 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1720 FIXME("(%p, %d, %s, %d): stub\n",
1721 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1723 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1724 return 0;
1727 /***********************************************************************
1728 * ImmGetGuideLineW (IMM32.@)
1730 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1732 FIXME("(%p, %d, %s, %d): stub\n",
1733 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1735 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1736 return 0;
1739 /***********************************************************************
1740 * ImmGetIMEFileNameA (IMM32.@)
1742 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1744 LPWSTR bufW = NULL;
1745 UINT wBufLen = uBufLen;
1746 UINT rc;
1748 if (uBufLen && lpszFileName)
1749 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1750 else /* We need this to get the number of byte required */
1752 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1753 wBufLen = MAX_PATH;
1756 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1758 if (rc > 0)
1760 if (uBufLen && lpszFileName)
1761 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1762 uBufLen, NULL, NULL);
1763 else /* get the length */
1764 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1765 NULL);
1768 HeapFree(GetProcessHeap(),0,bufW);
1769 return rc;
1772 /***********************************************************************
1773 * ImmGetIMEFileNameW (IMM32.@)
1775 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1777 HKEY hkey;
1778 DWORD length;
1779 DWORD rc;
1780 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1782 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1783 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1784 if (rc != ERROR_SUCCESS)
1786 SetLastError(rc);
1787 return 0;
1790 length = 0;
1791 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1793 if (rc != ERROR_SUCCESS)
1795 RegCloseKey(hkey);
1796 SetLastError(rc);
1797 return 0;
1799 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1801 RegCloseKey(hkey);
1802 if (lpszFileName)
1804 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1805 return 0;
1807 else
1808 return length / sizeof(WCHAR);
1811 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1813 RegCloseKey(hkey);
1815 return length / sizeof(WCHAR);
1818 /***********************************************************************
1819 * ImmGetOpenStatus (IMM32.@)
1821 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1823 InputContextData *data = get_imc_data(hIMC);
1824 static int i;
1826 if (!data)
1827 return FALSE;
1829 TRACE("(%p): semi-stub\n", hIMC);
1831 if (!i++)
1832 FIXME("(%p): semi-stub\n", hIMC);
1834 return data->IMC.fOpen;
1837 /***********************************************************************
1838 * ImmGetProperty (IMM32.@)
1840 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1842 DWORD rc = 0;
1843 ImmHkl *kbd;
1845 TRACE("(%p, %d)\n", hKL, fdwIndex);
1846 kbd = IMM_GetImmHkl(hKL);
1848 if (kbd && kbd->hIME)
1850 switch (fdwIndex)
1852 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1853 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1854 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1855 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1856 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1857 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1858 case IGP_UI: rc = 0; break;
1859 default: rc = 0;
1862 return rc;
1865 /***********************************************************************
1866 * ImmGetRegisterWordStyleA (IMM32.@)
1868 UINT WINAPI ImmGetRegisterWordStyleA(
1869 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1871 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1872 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1873 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1875 if (!is_kbd_ime_unicode(immHkl))
1876 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1877 else
1879 STYLEBUFW sbw;
1880 UINT rc;
1882 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1883 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1884 lpStyleBuf->szDescription, 32, NULL, NULL);
1885 lpStyleBuf->dwStyle = sbw.dwStyle;
1886 return rc;
1889 else
1890 return 0;
1893 /***********************************************************************
1894 * ImmGetRegisterWordStyleW (IMM32.@)
1896 UINT WINAPI ImmGetRegisterWordStyleW(
1897 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1899 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1900 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1901 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1903 if (is_kbd_ime_unicode(immHkl))
1904 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1905 else
1907 STYLEBUFA sba;
1908 UINT rc;
1910 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1911 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1912 lpStyleBuf->szDescription, 32);
1913 lpStyleBuf->dwStyle = sba.dwStyle;
1914 return rc;
1917 else
1918 return 0;
1921 /***********************************************************************
1922 * ImmGetStatusWindowPos (IMM32.@)
1924 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1926 InputContextData *data = get_imc_data(hIMC);
1928 TRACE("(%p, %p)\n", hIMC, lpptPos);
1930 if (!data || !lpptPos)
1931 return FALSE;
1933 *lpptPos = data->IMC.ptStatusWndPos;
1935 return TRUE;
1938 /***********************************************************************
1939 * ImmGetVirtualKey (IMM32.@)
1941 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1943 OSVERSIONINFOA version;
1944 InputContextData *data = ImmGetContext( hWnd );
1945 TRACE("%p\n", hWnd);
1947 if ( data )
1948 return data->lastVK;
1950 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
1951 GetVersionExA( &version );
1952 switch(version.dwPlatformId)
1954 case VER_PLATFORM_WIN32_WINDOWS:
1955 return VK_PROCESSKEY;
1956 case VER_PLATFORM_WIN32_NT:
1957 return 0;
1958 default:
1959 FIXME("%d not supported\n",version.dwPlatformId);
1960 return VK_PROCESSKEY;
1964 /***********************************************************************
1965 * ImmInstallIMEA (IMM32.@)
1967 HKL WINAPI ImmInstallIMEA(
1968 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1970 LPWSTR lpszwIMEFileName;
1971 LPWSTR lpszwLayoutText;
1972 HKL hkl;
1974 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
1975 debugstr_a(lpszLayoutText));
1977 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
1978 lpszwLayoutText = strdupAtoW(lpszLayoutText);
1980 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
1982 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
1983 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
1984 return hkl;
1987 /***********************************************************************
1988 * ImmInstallIMEW (IMM32.@)
1990 HKL WINAPI ImmInstallIMEW(
1991 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1993 INT lcid = GetUserDefaultLCID();
1994 INT count;
1995 HKL hkl;
1996 DWORD rc;
1997 HKEY hkey;
1998 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
2000 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
2001 debugstr_w(lpszLayoutText));
2003 /* Start with 2. e001 will be blank and so default to the wine internal IME */
2004 count = 2;
2006 while (count < 0xfff)
2008 DWORD disposition = 0;
2010 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
2011 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
2013 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
2014 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
2015 break;
2016 else if (rc == ERROR_SUCCESS)
2017 RegCloseKey(hkey);
2019 count++;
2022 if (count == 0xfff)
2024 WARN("Unable to find slot to install IME\n");
2025 return 0;
2028 if (rc == ERROR_SUCCESS)
2030 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
2031 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
2032 if (rc == ERROR_SUCCESS)
2033 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
2034 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
2035 RegCloseKey(hkey);
2036 return hkl;
2038 else
2040 WARN("Unable to set IME registry values\n");
2041 return 0;
2045 /***********************************************************************
2046 * ImmIsIME (IMM32.@)
2048 BOOL WINAPI ImmIsIME(HKL hKL)
2050 ImmHkl *ptr;
2051 TRACE("(%p):\n", hKL);
2052 ptr = IMM_GetImmHkl(hKL);
2053 return (ptr && ptr->hIME);
2056 /***********************************************************************
2057 * ImmIsUIMessageA (IMM32.@)
2059 BOOL WINAPI ImmIsUIMessageA(
2060 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2062 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2063 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2064 (msg == WM_IME_SETCONTEXT) ||
2065 (msg == WM_IME_NOTIFY) ||
2066 (msg == WM_IME_COMPOSITIONFULL) ||
2067 (msg == WM_IME_SELECT) ||
2068 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2070 if (hWndIME)
2071 SendMessageA(hWndIME, msg, wParam, lParam);
2073 return TRUE;
2075 return FALSE;
2078 /***********************************************************************
2079 * ImmIsUIMessageW (IMM32.@)
2081 BOOL WINAPI ImmIsUIMessageW(
2082 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2084 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2085 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2086 (msg == WM_IME_SETCONTEXT) ||
2087 (msg == WM_IME_NOTIFY) ||
2088 (msg == WM_IME_COMPOSITIONFULL) ||
2089 (msg == WM_IME_SELECT) ||
2090 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2092 if (hWndIME)
2093 SendMessageW(hWndIME, msg, wParam, lParam);
2095 return TRUE;
2097 return FALSE;
2100 /***********************************************************************
2101 * ImmNotifyIME (IMM32.@)
2103 BOOL WINAPI ImmNotifyIME(
2104 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
2106 InputContextData *data = get_imc_data(hIMC);
2108 TRACE("(%p, %d, %d, %d)\n",
2109 hIMC, dwAction, dwIndex, dwValue);
2111 if (hIMC == NULL)
2113 SetLastError(ERROR_SUCCESS);
2114 return FALSE;
2117 if (!data || ! data->immKbd->pNotifyIME)
2119 return FALSE;
2122 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
2125 /***********************************************************************
2126 * ImmRegisterWordA (IMM32.@)
2128 BOOL WINAPI ImmRegisterWordA(
2129 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
2131 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2132 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2133 debugstr_a(lpszRegister));
2134 if (immHkl->hIME && immHkl->pImeRegisterWord)
2136 if (!is_kbd_ime_unicode(immHkl))
2137 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
2138 (LPCWSTR)lpszRegister);
2139 else
2141 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2142 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
2143 BOOL rc;
2145 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
2146 HeapFree(GetProcessHeap(),0,lpszwReading);
2147 HeapFree(GetProcessHeap(),0,lpszwRegister);
2148 return rc;
2151 else
2152 return FALSE;
2155 /***********************************************************************
2156 * ImmRegisterWordW (IMM32.@)
2158 BOOL WINAPI ImmRegisterWordW(
2159 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
2161 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2162 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2163 debugstr_w(lpszRegister));
2164 if (immHkl->hIME && immHkl->pImeRegisterWord)
2166 if (is_kbd_ime_unicode(immHkl))
2167 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
2168 else
2170 LPSTR lpszaReading = strdupWtoA(lpszReading);
2171 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
2172 BOOL rc;
2174 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
2175 (LPCWSTR)lpszaRegister);
2176 HeapFree(GetProcessHeap(),0,lpszaReading);
2177 HeapFree(GetProcessHeap(),0,lpszaRegister);
2178 return rc;
2181 else
2182 return FALSE;
2185 /***********************************************************************
2186 * ImmReleaseContext (IMM32.@)
2188 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2190 static BOOL shown = FALSE;
2192 if (!shown) {
2193 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2194 shown = TRUE;
2196 return TRUE;
2199 /***********************************************************************
2200 * ImmRequestMessageA(IMM32.@)
2202 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2204 InputContextData *data = get_imc_data(hIMC);
2206 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2208 if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2210 SetLastError(ERROR_INVALID_HANDLE);
2211 return 0;
2214 /***********************************************************************
2215 * ImmRequestMessageW(IMM32.@)
2217 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2219 InputContextData *data = get_imc_data(hIMC);
2221 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2223 if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2225 SetLastError(ERROR_INVALID_HANDLE);
2226 return 0;
2229 /***********************************************************************
2230 * ImmSetCandidateWindow (IMM32.@)
2232 BOOL WINAPI ImmSetCandidateWindow(
2233 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2235 InputContextData *data = get_imc_data(hIMC);
2237 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2239 if (!data || !lpCandidate)
2240 return FALSE;
2242 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2243 return FALSE;
2245 TRACE("\t%x, %x, %s, %s\n",
2246 lpCandidate->dwIndex, lpCandidate->dwStyle,
2247 wine_dbgstr_point(&lpCandidate->ptCurrentPos),
2248 wine_dbgstr_rect(&lpCandidate->rcArea));
2250 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
2251 return FALSE;
2253 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2254 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2255 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2257 return TRUE;
2260 /***********************************************************************
2261 * ImmSetCompositionFontA (IMM32.@)
2263 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2265 InputContextData *data = get_imc_data(hIMC);
2266 TRACE("(%p, %p)\n", hIMC, lplf);
2268 if (!data || !lplf)
2270 SetLastError(ERROR_INVALID_HANDLE);
2271 return FALSE;
2274 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2275 return FALSE;
2277 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2278 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2279 LF_FACESIZE);
2280 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2281 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2283 return TRUE;
2286 /***********************************************************************
2287 * ImmSetCompositionFontW (IMM32.@)
2289 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2291 InputContextData *data = get_imc_data(hIMC);
2292 TRACE("(%p, %p)\n", hIMC, lplf);
2294 if (!data || !lplf)
2296 SetLastError(ERROR_INVALID_HANDLE);
2297 return FALSE;
2300 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2301 return FALSE;
2303 data->IMC.lfFont.W = *lplf;
2304 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2305 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2307 return TRUE;
2310 /***********************************************************************
2311 * ImmSetCompositionStringA (IMM32.@)
2313 BOOL WINAPI ImmSetCompositionStringA(
2314 HIMC hIMC, DWORD dwIndex,
2315 LPCVOID lpComp, DWORD dwCompLen,
2316 LPCVOID lpRead, DWORD dwReadLen)
2318 DWORD comp_len;
2319 DWORD read_len;
2320 WCHAR *CompBuffer = NULL;
2321 WCHAR *ReadBuffer = NULL;
2322 BOOL rc;
2323 InputContextData *data = get_imc_data(hIMC);
2325 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2326 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2328 if (!data)
2329 return FALSE;
2331 if (!(dwIndex == SCS_SETSTR ||
2332 dwIndex == SCS_CHANGEATTR ||
2333 dwIndex == SCS_CHANGECLAUSE ||
2334 dwIndex == SCS_SETRECONVERTSTRING ||
2335 dwIndex == SCS_QUERYRECONVERTSTRING))
2336 return FALSE;
2338 if (!is_himc_ime_unicode(data))
2339 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2340 dwCompLen, lpRead, dwReadLen);
2342 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2343 if (comp_len)
2345 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2346 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2349 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2350 if (read_len)
2352 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2353 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2356 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2357 ReadBuffer, read_len);
2359 HeapFree(GetProcessHeap(), 0, CompBuffer);
2360 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2362 return rc;
2365 /***********************************************************************
2366 * ImmSetCompositionStringW (IMM32.@)
2368 BOOL WINAPI ImmSetCompositionStringW(
2369 HIMC hIMC, DWORD dwIndex,
2370 LPCVOID lpComp, DWORD dwCompLen,
2371 LPCVOID lpRead, DWORD dwReadLen)
2373 DWORD comp_len;
2374 DWORD read_len;
2375 CHAR *CompBuffer = NULL;
2376 CHAR *ReadBuffer = NULL;
2377 BOOL rc;
2378 InputContextData *data = get_imc_data(hIMC);
2380 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2381 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2383 if (!data)
2384 return FALSE;
2386 if (!(dwIndex == SCS_SETSTR ||
2387 dwIndex == SCS_CHANGEATTR ||
2388 dwIndex == SCS_CHANGECLAUSE ||
2389 dwIndex == SCS_SETRECONVERTSTRING ||
2390 dwIndex == SCS_QUERYRECONVERTSTRING))
2391 return FALSE;
2393 if (is_himc_ime_unicode(data))
2394 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2395 dwCompLen, lpRead, dwReadLen);
2397 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2398 NULL);
2399 if (comp_len)
2401 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2402 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2403 NULL, NULL);
2406 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2407 NULL);
2408 if (read_len)
2410 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2411 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2412 NULL, NULL);
2415 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2416 ReadBuffer, read_len);
2418 HeapFree(GetProcessHeap(), 0, CompBuffer);
2419 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2421 return rc;
2424 /***********************************************************************
2425 * ImmSetCompositionWindow (IMM32.@)
2427 BOOL WINAPI ImmSetCompositionWindow(
2428 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2430 BOOL reshow = FALSE;
2431 InputContextData *data = get_imc_data(hIMC);
2433 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2434 if (lpCompForm)
2435 TRACE("\t%x, %s, %s\n", lpCompForm->dwStyle,
2436 wine_dbgstr_point(&lpCompForm->ptCurrentPos),
2437 wine_dbgstr_rect(&lpCompForm->rcArea));
2439 if (!data)
2441 SetLastError(ERROR_INVALID_HANDLE);
2442 return FALSE;
2445 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2446 return FALSE;
2448 data->IMC.cfCompForm = *lpCompForm;
2450 if (IsWindowVisible(data->immKbd->UIWnd))
2452 reshow = TRUE;
2453 ShowWindow(data->immKbd->UIWnd,SW_HIDE);
2456 /* FIXME: this is a partial stub */
2458 if (reshow)
2459 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE);
2461 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2462 return TRUE;
2465 /***********************************************************************
2466 * ImmSetConversionStatus (IMM32.@)
2468 BOOL WINAPI ImmSetConversionStatus(
2469 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2471 DWORD oldConversion, oldSentence;
2472 InputContextData *data = get_imc_data(hIMC);
2474 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2476 if (!data)
2478 SetLastError(ERROR_INVALID_HANDLE);
2479 return FALSE;
2482 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2483 return FALSE;
2485 if ( fdwConversion != data->IMC.fdwConversion )
2487 oldConversion = data->IMC.fdwConversion;
2488 data->IMC.fdwConversion = fdwConversion;
2489 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2490 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2492 if ( fdwSentence != data->IMC.fdwSentence )
2494 oldSentence = data->IMC.fdwSentence;
2495 data->IMC.fdwSentence = fdwSentence;
2496 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2497 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2500 return TRUE;
2503 /***********************************************************************
2504 * ImmSetOpenStatus (IMM32.@)
2506 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2508 InputContextData *data = get_imc_data(hIMC);
2510 TRACE("%p %d\n", hIMC, fOpen);
2512 if (!data)
2514 SetLastError(ERROR_INVALID_HANDLE);
2515 return FALSE;
2518 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2519 return FALSE;
2521 if (data->immKbd->UIWnd == NULL)
2523 /* create the ime window */
2524 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2525 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2526 0, data->immKbd->hIME, 0);
2527 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2529 else if (fOpen)
2530 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2532 if (!fOpen != !data->IMC.fOpen)
2534 data->IMC.fOpen = fOpen;
2535 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2536 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2539 return TRUE;
2542 /***********************************************************************
2543 * ImmSetStatusWindowPos (IMM32.@)
2545 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2547 InputContextData *data = get_imc_data(hIMC);
2549 TRACE("(%p, %p)\n", hIMC, lpptPos);
2551 if (!data || !lpptPos)
2553 SetLastError(ERROR_INVALID_HANDLE);
2554 return FALSE;
2557 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2558 return FALSE;
2560 TRACE("\t%s\n", wine_dbgstr_point(lpptPos));
2562 data->IMC.ptStatusWndPos = *lpptPos;
2563 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2564 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2566 return TRUE;
2569 /***********************************************************************
2570 * ImmCreateSoftKeyboard(IMM32.@)
2572 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2574 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2575 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2576 return 0;
2579 /***********************************************************************
2580 * ImmDestroySoftKeyboard(IMM32.@)
2582 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2584 FIXME("(%p): stub\n", hSoftWnd);
2585 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2586 return FALSE;
2589 /***********************************************************************
2590 * ImmShowSoftKeyboard(IMM32.@)
2592 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2594 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2595 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2596 return FALSE;
2599 /***********************************************************************
2600 * ImmSimulateHotKey (IMM32.@)
2602 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2604 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2605 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2606 return FALSE;
2609 /***********************************************************************
2610 * ImmUnregisterWordA (IMM32.@)
2612 BOOL WINAPI ImmUnregisterWordA(
2613 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2615 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2616 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2617 debugstr_a(lpszUnregister));
2618 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2620 if (!is_kbd_ime_unicode(immHkl))
2621 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2622 (LPCWSTR)lpszUnregister);
2623 else
2625 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2626 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2627 BOOL rc;
2629 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2630 HeapFree(GetProcessHeap(),0,lpszwReading);
2631 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2632 return rc;
2635 else
2636 return FALSE;
2639 /***********************************************************************
2640 * ImmUnregisterWordW (IMM32.@)
2642 BOOL WINAPI ImmUnregisterWordW(
2643 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2645 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2646 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2647 debugstr_w(lpszUnregister));
2648 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2650 if (is_kbd_ime_unicode(immHkl))
2651 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2652 else
2654 LPSTR lpszaReading = strdupWtoA(lpszReading);
2655 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2656 BOOL rc;
2658 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2659 (LPCWSTR)lpszaUnregister);
2660 HeapFree(GetProcessHeap(),0,lpszaReading);
2661 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2662 return rc;
2665 else
2666 return FALSE;
2669 /***********************************************************************
2670 * ImmGetImeMenuItemsA (IMM32.@)
2672 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2673 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2674 DWORD dwSize)
2676 InputContextData *data = get_imc_data(hIMC);
2677 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2678 lpImeParentMenu, lpImeMenu, dwSize);
2680 if (!data)
2682 SetLastError(ERROR_INVALID_HANDLE);
2683 return 0;
2686 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2688 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2689 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2690 (IMEMENUITEMINFOW*)lpImeParentMenu,
2691 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2692 else
2694 IMEMENUITEMINFOW lpImeParentMenuW;
2695 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2696 DWORD rc;
2698 if (lpImeParentMenu)
2699 parent = &lpImeParentMenuW;
2700 if (lpImeMenu)
2702 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2703 dwSize = count * sizeof(IMEMENUITEMINFOW);
2704 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2706 else
2707 lpImeMenuW = NULL;
2709 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2710 parent, lpImeMenuW, dwSize);
2712 if (lpImeParentMenu)
2714 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2715 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2716 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2717 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2718 NULL, NULL);
2720 if (lpImeMenu && rc)
2722 unsigned int i;
2723 for (i = 0; i < rc; i++)
2725 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2726 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2727 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2728 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2729 NULL, NULL);
2732 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2733 return rc;
2736 else
2737 return 0;
2740 /***********************************************************************
2741 * ImmGetImeMenuItemsW (IMM32.@)
2743 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2744 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2745 DWORD dwSize)
2747 InputContextData *data = get_imc_data(hIMC);
2748 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2749 lpImeParentMenu, lpImeMenu, dwSize);
2751 if (!data)
2753 SetLastError(ERROR_INVALID_HANDLE);
2754 return 0;
2757 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2759 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2760 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2761 lpImeParentMenu, lpImeMenu, dwSize);
2762 else
2764 IMEMENUITEMINFOA lpImeParentMenuA;
2765 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2766 DWORD rc;
2768 if (lpImeParentMenu)
2769 parent = &lpImeParentMenuA;
2770 if (lpImeMenu)
2772 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2773 dwSize = count * sizeof(IMEMENUITEMINFOA);
2774 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2776 else
2777 lpImeMenuA = NULL;
2779 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2780 (IMEMENUITEMINFOW*)parent,
2781 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2783 if (lpImeParentMenu)
2785 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2786 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2787 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2788 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2790 if (lpImeMenu && rc)
2792 unsigned int i;
2793 for (i = 0; i < rc; i++)
2795 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2796 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2797 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2798 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2801 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2802 return rc;
2805 else
2806 return 0;
2809 /***********************************************************************
2810 * ImmLockIMC(IMM32.@)
2812 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2814 InputContextData *data = get_imc_data(hIMC);
2816 if (!data)
2817 return NULL;
2818 data->dwLock++;
2819 return &data->IMC;
2822 /***********************************************************************
2823 * ImmUnlockIMC(IMM32.@)
2825 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2827 InputContextData *data = get_imc_data(hIMC);
2829 if (!data)
2830 return FALSE;
2831 if (data->dwLock)
2832 data->dwLock--;
2833 return TRUE;
2836 /***********************************************************************
2837 * ImmGetIMCLockCount(IMM32.@)
2839 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2841 InputContextData *data = get_imc_data(hIMC);
2842 if (!data)
2843 return 0;
2844 return data->dwLock;
2847 /***********************************************************************
2848 * ImmCreateIMCC(IMM32.@)
2850 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2852 return GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, size);
2855 /***********************************************************************
2856 * ImmDestroyIMCC(IMM32.@)
2858 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2860 return GlobalFree(block);
2863 /***********************************************************************
2864 * ImmLockIMCC(IMM32.@)
2866 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2868 return GlobalLock(imcc);
2871 /***********************************************************************
2872 * ImmUnlockIMCC(IMM32.@)
2874 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2876 return GlobalUnlock(imcc);
2879 /***********************************************************************
2880 * ImmGetIMCCLockCount(IMM32.@)
2882 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2884 return GlobalFlags(imcc) & GMEM_LOCKCOUNT;
2887 /***********************************************************************
2888 * ImmReSizeIMCC(IMM32.@)
2890 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2892 return GlobalReAlloc(imcc, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
2895 /***********************************************************************
2896 * ImmGetIMCCSize(IMM32.@)
2898 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2900 return GlobalSize(imcc);
2903 /***********************************************************************
2904 * ImmGenerateMessage(IMM32.@)
2906 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2908 InputContextData *data = get_imc_data(hIMC);
2910 if (!data)
2912 SetLastError(ERROR_INVALID_HANDLE);
2913 return FALSE;
2916 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2917 if (data->IMC.dwNumMsgBuf > 0)
2919 LPTRANSMSG lpTransMsg;
2920 HIMCC hMsgBuf;
2921 DWORD i, dwNumMsgBuf;
2923 /* We are going to detach our hMsgBuff so that if processing messages
2924 generates new messages they go into a new buffer */
2925 hMsgBuf = data->IMC.hMsgBuf;
2926 dwNumMsgBuf = data->IMC.dwNumMsgBuf;
2928 data->IMC.hMsgBuf = ImmCreateIMCC(0);
2929 data->IMC.dwNumMsgBuf = 0;
2931 lpTransMsg = ImmLockIMCC(hMsgBuf);
2932 for (i = 0; i < dwNumMsgBuf; i++)
2933 ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2935 ImmUnlockIMCC(hMsgBuf);
2936 ImmDestroyIMCC(hMsgBuf);
2939 return TRUE;
2942 /***********************************************************************
2943 * ImmTranslateMessage(IMM32.@)
2944 * ( Undocumented, call internally and from user32.dll )
2946 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2948 InputContextData *data;
2949 HIMC imc = ImmGetContext(hwnd);
2950 BYTE state[256];
2951 UINT scancode;
2952 LPVOID list = 0;
2953 UINT msg_count;
2954 UINT uVirtKey;
2955 static const DWORD list_count = 10;
2957 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2959 if (imc)
2960 data = imc;
2961 else
2962 return FALSE;
2964 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2965 return FALSE;
2967 GetKeyboardState(state);
2968 scancode = lKeyData >> 0x10 & 0xff;
2970 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2971 ((DWORD*)list)[0] = list_count;
2973 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2975 WCHAR chr;
2977 if (!is_himc_ime_unicode(data))
2978 ToAscii(data->lastVK, scancode, state, &chr, 0);
2979 else
2980 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2981 uVirtKey = MAKELONG(data->lastVK,chr);
2983 else
2984 uVirtKey = data->lastVK;
2986 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2987 TRACE("%i messages generated\n",msg_count);
2988 if (msg_count && msg_count <= list_count)
2990 UINT i;
2991 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2993 for (i = 0; i < msg_count; i++)
2994 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2996 else if (msg_count > list_count)
2997 ImmGenerateMessage(imc);
2999 HeapFree(GetProcessHeap(),0,list);
3001 data->lastVK = VK_PROCESSKEY;
3003 return (msg_count > 0);
3006 /***********************************************************************
3007 * ImmProcessKey(IMM32.@)
3008 * ( Undocumented, called from user32.dll )
3010 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
3012 InputContextData *data;
3013 HIMC imc = ImmGetContext(hwnd);
3014 BYTE state[256];
3016 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
3018 if (imc)
3019 data = imc;
3020 else
3021 return FALSE;
3023 /* Make sure we are inputting to the correct keyboard */
3024 if (data->immKbd->hkl != hKL)
3026 ImmHkl *new_hkl = IMM_GetImmHkl(hKL);
3027 if (new_hkl)
3029 data->immKbd->pImeSelect(imc, FALSE);
3030 data->immKbd->uSelected--;
3031 data->immKbd = new_hkl;
3032 data->immKbd->pImeSelect(imc, TRUE);
3033 data->immKbd->uSelected++;
3035 else
3036 return FALSE;
3039 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
3040 return FALSE;
3042 GetKeyboardState(state);
3043 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
3045 data->lastVK = vKey;
3046 return TRUE;
3049 data->lastVK = VK_PROCESSKEY;
3050 return FALSE;
3053 /***********************************************************************
3054 * ImmDisableTextFrameService(IMM32.@)
3056 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread)
3058 FIXME("Stub\n");
3059 return FALSE;
3062 /***********************************************************************
3063 * ImmEnumInputContext(IMM32.@)
3066 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam)
3068 FIXME("Stub\n");
3069 return FALSE;
3072 /***********************************************************************
3073 * ImmGetHotKey(IMM32.@)
3076 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl)
3078 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl);
3079 return FALSE;