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