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