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