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