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