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 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)GetKeyboardLayout(0));
660
661 new_context->immKbd->uSelected++;
662 TRACE("Created context %p\n",new_context);
663
664 return new_context;
665 }
666
667 static BOOL IMM_DestroyContext(HIMC hIMC)
668 {
669 InputContextData *data = hIMC;
670
671 TRACE("Destroying %p\n",hIMC);
672
673 if (hIMC)
674 {
675 data->immKbd->uSelected --;
676 data->immKbd->pImeSelect(hIMC, FALSE);
677 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
678
679 if (IMM_GetThreadData()->hwndDefault == data->imeWnd)
680 IMM_GetThreadData()->hwndDefault = NULL;
681 DestroyWindow(data->imeWnd);
682
683 ImmDestroyIMCC(data->IMC.hCompStr);
684 ImmDestroyIMCC(data->IMC.hCandInfo);
685 ImmDestroyIMCC(data->IMC.hGuideLine);
686 ImmDestroyIMCC(data->IMC.hPrivate);
687 ImmDestroyIMCC(data->IMC.hMsgBuf);
688
689 HeapFree(GetProcessHeap(),0,data);
690 }
691 return TRUE;
692 }
693
694 /***********************************************************************
695 * ImmDestroyContext (IMM32.@)
696 */
697 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
698 {
699 if (hIMC != IMM_GetThreadData()->defaultContext)
700 return IMM_DestroyContext(hIMC);
701 else
702 return FALSE;
703 }
704
705 /***********************************************************************
706 * ImmDisableIME (IMM32.@)
707 */
708 BOOL WINAPI ImmDisableIME(DWORD idThread)
709 {
710 FIXME("(%d): stub\n", idThread);
711 return TRUE;
712 }
713
714 /***********************************************************************
715 * ImmEnumRegisterWordA (IMM32.@)
716 */
717 UINT WINAPI ImmEnumRegisterWordA(
718 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
719 LPCSTR lpszReading, DWORD dwStyle,
720 LPCSTR lpszRegister, LPVOID lpData)
721 {
722 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
723 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
724 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
725 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
726 {
727 if (!is_kbd_ime_unicode(immHkl))
728 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
729 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
730 else
731 {
732 LPWSTR lpszwReading = strdupAtoW(lpszReading);
733 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
734 BOOL rc;
735
736 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
737 lpszwReading, dwStyle, lpszwRegister,
738 lpData);
739
740 HeapFree(GetProcessHeap(),0,lpszwReading);
741 HeapFree(GetProcessHeap(),0,lpszwRegister);
742 return rc;
743 }
744 }
745 else
746 return 0;
747 }
748
749 /***********************************************************************
750 * ImmEnumRegisterWordW (IMM32.@)
751 */
752 UINT WINAPI ImmEnumRegisterWordW(
753 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
754 LPCWSTR lpszReading, DWORD dwStyle,
755 LPCWSTR lpszRegister, LPVOID lpData)
756 {
757 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
758 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
759 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
760 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
761 {
762 if (is_kbd_ime_unicode(immHkl))
763 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
764 lpszRegister, lpData);
765 else
766 {
767 LPSTR lpszaReading = strdupWtoA(lpszReading);
768 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
769 BOOL rc;
770
771 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
772 dwStyle, (LPCWSTR)lpszaRegister, lpData);
773
774 HeapFree(GetProcessHeap(),0,lpszaReading);
775 HeapFree(GetProcessHeap(),0,lpszaRegister);
776 return rc;
777 }
778 }
779 else
780 return 0;
781 }
782
783 static inline BOOL EscapeRequiresWA(UINT uEscape)
784 {
785 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
786 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
787 uEscape == IME_ESC_IME_NAME ||
788 uEscape == IME_ESC_GETHELPFILENAME)
789 return TRUE;
790 return FALSE;
791 }
792
793 /***********************************************************************
794 * ImmEscapeA (IMM32.@)
795 */
796 LRESULT WINAPI ImmEscapeA(
797 HKL hKL, HIMC hIMC,
798 UINT uEscape, LPVOID lpData)
799 {
800 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
801 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
802
803 if (immHkl->hIME && immHkl->pImeEscape)
804 {
805 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
806 return immHkl->pImeEscape(hIMC,uEscape,lpData);
807 else
808 {
809 WCHAR buffer[81]; /* largest required buffer should be 80 */
810 LRESULT rc;
811 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
812 {
813 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
814 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
815 }
816 else
817 {
818 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
819 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
820 }
821 return rc;
822 }
823 }
824 else
825 return 0;
826 }
827
828 /***********************************************************************
829 * ImmEscapeW (IMM32.@)
830 */
831 LRESULT WINAPI ImmEscapeW(
832 HKL hKL, HIMC hIMC,
833 UINT uEscape, LPVOID lpData)
834 {
835 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
836 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
837
838 if (immHkl->hIME && immHkl->pImeEscape)
839 {
840 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
841 return immHkl->pImeEscape(hIMC,uEscape,lpData);
842 else
843 {
844 CHAR buffer[81]; /* largest required buffer should be 80 */
845 LRESULT rc;
846 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
847 {
848 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
849 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
850 }
851 else
852 {
853 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
854 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
855 }
856 return rc;
857 }
858 }
859 else
860 return 0;
861 }
862
863 /***********************************************************************
864 * ImmGetCandidateListA (IMM32.@)
865 */
866 DWORD WINAPI ImmGetCandidateListA(
867 HIMC hIMC, DWORD dwIndex,
868 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
869 {
870 InputContextData *data = hIMC;
871 LPCANDIDATEINFO candinfo;
872 LPCANDIDATELIST candlist;
873 DWORD ret = 0;
874
875 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
876
877 if (!data || !data->IMC.hCandInfo)
878 return 0;
879
880 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
881 if ( dwIndex >= candinfo->dwCount ||
882 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
883 goto done;
884
885 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
886 if ( !candlist->dwSize || !candlist->dwCount )
887 goto done;
888
889 if ( !is_himc_ime_unicode(data) )
890 {
891 ret = candlist->dwSize;
892 if ( lpCandList && dwBufLen >= ret )
893 memcpy(lpCandList, candlist, ret);
894 }
895 else
896 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
897
898 done:
899 ImmUnlockIMCC(data->IMC.hCandInfo);
900 return ret;
901 }
902
903 /***********************************************************************
904 * ImmGetCandidateListCountA (IMM32.@)
905 */
906 DWORD WINAPI ImmGetCandidateListCountA(
907 HIMC hIMC, LPDWORD lpdwListCount)
908 {
909 InputContextData *data = hIMC;
910 LPCANDIDATEINFO candinfo;
911 DWORD ret, count;
912
913 TRACE("%p, %p\n", hIMC, lpdwListCount);
914
915 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
916 return 0;
917
918 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
919
920 *lpdwListCount = count = candinfo->dwCount;
921
922 if ( !is_himc_ime_unicode(data) )
923 ret = candinfo->dwSize;
924 else
925 {
926 ret = sizeof(CANDIDATEINFO);
927 while ( count-- )
928 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
929 }
930
931 ImmUnlockIMCC(data->IMC.hCandInfo);
932 return ret;
933 }
934
935 /***********************************************************************
936 * ImmGetCandidateListCountW (IMM32.@)
937 */
938 DWORD WINAPI ImmGetCandidateListCountW(
939 HIMC hIMC, LPDWORD lpdwListCount)
940 {
941 InputContextData *data = hIMC;
942 LPCANDIDATEINFO candinfo;
943 DWORD ret, count;
944
945 TRACE("%p, %p\n", hIMC, lpdwListCount);
946
947 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
948 return 0;
949
950 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
951
952 *lpdwListCount = count = candinfo->dwCount;
953
954 if ( is_himc_ime_unicode(data) )
955 ret = candinfo->dwSize;
956 else
957 {
958 ret = sizeof(CANDIDATEINFO);
959 while ( count-- )
960 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
961 }
962
963 ImmUnlockIMCC(data->IMC.hCandInfo);
964 return ret;
965 }
966
967 /***********************************************************************
968 * ImmGetCandidateListW (IMM32.@)
969 */
970 DWORD WINAPI ImmGetCandidateListW(
971 HIMC hIMC, DWORD dwIndex,
972 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
973 {
974 InputContextData *data = hIMC;
975 LPCANDIDATEINFO candinfo;
976 LPCANDIDATELIST candlist;
977 DWORD ret = 0;
978
979 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
980
981 if (!data || !data->IMC.hCandInfo)
982 return 0;
983
984 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
985 if ( dwIndex >= candinfo->dwCount ||
986 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
987 goto done;
988
989 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
990 if ( !candlist->dwSize || !candlist->dwCount )
991 goto done;
992
993 if ( is_himc_ime_unicode(data) )
994 {
995 ret = candlist->dwSize;
996 if ( lpCandList && dwBufLen >= ret )
997 memcpy(lpCandList, candlist, ret);
998 }
999 else
1000 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1001
1002 done:
1003 ImmUnlockIMCC(data->IMC.hCandInfo);
1004 return ret;
1005 }
1006
1007 /***********************************************************************
1008 * ImmGetCandidateWindow (IMM32.@)
1009 */
1010 BOOL WINAPI ImmGetCandidateWindow(
1011 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1012 {
1013 InputContextData *data = hIMC;
1014
1015 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1016
1017 if (!data || !lpCandidate)
1018 return FALSE;
1019
1020 if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1021 return FALSE;
1022
1023 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1024
1025 return TRUE;
1026 }
1027
1028 /***********************************************************************
1029 * ImmGetCompositionFontA (IMM32.@)
1030 */
1031 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1032 {
1033 LOGFONTW lfW;
1034 BOOL rc;
1035
1036 TRACE("(%p, %p):\n", hIMC, lplf);
1037
1038 rc = ImmGetCompositionFontW(hIMC,&lfW);
1039 if (!rc || !lplf)
1040 return FALSE;
1041
1042 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1043 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1044 LF_FACESIZE, NULL, NULL);
1045 return TRUE;
1046 }
1047
1048 /***********************************************************************
1049 * ImmGetCompositionFontW (IMM32.@)
1050 */
1051 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1052 {
1053 InputContextData *data = hIMC;
1054
1055 TRACE("(%p, %p):\n", hIMC, lplf);
1056
1057 if (!data || !lplf)
1058 return FALSE;
1059
1060 *lplf = data->IMC.lfFont.W;
1061
1062 return TRUE;
1063 }
1064
1065
1066 /* Helpers for the GetCompositionString functions */
1067
1068 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1069 BOOL unicode )
1070 {
1071 INT rc;
1072
1073 if (is_himc_ime_unicode(data) && !unicode)
1074 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1075 else if (!is_himc_ime_unicode(data) && unicode)
1076 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1077 else
1078 {
1079 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1080 memcpy( target, source, min(slen,tlen)*dlen);
1081 rc = slen*dlen;
1082 }
1083
1084 return rc;
1085 }
1086
1087 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1088 LPBYTE target, INT tlen, BOOL unicode )
1089 {
1090 INT rc;
1091
1092 if (is_himc_ime_unicode(data) && !unicode)
1093 {
1094 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1095 if (tlen)
1096 {
1097 const BYTE *src = source;
1098 LPBYTE dst = target;
1099 int i, j = 0, k = 0;
1100
1101 if (rc < tlen)
1102 tlen = rc;
1103 for (i = 0; i < sslen; ++i)
1104 {
1105 int len;
1106
1107 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1108 NULL, 0, NULL, NULL);
1109 for (; len > 0; --len)
1110 {
1111 dst[j++] = src[k];
1112
1113 if (j >= tlen)
1114 goto end;
1115 }
1116 ++k;
1117 }
1118 end:
1119 rc = j;
1120 }
1121 }
1122 else if (!is_himc_ime_unicode(data) && unicode)
1123 {
1124 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1125 if (tlen)
1126 {
1127 const BYTE *src = source;
1128 LPBYTE dst = target;
1129 int i, j = 0;
1130
1131 if (rc < tlen)
1132 tlen = rc;
1133 for (i = 0; i < sslen; ++i)
1134 {
1135 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1136 continue;
1137
1138 dst[j++] = src[i];
1139
1140 if (j >= tlen)
1141 break;
1142 }
1143 rc = j;
1144 }
1145 }
1146 else
1147 {
1148 memcpy( target, source, min(slen,tlen));
1149 rc = slen;
1150 }
1151
1152 return rc;
1153 }
1154
1155 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1156 LPBYTE target, INT tlen, BOOL unicode )
1157 {
1158 INT rc;
1159
1160 if (is_himc_ime_unicode(data) && !unicode)
1161 {
1162 if (tlen)
1163 {
1164 int i;
1165
1166 if (slen < tlen)
1167 tlen = slen;
1168 tlen /= sizeof (DWORD);
1169 for (i = 0; i < tlen; ++i)
1170 {
1171 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1172 ((DWORD *)source)[i],
1173 NULL, 0,
1174 NULL, NULL);
1175 }
1176 rc = sizeof (DWORD) * i;
1177 }
1178 else
1179 rc = slen;
1180 }
1181 else if (!is_himc_ime_unicode(data) && unicode)
1182 {
1183 if (tlen)
1184 {
1185 int i;
1186
1187 if (slen < tlen)
1188 tlen = slen;
1189 tlen /= sizeof (DWORD);
1190 for (i = 0; i < tlen; ++i)
1191 {
1192 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1193 ((DWORD *)source)[i],
1194 NULL, 0);
1195 }
1196 rc = sizeof (DWORD) * i;
1197 }
1198 else
1199 rc = slen;
1200 }
1201 else
1202 {
1203 memcpy( target, source, min(slen,tlen));
1204 rc = slen;
1205 }
1206
1207 return rc;
1208 }
1209
1210 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1211 {
1212 int rc;
1213
1214 if (is_himc_ime_unicode(data) && !unicode)
1215 {
1216 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1217 }
1218 else if (!is_himc_ime_unicode(data) && unicode)
1219 {
1220 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1221 }
1222 else
1223 rc = offset;
1224
1225 return rc;
1226 }
1227
1228 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1229 DWORD dwBufLen, BOOL unicode)
1230 {
1231 LONG rc = 0;
1232 InputContextData *data = hIMC;
1233 LPCOMPOSITIONSTRING compstr;
1234 LPBYTE compdata;
1235
1236 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1237
1238 if (!data)
1239 return FALSE;
1240
1241 if (!data->IMC.hCompStr)
1242 return FALSE;
1243
1244 compdata = ImmLockIMCC(data->IMC.hCompStr);
1245 compstr = (LPCOMPOSITIONSTRING)compdata;
1246
1247 switch (dwIndex)
1248 {
1249 case GCS_RESULTSTR:
1250 TRACE("GCS_RESULTSTR\n");
1251 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1252 break;
1253 case GCS_COMPSTR:
1254 TRACE("GCS_COMPSTR\n");
1255 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1256 break;
1257 case GCS_COMPATTR:
1258 TRACE("GCS_COMPATTR\n");
1259 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1260 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1261 lpBuf, dwBufLen, unicode);
1262 break;
1263 case GCS_COMPCLAUSE:
1264 TRACE("GCS_COMPCLAUSE\n");
1265 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1266 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1267 lpBuf, dwBufLen, unicode);
1268 break;
1269 case GCS_RESULTCLAUSE:
1270 TRACE("GCS_RESULTCLAUSE\n");
1271 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1272 compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen,
1273 lpBuf, dwBufLen, unicode);
1274 break;
1275 case GCS_RESULTREADSTR:
1276 TRACE("GCS_RESULTREADSTR\n");
1277 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1278 break;
1279 case GCS_RESULTREADCLAUSE:
1280 TRACE("GCS_RESULTREADCLAUSE\n");
1281 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1282 compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen,
1283 lpBuf, dwBufLen, unicode);
1284 break;
1285 case GCS_COMPREADSTR:
1286 TRACE("GCS_COMPREADSTR\n");
1287 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1288 break;
1289 case GCS_COMPREADATTR:
1290 TRACE("GCS_COMPREADATTR\n");
1291 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1292 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1293 lpBuf, dwBufLen, unicode);
1294 break;
1295 case GCS_COMPREADCLAUSE:
1296 TRACE("GCS_COMPREADCLAUSE\n");
1297 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1298 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1299 lpBuf, dwBufLen, unicode);
1300 break;
1301 case GCS_CURSORPOS:
1302 TRACE("GCS_CURSORPOS\n");
1303 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1304 break;
1305 case GCS_DELTASTART:
1306 TRACE("GCS_DELTASTART\n");
1307 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1308 break;
1309 default:
1310 FIXME("Unhandled index 0x%x\n",dwIndex);
1311 break;
1312 }
1313
1314 ImmUnlockIMCC(data->IMC.hCompStr);
1315
1316 return rc;
1317 }
1318
1319 /***********************************************************************
1320 * ImmGetCompositionStringA (IMM32.@)
1321 */
1322 LONG WINAPI ImmGetCompositionStringA(
1323 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1324 {
1325 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1326 }
1327
1328
1329 /***********************************************************************
1330 * ImmGetCompositionStringW (IMM32.@)
1331 */
1332 LONG WINAPI ImmGetCompositionStringW(
1333 HIMC hIMC, DWORD dwIndex,
1334 LPVOID lpBuf, DWORD dwBufLen)
1335 {
1336 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1337 }
1338
1339 /***********************************************************************
1340 * ImmGetCompositionWindow (IMM32.@)
1341 */
1342 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1343 {
1344 InputContextData *data = hIMC;
1345
1346 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1347
1348 if (!data)
1349 return FALSE;
1350
1351 *lpCompForm = data->IMC.cfCompForm;
1352 return 1;
1353 }
1354
1355 /***********************************************************************
1356 * ImmGetContext (IMM32.@)
1357 *
1358 */
1359 HIMC WINAPI ImmGetContext(HWND hWnd)
1360 {
1361 HIMC rc = NULL;
1362
1363 TRACE("%p\n", hWnd);
1364 if (!IMM_GetThreadData()->defaultContext)
1365 IMM_GetThreadData()->defaultContext = ImmCreateContext();
1366
1367 rc = GetPropW(hWnd,szwWineIMCProperty);
1368 if (rc == (HIMC)-1)
1369 rc = NULL;
1370 else if (rc == NULL)
1371 rc = IMM_GetThreadData()->defaultContext;
1372
1373 if (rc)
1374 {
1375 InputContextData *data = rc;
1376 data->IMC.hWnd = hWnd;
1377 }
1378 TRACE("returning %p\n", rc);
1379
1380 return rc;
1381 }
1382
1383 /***********************************************************************
1384 * ImmGetConversionListA (IMM32.@)
1385 */
1386 DWORD WINAPI ImmGetConversionListA(
1387 HKL hKL, HIMC hIMC,
1388 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1389 DWORD dwBufLen, UINT uFlag)
1390 {
1391 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1392 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1393 dwBufLen, uFlag);
1394 if (immHkl->hIME && immHkl->pImeConversionList)
1395 {
1396 if (!is_kbd_ime_unicode(immHkl))
1397 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1398 else
1399 {
1400 LPCANDIDATELIST lpwDst;
1401 DWORD ret = 0, len;
1402 LPWSTR pwSrc = strdupAtoW(pSrc);
1403
1404 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1405 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1406 if ( lpwDst )
1407 {
1408 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1409 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1410 HeapFree(GetProcessHeap(), 0, lpwDst);
1411 }
1412 HeapFree(GetProcessHeap(), 0, pwSrc);
1413
1414 return ret;
1415 }
1416 }
1417 else
1418 return 0;
1419 }
1420
1421 /***********************************************************************
1422 * ImmGetConversionListW (IMM32.@)
1423 */
1424 DWORD WINAPI ImmGetConversionListW(
1425 HKL hKL, HIMC hIMC,
1426 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1427 DWORD dwBufLen, UINT uFlag)
1428 {
1429 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1430 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1431 dwBufLen, uFlag);
1432 if (immHkl->hIME && immHkl->pImeConversionList)
1433 {
1434 if (is_kbd_ime_unicode(immHkl))
1435 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1436 else
1437 {
1438 LPCANDIDATELIST lpaDst;
1439 DWORD ret = 0, len;
1440 LPSTR paSrc = strdupWtoA(pSrc);
1441
1442 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1443 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1444 if ( lpaDst )
1445 {
1446 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1447 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1448 HeapFree(GetProcessHeap(), 0, lpaDst);
1449 }
1450 HeapFree(GetProcessHeap(), 0, paSrc);
1451
1452 return ret;
1453 }
1454 }
1455 else
1456 return 0;
1457 }
1458
1459 /***********************************************************************
1460 * ImmGetConversionStatus (IMM32.@)
1461 */
1462 BOOL WINAPI ImmGetConversionStatus(
1463 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1464 {
1465 InputContextData *data = hIMC;
1466
1467 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1468
1469 if (!data)
1470 return FALSE;
1471
1472 if (lpfdwConversion)
1473 *lpfdwConversion = data->IMC.fdwConversion;
1474 if (lpfdwSentence)
1475 *lpfdwSentence = data->IMC.fdwSentence;
1476
1477 return TRUE;
1478 }
1479
1480 /***********************************************************************
1481 * ImmGetDefaultIMEWnd (IMM32.@)
1482 */
1483 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1484 {
1485 TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault);
1486 return IMM_GetThreadData()->hwndDefault;
1487 }
1488
1489 /***********************************************************************
1490 * ImmGetDescriptionA (IMM32.@)
1491 */
1492 UINT WINAPI ImmGetDescriptionA(
1493 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1494 {
1495 WCHAR *buf;
1496 DWORD len;
1497
1498 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1499
1500 /* find out how many characters in the unicode buffer */
1501 len = ImmGetDescriptionW( hKL, NULL, 0 );
1502
1503 /* allocate a buffer of that size */
1504 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1505 if( !buf )
1506 return 0;
1507
1508 /* fetch the unicode buffer */
1509 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1510
1511 /* convert it back to ASCII */
1512 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1513 lpszDescription, uBufLen, NULL, NULL );
1514
1515 HeapFree( GetProcessHeap(), 0, buf );
1516
1517 return len;
1518 }
1519
1520 /***********************************************************************
1521 * ImmGetDescriptionW (IMM32.@)
1522 */
1523 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1524 {
1525 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1526
1527 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1528
1529 if (!uBufLen) return lstrlenW( name );
1530 lstrcpynW( lpszDescription, name, uBufLen );
1531 return lstrlenW( lpszDescription );
1532 }
1533
1534 /***********************************************************************
1535 * ImmGetGuideLineA (IMM32.@)
1536 */
1537 DWORD WINAPI ImmGetGuideLineA(
1538 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1539 {
1540 FIXME("(%p, %d, %s, %d): stub\n",
1541 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1542 );
1543 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1544 return 0;
1545 }
1546
1547 /***********************************************************************
1548 * ImmGetGuideLineW (IMM32.@)
1549 */
1550 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1551 {
1552 FIXME("(%p, %d, %s, %d): stub\n",
1553 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1554 );
1555 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1556 return 0;
1557 }
1558
1559 /***********************************************************************
1560 * ImmGetIMEFileNameA (IMM32.@)
1561 */
1562 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1563 {
1564 LPWSTR bufW = NULL;
1565 UINT wBufLen = uBufLen;
1566 UINT rc;
1567
1568 if (uBufLen && lpszFileName)
1569 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1570 else /* We need this to get the number of byte required */
1571 {
1572 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1573 wBufLen = MAX_PATH;
1574 }
1575
1576 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1577
1578 if (rc > 0)
1579 {
1580 if (uBufLen && lpszFileName)
1581 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1582 uBufLen, NULL, NULL);
1583 else /* get the length */
1584 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1585 NULL);
1586 }
1587
1588 HeapFree(GetProcessHeap(),0,bufW);
1589 return rc;
1590 }
1591
1592 /***********************************************************************
1593 * ImmGetIMEFileNameW (IMM32.@)
1594 */
1595 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1596 {
1597 HKEY hkey;
1598 DWORD length;
1599 DWORD rc;
1600 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1601
1602 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1603 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1604 if (rc != ERROR_SUCCESS)
1605 {
1606 SetLastError(rc);
1607 return 0;
1608 }
1609
1610 length = 0;
1611 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1612
1613 if (rc != ERROR_SUCCESS)
1614 {
1615 RegCloseKey(hkey);
1616 SetLastError(rc);
1617 return 0;
1618 }
1619 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1620 {
1621 RegCloseKey(hkey);
1622 if (lpszFileName)
1623 {
1624 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1625 return 0;
1626 }
1627 else
1628 return length / sizeof(WCHAR);
1629 }
1630
1631 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1632
1633 RegCloseKey(hkey);
1634
1635 return length / sizeof(WCHAR);
1636 }
1637
1638 /***********************************************************************
1639 * ImmGetOpenStatus (IMM32.@)
1640 */
1641 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1642 {
1643 InputContextData *data = hIMC;
1644
1645 if (!data)
1646 return FALSE;
1647 FIXME("(%p): semi-stub\n", hIMC);
1648
1649 return data->IMC.fOpen;
1650 }
1651
1652 /***********************************************************************
1653 * ImmGetProperty (IMM32.@)
1654 */
1655 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1656 {
1657 DWORD rc = 0;
1658 ImmHkl *kbd;
1659
1660 TRACE("(%p, %d)\n", hKL, fdwIndex);
1661 kbd = IMM_GetImmHkl(hKL);
1662
1663 if (kbd && kbd->hIME)
1664 {
1665 switch (fdwIndex)
1666 {
1667 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1668 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1669 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1670 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1671 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1672 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1673 case IGP_UI: rc = 0; break;
1674 default: rc = 0;
1675 }
1676 }
1677 return rc;
1678 }
1679
1680 /***********************************************************************
1681 * ImmGetRegisterWordStyleA (IMM32.@)
1682 */
1683 UINT WINAPI ImmGetRegisterWordStyleA(
1684 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1685 {
1686 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1687 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1688 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1689 {
1690 if (!is_kbd_ime_unicode(immHkl))
1691 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1692 else
1693 {
1694 STYLEBUFW sbw;
1695 UINT rc;
1696
1697 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1698 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1699 lpStyleBuf->szDescription, 32, NULL, NULL);
1700 lpStyleBuf->dwStyle = sbw.dwStyle;
1701 return rc;
1702 }
1703 }
1704 else
1705 return 0;
1706 }
1707
1708 /***********************************************************************
1709 * ImmGetRegisterWordStyleW (IMM32.@)
1710 */
1711 UINT WINAPI ImmGetRegisterWordStyleW(
1712 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1713 {
1714 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1715 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1716 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1717 {
1718 if (is_kbd_ime_unicode(immHkl))
1719 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1720 else
1721 {
1722 STYLEBUFA sba;
1723 UINT rc;
1724
1725 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1726 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1727 lpStyleBuf->szDescription, 32);
1728 lpStyleBuf->dwStyle = sba.dwStyle;
1729 return rc;
1730 }
1731 }
1732 else
1733 return 0;
1734 }
1735
1736 /***********************************************************************
1737 * ImmGetStatusWindowPos (IMM32.@)
1738 */
1739 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1740 {
1741 InputContextData *data = hIMC;
1742
1743 TRACE("(%p, %p)\n", hIMC, lpptPos);
1744
1745 if (!data || !lpptPos)
1746 return FALSE;
1747
1748 *lpptPos = data->IMC.ptStatusWndPos;
1749
1750 return TRUE;
1751 }
1752
1753 /***********************************************************************
1754 * ImmGetVirtualKey (IMM32.@)
1755 */
1756 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1757 {
1758 OSVERSIONINFOA version;
1759 InputContextData *data = ImmGetContext( hWnd );
1760 TRACE("%p\n", hWnd);
1761
1762 if ( data )
1763 return data->lastVK;
1764
1765 GetVersionExA( &version );
1766 switch(version.dwPlatformId)
1767 {
1768 case VER_PLATFORM_WIN32_WINDOWS:
1769 return VK_PROCESSKEY;
1770 case VER_PLATFORM_WIN32_NT:
1771 return 0;
1772 default:
1773 FIXME("%d not supported\n",version.dwPlatformId);
1774 return VK_PROCESSKEY;
1775 }
1776 }
1777
1778 /***********************************************************************
1779 * ImmInstallIMEA (IMM32.@)
1780 */
1781 HKL WINAPI ImmInstallIMEA(
1782 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1783 {
1784 LPWSTR lpszwIMEFileName;
1785 LPWSTR lpszwLayoutText;
1786 HKL hkl;
1787
1788 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
1789 debugstr_a(lpszLayoutText));
1790
1791 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
1792 lpszwLayoutText = strdupAtoW(lpszLayoutText);
1793
1794 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
1795
1796 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
1797 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
1798 return hkl;
1799 }
1800
1801 /***********************************************************************
1802 * ImmInstallIMEW (IMM32.@)
1803 */
1804 HKL WINAPI ImmInstallIMEW(
1805 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1806 {
1807 INT lcid = GetUserDefaultLCID();
1808 INT count;
1809 HKL hkl;
1810 DWORD rc;
1811 HKEY hkey;
1812 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1813
1814 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
1815 debugstr_w(lpszLayoutText));
1816
1817 /* Start with 2. e001 will be blank and so default to the wine internal IME */
1818 count = 2;
1819
1820 while (count < 0xfff)
1821 {
1822 DWORD disposition = 0;
1823
1824 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
1825 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
1826
1827 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
1828 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
1829 break;
1830 else if (rc == ERROR_SUCCESS)
1831 RegCloseKey(hkey);
1832
1833 count++;
1834 }
1835
1836 if (count == 0xfff)
1837 {
1838 WARN("Unable to find slot to install IME\n");
1839 return 0;
1840 }
1841
1842 if (rc == ERROR_SUCCESS)
1843 {
1844 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (LPBYTE)lpszIMEFileName,
1845 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
1846 if (rc == ERROR_SUCCESS)
1847 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (LPBYTE)lpszLayoutText,
1848 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
1849 RegCloseKey(hkey);
1850 return hkl;
1851 }
1852 else
1853 {
1854 WARN("Unable to set IME registry values\n");
1855 return 0;
1856 }
1857 }
1858
1859 /***********************************************************************
1860 * ImmIsIME (IMM32.@)
1861 */
1862 BOOL WINAPI ImmIsIME(HKL hKL)
1863 {
1864 ImmHkl *ptr;
1865 TRACE("(%p):\n", hKL);
1866 ptr = IMM_GetImmHkl(hKL);
1867 return (ptr && ptr->hIME);
1868 }
1869
1870 /***********************************************************************
1871 * ImmIsUIMessageA (IMM32.@)
1872 */
1873 BOOL WINAPI ImmIsUIMessageA(
1874 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1875 {
1876 BOOL rc = FALSE;
1877
1878 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1879 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1880 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1881 (msg == WM_MSIME_SERVICE) ||
1882 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1883 (msg == WM_MSIME_MOUSE) ||
1884 (msg == WM_MSIME_RECONVERTREQUEST) ||
1885 (msg == WM_MSIME_RECONVERT) ||
1886 (msg == WM_MSIME_QUERYPOSITION) ||
1887 (msg == WM_MSIME_DOCUMENTFEED))
1888
1889 {
1890 if (!IMM_GetThreadData()->hwndDefault)
1891 ImmGetDefaultIMEWnd(NULL);
1892
1893 if (hWndIME == NULL)
1894 PostMessageA(IMM_GetThreadData()->hwndDefault, msg, wParam, lParam);
1895
1896 rc = TRUE;
1897 }
1898 return rc;
1899 }
1900
1901 /***********************************************************************
1902 * ImmIsUIMessageW (IMM32.@)
1903 */
1904 BOOL WINAPI ImmIsUIMessageW(
1905 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1906 {
1907 BOOL rc = FALSE;
1908 TRACE("(%p, %d, %ld, %ld):\n", hWndIME, msg, wParam, lParam);
1909 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1910 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1911 (msg == WM_MSIME_SERVICE) ||
1912 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1913 (msg == WM_MSIME_MOUSE) ||
1914 (msg == WM_MSIME_RECONVERTREQUEST) ||
1915 (msg == WM_MSIME_RECONVERT) ||
1916 (msg == WM_MSIME_QUERYPOSITION) ||
1917 (msg == WM_MSIME_DOCUMENTFEED))
1918 rc = TRUE;
1919 return rc;
1920 }
1921
1922 /***********************************************************************
1923 * ImmNotifyIME (IMM32.@)
1924 */
1925 BOOL WINAPI ImmNotifyIME(
1926 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1927 {
1928 InputContextData *data = hIMC;
1929
1930 TRACE("(%p, %d, %d, %d)\n",
1931 hIMC, dwAction, dwIndex, dwValue);
1932
1933 if (!data || ! data->immKbd->pNotifyIME)
1934 return FALSE;
1935
1936 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
1937 }
1938
1939 /***********************************************************************
1940 * ImmRegisterWordA (IMM32.@)
1941 */
1942 BOOL WINAPI ImmRegisterWordA(
1943 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1944 {
1945 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1946 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
1947 debugstr_a(lpszRegister));
1948 if (immHkl->hIME && immHkl->pImeRegisterWord)
1949 {
1950 if (!is_kbd_ime_unicode(immHkl))
1951 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
1952 (LPCWSTR)lpszRegister);
1953 else
1954 {
1955 LPWSTR lpszwReading = strdupAtoW(lpszReading);
1956 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
1957 BOOL rc;
1958
1959 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
1960 HeapFree(GetProcessHeap(),0,lpszwReading);
1961 HeapFree(GetProcessHeap(),0,lpszwRegister);
1962 return rc;
1963 }
1964 }
1965 else
1966 return FALSE;
1967 }
1968
1969 /***********************************************************************
1970 * ImmRegisterWordW (IMM32.@)
1971 */
1972 BOOL WINAPI ImmRegisterWordW(
1973 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1974 {
1975 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1976 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
1977 debugstr_w(lpszRegister));
1978 if (immHkl->hIME && immHkl->pImeRegisterWord)
1979 {
1980 if (is_kbd_ime_unicode(immHkl))
1981 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
1982 else
1983 {
1984 LPSTR lpszaReading = strdupWtoA(lpszReading);
1985 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
1986 BOOL rc;
1987
1988 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
1989 (LPCWSTR)lpszaRegister);
1990 HeapFree(GetProcessHeap(),0,lpszaReading);
1991 HeapFree(GetProcessHeap(),0,lpszaRegister);
1992 return rc;
1993 }
1994 }
1995 else
1996 return FALSE;
1997 }
1998
1999 /***********************************************************************
2000 * ImmReleaseContext (IMM32.@)
2001 */
2002 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2003 {
2004 static int shown = 0;
2005
2006 if (!shown) {
2007 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2008 shown = 1;
2009 }
2010 return TRUE;
2011 }
2012
2013 /***********************************************************************
2014 * ImmRequestMessageA(IMM32.@)
2015 */
2016 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2017 {
2018 InputContextData *data = hIMC;
2019
2020 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2021
2022 if (data && IsWindow(data->IMC.hWnd))
2023 return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2024
2025 return 0;
2026 }
2027
2028 /***********************************************************************
2029 * ImmRequestMessageW(IMM32.@)
2030 */
2031 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2032 {
2033 InputContextData *data = hIMC;
2034
2035 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2036
2037 if (data && IsWindow(data->IMC.hWnd))
2038 return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2039
2040 return 0;
2041 }
2042
2043 /***********************************************************************
2044 * ImmSetCandidateWindow (IMM32.@)
2045 */
2046 BOOL WINAPI ImmSetCandidateWindow(
2047 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2048 {
2049 InputContextData *data = hIMC;
2050
2051 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2052
2053 if (!data || !lpCandidate)
2054 return FALSE;
2055
2056 TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
2057 lpCandidate->dwIndex, lpCandidate->dwStyle,
2058 lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
2059 lpCandidate->rcArea.top, lpCandidate->rcArea.left,
2060 lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
2061
2062 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
2063 return FALSE;
2064
2065 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2066 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2067 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2068
2069 return TRUE;
2070 }
2071
2072 /***********************************************************************
2073 * ImmSetCompositionFontA (IMM32.@)
2074 */
2075 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2076 {
2077 InputContextData *data = hIMC;
2078 TRACE("(%p, %p)\n", hIMC, lplf);
2079
2080 if (!data || !lplf)
2081 return FALSE;
2082
2083 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2084 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2085 LF_FACESIZE);
2086 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2087 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2088
2089 return TRUE;
2090 }
2091
2092 /***********************************************************************
2093 * ImmSetCompositionFontW (IMM32.@)
2094 */
2095 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2096 {
2097 InputContextData *data = hIMC;
2098 TRACE("(%p, %p)\n", hIMC, lplf);
2099
2100 if (!data || !lplf)
2101 return FALSE;
2102
2103 data->IMC.lfFont.W = *lplf;
2104 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2105 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2106
2107 return TRUE;
2108 }
2109
2110 /***********************************************************************
2111 * ImmSetCompositionStringA (IMM32.@)
2112 */
2113 BOOL WINAPI ImmSetCompositionStringA(
2114 HIMC hIMC, DWORD dwIndex,
2115 LPCVOID lpComp, DWORD dwCompLen,
2116 LPCVOID lpRead, DWORD dwReadLen)
2117 {
2118 DWORD comp_len;
2119 DWORD read_len;
2120 WCHAR *CompBuffer = NULL;
2121 WCHAR *ReadBuffer = NULL;
2122 BOOL rc;
2123 InputContextData *data = hIMC;
2124
2125 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2126 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2127
2128 if (!data)
2129 return FALSE;
2130
2131 if (!is_himc_ime_unicode(data))
2132 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2133 dwCompLen, lpRead, dwReadLen);
2134
2135 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2136 if (comp_len)
2137 {
2138 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2139 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2140 }
2141
2142 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2143 if (read_len)
2144 {
2145 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2146 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2147 }
2148
2149 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2150 ReadBuffer, read_len);
2151
2152 HeapFree(GetProcessHeap(), 0, CompBuffer);
2153 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2154
2155 return rc;
2156 }
2157
2158 /***********************************************************************
2159 * ImmSetCompositionStringW (IMM32.@)
2160 */
2161 BOOL WINAPI ImmSetCompositionStringW(
2162 HIMC hIMC, DWORD dwIndex,
2163 LPCVOID lpComp, DWORD dwCompLen,
2164 LPCVOID lpRead, DWORD dwReadLen)
2165 {
2166 DWORD comp_len;
2167 DWORD read_len;
2168 CHAR *CompBuffer = NULL;
2169 CHAR *ReadBuffer = NULL;
2170 BOOL rc;
2171 InputContextData *data = hIMC;
2172
2173 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2174 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2175
2176 if (!data)
2177 return FALSE;
2178
2179 if (is_himc_ime_unicode(data))
2180 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2181 dwCompLen, lpRead, dwReadLen);
2182
2183 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2184 NULL);
2185 if (comp_len)
2186 {
2187 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2188 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2189 NULL, NULL);
2190 }
2191
2192 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2193 NULL);
2194 if (read_len)
2195 {
2196 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2197 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2198 NULL, NULL);
2199 }
2200
2201 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2202 ReadBuffer, read_len);
2203
2204 HeapFree(GetProcessHeap(), 0, CompBuffer);
2205 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2206
2207 return rc;
2208 }
2209
2210 /***********************************************************************
2211 * ImmSetCompositionWindow (IMM32.@)
2212 */
2213 BOOL WINAPI ImmSetCompositionWindow(
2214 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2215 {
2216 BOOL reshow = FALSE;
2217 InputContextData *data = hIMC;
2218
2219 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2220 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2221 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2222 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2223
2224 if (!data)
2225 return FALSE;
2226
2227 data->IMC.cfCompForm = *lpCompForm;
2228
2229 if (IsWindowVisible(IMM_GetThreadData()->hwndDefault))
2230 {
2231 reshow = TRUE;
2232 ShowWindow(IMM_GetThreadData()->hwndDefault,SW_HIDE);
2233 }
2234
2235 /* FIXME: this is a partial stub */
2236
2237 if (reshow)
2238 ShowWindow(IMM_GetThreadData()->hwndDefault,SW_SHOWNOACTIVATE);
2239
2240 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2241 return TRUE;
2242 }
2243
2244 /***********************************************************************
2245 * ImmSetConversionStatus (IMM32.@)
2246 */
2247 BOOL WINAPI ImmSetConversionStatus(
2248 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2249 {
2250 DWORD oldConversion, oldSentence;
2251 InputContextData *data = hIMC;
2252
2253 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2254
2255 if (!data)
2256 return FALSE;
2257
2258 if ( fdwConversion != data->IMC.fdwConversion )
2259 {
2260 oldConversion = data->IMC.fdwConversion;
2261 data->IMC.fdwConversion = fdwConversion;
2262 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2263 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2264 }
2265 if ( fdwSentence != data->IMC.fdwSentence )
2266 {
2267 oldSentence = data->IMC.fdwSentence;
2268 data->IMC.fdwSentence = fdwSentence;
2269 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2270 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2271 }
2272
2273 return TRUE;
2274 }
2275
2276 /***********************************************************************
2277 * ImmSetOpenStatus (IMM32.@)
2278 */
2279 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2280 {
2281 InputContextData *data = hIMC;
2282
2283 TRACE("%p %d\n", hIMC, fOpen);
2284
2285 if (!data)
2286 return FALSE;
2287
2288 if (data->imeWnd == NULL)
2289 {
2290 /* create the ime window */
2291 data->imeWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2292 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2293 0, data->immKbd->hIME, 0);
2294 SetWindowLongPtrW(data->imeWnd, IMMGWL_IMC, (LONG_PTR)data);
2295 IMM_GetThreadData()->hwndDefault = data->imeWnd;
2296 }
2297
2298 if (!fOpen != !data->IMC.fOpen)
2299 {
2300 data->IMC.fOpen = fOpen;
2301 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2302 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2303 }
2304
2305 return TRUE;
2306 }
2307
2308 /***********************************************************************
2309 * ImmSetStatusWindowPos (IMM32.@)
2310 */
2311 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2312 {
2313 InputContextData *data = hIMC;
2314
2315 TRACE("(%p, %p)\n", hIMC, lpptPos);
2316
2317 if (!data || !lpptPos)
2318 return FALSE;
2319
2320 TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2321
2322 data->IMC.ptStatusWndPos = *lpptPos;
2323 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2324 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2325
2326 return TRUE;
2327 }
2328
2329 /***********************************************************************
2330 * ImmCreateSoftKeyboard(IMM32.@)
2331 */
2332 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2333 {
2334 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2335 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2336 return 0;
2337 }
2338
2339 /***********************************************************************
2340 * ImmDestroySoftKeyboard(IMM32.@)
2341 */
2342 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2343 {
2344 FIXME("(%p): stub\n", hSoftWnd);
2345 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2346 return FALSE;
2347 }
2348
2349 /***********************************************************************
2350 * ImmShowSoftKeyboard(IMM32.@)
2351 */
2352 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2353 {
2354 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2355 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2356 return FALSE;
2357 }
2358
2359 /***********************************************************************
2360 * ImmSimulateHotKey (IMM32.@)
2361 */
2362 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2363 {
2364 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2365 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2366 return FALSE;
2367 }
2368
2369 /***********************************************************************
2370 * ImmUnregisterWordA (IMM32.@)
2371 */
2372 BOOL WINAPI ImmUnregisterWordA(
2373 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2374 {
2375 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2376 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2377 debugstr_a(lpszUnregister));
2378 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2379 {
2380 if (!is_kbd_ime_unicode(immHkl))
2381 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2382 (LPCWSTR)lpszUnregister);
2383 else
2384 {
2385 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2386 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2387 BOOL rc;
2388
2389 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2390 HeapFree(GetProcessHeap(),0,lpszwReading);
2391 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2392 return rc;
2393 }
2394 }
2395 else
2396 return FALSE;
2397 }
2398
2399 /***********************************************************************
2400 * ImmUnregisterWordW (IMM32.@)
2401 */
2402 BOOL WINAPI ImmUnregisterWordW(
2403 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2404 {
2405 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2406 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2407 debugstr_w(lpszUnregister));
2408 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2409 {
2410 if (is_kbd_ime_unicode(immHkl))
2411 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2412 else
2413 {
2414 LPSTR lpszaReading = strdupWtoA(lpszReading);
2415 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2416 BOOL rc;
2417
2418 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2419 (LPCWSTR)lpszaUnregister);
2420 HeapFree(GetProcessHeap(),0,lpszaReading);
2421 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2422 return rc;
2423 }
2424 }
2425 else
2426 return FALSE;
2427 }
2428
2429 /***********************************************************************
2430 * ImmGetImeMenuItemsA (IMM32.@)
2431 */
2432 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2433 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2434 DWORD dwSize)
2435 {
2436 InputContextData *data = hIMC;
2437 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2438 lpImeParentMenu, lpImeMenu, dwSize);
2439 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2440 {
2441 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2442 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2443 (IMEMENUITEMINFOW*)lpImeParentMenu,
2444 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2445 else
2446 {
2447 IMEMENUITEMINFOW lpImeParentMenuW;
2448 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2449 DWORD rc;
2450
2451 if (lpImeParentMenu)
2452 parent = &lpImeParentMenuW;
2453 if (lpImeMenu)
2454 {
2455 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2456 dwSize = count * sizeof(IMEMENUITEMINFOW);
2457 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2458 }
2459 else
2460 lpImeMenuW = NULL;
2461
2462 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2463 parent, lpImeMenuW, dwSize);
2464
2465 if (lpImeParentMenu)
2466 {
2467 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2468 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2469 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2470 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2471 NULL, NULL);
2472 }
2473 if (lpImeMenu && rc)
2474 {
2475 unsigned int i;
2476 for (i = 0; i < rc; i++)
2477 {
2478 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2479 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2480 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2481 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2482 NULL, NULL);
2483 }
2484 }
2485 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2486 return rc;
2487 }
2488 }
2489 else
2490 return 0;
2491 }
2492
2493 /***********************************************************************
2494 * ImmGetImeMenuItemsW (IMM32.@)
2495 */
2496 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2497 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2498 DWORD dwSize)
2499 {
2500 InputContextData *data = hIMC;
2501 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2502 lpImeParentMenu, lpImeMenu, dwSize);
2503 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2504 {
2505 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2506 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2507 lpImeParentMenu, lpImeMenu, dwSize);
2508 else
2509 {
2510 IMEMENUITEMINFOA lpImeParentMenuA;
2511 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2512 DWORD rc;
2513
2514 if (lpImeParentMenu)
2515 parent = &lpImeParentMenuA;
2516 if (lpImeMenu)
2517 {
2518 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2519 dwSize = count * sizeof(IMEMENUITEMINFOA);
2520 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2521 }
2522 else
2523 lpImeMenuA = NULL;
2524
2525 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2526 (IMEMENUITEMINFOW*)parent,
2527 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2528
2529 if (lpImeParentMenu)
2530 {
2531 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2532 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2533 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2534 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2535 }
2536 if (lpImeMenu && rc)
2537 {
2538 unsigned int i;
2539 for (i = 0; i < rc; i++)
2540 {
2541 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2542 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2543 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2544 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2545 }
2546 }
2547 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2548 return rc;
2549 }
2550 }
2551 else
2552 return 0;
2553 }
2554
2555 /***********************************************************************
2556 * ImmLockIMC(IMM32.@)
2557 */
2558 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2559 {
2560 InputContextData *data = hIMC;
2561
2562 if (!data)
2563 return NULL;
2564 data->dwLock++;
2565 return &data->IMC;
2566 }
2567
2568 /***********************************************************************
2569 * ImmUnlockIMC(IMM32.@)
2570 */
2571 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2572 {
2573 InputContextData *data = hIMC;
2574 data->dwLock--;
2575 return (data->dwLock!=0);
2576 }
2577
2578 /***********************************************************************
2579 * ImmGetIMCLockCount(IMM32.@)
2580 */
2581 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2582 {
2583 InputContextData *data = hIMC;
2584 return data->dwLock;
2585 }
2586
2587 /***********************************************************************
2588 * ImmCreateIMCC(IMM32.@)
2589 */
2590 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2591 {
2592 IMCCInternal *internal;
2593 int real_size = size + sizeof(IMCCInternal);
2594
2595 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2596 if (internal == NULL)
2597 return NULL;
2598
2599 internal->dwSize = size;
2600 return internal;
2601 }
2602
2603 /***********************************************************************
2604 * ImmDestroyIMCC(IMM32.@)
2605 */
2606 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2607 {
2608 HeapFree(GetProcessHeap(),0,block);
2609 return NULL;
2610 }
2611
2612 /***********************************************************************
2613 * ImmLockIMCC(IMM32.@)
2614 */
2615 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2616 {
2617 IMCCInternal *internal;
2618 internal = imcc;
2619
2620 internal->dwLock ++;
2621 return internal + 1;
2622 }
2623
2624 /***********************************************************************
2625 * ImmUnlockIMCC(IMM32.@)
2626 */
2627 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2628 {
2629 IMCCInternal *internal;
2630 internal = imcc;
2631
2632 internal->dwLock --;
2633 return (internal->dwLock!=0);
2634 }
2635
2636 /***********************************************************************
2637 * ImmGetIMCCLockCount(IMM32.@)
2638 */
2639 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2640 {
2641 IMCCInternal *internal;
2642 internal = imcc;
2643
2644 return internal->dwLock;
2645 }
2646
2647 /***********************************************************************
2648 * ImmReSizeIMCC(IMM32.@)
2649 */
2650 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2651 {
2652 IMCCInternal *internal,*newone;
2653 int real_size = size + sizeof(IMCCInternal);
2654
2655 internal = imcc;
2656
2657 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2658 newone->dwSize = size;
2659
2660 return newone;
2661 }
2662
2663 /***********************************************************************
2664 * ImmGetIMCCSize(IMM32.@)
2665 */
2666 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2667 {
2668 IMCCInternal *internal;
2669 internal = imcc;
2670
2671 return internal->dwSize;
2672 }
2673
2674 /***********************************************************************
2675 * ImmGenerateMessage(IMM32.@)
2676 */
2677 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2678 {
2679 InputContextData *data = hIMC;
2680
2681 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2682 if (data->IMC.dwNumMsgBuf > 0)
2683 {
2684 LPTRANSMSG lpTransMsg;
2685 DWORD i;
2686
2687 lpTransMsg = ImmLockIMCC(data->IMC.hMsgBuf);
2688 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2689 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2690
2691 ImmUnlockIMCC(data->IMC.hMsgBuf);
2692
2693 data->IMC.dwNumMsgBuf = 0;
2694 }
2695
2696 return TRUE;
2697 }
2698
2699 /***********************************************************************
2700 * ImmTranslateMessage(IMM32.@)
2701 * ( Undocumented, call internally and from user32.dll )
2702 */
2703 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2704 {
2705 InputContextData *data;
2706 HIMC imc = ImmGetContext(hwnd);
2707 BYTE state[256];
2708 UINT scancode;
2709 LPVOID list = 0;
2710 UINT msg_count;
2711 UINT uVirtKey;
2712 static const DWORD list_count = 10;
2713
2714 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2715
2716 if (imc)
2717 data = imc;
2718 else
2719 return FALSE;
2720
2721 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2722 return FALSE;
2723
2724 GetKeyboardState(state);
2725 scancode = lKeyData >> 0x10 & 0xff;
2726
2727 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2728 ((DWORD*)list)[0] = list_count;
2729
2730 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2731 {
2732 WCHAR chr;
2733
2734 if (!is_himc_ime_unicode(data))
2735 ToAscii(data->lastVK, scancode, state, &chr, 0);
2736 else
2737 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2738 uVirtKey = MAKELONG(data->lastVK,chr);
2739 }
2740 else
2741 uVirtKey = data->lastVK;
2742
2743 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2744 TRACE("%i messages generated\n",msg_count);
2745 if (msg_count && msg_count <= list_count)
2746 {
2747 UINT i;
2748 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2749
2750 for (i = 0; i < msg_count; i++)
2751 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2752 }
2753 else if (msg_count > list_count)
2754 ImmGenerateMessage(imc);
2755
2756 HeapFree(GetProcessHeap(),0,list);
2757
2758 data->lastVK = VK_PROCESSKEY;
2759
2760 return (msg_count > 0);
2761 }
2762
2763 /***********************************************************************
2764 * ImmProcessKey(IMM32.@)
2765 * ( Undocumented, called from user32.dll )
2766 */
2767 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2768 {
2769 InputContextData *data;
2770 HIMC imc = ImmGetContext(hwnd);
2771 BYTE state[256];
2772
2773 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2774
2775 if (imc)
2776 data = imc;
2777 else
2778 return FALSE;
2779
2780 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
2781 return FALSE;
2782
2783 GetKeyboardState(state);
2784 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
2785 {
2786 data->lastVK = vKey;
2787 return TRUE;
2788 }
2789
2790 data->lastVK = VK_PROCESSKEY;
2791 return FALSE;
2792 }
2793
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.