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