28eb00f355a00d21c9f91b502f177670ecebe791
[reactos.git] / dll / win32 / imm32 / imm.c
1 /*
2 * IMM32 library
3 *
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include <stdarg.h>
23 #include <stdio.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "winerror.h"
30 #include "wine/debug.h"
31 #include "imm.h"
32 #include "ddk/imm.h"
33 #include "winnls.h"
34 #include "winreg.h"
35 #include "wine/list.h"
36 #include "wine/unicode.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(imm);
39
40 #define IMM_INIT_MAGIC 0x19650412
41 BOOL WINAPI User32InitializeImmEntryTable(DWORD);
42
43 typedef struct _tagImmHkl{
44 struct list entry;
45 HKL hkl;
46 HMODULE hIME;
47 IMEINFO imeInfo;
48 WCHAR imeClassName[17]; /* 16 character max */
49 ULONG uSelected;
50 HWND UIWnd;
51
52 /* Function Pointers */
53 BOOL (WINAPI *pImeInquire)(IMEINFO *, WCHAR *, const WCHAR *);
54 BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *);
55 BOOL (WINAPI *pImeDestroy)(UINT);
56 LRESULT (WINAPI *pImeEscape)(HIMC, UINT, void *);
57 BOOL (WINAPI *pImeSelect)(HIMC, BOOL);
58 BOOL (WINAPI *pImeSetActiveContext)(HIMC, BOOL);
59 UINT (WINAPI *pImeToAsciiEx)(UINT, UINT, const BYTE *, DWORD *, UINT, HIMC);
60 BOOL (WINAPI *pNotifyIME)(HIMC, DWORD, DWORD, DWORD);
61 BOOL (WINAPI *pImeRegisterWord)(const WCHAR *, DWORD, const WCHAR *);
62 BOOL (WINAPI *pImeUnregisterWord)(const WCHAR *, DWORD, const WCHAR *);
63 UINT (WINAPI *pImeEnumRegisterWord)(REGISTERWORDENUMPROCW, const WCHAR *, DWORD, const WCHAR *, void *);
64 BOOL (WINAPI *pImeSetCompositionString)(HIMC, DWORD, const void *, DWORD, const void *, DWORD);
65 DWORD (WINAPI *pImeConversionList)(HIMC, const WCHAR *, CANDIDATELIST *, DWORD, UINT);
66 BOOL (WINAPI *pImeProcessKey)(HIMC, UINT, LPARAM, const BYTE *);
67 UINT (WINAPI *pImeGetRegisterWordStyle)(UINT, STYLEBUFW *);
68 DWORD (WINAPI *pImeGetImeMenuItems)(HIMC, DWORD, DWORD, IMEMENUITEMINFOW *, IMEMENUITEMINFOW *, DWORD);
69 } ImmHkl;
70
71 typedef struct tagInputContextData
72 {
73 DWORD dwLock;
74 INPUTCONTEXT IMC;
75 DWORD threadID;
76
77 ImmHkl *immKbd;
78 UINT lastVK;
79 BOOL threadDefault;
80 DWORD magic;
81 } InputContextData;
82
83 #define WINE_IMC_VALID_MAGIC 0x56434D49
84
85 typedef struct _tagTRANSMSG {
86 UINT message;
87 WPARAM wParam;
88 LPARAM lParam;
89 } TRANSMSG, *LPTRANSMSG;
90
91 typedef struct _tagIMMThreadData {
92 struct list entry;
93 DWORD threadID;
94 HIMC defaultContext;
95 HWND hwndDefault;
96 BOOL disableIME;
97 DWORD windowRefs;
98 } IMMThreadData;
99
100 static struct list ImmHklList = LIST_INIT(ImmHklList);
101 static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList);
102
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};
104
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};
108
109 static const WCHAR szwIME[] = {'I','M','E',0};
110 static const WCHAR szwDefaultIME[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
111
112 static CRITICAL_SECTION threaddata_cs;
113 static CRITICAL_SECTION_DEBUG critsect_debug =
114 {
115 0, 0, &threaddata_cs,
116 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
117 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
118 };
119 static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
120 static BOOL disable_ime;
121
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)
124
125 static BOOL IMM_DestroyContext(HIMC hIMC);
126 static InputContextData* get_imc_data(HIMC hIMC);
127
128 static inline WCHAR *strdupAtoW( const char *str )
129 {
130 WCHAR *ret = NULL;
131 if (str)
132 {
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 );
136 }
137 return ret;
138 }
139
140 static inline CHAR *strdupWtoA( const WCHAR *str )
141 {
142 CHAR *ret = NULL;
143 if (str)
144 {
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 );
148 }
149 return ret;
150 }
151
152 static DWORD convert_candidatelist_WtoA(
153 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
154 {
155 DWORD ret, i, len;
156
157 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
158 if ( lpDst && dwBufLen > 0 )
159 {
160 *lpDst = *lpSrc;
161 lpDst->dwOffset[0] = ret;
162 }
163
164 for ( i = 0; i < lpSrc->dwCount; i++)
165 {
166 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
167
168 if ( lpDst && dwBufLen > 0 )
169 {
170 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
171
172 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1,
173 (LPSTR)dest, dwBufLen, NULL, NULL);
174
175 if ( i + 1 < lpSrc->dwCount )
176 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
177 dwBufLen -= len * sizeof(char);
178 }
179 else
180 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL);
181
182 ret += len * sizeof(char);
183 }
184
185 if ( lpDst )
186 lpDst->dwSize = ret;
187
188 return ret;
189 }
190
191 static DWORD convert_candidatelist_AtoW(
192 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
193 {
194 DWORD ret, i, len;
195
196 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
197 if ( lpDst && dwBufLen > 0 )
198 {
199 *lpDst = *lpSrc;
200 lpDst->dwOffset[0] = ret;
201 }
202
203 for ( i = 0; i < lpSrc->dwCount; i++)
204 {
205 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
206
207 if ( lpDst && dwBufLen > 0 )
208 {
209 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
210
211 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1,
212 (LPWSTR)dest, dwBufLen);
213
214 if ( i + 1 < lpSrc->dwCount )
215 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
216 dwBufLen -= len * sizeof(WCHAR);
217 }
218 else
219 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
220
221 ret += len * sizeof(WCHAR);
222 }
223
224 if ( lpDst )
225 lpDst->dwSize = ret;
226
227 return ret;
228 }
229
230 static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD thread)
231 {
232 IMMThreadData *data;
233 DWORD process;
234
235 if (hwnd)
236 {
237 if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL;
238 if (process != GetCurrentProcessId()) return NULL;
239 }
240 else if (thread)
241 {
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;
247 }
248 else
249 thread = GetCurrentThreadId();
250
251 EnterCriticalSection(&threaddata_cs);
252 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
253 if (data->threadID == thread) return data;
254
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;
260 }
261
262 static BOOL IMM_IsDefaultContext(HIMC imc)
263 {
264 InputContextData *data = get_imc_data(imc);
265
266 if (!data)
267 return FALSE;
268
269 return data->threadDefault;
270 }
271
272 static void IMM_FreeThreadData(void)
273 {
274 IMMThreadData *data;
275
276 EnterCriticalSection(&threaddata_cs);
277 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
278 {
279 if (data->threadID == GetCurrentThreadId())
280 {
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;
287 }
288 }
289 LeaveCriticalSection(&threaddata_cs);
290 }
291
292 static HMODULE load_graphics_driver(void)
293 {
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};
304
305 HMODULE ret = 0;
306 HKEY hkey;
307 DWORD size;
308 WCHAR path[MAX_PATH];
309 WCHAR key[ARRAY_SIZE( key_pathW ) + ARRAY_SIZE( displayW ) + 40];
310 UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
311
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;
322 }
323
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)
327 {
328 ImmHkl *ptr;
329 WCHAR filename[MAX_PATH];
330
331 TRACE("Seeking ime for keyboard %p\n",hkl);
332
333 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
334 {
335 if (ptr->hkl == hkl)
336 return ptr;
337 }
338 /* not found... create it */
339
340 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
341
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)
346 {
347 LOAD_FUNCPTR(ImeInquire);
348 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
349 {
350 FreeLibrary(ptr->hIME);
351 ptr->hIME = NULL;
352 }
353 else
354 {
355 LOAD_FUNCPTR(ImeDestroy);
356 LOAD_FUNCPTR(ImeSelect);
357 if (!ptr->pImeSelect || !ptr->pImeDestroy)
358 {
359 FreeLibrary(ptr->hIME);
360 ptr->hIME = NULL;
361 }
362 else
363 {
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))
379 {
380 WCHAR bufW[17];
381 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
382 -1, bufW, 17);
383 lstrcpyW(ptr->imeClassName, bufW);
384 }
385 }
386 }
387 }
388 list_add_head(&ImmHklList,&ptr->entry);
389
390 return ptr;
391 }
392 #undef LOAD_FUNCPTR
393
394 HWND WINAPI __wine_get_ui_window(HKL hkl)
395 {
396 ImmHkl *immHkl = IMM_GetImmHkl(hkl);
397 return immHkl->UIWnd;
398 }
399
400 static void IMM_FreeAllImmHkl(void)
401 {
402 ImmHkl *ptr,*cursor2;
403
404 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
405 {
406 list_remove(&ptr->entry);
407 if (ptr->hIME)
408 {
409 ptr->pImeDestroy(1);
410 FreeLibrary(ptr->hIME);
411 }
412 if (ptr->UIWnd)
413 DestroyWindow(ptr->UIWnd);
414 HeapFree(GetProcessHeap(),0,ptr);
415 }
416 }
417
418 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
419 {
420 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
421 switch (fdwReason)
422 {
423 case DLL_PROCESS_ATTACH:
424 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
425 {
426 return FALSE;
427 }
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;
439 }
440 return TRUE;
441 }
442
443 /* for posting messages as the IME */
444 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
445 {
446 HWND target = GetFocus();
447 if (!target)
448 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
449 else
450 PostMessageW(target, msg, wParam, lParam);
451 }
452
453 /* for sending messages as the IME */
454 static void ImmInternalSendIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
455 {
456 HWND target = GetFocus();
457 if (!target)
458 SendMessageW(data->IMC.hWnd,msg,wParam,lParam);
459 else
460 SendMessageW(target, msg, wParam, lParam);
461 }
462
463 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
464 {
465 HWND target;
466
467 target = data->IMC.hWnd;
468 if (!target) target = GetFocus();
469
470 if (target)
471 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
472
473 return 0;
474 }
475
476 static HIMCC ImmCreateBlankCompStr(void)
477 {
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;
486 }
487
488 static InputContextData* get_imc_data(HIMC hIMC)
489 {
490 InputContextData *data = hIMC;
491
492 if (hIMC == NULL)
493 return NULL;
494
495 if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
496 {
497 SetLastError(ERROR_INVALID_HANDLE);
498 return NULL;
499 }
500 return data;
501 }
502
503 static HIMC get_default_context( HWND hwnd )
504 {
505 HIMC ret;
506 IMMThreadData* thread_data = IMM_GetThreadData( hwnd, 0 );
507
508 if (!thread_data) return 0;
509
510 if (thread_data->defaultContext)
511 {
512 ret = thread_data->defaultContext;
513 LeaveCriticalSection(&threaddata_cs);
514 return ret;
515 }
516
517 /* can't create a default context in another thread */
518 if (thread_data->threadID != GetCurrentThreadId())
519 {
520 LeaveCriticalSection(&threaddata_cs);
521 return 0;
522 }
523
524 LeaveCriticalSection(&threaddata_cs);
525
526 ret = ImmCreateContext();
527 if (!ret) return 0;
528 ((InputContextData*)ret)->threadDefault = TRUE;
529
530 /* thread_data is in the current thread so we can assume it's still valid */
531 EnterCriticalSection(&threaddata_cs);
532
533 if (thread_data->defaultContext) /* someone beat us */
534 {
535 IMM_DestroyContext( ret );
536 ret = thread_data->defaultContext;
537 }
538 else thread_data->defaultContext = ret;
539
540 LeaveCriticalSection(&threaddata_cs);
541 return ret;
542 }
543
544 static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
545 {
546 InputContextData *data;
547
548 if (hWnd)
549 {
550 DWORD thread = GetWindowThreadProcessId(hWnd, NULL);
551 if (thread != GetCurrentThreadId()) return TRUE;
552 }
553 data = get_imc_data(hIMC);
554 if (data && data->threadID != GetCurrentThreadId())
555 return TRUE;
556
557 return FALSE;
558 }
559
560 /***********************************************************************
561 * ImmAssociateContext (IMM32.@)
562 */
563 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
564 {
565 HIMC old = NULL;
566 InputContextData *data = get_imc_data(hIMC);
567
568 TRACE("(%p, %p):\n", hWnd, hIMC);
569
570 if(hIMC && !data)
571 return NULL;
572
573 /*
574 * If already associated just return
575 */
576 if (hIMC && data->IMC.hWnd == hWnd)
577 return hIMC;
578
579 if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
580 return NULL;
581
582 if (hWnd)
583 {
584 HIMC defaultContext = get_default_context( hWnd );
585 old = RemovePropW(hWnd,szwWineIMCProperty);
586
587 if (old == NULL)
588 old = defaultContext;
589 else if (old == (HIMC)-1)
590 old = NULL;
591
592 if (hIMC != defaultContext)
593 {
594 if (hIMC == NULL) /* Meaning disable imm for that window*/
595 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
596 else
597 SetPropW(hWnd,szwWineIMCProperty,hIMC);
598 }
599
600 if (old)
601 {
602 InputContextData *old_data = old;
603 if (old_data->IMC.hWnd == hWnd)
604 old_data->IMC.hWnd = NULL;
605 }
606 }
607
608 if (!hIMC)
609 return old;
610
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);
614
615 return old;
616 }
617
618
619 /*
620 * Helper function for ImmAssociateContextEx
621 */
622 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
623 {
624 HIMC hImc = (HIMC)lParam;
625 ImmAssociateContext(hwnd,hImc);
626 return TRUE;
627 }
628
629 /***********************************************************************
630 * ImmAssociateContextEx (IMM32.@)
631 */
632 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
633 {
634 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
635
636 if (!hWnd)
637 return FALSE;
638
639 switch (dwFlags)
640 {
641 case 0:
642 ImmAssociateContext(hWnd,hIMC);
643 return TRUE;
644 case IACE_DEFAULT:
645 {
646 HIMC defaultContext = get_default_context( hWnd );
647 if (!defaultContext) return FALSE;
648 ImmAssociateContext(hWnd,defaultContext);
649 return TRUE;
650 }
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;
661 }
662 }
663
664 /***********************************************************************
665 * ImmConfigureIMEA (IMM32.@)
666 */
667 BOOL WINAPI ImmConfigureIMEA(
668 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
669 {
670 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
671
672 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
673
674 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
675 return FALSE;
676
677 if (immHkl->hIME && immHkl->pImeConfigure)
678 {
679 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
680 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
681 else
682 {
683 REGISTERWORDW rww;
684 REGISTERWORDA *rwa = lpData;
685 BOOL rc;
686
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;
693 }
694 }
695 else
696 return FALSE;
697 }
698
699 /***********************************************************************
700 * ImmConfigureIMEW (IMM32.@)
701 */
702 BOOL WINAPI ImmConfigureIMEW(
703 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
704 {
705 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
706
707 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
708
709 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
710 return FALSE;
711
712 if (immHkl->hIME && immHkl->pImeConfigure)
713 {
714 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
715 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
716 else
717 {
718 REGISTERWORDW *rww = lpData;
719 REGISTERWORDA rwa;
720 BOOL rc;
721
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;
728 }
729 }
730 else
731 return FALSE;
732 }
733
734 /***********************************************************************
735 * ImmCreateContext (IMM32.@)
736 */
737 HIMC WINAPI ImmCreateContext(void)
738 {
739 InputContextData *new_context;
740 LPGUIDELINE gl;
741 LPCANDIDATEINFO ci;
742 int i;
743
744 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
745
746 /* Load the IME */
747 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
748
749 if (!new_context->immKbd->hIME)
750 {
751 TRACE("IME dll could not be loaded\n");
752 HeapFree(GetProcessHeap(),0,new_context);
753 return 0;
754 }
755
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);
769
770 for (i = 0; i < ARRAY_SIZE(new_context->IMC.cfCandForm); i++)
771 new_context->IMC.cfCandForm[i].dwIndex = ~0u;
772
773 /* Initialize the IME Private */
774 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
775
776 new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps;
777 new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps;
778
779 if (!new_context->immKbd->pImeSelect(new_context, TRUE))
780 {
781 TRACE("Selection of IME failed\n");
782 IMM_DestroyContext(new_context);
783 return 0;
784 }
785 new_context->threadID = GetCurrentThreadId();
786 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd);
787
788 new_context->immKbd->uSelected++;
789 TRACE("Created context %p\n",new_context);
790
791 new_context->magic = WINE_IMC_VALID_MAGIC;
792 return new_context;
793 }
794
795 static BOOL IMM_DestroyContext(HIMC hIMC)
796 {
797 InputContextData *data = get_imc_data(hIMC);
798
799 TRACE("Destroying %p\n",hIMC);
800
801 if (!data)
802 return FALSE;
803
804 data->immKbd->uSelected --;
805 data->immKbd->pImeSelect(hIMC, FALSE);
806 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd);
807
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);
813
814 data->magic = 0;
815 HeapFree(GetProcessHeap(),0,data);
816
817 return TRUE;
818 }
819
820 /***********************************************************************
821 * ImmDestroyContext (IMM32.@)
822 */
823 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
824 {
825 if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
826 return IMM_DestroyContext(hIMC);
827 else
828 return FALSE;
829 }
830
831 /***********************************************************************
832 * ImmDisableIME (IMM32.@)
833 */
834 BOOL WINAPI ImmDisableIME(DWORD idThread)
835 {
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);
843 }
844 return TRUE;
845 }
846
847 /***********************************************************************
848 * ImmEnumRegisterWordA (IMM32.@)
849 */
850 UINT WINAPI ImmEnumRegisterWordA(
851 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
852 LPCSTR lpszReading, DWORD dwStyle,
853 LPCSTR lpszRegister, LPVOID lpData)
854 {
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)
859 {
860 if (!is_kbd_ime_unicode(immHkl))
861 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
862 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
863 else
864 {
865 LPWSTR lpszwReading = strdupAtoW(lpszReading);
866 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
867 BOOL rc;
868
869 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
870 lpszwReading, dwStyle, lpszwRegister,
871 lpData);
872
873 HeapFree(GetProcessHeap(),0,lpszwReading);
874 HeapFree(GetProcessHeap(),0,lpszwRegister);
875 return rc;
876 }
877 }
878 else
879 return 0;
880 }
881
882 /***********************************************************************
883 * ImmEnumRegisterWordW (IMM32.@)
884 */
885 UINT WINAPI ImmEnumRegisterWordW(
886 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
887 LPCWSTR lpszReading, DWORD dwStyle,
888 LPCWSTR lpszRegister, LPVOID lpData)
889 {
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)
894 {
895 if (is_kbd_ime_unicode(immHkl))
896 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
897 lpszRegister, lpData);
898 else
899 {
900 LPSTR lpszaReading = strdupWtoA(lpszReading);
901 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
902 BOOL rc;
903
904 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
905 dwStyle, (LPCWSTR)lpszaRegister, lpData);
906
907 HeapFree(GetProcessHeap(),0,lpszaReading);
908 HeapFree(GetProcessHeap(),0,lpszaRegister);
909 return rc;
910 }
911 }
912 else
913 return 0;
914 }
915
916 static inline BOOL EscapeRequiresWA(UINT uEscape)
917 {
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;
924 }
925
926 /***********************************************************************
927 * ImmEscapeA (IMM32.@)
928 */
929 LRESULT WINAPI ImmEscapeA(
930 HKL hKL, HIMC hIMC,
931 UINT uEscape, LPVOID lpData)
932 {
933 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
934 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
935
936 if (immHkl->hIME && immHkl->pImeEscape)
937 {
938 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
939 return immHkl->pImeEscape(hIMC,uEscape,lpData);
940 else
941 {
942 WCHAR buffer[81]; /* largest required buffer should be 80 */
943 LRESULT rc;
944 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
945 {
946 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
947 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
948 }
949 else
950 {
951 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
952 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
953 }
954 return rc;
955 }
956 }
957 else
958 return 0;
959 }
960
961 /***********************************************************************
962 * ImmEscapeW (IMM32.@)
963 */
964 LRESULT WINAPI ImmEscapeW(
965 HKL hKL, HIMC hIMC,
966 UINT uEscape, LPVOID lpData)
967 {
968 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
969 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
970
971 if (immHkl->hIME && immHkl->pImeEscape)
972 {
973 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
974 return immHkl->pImeEscape(hIMC,uEscape,lpData);
975 else
976 {
977 CHAR buffer[81]; /* largest required buffer should be 80 */
978 LRESULT rc;
979 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
980 {
981 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
982 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
983 }
984 else
985 {
986 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
987 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
988 }
989 return rc;
990 }
991 }
992 else
993 return 0;
994 }
995
996 /***********************************************************************
997 * ImmGetCandidateListA (IMM32.@)
998 */
999 DWORD WINAPI ImmGetCandidateListA(
1000 HIMC hIMC, DWORD dwIndex,
1001 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1002 {
1003 InputContextData *data = get_imc_data(hIMC);
1004 LPCANDIDATEINFO candinfo;
1005 LPCANDIDATELIST candlist;
1006 DWORD ret = 0;
1007
1008 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1009
1010 if (!data || !data->IMC.hCandInfo)
1011 return 0;
1012
1013 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1014 if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset))
1015 goto done;
1016
1017 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1018 if ( !candlist->dwSize || !candlist->dwCount )
1019 goto done;
1020
1021 if ( !is_himc_ime_unicode(data) )
1022 {
1023 ret = candlist->dwSize;
1024 if ( lpCandList && dwBufLen >= ret )
1025 memcpy(lpCandList, candlist, ret);
1026 }
1027 else
1028 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
1029
1030 done:
1031 ImmUnlockIMCC(data->IMC.hCandInfo);
1032 return ret;
1033 }
1034
1035 /***********************************************************************
1036 * ImmGetCandidateListCountA (IMM32.@)
1037 */
1038 DWORD WINAPI ImmGetCandidateListCountA(
1039 HIMC hIMC, LPDWORD lpdwListCount)
1040 {
1041 InputContextData *data = get_imc_data(hIMC);
1042 LPCANDIDATEINFO candinfo;
1043 DWORD ret, count;
1044
1045 TRACE("%p, %p\n", hIMC, lpdwListCount);
1046
1047 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
1048 return 0;
1049
1050 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1051
1052 *lpdwListCount = count = candinfo->dwCount;
1053
1054 if ( !is_himc_ime_unicode(data) )
1055 ret = candinfo->dwSize;
1056 else
1057 {
1058 ret = sizeof(CANDIDATEINFO);
1059 while ( count-- )
1060 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
1061 }
1062
1063 ImmUnlockIMCC(data->IMC.hCandInfo);
1064 return ret;
1065 }
1066
1067 /***********************************************************************
1068 * ImmGetCandidateListCountW (IMM32.@)
1069 */
1070 DWORD WINAPI ImmGetCandidateListCountW(
1071 HIMC hIMC, LPDWORD lpdwListCount)
1072 {
1073 InputContextData *data = get_imc_data(hIMC);
1074 LPCANDIDATEINFO candinfo;
1075 DWORD ret, count;
1076
1077 TRACE("%p, %p\n", hIMC, lpdwListCount);
1078
1079 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
1080 return 0;
1081
1082 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1083
1084 *lpdwListCount = count = candinfo->dwCount;
1085
1086 if ( is_himc_ime_unicode(data) )
1087 ret = candinfo->dwSize;
1088 else
1089 {
1090 ret = sizeof(CANDIDATEINFO);
1091 while ( count-- )
1092 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
1093 }
1094
1095 ImmUnlockIMCC(data->IMC.hCandInfo);
1096 return ret;
1097 }
1098
1099 /***********************************************************************
1100 * ImmGetCandidateListW (IMM32.@)
1101 */
1102 DWORD WINAPI ImmGetCandidateListW(
1103 HIMC hIMC, DWORD dwIndex,
1104 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1105 {
1106 InputContextData *data = get_imc_data(hIMC);
1107 LPCANDIDATEINFO candinfo;
1108 LPCANDIDATELIST candlist;
1109 DWORD ret = 0;
1110
1111 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1112
1113 if (!data || !data->IMC.hCandInfo)
1114 return 0;
1115
1116 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1117 if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset))
1118 goto done;
1119
1120 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1121 if ( !candlist->dwSize || !candlist->dwCount )
1122 goto done;
1123
1124 if ( is_himc_ime_unicode(data) )
1125 {
1126 ret = candlist->dwSize;
1127 if ( lpCandList && dwBufLen >= ret )
1128 memcpy(lpCandList, candlist, ret);
1129 }
1130 else
1131 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1132
1133 done:
1134 ImmUnlockIMCC(data->IMC.hCandInfo);
1135 return ret;
1136 }
1137
1138 /***********************************************************************
1139 * ImmGetCandidateWindow (IMM32.@)
1140 */
1141 BOOL WINAPI ImmGetCandidateWindow(
1142 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1143 {
1144 InputContextData *data = get_imc_data(hIMC);
1145
1146 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1147
1148 if (!data || !lpCandidate)
1149 return FALSE;
1150
1151 if (dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm))
1152 return FALSE;
1153
1154 if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex)
1155 return FALSE;
1156
1157 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1158
1159 return TRUE;
1160 }
1161
1162 /***********************************************************************
1163 * ImmGetCompositionFontA (IMM32.@)
1164 */
1165 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1166 {
1167 LOGFONTW lfW;
1168 BOOL rc;
1169
1170 TRACE("(%p, %p):\n", hIMC, lplf);
1171
1172 rc = ImmGetCompositionFontW(hIMC,&lfW);
1173 if (!rc || !lplf)
1174 return FALSE;
1175
1176 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1177 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1178 LF_FACESIZE, NULL, NULL);
1179 return TRUE;
1180 }
1181
1182 /***********************************************************************
1183 * ImmGetCompositionFontW (IMM32.@)
1184 */
1185 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1186 {
1187 InputContextData *data = get_imc_data(hIMC);
1188
1189 TRACE("(%p, %p):\n", hIMC, lplf);
1190
1191 if (!data || !lplf)
1192 return FALSE;
1193
1194 *lplf = data->IMC.lfFont.W;
1195
1196 return TRUE;
1197 }
1198
1199
1200 /* Helpers for the GetCompositionString functions */
1201
1202 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1203 BOOL unicode )
1204 {
1205 INT rc;
1206
1207 if (is_himc_ime_unicode(data) && !unicode)
1208 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1209 else if (!is_himc_ime_unicode(data) && unicode)
1210 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1211 else
1212 {
1213 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1214 memcpy( target, source, min(slen,tlen)*dlen);
1215 rc = slen*dlen;
1216 }
1217
1218 return rc;
1219 }
1220
1221 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1222 LPBYTE target, INT tlen, BOOL unicode )
1223 {
1224 INT rc;
1225
1226 if (is_himc_ime_unicode(data) && !unicode)
1227 {
1228 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1229 if (tlen)
1230 {
1231 const BYTE *src = source;
1232 LPBYTE dst = target;
1233 int i, j = 0, k = 0;
1234
1235 if (rc < tlen)
1236 tlen = rc;
1237 for (i = 0; i < sslen; ++i)
1238 {
1239 int len;
1240
1241 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1242 NULL, 0, NULL, NULL);
1243 for (; len > 0; --len)
1244 {
1245 dst[j++] = src[k];
1246
1247 if (j >= tlen)
1248 goto end;
1249 }
1250 ++k;
1251 }
1252 end:
1253 rc = j;
1254 }
1255 }
1256 else if (!is_himc_ime_unicode(data) && unicode)
1257 {
1258 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1259 if (tlen)
1260 {
1261 const BYTE *src = source;
1262 LPBYTE dst = target;
1263 int i, j = 0;
1264
1265 if (rc < tlen)
1266 tlen = rc;
1267 for (i = 0; i < sslen; ++i)
1268 {
1269 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1270 continue;
1271
1272 dst[j++] = src[i];
1273
1274 if (j >= tlen)
1275 break;
1276 }
1277 rc = j;
1278 }
1279 }
1280 else
1281 {
1282 memcpy( target, source, min(slen,tlen));
1283 rc = slen;
1284 }
1285
1286 return rc;
1287 }
1288
1289 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
1290 LPBYTE target, INT tlen, BOOL unicode )
1291 {
1292 INT rc;
1293
1294 if (is_himc_ime_unicode(data) && !unicode)
1295 {
1296 if (tlen)
1297 {
1298 int i;
1299
1300 if (slen < tlen)
1301 tlen = slen;
1302 tlen /= sizeof (DWORD);
1303 for (i = 0; i < tlen; ++i)
1304 {
1305 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1306 ((DWORD *)source)[i],
1307 NULL, 0,
1308 NULL, NULL);
1309 }
1310 rc = sizeof (DWORD) * i;
1311 }
1312 else
1313 rc = slen;
1314 }
1315 else if (!is_himc_ime_unicode(data) && unicode)
1316 {
1317 if (tlen)
1318 {
1319 int i;
1320
1321 if (slen < tlen)
1322 tlen = slen;
1323 tlen /= sizeof (DWORD);
1324 for (i = 0; i < tlen; ++i)
1325 {
1326 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1327 ((DWORD *)source)[i],
1328 NULL, 0);
1329 }
1330 rc = sizeof (DWORD) * i;
1331 }
1332 else
1333 rc = slen;
1334 }
1335 else
1336 {
1337 memcpy( target, source, min(slen,tlen));
1338 rc = slen;
1339 }
1340
1341 return rc;
1342 }
1343
1344 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1345 {
1346 int rc;
1347
1348 if (is_himc_ime_unicode(data) && !unicode)
1349 {
1350 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1351 }
1352 else if (!is_himc_ime_unicode(data) && unicode)
1353 {
1354 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1355 }
1356 else
1357 rc = offset;
1358
1359 return rc;
1360 }
1361
1362 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1363 DWORD dwBufLen, BOOL unicode)
1364 {
1365 LONG rc = 0;
1366 InputContextData *data = get_imc_data(hIMC);
1367 LPCOMPOSITIONSTRING compstr;
1368 LPBYTE compdata;
1369
1370 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1371
1372 if (!data)
1373 return FALSE;
1374
1375 if (!data->IMC.hCompStr)
1376 return FALSE;
1377
1378 compdata = ImmLockIMCC(data->IMC.hCompStr);
1379 compstr = (LPCOMPOSITIONSTRING)compdata;
1380
1381 switch (dwIndex)
1382 {
1383 case GCS_RESULTSTR:
1384 TRACE("GCS_RESULTSTR\n");
1385 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1386 break;
1387 case GCS_COMPSTR:
1388 TRACE("GCS_COMPSTR\n");
1389 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1390 break;
1391 case GCS_COMPATTR:
1392 TRACE("GCS_COMPATTR\n");
1393 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1394 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1395 lpBuf, dwBufLen, unicode);
1396 break;
1397 case GCS_COMPCLAUSE:
1398 TRACE("GCS_COMPCLAUSE\n");
1399 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1400 compdata + compstr->dwCompStrOffset,
1401 lpBuf, dwBufLen, unicode);
1402 break;
1403 case GCS_RESULTCLAUSE:
1404 TRACE("GCS_RESULTCLAUSE\n");
1405 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1406 compdata + compstr->dwResultStrOffset,
1407 lpBuf, dwBufLen, unicode);
1408 break;
1409 case GCS_RESULTREADSTR:
1410 TRACE("GCS_RESULTREADSTR\n");
1411 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1412 break;
1413 case GCS_RESULTREADCLAUSE:
1414 TRACE("GCS_RESULTREADCLAUSE\n");
1415 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1416 compdata + compstr->dwResultStrOffset,
1417 lpBuf, dwBufLen, unicode);
1418 break;
1419 case GCS_COMPREADSTR:
1420 TRACE("GCS_COMPREADSTR\n");
1421 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1422 break;
1423 case GCS_COMPREADATTR:
1424 TRACE("GCS_COMPREADATTR\n");
1425 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1426 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1427 lpBuf, dwBufLen, unicode);
1428 break;
1429 case GCS_COMPREADCLAUSE:
1430 TRACE("GCS_COMPREADCLAUSE\n");
1431 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1432 compdata + compstr->dwCompStrOffset,
1433 lpBuf, dwBufLen, unicode);
1434 break;
1435 case GCS_CURSORPOS:
1436 TRACE("GCS_CURSORPOS\n");
1437 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1438 break;
1439 case GCS_DELTASTART:
1440 TRACE("GCS_DELTASTART\n");
1441 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1442 break;
1443 default:
1444 FIXME("Unhandled index 0x%x\n",dwIndex);
1445 break;
1446 }
1447
1448 ImmUnlockIMCC(data->IMC.hCompStr);
1449
1450 return rc;
1451 }
1452
1453 /***********************************************************************
1454 * ImmGetCompositionStringA (IMM32.@)
1455 */
1456 LONG WINAPI ImmGetCompositionStringA(
1457 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1458 {
1459 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1460 }
1461
1462
1463 /***********************************************************************
1464 * ImmGetCompositionStringW (IMM32.@)
1465 */
1466 LONG WINAPI ImmGetCompositionStringW(
1467 HIMC hIMC, DWORD dwIndex,
1468 LPVOID lpBuf, DWORD dwBufLen)
1469 {
1470 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1471 }
1472
1473 /***********************************************************************
1474 * ImmGetCompositionWindow (IMM32.@)
1475 */
1476 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1477 {
1478 InputContextData *data = get_imc_data(hIMC);
1479
1480 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1481
1482 if (!data)
1483 return FALSE;
1484
1485 *lpCompForm = data->IMC.cfCompForm;
1486 return TRUE;
1487 }
1488
1489 /***********************************************************************
1490 * ImmGetContext (IMM32.@)
1491 *
1492 */
1493 HIMC WINAPI ImmGetContext(HWND hWnd)
1494 {
1495 HIMC rc;
1496
1497 TRACE("%p\n", hWnd);
1498
1499 if (!IsWindow(hWnd))
1500 {
1501 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1502 return NULL;
1503 }
1504
1505 rc = GetPropW(hWnd,szwWineIMCProperty);
1506 if (rc == (HIMC)-1)
1507 rc = NULL;
1508 else if (rc == NULL)
1509 rc = get_default_context( hWnd );
1510
1511 if (rc)
1512 {
1513 InputContextData *data = rc;
1514 data->IMC.hWnd = hWnd;
1515 }
1516
1517 TRACE("returning %p\n", rc);
1518
1519 return rc;
1520 }
1521
1522 /***********************************************************************
1523 * ImmGetConversionListA (IMM32.@)
1524 */
1525 DWORD WINAPI ImmGetConversionListA(
1526 HKL hKL, HIMC hIMC,
1527 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1528 DWORD dwBufLen, UINT uFlag)
1529 {
1530 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1531 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1532 dwBufLen, uFlag);
1533 if (immHkl->hIME && immHkl->pImeConversionList)
1534 {
1535 if (!is_kbd_ime_unicode(immHkl))
1536 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1537 else
1538 {
1539 LPCANDIDATELIST lpwDst;
1540 DWORD ret = 0, len;
1541 LPWSTR pwSrc = strdupAtoW(pSrc);
1542
1543 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1544 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1545 if ( lpwDst )
1546 {
1547 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1548 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1549 HeapFree(GetProcessHeap(), 0, lpwDst);
1550 }
1551 HeapFree(GetProcessHeap(), 0, pwSrc);
1552
1553 return ret;
1554 }
1555 }
1556 else
1557 return 0;
1558 }
1559
1560 /***********************************************************************
1561 * ImmGetConversionListW (IMM32.@)
1562 */
1563 DWORD WINAPI ImmGetConversionListW(
1564 HKL hKL, HIMC hIMC,
1565 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1566 DWORD dwBufLen, UINT uFlag)
1567 {
1568 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1569 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1570 dwBufLen, uFlag);
1571 if (immHkl->hIME && immHkl->pImeConversionList)
1572 {
1573 if (is_kbd_ime_unicode(immHkl))
1574 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1575 else
1576 {
1577 LPCANDIDATELIST lpaDst;
1578 DWORD ret = 0, len;
1579 LPSTR paSrc = strdupWtoA(pSrc);
1580
1581 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1582 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1583 if ( lpaDst )
1584 {
1585 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1586 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1587 HeapFree(GetProcessHeap(), 0, lpaDst);
1588 }
1589 HeapFree(GetProcessHeap(), 0, paSrc);
1590
1591 return ret;
1592 }
1593 }
1594 else
1595 return 0;
1596 }
1597
1598 /***********************************************************************
1599 * ImmGetConversionStatus (IMM32.@)
1600 */
1601 BOOL WINAPI ImmGetConversionStatus(
1602 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1603 {
1604 InputContextData *data = get_imc_data(hIMC);
1605
1606 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1607
1608 if (!data)
1609 return FALSE;
1610
1611 if (lpfdwConversion)
1612 *lpfdwConversion = data->IMC.fdwConversion;
1613 if (lpfdwSentence)
1614 *lpfdwSentence = data->IMC.fdwSentence;
1615
1616 return TRUE;
1617 }
1618
1619 static BOOL needs_ime_window(HWND hwnd)
1620 {
1621 WCHAR classW[8];
1622
1623 if (GetClassNameW(hwnd, classW, ARRAY_SIZE(classW)) && !strcmpW(classW, szwIME))
1624 return FALSE;
1625 if (GetClassLongPtrW(hwnd, GCL_STYLE) & CS_IME) return FALSE;
1626
1627 return TRUE;
1628 }
1629
1630 /***********************************************************************
1631 * __wine_register_window (IMM32.@)
1632 */
1633 BOOL WINAPI __wine_register_window(HWND hwnd)
1634 {
1635 HWND new = NULL;
1636 IMMThreadData *thread_data;
1637 TRACE("(%p)\n", hwnd);
1638
1639 if (!needs_ime_window(hwnd))
1640 return FALSE;
1641
1642 thread_data = IMM_GetThreadData(hwnd, 0);
1643 if (!thread_data)
1644 return FALSE;
1645
1646 if (thread_data->disableIME || disable_ime)
1647 {
1648 TRACE("IME for this thread is disabled\n");
1649 LeaveCriticalSection(&threaddata_cs);
1650 return FALSE;
1651 }
1652 thread_data->windowRefs++;
1653 TRACE("windowRefs=%u, hwndDefault=%p\n",
1654 thread_data->windowRefs, thread_data->hwndDefault);
1655
1656 /* Create default IME window */
1657 if (thread_data->windowRefs == 1)
1658 {
1659 /* Do not create the window inside of a critical section */
1660 LeaveCriticalSection(&threaddata_cs);
1661 new = CreateWindowExW( 0, szwIME, szwDefaultIME,
1662 WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS,
1663 0, 0, 1, 1, 0, 0, 0, 0);
1664 /* thread_data is in the current thread so we can assume it's still valid */
1665 EnterCriticalSection(&threaddata_cs);
1666 /* See if anyone beat us */
1667 if (thread_data->hwndDefault == NULL)
1668 {
1669 thread_data->hwndDefault = new;
1670 new = NULL;
1671 TRACE("Default is %p\n", thread_data->hwndDefault);
1672 }
1673 }
1674
1675 LeaveCriticalSection(&threaddata_cs);
1676
1677 /* Clean up an unused new window outside of the critical section */
1678 if (new != NULL)
1679 DestroyWindow(new);
1680 return TRUE;
1681 }
1682
1683 /***********************************************************************
1684 * __wine_unregister_window (IMM32.@)
1685 */
1686 void WINAPI __wine_unregister_window(HWND hwnd)
1687 {
1688 HWND to_destroy = 0;
1689 IMMThreadData *thread_data;
1690 TRACE("(%p)\n", hwnd);
1691
1692 thread_data = IMM_GetThreadData(hwnd, 0);
1693 if (!thread_data) return;
1694
1695 thread_data->windowRefs--;
1696 TRACE("windowRefs=%u, hwndDefault=%p\n",
1697 thread_data->windowRefs, thread_data->hwndDefault);
1698
1699 /* Destroy default IME window */
1700 if (thread_data->windowRefs == 0 && thread_data->hwndDefault)
1701 {
1702 to_destroy = thread_data->hwndDefault;
1703 thread_data->hwndDefault = NULL;
1704 }
1705 LeaveCriticalSection(&threaddata_cs);
1706
1707 if (to_destroy) DestroyWindow( to_destroy );
1708 }
1709
1710 /***********************************************************************
1711 * ImmGetDefaultIMEWnd (IMM32.@)
1712 */
1713 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1714 {
1715 HWND ret;
1716 IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0);
1717 if (!thread_data)
1718 return NULL;
1719 ret = thread_data->hwndDefault;
1720 LeaveCriticalSection(&threaddata_cs);
1721 TRACE("Default is %p\n",ret);
1722 return ret;
1723 }
1724
1725 /***********************************************************************
1726 * ImmGetDescriptionA (IMM32.@)
1727 */
1728 UINT WINAPI ImmGetDescriptionA(
1729 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1730 {
1731 WCHAR *buf;
1732 DWORD len;
1733
1734 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1735
1736 /* find out how many characters in the unicode buffer */
1737 len = ImmGetDescriptionW( hKL, NULL, 0 );
1738 if (!len)
1739 return 0;
1740
1741 /* allocate a buffer of that size */
1742 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1743 if( !buf )
1744 return 0;
1745
1746 /* fetch the unicode buffer */
1747 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1748
1749 /* convert it back to ASCII */
1750 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1751 lpszDescription, uBufLen, NULL, NULL );
1752
1753 HeapFree( GetProcessHeap(), 0, buf );
1754
1755 if (len == 0)
1756 return 0;
1757
1758 return len - 1;
1759 }
1760
1761 /***********************************************************************
1762 * ImmGetDescriptionW (IMM32.@)
1763 */
1764 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1765 {
1766 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1767
1768 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1769
1770 if (!hKL) return 0;
1771 if (!uBufLen) return lstrlenW( name );
1772 lstrcpynW( lpszDescription, name, uBufLen );
1773 return lstrlenW( lpszDescription );
1774 }
1775
1776 /***********************************************************************
1777 * ImmGetGuideLineA (IMM32.@)
1778 */
1779 DWORD WINAPI ImmGetGuideLineA(
1780 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1781 {
1782 FIXME("(%p, %d, %s, %d): stub\n",
1783 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1784 );
1785 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1786 return 0;
1787 }
1788
1789 /***********************************************************************
1790 * ImmGetGuideLineW (IMM32.@)
1791 */
1792 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1793 {
1794 FIXME("(%p, %d, %s, %d): stub\n",
1795 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1796 );
1797 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1798 return 0;
1799 }
1800
1801 /***********************************************************************
1802 * ImmGetIMEFileNameA (IMM32.@)
1803 */
1804 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1805 {
1806 LPWSTR bufW = NULL;
1807 UINT wBufLen = uBufLen;
1808 UINT rc;
1809
1810 if (uBufLen && lpszFileName)
1811 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1812 else /* We need this to get the number of byte required */
1813 {
1814 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1815 wBufLen = MAX_PATH;
1816 }
1817
1818 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1819
1820 if (rc > 0)
1821 {
1822 if (uBufLen && lpszFileName)
1823 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1824 uBufLen, NULL, NULL);
1825 else /* get the length */
1826 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1827 NULL);
1828 }
1829
1830 HeapFree(GetProcessHeap(),0,bufW);
1831 return rc;
1832 }
1833
1834 /***********************************************************************
1835 * ImmGetIMEFileNameW (IMM32.@)
1836 */
1837 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1838 {
1839 HKEY hkey;
1840 DWORD length;
1841 DWORD rc;
1842 WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
1843
1844 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1845 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1846 if (rc != ERROR_SUCCESS)
1847 {
1848 SetLastError(rc);
1849 return 0;
1850 }
1851
1852 length = 0;
1853 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1854
1855 if (rc != ERROR_SUCCESS)
1856 {
1857 RegCloseKey(hkey);
1858 SetLastError(rc);
1859 return 0;
1860 }
1861 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1862 {
1863 RegCloseKey(hkey);
1864 if (lpszFileName)
1865 {
1866 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1867 return 0;
1868 }
1869 else
1870 return length / sizeof(WCHAR);
1871 }
1872
1873 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1874
1875 RegCloseKey(hkey);
1876
1877 return length / sizeof(WCHAR);
1878 }
1879
1880 /***********************************************************************
1881 * ImmGetOpenStatus (IMM32.@)
1882 */
1883 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1884 {
1885 InputContextData *data = get_imc_data(hIMC);
1886 static int i;
1887
1888 if (!data)
1889 return FALSE;
1890
1891 TRACE("(%p): semi-stub\n", hIMC);
1892
1893 if (!i++)
1894 FIXME("(%p): semi-stub\n", hIMC);
1895
1896 return data->IMC.fOpen;
1897 }
1898
1899 /***********************************************************************
1900 * ImmGetProperty (IMM32.@)
1901 */
1902 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1903 {
1904 DWORD rc = 0;
1905 ImmHkl *kbd;
1906
1907 TRACE("(%p, %d)\n", hKL, fdwIndex);
1908 kbd = IMM_GetImmHkl(hKL);
1909
1910 if (kbd && kbd->hIME)
1911 {
1912 switch (fdwIndex)
1913 {
1914 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1915 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1916 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1917 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1918 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1919 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1920 case IGP_UI: rc = 0; break;
1921 default: rc = 0;
1922 }
1923 }
1924 return rc;
1925 }
1926
1927 /***********************************************************************
1928 * ImmGetRegisterWordStyleA (IMM32.@)
1929 */
1930 UINT WINAPI ImmGetRegisterWordStyleA(
1931 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1932 {
1933 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1934 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1935 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1936 {
1937 if (!is_kbd_ime_unicode(immHkl))
1938 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1939 else
1940 {
1941 STYLEBUFW sbw;
1942 UINT rc;
1943
1944 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1945 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1946 lpStyleBuf->szDescription, 32, NULL, NULL);
1947 lpStyleBuf->dwStyle = sbw.dwStyle;
1948 return rc;
1949 }
1950 }
1951 else
1952 return 0;
1953 }
1954
1955 /***********************************************************************
1956 * ImmGetRegisterWordStyleW (IMM32.@)
1957 */
1958 UINT WINAPI ImmGetRegisterWordStyleW(
1959 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1960 {
1961 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1962 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1963 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1964 {
1965 if (is_kbd_ime_unicode(immHkl))
1966 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1967 else
1968 {
1969 STYLEBUFA sba;
1970 UINT rc;
1971
1972 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1973 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1974 lpStyleBuf->szDescription, 32);
1975 lpStyleBuf->dwStyle = sba.dwStyle;
1976 return rc;
1977 }
1978 }
1979 else
1980 return 0;
1981 }
1982
1983 /***********************************************************************
1984 * ImmGetStatusWindowPos (IMM32.@)
1985 */
1986 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1987 {
1988 InputContextData *data = get_imc_data(hIMC);
1989
1990 TRACE("(%p, %p)\n", hIMC, lpptPos);
1991
1992 if (!data || !lpptPos)
1993 return FALSE;
1994
1995 *lpptPos = data->IMC.ptStatusWndPos;
1996
1997 return TRUE;
1998 }
1999
2000 /***********************************************************************
2001 * ImmGetVirtualKey (IMM32.@)
2002 */
2003 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
2004 {
2005 OSVERSIONINFOA version;
2006 InputContextData *data = ImmGetContext( hWnd );
2007 TRACE("%p\n", hWnd);
2008
2009 if ( data )
2010 return data->lastVK;
2011
2012 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
2013 GetVersionExA( &version );
2014 switch(version.dwPlatformId)
2015 {
2016 case VER_PLATFORM_WIN32_WINDOWS:
2017 return VK_PROCESSKEY;
2018 case VER_PLATFORM_WIN32_NT:
2019 return 0;
2020 default:
2021 FIXME("%d not supported\n",version.dwPlatformId);
2022 return VK_PROCESSKEY;
2023 }
2024 }
2025
2026 /***********************************************************************
2027 * ImmInstallIMEA (IMM32.@)
2028 */
2029 HKL WINAPI ImmInstallIMEA(
2030 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
2031 {
2032 LPWSTR lpszwIMEFileName;
2033 LPWSTR lpszwLayoutText;
2034 HKL hkl;
2035
2036 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
2037 debugstr_a(lpszLayoutText));
2038
2039 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
2040 lpszwLayoutText = strdupAtoW(lpszLayoutText);
2041
2042 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
2043
2044 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
2045 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
2046 return hkl;
2047 }
2048
2049 /***********************************************************************
2050 * ImmInstallIMEW (IMM32.@)
2051 */
2052 HKL WINAPI ImmInstallIMEW(
2053 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
2054 {
2055 INT lcid = GetUserDefaultLCID();
2056 INT count;
2057 HKL hkl;
2058 DWORD rc;
2059 HKEY hkey;
2060 WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
2061
2062 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
2063 debugstr_w(lpszLayoutText));
2064
2065 /* Start with 2. e001 will be blank and so default to the wine internal IME */
2066 count = 2;
2067
2068 while (count < 0xfff)
2069 {
2070 DWORD disposition = 0;
2071
2072 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
2073 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
2074
2075 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
2076 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
2077 break;
2078 else if (rc == ERROR_SUCCESS)
2079 RegCloseKey(hkey);
2080
2081 count++;
2082 }
2083
2084 if (count == 0xfff)
2085 {
2086 WARN("Unable to find slot to install IME\n");
2087 return 0;
2088 }
2089
2090 if (rc == ERROR_SUCCESS)
2091 {
2092 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
2093 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
2094 if (rc == ERROR_SUCCESS)
2095 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
2096 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
2097 RegCloseKey(hkey);
2098 return hkl;
2099 }
2100 else
2101 {
2102 WARN("Unable to set IME registry values\n");
2103 return 0;
2104 }
2105 }
2106
2107 /***********************************************************************
2108 * ImmIsIME (IMM32.@)
2109 */
2110 BOOL WINAPI ImmIsIME(HKL hKL)
2111 {
2112 ImmHkl *ptr;
2113 TRACE("(%p):\n", hKL);
2114 ptr = IMM_GetImmHkl(hKL);
2115 return (ptr && ptr->hIME);
2116 }
2117
2118 /***********************************************************************
2119 * ImmIsUIMessageA (IMM32.@)
2120 */
2121 BOOL WINAPI ImmIsUIMessageA(
2122 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2123 {
2124 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2125 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2126 (msg == WM_IME_SETCONTEXT) ||
2127 (msg == WM_IME_NOTIFY) ||
2128 (msg == WM_IME_COMPOSITIONFULL) ||
2129 (msg == WM_IME_SELECT) ||
2130 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2131 {
2132 if (hWndIME)
2133 SendMessageA(hWndIME, msg, wParam, lParam);
2134
2135 return TRUE;
2136 }
2137 return FALSE;
2138 }
2139
2140 /***********************************************************************
2141 * ImmIsUIMessageW (IMM32.@)
2142 */
2143 BOOL WINAPI ImmIsUIMessageW(
2144 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2145 {
2146 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2147 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2148 (msg == WM_IME_SETCONTEXT) ||
2149 (msg == WM_IME_NOTIFY) ||
2150 (msg == WM_IME_COMPOSITIONFULL) ||
2151 (msg == WM_IME_SELECT) ||
2152 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2153 {
2154 if (hWndIME)
2155 SendMessageW(hWndIME, msg, wParam, lParam);
2156
2157 return TRUE;
2158 }
2159 return FALSE;
2160 }
2161
2162 /***********************************************************************
2163 * ImmNotifyIME (IMM32.@)
2164 */
2165 BOOL WINAPI ImmNotifyIME(
2166 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
2167 {
2168 InputContextData *data = get_imc_data(hIMC);
2169
2170 TRACE("(%p, %d, %d, %d)\n",
2171 hIMC, dwAction, dwIndex, dwValue);
2172
2173 if (hIMC == NULL)
2174 {
2175 SetLastError(ERROR_SUCCESS);
2176 return FALSE;
2177 }
2178
2179 if (!data || ! data->immKbd->pNotifyIME)
2180 {
2181 return FALSE;
2182 }
2183
2184 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
2185 }
2186
2187 /***********************************************************************
2188 * ImmRegisterWordA (IMM32.@)
2189 */
2190 BOOL WINAPI ImmRegisterWordA(
2191 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
2192 {
2193 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2194 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2195 debugstr_a(lpszRegister));
2196 if (immHkl->hIME && immHkl->pImeRegisterWord)
2197 {
2198 if (!is_kbd_ime_unicode(immHkl))
2199 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
2200 (LPCWSTR)lpszRegister);
2201 else
2202 {
2203 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2204 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
2205 BOOL rc;
2206
2207 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
2208 HeapFree(GetProcessHeap(),0,lpszwReading);
2209 HeapFree(GetProcessHeap(),0,lpszwRegister);
2210 return rc;
2211 }
2212 }
2213 else
2214 return FALSE;
2215 }
2216
2217 /***********************************************************************
2218 * ImmRegisterWordW (IMM32.@)
2219 */
2220 BOOL WINAPI ImmRegisterWordW(
2221 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
2222 {
2223 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2224 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2225 debugstr_w(lpszRegister));
2226 if (immHkl->hIME && immHkl->pImeRegisterWord)
2227 {
2228 if (is_kbd_ime_unicode(immHkl))
2229 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
2230 else
2231 {
2232 LPSTR lpszaReading = strdupWtoA(lpszReading);
2233 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
2234 BOOL rc;
2235
2236 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
2237 (LPCWSTR)lpszaRegister);
2238 HeapFree(GetProcessHeap(),0,lpszaReading);
2239 HeapFree(GetProcessHeap(),0,lpszaRegister);
2240 return rc;
2241 }
2242 }
2243 else
2244 return FALSE;
2245 }
2246
2247 /***********************************************************************
2248 * ImmReleaseContext (IMM32.@)
2249 */
2250 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2251 {
2252 static BOOL shown = FALSE;
2253
2254 if (!shown) {
2255 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2256 shown = TRUE;
2257 }
2258 return TRUE;
2259 }
2260
2261 /***********************************************************************
2262 * ImmRequestMessageA(IMM32.@)
2263 */
2264 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2265 {
2266 InputContextData *data = get_imc_data(hIMC);
2267
2268 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2269
2270 if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2271
2272 SetLastError(ERROR_INVALID_HANDLE);
2273 return 0;
2274 }
2275
2276 /***********************************************************************
2277 * ImmRequestMessageW(IMM32.@)
2278 */
2279 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2280 {
2281 InputContextData *data = get_imc_data(hIMC);
2282
2283 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2284
2285 if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2286
2287 SetLastError(ERROR_INVALID_HANDLE);
2288 return 0;
2289 }
2290
2291 /***********************************************************************
2292 * ImmSetCandidateWindow (IMM32.@)
2293 */
2294 BOOL WINAPI ImmSetCandidateWindow(
2295 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2296 {
2297 InputContextData *data = get_imc_data(hIMC);
2298
2299 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2300
2301 if (!data || !lpCandidate)
2302 return FALSE;
2303
2304 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2305 return FALSE;
2306
2307 TRACE("\t%x, %x, %s, %s\n",
2308 lpCandidate->dwIndex, lpCandidate->dwStyle,
2309 wine_dbgstr_point(&lpCandidate->ptCurrentPos),
2310 wine_dbgstr_rect(&lpCandidate->rcArea));
2311
2312 if (lpCandidate->dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm))
2313 return FALSE;
2314
2315 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2316 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2317 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2318
2319 return TRUE;
2320 }
2321
2322 /***********************************************************************
2323 * ImmSetCompositionFontA (IMM32.@)
2324 */
2325 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2326 {
2327 InputContextData *data = get_imc_data(hIMC);
2328 TRACE("(%p, %p)\n", hIMC, lplf);
2329
2330 if (!data || !lplf)
2331 {
2332 SetLastError(ERROR_INVALID_HANDLE);
2333 return FALSE;
2334 }
2335
2336 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2337 return FALSE;
2338
2339 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2340 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2341 LF_FACESIZE);
2342 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2343 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2344
2345 return TRUE;
2346 }
2347
2348 /***********************************************************************
2349 * ImmSetCompositionFontW (IMM32.@)
2350 */
2351 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2352 {
2353 InputContextData *data = get_imc_data(hIMC);
2354 TRACE("(%p, %p)\n", hIMC, lplf);
2355
2356 if (!data || !lplf)
2357 {
2358 SetLastError(ERROR_INVALID_HANDLE);
2359 return FALSE;
2360 }
2361
2362 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2363 return FALSE;
2364
2365 data->IMC.lfFont.W = *lplf;
2366 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2367 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2368
2369 return TRUE;
2370 }
2371
2372 /***********************************************************************
2373 * ImmSetCompositionStringA (IMM32.@)
2374 */
2375 BOOL WINAPI ImmSetCompositionStringA(
2376 HIMC hIMC, DWORD dwIndex,
2377 LPCVOID lpComp, DWORD dwCompLen,
2378 LPCVOID lpRead, DWORD dwReadLen)
2379 {
2380 DWORD comp_len;
2381 DWORD read_len;
2382 WCHAR *CompBuffer = NULL;
2383 WCHAR *ReadBuffer = NULL;
2384 BOOL rc;
2385 InputContextData *data = get_imc_data(hIMC);
2386
2387 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2388 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2389
2390 if (!data)
2391 return FALSE;
2392
2393 if (!(dwIndex == SCS_SETSTR ||
2394 dwIndex == SCS_CHANGEATTR ||
2395 dwIndex == SCS_CHANGECLAUSE ||
2396 dwIndex == SCS_SETRECONVERTSTRING ||
2397 dwIndex == SCS_QUERYRECONVERTSTRING))
2398 return FALSE;
2399
2400 if (!is_himc_ime_unicode(data))
2401 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2402 dwCompLen, lpRead, dwReadLen);
2403
2404 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2405 if (comp_len)
2406 {
2407 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2408 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2409 }
2410
2411 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2412 if (read_len)
2413 {
2414 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2415 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2416 }
2417
2418 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2419 ReadBuffer, read_len);
2420
2421 HeapFree(GetProcessHeap(), 0, CompBuffer);
2422 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2423
2424 return rc;
2425 }
2426
2427 /***********************************************************************
2428 * ImmSetCompositionStringW (IMM32.@)
2429 */
2430 BOOL WINAPI ImmSetCompositionStringW(
2431 HIMC hIMC, DWORD dwIndex,
2432 LPCVOID lpComp, DWORD dwCompLen,
2433 LPCVOID lpRead, DWORD dwReadLen)
2434 {
2435 DWORD comp_len;
2436 DWORD read_len;
2437 CHAR *CompBuffer = NULL;
2438 CHAR *ReadBuffer = NULL;
2439 BOOL rc;
2440 InputContextData *data = get_imc_data(hIMC);
2441
2442 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2443 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2444
2445 if (!data)
2446 return FALSE;
2447
2448 if (!(dwIndex == SCS_SETSTR ||
2449 dwIndex == SCS_CHANGEATTR ||
2450 dwIndex == SCS_CHANGECLAUSE ||
2451 dwIndex == SCS_SETRECONVERTSTRING ||
2452 dwIndex == SCS_QUERYRECONVERTSTRING))
2453 return FALSE;
2454
2455 if (is_himc_ime_unicode(data))
2456 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2457 dwCompLen, lpRead, dwReadLen);
2458
2459 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2460 NULL);
2461 if (comp_len)
2462 {
2463 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2464 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2465 NULL, NULL);
2466 }
2467
2468 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2469 NULL);
2470 if (read_len)
2471 {
2472 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2473 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2474 NULL, NULL);
2475 }
2476
2477 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2478 ReadBuffer, read_len);
2479
2480 HeapFree(GetProcessHeap(), 0, CompBuffer);
2481 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2482
2483 return rc;
2484 }
2485
2486 /***********************************************************************
2487 * ImmSetCompositionWindow (IMM32.@)
2488 */
2489 BOOL WINAPI ImmSetCompositionWindow(
2490 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2491 {
2492 BOOL reshow = FALSE;
2493 InputContextData *data = get_imc_data(hIMC);
2494
2495 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2496 if (lpCompForm)
2497 TRACE("\t%x, %s, %s\n", lpCompForm->dwStyle,
2498 wine_dbgstr_point(&lpCompForm->ptCurrentPos),
2499 wine_dbgstr_rect(&lpCompForm->rcArea));
2500
2501 if (!data)
2502 {
2503 SetLastError(ERROR_INVALID_HANDLE);
2504 return FALSE;
2505 }
2506
2507 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2508 return FALSE;
2509
2510 data->IMC.cfCompForm = *lpCompForm;
2511
2512 if (IsWindowVisible(data->immKbd->UIWnd))
2513 {
2514 reshow = TRUE;
2515 ShowWindow(data->immKbd->UIWnd,SW_HIDE);
2516 }
2517
2518 /* FIXME: this is a partial stub */
2519
2520 if (reshow)
2521 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE);
2522
2523 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2524 return TRUE;
2525 }
2526
2527 /***********************************************************************
2528 * ImmSetConversionStatus (IMM32.@)
2529 */
2530 BOOL WINAPI ImmSetConversionStatus(
2531 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2532 {
2533 DWORD oldConversion, oldSentence;
2534 InputContextData *data = get_imc_data(hIMC);
2535
2536 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2537
2538 if (!data)
2539 {
2540 SetLastError(ERROR_INVALID_HANDLE);
2541 return FALSE;
2542 }
2543
2544 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2545 return FALSE;
2546
2547 if ( fdwConversion != data->IMC.fdwConversion )
2548 {
2549 oldConversion = data->IMC.fdwConversion;
2550 data->IMC.fdwConversion = fdwConversion;
2551 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2552 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2553 }
2554 if ( fdwSentence != data->IMC.fdwSentence )
2555 {
2556 oldSentence = data->IMC.fdwSentence;
2557 data->IMC.fdwSentence = fdwSentence;
2558 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2559 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2560 }
2561
2562 return TRUE;
2563 }
2564
2565 /***********************************************************************
2566 * ImmSetOpenStatus (IMM32.@)
2567 */
2568 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2569 {
2570 InputContextData *data = get_imc_data(hIMC);
2571
2572 TRACE("%p %d\n", hIMC, fOpen);
2573
2574 if (!data)
2575 {
2576 SetLastError(ERROR_INVALID_HANDLE);
2577 return FALSE;
2578 }
2579
2580 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2581 return FALSE;
2582
2583 if (data->immKbd->UIWnd == NULL)
2584 {
2585 /* create the ime window */
2586 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2587 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2588 0, data->immKbd->hIME, 0);
2589 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2590 }
2591 else if (fOpen)
2592 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2593
2594 if (!fOpen != !data->IMC.fOpen)
2595 {
2596 data->IMC.fOpen = fOpen;
2597 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2598 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2599 }
2600
2601 return TRUE;
2602 }
2603
2604 /***********************************************************************
2605 * ImmSetStatusWindowPos (IMM32.@)
2606 */
2607 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2608 {
2609 InputContextData *data = get_imc_data(hIMC);
2610
2611 TRACE("(%p, %p)\n", hIMC, lpptPos);
2612
2613 if (!data || !lpptPos)
2614 {
2615 SetLastError(ERROR_INVALID_HANDLE);
2616 return FALSE;
2617 }
2618
2619 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2620 return FALSE;
2621
2622 TRACE("\t%s\n", wine_dbgstr_point(lpptPos));
2623
2624 data->IMC.ptStatusWndPos = *lpptPos;
2625 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2626 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2627
2628 return TRUE;
2629 }
2630
2631 /***********************************************************************
2632 * ImmCreateSoftKeyboard(IMM32.@)
2633 */
2634 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2635 {
2636 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2637 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2638 return 0;
2639 }
2640
2641 /***********************************************************************
2642 * ImmDestroySoftKeyboard(IMM32.@)
2643 */
2644 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2645 {
2646 FIXME("(%p): stub\n", hSoftWnd);
2647 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2648 return FALSE;
2649 }
2650
2651 /***********************************************************************
2652 * ImmShowSoftKeyboard(IMM32.@)
2653 */
2654 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2655 {
2656 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2657 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2658 return FALSE;
2659 }
2660
2661 /***********************************************************************
2662 * ImmSimulateHotKey (IMM32.@)
2663 */
2664 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2665 {
2666 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2667 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2668 return FALSE;
2669 }
2670
2671 /***********************************************************************
2672 * ImmUnregisterWordA (IMM32.@)
2673 */
2674 BOOL WINAPI ImmUnregisterWordA(
2675 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2676 {
2677 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2678 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2679 debugstr_a(lpszUnregister));
2680 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2681 {
2682 if (!is_kbd_ime_unicode(immHkl))
2683 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2684 (LPCWSTR)lpszUnregister);
2685 else
2686 {
2687 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2688 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2689 BOOL rc;
2690
2691 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2692 HeapFree(GetProcessHeap(),0,lpszwReading);
2693 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2694 return rc;
2695 }
2696 }
2697 else
2698 return FALSE;
2699 }
2700
2701 /***********************************************************************
2702 * ImmUnregisterWordW (IMM32.@)
2703 */
2704 BOOL WINAPI ImmUnregisterWordW(
2705 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2706 {
2707 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2708 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2709 debugstr_w(lpszUnregister));
2710 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2711 {
2712 if (is_kbd_ime_unicode(immHkl))
2713 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2714 else
2715 {
2716 LPSTR lpszaReading = strdupWtoA(lpszReading);
2717 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2718 BOOL rc;
2719
2720 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2721 (LPCWSTR)lpszaUnregister);
2722 HeapFree(GetProcessHeap(),0,lpszaReading);
2723 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2724 return rc;
2725 }
2726 }
2727 else
2728 return FALSE;
2729 }
2730
2731 /***********************************************************************
2732 * ImmGetImeMenuItemsA (IMM32.@)
2733 */
2734 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2735 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2736 DWORD dwSize)
2737 {
2738 InputContextData *data = get_imc_data(hIMC);
2739 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2740 lpImeParentMenu, lpImeMenu, dwSize);
2741
2742 if (!data)
2743 {
2744 SetLastError(ERROR_INVALID_HANDLE);
2745 return 0;
2746 }
2747
2748 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2749 {
2750 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2751 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2752 (IMEMENUITEMINFOW*)lpImeParentMenu,
2753 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2754 else
2755 {
2756 IMEMENUITEMINFOW lpImeParentMenuW;
2757 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2758 DWORD rc;
2759
2760 if (lpImeParentMenu)
2761 parent = &lpImeParentMenuW;
2762 if (lpImeMenu)
2763 {
2764 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2765 dwSize = count * sizeof(IMEMENUITEMINFOW);
2766 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2767 }
2768 else
2769 lpImeMenuW = NULL;
2770
2771 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2772 parent, lpImeMenuW, dwSize);
2773
2774 if (lpImeParentMenu)
2775 {
2776 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2777 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2778 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2779 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2780 NULL, NULL);
2781 }
2782 if (lpImeMenu && rc)
2783 {
2784 unsigned int i;
2785 for (i = 0; i < rc; i++)
2786 {
2787 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2788 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2789 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2790 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2791 NULL, NULL);
2792 }
2793 }
2794 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2795 return rc;
2796 }
2797 }
2798 else
2799 return 0;
2800 }
2801
2802 /***********************************************************************
2803 * ImmGetImeMenuItemsW (IMM32.@)
2804 */
2805 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2806 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2807 DWORD dwSize)
2808 {
2809 InputContextData *data = get_imc_data(hIMC);
2810 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2811 lpImeParentMenu, lpImeMenu, dwSize);
2812
2813 if (!data)
2814 {
2815 SetLastError(ERROR_INVALID_HANDLE);
2816 return 0;
2817 }
2818
2819 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2820 {
2821 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2822 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2823 lpImeParentMenu, lpImeMenu, dwSize);
2824 else
2825 {
2826 IMEMENUITEMINFOA lpImeParentMenuA;
2827 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2828 DWORD rc;
2829
2830 if (lpImeParentMenu)
2831 parent = &lpImeParentMenuA;
2832 if (lpImeMenu)
2833 {
2834 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2835 dwSize = count * sizeof(IMEMENUITEMINFOA);
2836 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2837 }
2838 else
2839 lpImeMenuA = NULL;
2840
2841 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2842 (IMEMENUITEMINFOW*)parent,
2843 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2844
2845 if (lpImeParentMenu)
2846 {
2847 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2848 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2849 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2850 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2851 }
2852 if (lpImeMenu && rc)
2853 {
2854 unsigned int i;
2855 for (i = 0; i < rc; i++)
2856 {
2857 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2858 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2859 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2860 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2861 }
2862 }
2863 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2864 return rc;
2865 }
2866 }
2867 else
2868 return 0;
2869 }
2870
2871 /***********************************************************************
2872 * ImmLockIMC(IMM32.@)
2873 */
2874 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2875 {
2876 InputContextData *data = get_imc_data(hIMC);
2877
2878 if (!data)
2879 return NULL;
2880 data->dwLock++;
2881 return &data->IMC;
2882 }
2883
2884 /***********************************************************************
2885 * ImmUnlockIMC(IMM32.@)
2886 */
2887 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2888 {
2889 InputContextData *data = get_imc_data(hIMC);
2890
2891 if (!data)
2892 return FALSE;
2893 if (data->dwLock)
2894 data->dwLock--;
2895 return TRUE;
2896 }
2897
2898 /***********************************************************************
2899 * ImmGetIMCLockCount(IMM32.@)
2900 */
2901 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2902 {
2903 InputContextData *data = get_imc_data(hIMC);
2904 if (!data)
2905 return 0;
2906 return data->dwLock;
2907 }
2908
2909 /***********************************************************************
2910 * ImmCreateIMCC(IMM32.@)
2911 */
2912 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2913 {
2914 return GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, size);
2915 }
2916
2917 /***********************************************************************
2918 * ImmDestroyIMCC(IMM32.@)
2919 */
2920 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2921 {
2922 return GlobalFree(block);
2923 }
2924
2925 /***********************************************************************
2926 * ImmLockIMCC(IMM32.@)
2927 */
2928 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2929 {
2930 return GlobalLock(imcc);
2931 }
2932
2933 /***********************************************************************
2934 * ImmUnlockIMCC(IMM32.@)
2935 */
2936 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2937 {
2938 return GlobalUnlock(imcc);
2939 }
2940
2941 /***********************************************************************
2942 * ImmGetIMCCLockCount(IMM32.@)
2943 */
2944 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2945 {
2946 return GlobalFlags(imcc) & GMEM_LOCKCOUNT;
2947 }
2948
2949 /***********************************************************************
2950 * ImmReSizeIMCC(IMM32.@)
2951 */
2952 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2953 {
2954 return GlobalReAlloc(imcc, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
2955 }
2956
2957 /***********************************************************************
2958 * ImmGetIMCCSize(IMM32.@)
2959 */
2960 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2961 {
2962 return GlobalSize(imcc);
2963 }
2964
2965 /***********************************************************************
2966 * ImmGenerateMessage(IMM32.@)
2967 */
2968 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2969 {
2970 InputContextData *data = get_imc_data(hIMC);
2971
2972 if (!data)
2973 {
2974 SetLastError(ERROR_INVALID_HANDLE);
2975 return FALSE;
2976 }
2977
2978 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2979 if (data->IMC.dwNumMsgBuf > 0)
2980 {
2981 LPTRANSMSG lpTransMsg;
2982 HIMCC hMsgBuf;
2983 DWORD i, dwNumMsgBuf;
2984
2985 /* We are going to detach our hMsgBuff so that if processing messages
2986 generates new messages they go into a new buffer */
2987 hMsgBuf = data->IMC.hMsgBuf;
2988 dwNumMsgBuf = data->IMC.dwNumMsgBuf;
2989
2990 data->IMC.hMsgBuf = ImmCreateIMCC(0);
2991 data->IMC.dwNumMsgBuf = 0;
2992
2993 lpTransMsg = ImmLockIMCC(hMsgBuf);
2994 for (i = 0; i < dwNumMsgBuf; i++)
2995 ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2996
2997 ImmUnlockIMCC(hMsgBuf);
2998 ImmDestroyIMCC(hMsgBuf);
2999 }
3000
3001 return TRUE;
3002 }
3003
3004 /***********************************************************************
3005 * ImmTranslateMessage(IMM32.@)
3006 * ( Undocumented, call internally and from user32.dll )
3007 */
3008 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
3009 {
3010 InputContextData *data;
3011 HIMC imc = ImmGetContext(hwnd);
3012 BYTE state[256];
3013 UINT scancode;
3014 LPVOID list = 0;
3015 UINT msg_count;
3016 UINT uVirtKey;
3017 static const DWORD list_count = 10;
3018
3019 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
3020
3021 if (imc)
3022 data = imc;
3023 else
3024 return FALSE;
3025
3026 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
3027 return FALSE;
3028
3029 GetKeyboardState(state);
3030 scancode = lKeyData >> 0x10 & 0xff;
3031
3032 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
3033 ((DWORD*)list)[0] = list_count;
3034
3035 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
3036 {
3037 WCHAR chr;
3038
3039 if (!is_himc_ime_unicode(data))
3040 ToAscii(data->lastVK, scancode, state, &chr, 0);
3041 else
3042 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
3043 uVirtKey = MAKELONG(data->lastVK,chr);
3044 }
3045 else
3046 uVirtKey = data->lastVK;
3047
3048 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
3049 TRACE("%i messages generated\n",msg_count);
3050 if (msg_count && msg_count <= list_count)
3051 {
3052 UINT i;
3053 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
3054
3055 for (i = 0; i < msg_count; i++)
3056 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
3057 }
3058 else if (msg_count > list_count)
3059 ImmGenerateMessage(imc);
3060
3061 HeapFree(GetProcessHeap(),0,list);
3062
3063 data->lastVK = VK_PROCESSKEY;
3064
3065 return (msg_count > 0);
3066 }
3067
3068 /***********************************************************************
3069 * ImmProcessKey(IMM32.@)
3070 * ( Undocumented, called from user32.dll )
3071 */
3072 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
3073 {
3074 InputContextData *data;
3075 HIMC imc = ImmGetContext(hwnd);
3076 BYTE state[256];
3077
3078 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
3079
3080 if (imc)
3081 data = imc;
3082 else
3083 return FALSE;
3084
3085 /* Make sure we are inputting to the correct keyboard */
3086 if (data->immKbd->hkl != hKL)
3087 {
3088 ImmHkl *new_hkl = IMM_GetImmHkl(hKL);
3089 if (new_hkl)
3090 {
3091 data->immKbd->pImeSelect(imc, FALSE);
3092 data->immKbd->uSelected--;
3093 data->immKbd = new_hkl;
3094 data->immKbd->pImeSelect(imc, TRUE);
3095 data->immKbd->uSelected++;
3096 }
3097 else
3098 return FALSE;
3099 }
3100
3101 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
3102 return FALSE;
3103
3104 GetKeyboardState(state);
3105 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
3106 {
3107 data->lastVK = vKey;
3108 return TRUE;
3109 }
3110
3111 data->lastVK = VK_PROCESSKEY;
3112 return FALSE;
3113 }
3114
3115 /***********************************************************************
3116 * ImmDisableTextFrameService(IMM32.@)
3117 */
3118 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread)
3119 {
3120 FIXME("Stub\n");
3121 return FALSE;
3122 }
3123
3124 /***********************************************************************
3125 * ImmEnumInputContext(IMM32.@)
3126 */
3127
3128 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam)
3129 {
3130 FIXME("Stub\n");
3131 return FALSE;
3132 }
3133
3134 /***********************************************************************
3135 * ImmGetHotKey(IMM32.@)
3136 */
3137
3138 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl)
3139 {
3140 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl);
3141 return FALSE;
3142 }
3143
3144 /***********************************************************************
3145 * ImmDisableLegacyIME(IMM32.@)
3146 */
3147 BOOL WINAPI ImmDisableLegacyIME(void)
3148 {
3149 FIXME("stub\n");
3150 return TRUE;
3151 }