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 * ImmGetCompositionStringA (IMM32.@)
990 */
991 LONG WINAPI ImmGetCompositionStringA(
992 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
993 {
994 BOOL isString = FALSE;
995 LPBYTE buffer = NULL;
996 CHAR *buf = NULL;
997 LONG rc = 0;
998 InputContextData *data = (InputContextData*)hIMC;
999 LPCOMPOSITIONSTRING compstr;
1000 LPBYTE compdata;
1001
1002 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1003
1004 if (!data)
1005 return FALSE;
1006
1007 if (!data->IMC.hCompStr)
1008 return FALSE;
1009
1010 compdata = ImmLockIMCC(data->IMC.hCompStr);
1011 compstr = (LPCOMPOSITIONSTRING)compdata;
1012
1013 switch (dwIndex)
1014 {
1015 case GCS_RESULTSTR:
1016 if (compstr->dwResultStrLen > 0 && compstr->dwResultStrOffset > 0)
1017 {
1018 isString = TRUE;
1019 buffer = compdata + compstr->dwResultStrOffset;
1020 rc = compstr->dwResultStrLen;
1021 TRACE("GCS_RESULTSTR %p %i\n", buffer, rc);
1022 }
1023 break;
1024 case GCS_COMPSTR:
1025 if (compstr->dwCompStrLen > 0 && compstr->dwCompStrOffset > 0)
1026 {
1027 isString = TRUE;
1028 buffer = compdata + compstr->dwCompStrOffset;
1029 rc = compstr->dwCompStrLen;
1030 TRACE("GCS_COMPSTR %p %i\n", buffer, rc);
1031 }
1032 break;
1033 case GCS_COMPATTR:
1034 if (compstr->dwCompAttrLen > 0 && compstr->dwCompAttrOffset > 0)
1035 {
1036 buffer = compdata + compstr->dwCompAttrOffset;
1037 rc = compstr->dwCompAttrLen;
1038 TRACE("GCS_COMPATTR %p %i\n", buffer, rc);
1039 }
1040 break;
1041 case GCS_COMPCLAUSE:
1042 if (compstr->dwCompClauseLen > 0 && compstr->dwCompClauseOffset > 0)
1043 {
1044 buffer = compdata + compstr->dwCompClauseOffset;
1045 rc = compstr->dwCompClauseLen;
1046 TRACE("GCS_COMPCLAUSE %p %i\n", buffer, rc);
1047 }
1048 break;
1049 case GCS_RESULTCLAUSE:
1050 if (compstr->dwResultClauseLen > 0 && compstr->dwResultClauseOffset > 0)
1051 {
1052 buffer = compdata + compstr->dwResultClauseOffset;
1053 rc = compstr->dwResultClauseLen;
1054 TRACE("GCS_RESULTCLAUSE %p %i\n", buffer, rc);
1055 }
1056 break;
1057 case GCS_RESULTREADSTR:
1058 if (compstr->dwResultReadStrLen > 0 && compstr->dwResultReadStrOffset > 0)
1059 {
1060 isString = TRUE;
1061 buffer = compdata + compstr->dwResultReadStrOffset;
1062 rc = compstr->dwResultReadStrLen;
1063 TRACE("GCS_RESULTREADSTR %p %i\n",buffer, rc);
1064 }
1065 break;
1066 case GCS_RESULTREADCLAUSE:
1067 if (compstr->dwResultReadClauseLen > 0 && compstr->dwResultReadClauseOffset > 0)
1068 {
1069 buffer = compdata + compstr->dwResultReadClauseOffset;
1070 rc = compstr->dwResultReadClauseLen;
1071 TRACE("GCS_RESULTREADCLAUSE %p %i\n", buffer, rc);
1072 }
1073 break;
1074 case GCS_COMPREADSTR:
1075 if (compstr->dwCompReadStrLen > 0 && compstr->dwCompReadStrOffset > 0)
1076 {
1077 isString = TRUE;
1078 buffer = compdata + compstr->dwCompReadStrOffset;
1079 rc = compstr->dwCompReadStrLen;
1080 TRACE("GCS_COMPREADSTR %p %i\n", buffer, rc);
1081 }
1082 break;
1083 case GCS_COMPREADATTR:
1084 if (compstr->dwCompReadAttrLen > 0 && compstr->dwCompReadAttrOffset > 0)
1085 {
1086 buffer = compdata + compstr->dwCompReadAttrOffset;
1087 rc = compstr->dwCompReadAttrLen;
1088 TRACE("GCS_COMPREADATTR %p %i\n", buffer, rc);
1089 }
1090 break;
1091 case GCS_COMPREADCLAUSE:
1092 if (compstr->dwCompReadClauseLen > 0 && compstr->dwCompReadClauseOffset > 0)
1093 {
1094 buffer = compdata + compstr->dwCompReadClauseOffset;
1095 rc = compstr->dwCompReadClauseLen;
1096 TRACE("GCS_COMPREADCLAUSE %p %i\n", buffer, rc);
1097 }
1098 break;
1099 case GCS_CURSORPOS:
1100 TRACE("GCS_CURSORPOS\n");
1101 rc = compstr->dwCursorPos;
1102 break;
1103 case GCS_DELTASTART:
1104 TRACE("GCS_DELTASTART\n");
1105 rc = compstr->dwDeltaStart;
1106 break;
1107 default:
1108 FIXME("Unhandled index 0x%x\n",dwIndex);
1109 break;
1110 }
1111
1112 if ( isString && buffer && is_himc_ime_unicode(data))
1113 {
1114 INT len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)buffer, rc, NULL, 0, NULL, NULL);
1115 buf = HeapAlloc( GetProcessHeap(), 0, len );
1116 if ( buf )
1117 rc = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)buffer, rc, buf, len, NULL, NULL);
1118 buffer = (LPBYTE)buf;
1119 }
1120
1121 if ( lpBuf && buffer && dwBufLen >= rc)
1122 memcpy(lpBuf, buffer, rc);
1123
1124 HeapFree( GetProcessHeap(), 0, buf );
1125 ImmUnlockIMCC(data->IMC.hCompStr);
1126
1127 return rc;
1128 }
1129
1130 /***********************************************************************
1131 * ImmGetCompositionStringW (IMM32.@)
1132 */
1133 LONG WINAPI ImmGetCompositionStringW(
1134 HIMC hIMC, DWORD dwIndex,
1135 LPVOID lpBuf, DWORD dwBufLen)
1136 {
1137 BOOL isString = FALSE;
1138 LPBYTE buffer = NULL;
1139 WCHAR *buf = NULL;
1140 LONG rc = 0;
1141 InputContextData *data = (InputContextData*)hIMC;
1142 LPCOMPOSITIONSTRING compstr;
1143 LPBYTE compdata;
1144
1145 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1146
1147 if (!data)
1148 return FALSE;
1149
1150 if (!data->IMC.hCompStr)
1151 return FALSE;
1152
1153 compdata = ImmLockIMCC(data->IMC.hCompStr);
1154 compstr = (LPCOMPOSITIONSTRING)compdata;
1155
1156 switch (dwIndex)
1157 {
1158 case GCS_RESULTSTR:
1159 if (compstr->dwResultStrLen > 0 && compstr->dwResultStrOffset > 0)
1160 {
1161 isString = TRUE;
1162 buffer = compdata + compstr->dwResultStrOffset;
1163 rc = compstr->dwResultStrLen;
1164 TRACE("GCS_RESULTSTR %p %i\n", buffer, rc);
1165 }
1166 break;
1167 case GCS_RESULTREADSTR:
1168 if (compstr->dwResultReadStrLen > 0 && compstr->dwResultReadStrOffset > 0)
1169 {
1170 isString = TRUE;
1171 buffer = compdata + compstr->dwResultReadStrOffset;
1172 rc = compstr->dwResultReadStrLen;
1173 TRACE("GCS_RESULTREADSTR %p %i\n",buffer, rc);
1174 }
1175 break;
1176 case GCS_COMPSTR:
1177 if (compstr->dwCompStrLen > 0 && compstr->dwCompStrOffset > 0)
1178 {
1179 isString = TRUE;
1180 buffer = compdata + compstr->dwCompStrOffset;
1181 rc = compstr->dwCompStrLen;
1182 TRACE("GCS_COMPSTR %p %i\n", buffer, rc);
1183 }
1184 break;
1185 case GCS_COMPATTR:
1186 if (compstr->dwCompAttrLen > 0 && compstr->dwCompAttrOffset > 0)
1187 {
1188 buffer = compdata + compstr->dwCompAttrOffset;
1189 rc = compstr->dwCompAttrLen;
1190 TRACE("GCS_COMPATTR %p %i\n", buffer, rc);
1191 }
1192 break;
1193 case GCS_COMPCLAUSE:
1194 if (compstr->dwCompClauseLen > 0 && compstr->dwCompClauseOffset > 0)
1195 {
1196 buffer = compdata + compstr->dwCompClauseOffset;
1197 rc = compstr->dwCompClauseLen;
1198 TRACE("GCS_COMPCLAUSE %p %i\n", buffer, rc);
1199 }
1200 break;
1201 case GCS_COMPREADSTR:
1202 if (compstr->dwCompReadStrLen > 0 && compstr->dwCompReadStrOffset > 0)
1203 {
1204 isString = TRUE;
1205 buffer = compdata + compstr->dwCompReadStrOffset;
1206 rc = compstr->dwCompReadStrLen;
1207 TRACE("GCS_COMPREADSTR %p %i\n", buffer, rc);
1208 }
1209 break;
1210 case GCS_COMPREADATTR:
1211 if (compstr->dwCompReadAttrLen > 0 && compstr->dwCompReadAttrOffset > 0)
1212 {
1213 buffer = compdata + compstr->dwCompReadAttrOffset;
1214 rc = compstr->dwCompReadAttrLen;
1215 TRACE("GCS_COMPREADATTR %p %i\n", buffer, rc);
1216 }
1217 break;
1218 case GCS_COMPREADCLAUSE:
1219 if (compstr->dwCompReadClauseLen > 0 && compstr->dwCompReadClauseOffset > 0)
1220 {
1221 buffer = compdata + compstr->dwCompReadClauseOffset;
1222 rc = compstr->dwCompReadClauseLen;
1223 TRACE("GCS_COMPREADCLAUSE %p %i\n", buffer, rc);
1224 }
1225 break;
1226 case GCS_RESULTREADCLAUSE:
1227 if (compstr->dwResultReadClauseLen > 0 && compstr->dwResultReadClauseOffset > 0)
1228 {
1229 buffer = compdata + compstr->dwResultReadClauseOffset;
1230 rc = compstr->dwResultReadClauseLen;
1231 TRACE("GCS_RESULTREADCLAUSE %p %i\n", buffer, rc);
1232 }
1233 break;
1234 case GCS_RESULTCLAUSE:
1235 if (compstr->dwResultClauseLen > 0 && compstr->dwResultClauseOffset > 0)
1236 {
1237 buffer = compdata + compstr->dwResultClauseOffset;
1238 rc = compstr->dwResultClauseLen;
1239 TRACE("GCS_RESULTCLAUSE %p %i\n", buffer, rc);
1240 }
1241 break;
1242 case GCS_CURSORPOS:
1243 TRACE("GCS_CURSORPOS\n");
1244 rc = compstr->dwCursorPos;
1245 break;
1246 case GCS_DELTASTART:
1247 TRACE("GCS_DELTASTART\n");
1248 rc = compstr->dwDeltaStart;
1249 break;
1250 default:
1251 FIXME("Unhandled index 0x%x\n",dwIndex);
1252 break;
1253 }
1254
1255 if ( isString && buffer )
1256 {
1257 if ( !is_himc_ime_unicode(data) )
1258 {
1259 INT len = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)buffer, rc, NULL, 0 );
1260 buf = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
1261 if ( buf )
1262 rc = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)buffer, rc, buf, len );
1263 buffer = (LPBYTE)buf;
1264 }
1265 rc *= sizeof(WCHAR);
1266 }
1267
1268 if ( lpBuf && buffer && dwBufLen >= rc )
1269 memcpy( lpBuf, buffer, rc );
1270
1271 HeapFree( GetProcessHeap(), 0, buf );
1272 ImmUnlockIMCC(data->IMC.hCompStr);
1273
1274 return rc;
1275 }
1276
1277 /***********************************************************************
1278 * ImmGetCompositionWindow (IMM32.@)
1279 */
1280 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1281 {
1282 InputContextData *data = (InputContextData*)hIMC;
1283
1284 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1285
1286 if (!data)
1287 return FALSE;
1288
1289 *lpCompForm = data->IMC.cfCompForm;
1290 return 1;
1291 }
1292
1293 /***********************************************************************
1294 * ImmGetContext (IMM32.@)
1295 *
1296 */
1297 HIMC WINAPI ImmGetContext(HWND hWnd)
1298 {
1299 HIMC rc = NULL;
1300
1301 TRACE("%p\n", hWnd);
1302 if (!IMM_GetThreadData()->defaultContext)
1303 IMM_GetThreadData()->defaultContext = ImmCreateContext();
1304
1305 rc = (HIMC)GetPropW(hWnd,szwWineIMCProperty);
1306 if (rc == (HIMC)-1)
1307 rc = NULL;
1308 else if (rc == NULL)
1309 rc = IMM_GetThreadData()->defaultContext;
1310
1311 if (rc)
1312 {
1313 InputContextData *data = (InputContextData*)rc;
1314 data->IMC.hWnd = hWnd;
1315 }
1316 TRACE("returning %p\n", rc);
1317
1318 return rc;
1319 }
1320
1321 /***********************************************************************
1322 * ImmGetConversionListA (IMM32.@)
1323 */
1324 DWORD WINAPI ImmGetConversionListA(
1325 HKL hKL, HIMC hIMC,
1326 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1327 DWORD dwBufLen, UINT uFlag)
1328 {
1329 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1330 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1331 dwBufLen, uFlag);
1332 if (immHkl->hIME && immHkl->pImeConversionList)
1333 {
1334 if (!is_kbd_ime_unicode(immHkl))
1335 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1336 else
1337 {
1338 LPCANDIDATELIST lpwDst;
1339 DWORD ret = 0, len;
1340 LPWSTR pwSrc = strdupAtoW(pSrc);
1341
1342 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1343 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1344 if ( lpwDst )
1345 {
1346 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1347 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1348 HeapFree(GetProcessHeap(), 0, lpwDst);
1349 }
1350 HeapFree(GetProcessHeap(), 0, pwSrc);
1351
1352 return ret;
1353 }
1354 }
1355 else
1356 return 0;
1357 }
1358
1359 /***********************************************************************
1360 * ImmGetConversionListW (IMM32.@)
1361 */
1362 DWORD WINAPI ImmGetConversionListW(
1363 HKL hKL, HIMC hIMC,
1364 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1365 DWORD dwBufLen, UINT uFlag)
1366 {
1367 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1368 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1369 dwBufLen, uFlag);
1370 if (immHkl->hIME && immHkl->pImeConversionList)
1371 {
1372 if (is_kbd_ime_unicode(immHkl))
1373 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1374 else
1375 {
1376 LPCANDIDATELIST lpaDst;
1377 DWORD ret = 0, len;
1378 LPSTR paSrc = strdupWtoA(pSrc);
1379
1380 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1381 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1382 if ( lpaDst )
1383 {
1384 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1385 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1386 HeapFree(GetProcessHeap(), 0, lpaDst);
1387 }
1388 HeapFree(GetProcessHeap(), 0, paSrc);
1389
1390 return ret;
1391 }
1392 }
1393 else
1394 return 0;
1395 }
1396
1397 /***********************************************************************
1398 * ImmGetConversionStatus (IMM32.@)
1399 */
1400 BOOL WINAPI ImmGetConversionStatus(
1401 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1402 {
1403 InputContextData *data = (InputContextData*)hIMC;
1404
1405 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1406
1407 if (!data)
1408 return FALSE;
1409
1410 if (lpfdwConversion)
1411 *lpfdwConversion = data->IMC.fdwConversion;
1412 if (lpfdwSentence)
1413 *lpfdwSentence = data->IMC.fdwSentence;
1414
1415 return TRUE;
1416 }
1417
1418 /***********************************************************************
1419 * ImmGetDefaultIMEWnd (IMM32.@)
1420 */
1421 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1422 {
1423 TRACE("Default is %x\n",(unsigned)IMM_GetThreadData()->hwndDefault);
1424 return IMM_GetThreadData()->hwndDefault;
1425 }
1426
1427 /***********************************************************************
1428 * ImmGetDescriptionA (IMM32.@)
1429 */
1430 UINT WINAPI ImmGetDescriptionA(
1431 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1432 {
1433 WCHAR *buf;
1434 DWORD len;
1435
1436 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1437
1438 /* find out how many characters in the unicode buffer */
1439 len = ImmGetDescriptionW( hKL, NULL, 0 );
1440
1441 /* allocate a buffer of that size */
1442 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1443 if( !buf )
1444 return 0;
1445
1446 /* fetch the unicode buffer */
1447 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1448
1449 /* convert it back to ASCII */
1450 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1451 lpszDescription, uBufLen, NULL, NULL );
1452
1453 HeapFree( GetProcessHeap(), 0, buf );
1454
1455 return len;
1456 }
1457
1458 /***********************************************************************
1459 * ImmGetDescriptionW (IMM32.@)
1460 */
1461 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1462 {
1463 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1464
1465 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1466
1467 if (!uBufLen) return lstrlenW( name );
1468 lstrcpynW( lpszDescription, name, uBufLen );
1469 return lstrlenW( lpszDescription );
1470 }
1471
1472 /***********************************************************************
1473 * ImmGetGuideLineA (IMM32.@)
1474 */
1475 DWORD WINAPI ImmGetGuideLineA(
1476 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1477 {
1478 FIXME("(%p, %d, %s, %d): stub\n",
1479 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1480 );
1481 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1482 return 0;
1483 }
1484
1485 /***********************************************************************
1486 * ImmGetGuideLineW (IMM32.@)
1487 */
1488 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1489 {
1490 FIXME("(%p, %d, %s, %d): stub\n",
1491 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1492 );
1493 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1494 return 0;
1495 }
1496
1497 /***********************************************************************
1498 * ImmGetIMEFileNameA (IMM32.@)
1499 */
1500 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1501 {
1502 LPWSTR bufW = NULL;
1503 UINT wBufLen = uBufLen;
1504 UINT rc;
1505
1506 if (uBufLen && lpszFileName)
1507 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1508 else /* We need this to get the number of byte required */
1509 {
1510 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1511 wBufLen = MAX_PATH;
1512 }
1513
1514 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1515
1516 if (rc > 0)
1517 {
1518 if (uBufLen && lpszFileName)
1519 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1520 uBufLen, NULL, NULL);
1521 else /* get the length */
1522 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1523 NULL);
1524 }
1525
1526 HeapFree(GetProcessHeap(),0,bufW);
1527 return rc;
1528 }
1529
1530 /***********************************************************************
1531 * ImmGetIMEFileNameW (IMM32.@)
1532 */
1533 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1534 {
1535 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
1536 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};
1537
1538 HKEY hkey;
1539 DWORD length;
1540 DWORD rc;
1541 WCHAR regKey[sizeof(fmt)/sizeof(WCHAR)+8];
1542
1543 wsprintfW( regKey, fmt, (unsigned)hKL );
1544 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1545 if (rc != ERROR_SUCCESS)
1546 {
1547 SetLastError(rc);
1548 return 0;
1549 }
1550
1551 length = 0;
1552 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1553
1554 if (rc != ERROR_SUCCESS)
1555 {
1556 RegCloseKey(hkey);
1557 SetLastError(rc);
1558 return 0;
1559 }
1560 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1561 {
1562 RegCloseKey(hkey);
1563 if (lpszFileName)
1564 {
1565 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1566 return 0;
1567 }
1568 else
1569 return length / sizeof(WCHAR);
1570 }
1571
1572 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1573
1574 RegCloseKey(hkey);
1575
1576 return length / sizeof(WCHAR);
1577 }
1578
1579 /***********************************************************************
1580 * ImmGetOpenStatus (IMM32.@)
1581 */
1582 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1583 {
1584 InputContextData *data = (InputContextData*)hIMC;
1585
1586 if (!data)
1587 return FALSE;
1588 FIXME("(%p): semi-stub\n", hIMC);
1589
1590 return data->IMC.fOpen;
1591 }
1592
1593 /***********************************************************************
1594 * ImmGetProperty (IMM32.@)
1595 */
1596 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1597 {
1598 DWORD rc = 0;
1599 ImmHkl *kbd;
1600
1601 TRACE("(%p, %d)\n", hKL, fdwIndex);
1602 kbd = IMM_GetImmHkl(hKL);
1603
1604 if (kbd && kbd->hIME)
1605 {
1606 switch (fdwIndex)
1607 {
1608 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1609 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1610 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1611 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1612 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1613 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1614 case IGP_UI: rc = 0; break;
1615 default: rc = 0;
1616 }
1617 }
1618 return rc;
1619 }
1620
1621 /***********************************************************************
1622 * ImmGetRegisterWordStyleA (IMM32.@)
1623 */
1624 UINT WINAPI ImmGetRegisterWordStyleA(
1625 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1626 {
1627 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1628 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1629 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1630 {
1631 if (!is_kbd_ime_unicode(immHkl))
1632 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1633 else
1634 {
1635 STYLEBUFW sbw;
1636 UINT rc;
1637
1638 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1639 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1640 lpStyleBuf->szDescription, 32, NULL, NULL);
1641 lpStyleBuf->dwStyle = sbw.dwStyle;
1642 return rc;
1643 }
1644 }
1645 else
1646 return 0;
1647 }
1648
1649 /***********************************************************************
1650 * ImmGetRegisterWordStyleW (IMM32.@)
1651 */
1652 UINT WINAPI ImmGetRegisterWordStyleW(
1653 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1654 {
1655 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1656 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1657 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1658 {
1659 if (is_kbd_ime_unicode(immHkl))
1660 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1661 else
1662 {
1663 STYLEBUFA sba;
1664 UINT rc;
1665
1666 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1667 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1668 lpStyleBuf->szDescription, 32);
1669 lpStyleBuf->dwStyle = sba.dwStyle;
1670 return rc;
1671 }
1672 }
1673 else
1674 return 0;
1675 }
1676
1677 /***********************************************************************
1678 * ImmGetStatusWindowPos (IMM32.@)
1679 */
1680 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1681 {
1682 InputContextData *data = (InputContextData*)hIMC;
1683
1684 TRACE("(%p, %p)\n", hIMC, lpptPos);
1685
1686 if (!data || !lpptPos)
1687 return FALSE;
1688
1689 *lpptPos = data->IMC.ptStatusWndPos;
1690
1691 return TRUE;
1692 }
1693
1694 /***********************************************************************
1695 * ImmGetVirtualKey (IMM32.@)
1696 */
1697 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1698 {
1699 OSVERSIONINFOA version;
1700 InputContextData *data = (InputContextData *)ImmGetContext( hWnd );
1701 TRACE("%p\n", hWnd);
1702
1703 if ( data )
1704 return data->lastVK;
1705
1706 GetVersionExA( &version );
1707 switch(version.dwPlatformId)
1708 {
1709 case VER_PLATFORM_WIN32_WINDOWS:
1710 return VK_PROCESSKEY;
1711 case VER_PLATFORM_WIN32_NT:
1712 return 0;
1713 default:
1714 FIXME("%d not supported\n",version.dwPlatformId);
1715 return VK_PROCESSKEY;
1716 }
1717 }
1718
1719 /***********************************************************************
1720 * ImmInstallIMEA (IMM32.@)
1721 */
1722 HKL WINAPI ImmInstallIMEA(
1723 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1724 {
1725 FIXME("(%s, %s): stub\n",
1726 debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText)
1727 );
1728 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1729 return NULL;
1730 }
1731
1732 /***********************************************************************
1733 * ImmInstallIMEW (IMM32.@)
1734 */
1735 HKL WINAPI ImmInstallIMEW(
1736 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1737 {
1738 FIXME("(%s, %s): stub\n",
1739 debugstr_w(lpszIMEFileName), debugstr_w(lpszLayoutText)
1740 );
1741 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1742 return NULL;
1743 }
1744
1745 /***********************************************************************
1746 * ImmIsIME (IMM32.@)
1747 */
1748 BOOL WINAPI ImmIsIME(HKL hKL)
1749 {
1750 ImmHkl *ptr;
1751 TRACE("(%p):\n", hKL);
1752 ptr = IMM_GetImmHkl(hKL);
1753 return (ptr && ptr->hIME);
1754 }
1755
1756 /***********************************************************************
1757 * ImmIsUIMessageA (IMM32.@)
1758 */
1759 BOOL WINAPI ImmIsUIMessageA(
1760 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1761 {
1762 BOOL rc = FALSE;
1763
1764 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1765 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1766 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1767 (msg == WM_MSIME_SERVICE) ||
1768 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1769 (msg == WM_MSIME_MOUSE) ||
1770 (msg == WM_MSIME_RECONVERTREQUEST) ||
1771 (msg == WM_MSIME_RECONVERT) ||
1772 (msg == WM_MSIME_QUERYPOSITION) ||
1773 (msg == WM_MSIME_DOCUMENTFEED))
1774
1775 {
1776 if (!IMM_GetThreadData()->hwndDefault)
1777 ImmGetDefaultIMEWnd(NULL);
1778
1779 if (hWndIME == NULL)
1780 PostMessageA(IMM_GetThreadData()->hwndDefault, msg, wParam, lParam);
1781
1782 rc = TRUE;
1783 }
1784 return rc;
1785 }
1786
1787 /***********************************************************************
1788 * ImmIsUIMessageW (IMM32.@)
1789 */
1790 BOOL WINAPI ImmIsUIMessageW(
1791 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1792 {
1793 BOOL rc = FALSE;
1794 TRACE("(%p, %d, %ld, %ld):\n", hWndIME, msg, wParam, lParam);
1795 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1796 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1797 (msg == WM_MSIME_SERVICE) ||
1798 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1799 (msg == WM_MSIME_MOUSE) ||
1800 (msg == WM_MSIME_RECONVERTREQUEST) ||
1801 (msg == WM_MSIME_RECONVERT) ||
1802 (msg == WM_MSIME_QUERYPOSITION) ||
1803 (msg == WM_MSIME_DOCUMENTFEED))
1804 rc = TRUE;
1805 return rc;
1806 }
1807
1808 /***********************************************************************
1809 * ImmNotifyIME (IMM32.@)
1810 */
1811 BOOL WINAPI ImmNotifyIME(
1812 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1813 {
1814 InputContextData *data = (InputContextData*)hIMC;
1815
1816 TRACE("(%p, %d, %d, %d)\n",
1817 hIMC, dwAction, dwIndex, dwValue);
1818
1819 if (!data || ! data->immKbd->pNotifyIME)
1820 return FALSE;
1821
1822 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
1823 }
1824
1825 /***********************************************************************
1826 * ImmRegisterWordA (IMM32.@)
1827 */
1828 BOOL WINAPI ImmRegisterWordA(
1829 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1830 {
1831 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1832 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
1833 debugstr_a(lpszRegister));
1834 if (immHkl->hIME && immHkl->pImeRegisterWord)
1835 {
1836 if (!is_kbd_ime_unicode(immHkl))
1837 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
1838 (LPCWSTR)lpszRegister);
1839 else
1840 {
1841 LPWSTR lpszwReading = strdupAtoW(lpszReading);
1842 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
1843 BOOL rc;
1844
1845 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
1846 HeapFree(GetProcessHeap(),0,lpszwReading);
1847 HeapFree(GetProcessHeap(),0,lpszwRegister);
1848 return rc;
1849 }
1850 }
1851 else
1852 return FALSE;
1853 }
1854
1855 /***********************************************************************
1856 * ImmRegisterWordW (IMM32.@)
1857 */
1858 BOOL WINAPI ImmRegisterWordW(
1859 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1860 {
1861 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1862 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
1863 debugstr_w(lpszRegister));
1864 if (immHkl->hIME && immHkl->pImeRegisterWord)
1865 {
1866 if (is_kbd_ime_unicode(immHkl))
1867 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
1868 else
1869 {
1870 LPSTR lpszaReading = strdupWtoA(lpszReading);
1871 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
1872 BOOL rc;
1873
1874 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
1875 (LPCWSTR)lpszaRegister);
1876 HeapFree(GetProcessHeap(),0,lpszaReading);
1877 HeapFree(GetProcessHeap(),0,lpszaRegister);
1878 return rc;
1879 }
1880 }
1881 else
1882 return FALSE;
1883 }
1884
1885 /***********************************************************************
1886 * ImmReleaseContext (IMM32.@)
1887 */
1888 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
1889 {
1890 static int shown = 0;
1891
1892 if (!shown) {
1893 FIXME("(%p, %p): stub\n", hWnd, hIMC);
1894 shown = 1;
1895 }
1896 return TRUE;
1897 }
1898
1899 /***********************************************************************
1900 * ImmRequestMessageA(IMM32.@)
1901 */
1902 LRESULT WINAPI ImmRequestMessageA(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 SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
1910
1911 return 0;
1912 }
1913
1914 /***********************************************************************
1915 * ImmRequestMessageW(IMM32.@)
1916 */
1917 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
1918 {
1919 InputContextData *data = (InputContextData*)hIMC;
1920
1921 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
1922
1923 if (data && IsWindow(data->IMC.hWnd))
1924 return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
1925
1926 return 0;
1927 }
1928
1929 /***********************************************************************
1930 * ImmSetCandidateWindow (IMM32.@)
1931 */
1932 BOOL WINAPI ImmSetCandidateWindow(
1933 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
1934 {
1935 InputContextData *data = (InputContextData*)hIMC;
1936
1937 TRACE("(%p, %p)\n", hIMC, lpCandidate);
1938
1939 if (!data || !lpCandidate)
1940 return FALSE;
1941
1942 TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
1943 lpCandidate->dwIndex, lpCandidate->dwStyle,
1944 lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
1945 lpCandidate->rcArea.top, lpCandidate->rcArea.left,
1946 lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
1947
1948 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1949 return FALSE;
1950
1951 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
1952 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
1953 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
1954
1955 return TRUE;
1956 }
1957
1958 /***********************************************************************
1959 * ImmSetCompositionFontA (IMM32.@)
1960 */
1961 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1962 {
1963 InputContextData *data = (InputContextData*)hIMC;
1964 TRACE("(%p, %p)\n", hIMC, lplf);
1965
1966 if (!data || !lplf)
1967 return FALSE;
1968
1969 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
1970 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
1971 LF_FACESIZE);
1972 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
1973 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1974
1975 return TRUE;
1976 }
1977
1978 /***********************************************************************
1979 * ImmSetCompositionFontW (IMM32.@)
1980 */
1981 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1982 {
1983 InputContextData *data = (InputContextData*)hIMC;
1984 TRACE("(%p, %p)\n", hIMC, lplf);
1985
1986 if (!data || !lplf)
1987 return FALSE;
1988
1989 data->IMC.lfFont.W = *lplf;
1990 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
1991 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
1992
1993 return TRUE;
1994 }
1995
1996 /***********************************************************************
1997 * ImmSetCompositionStringA (IMM32.@)
1998 */
1999 BOOL WINAPI ImmSetCompositionStringA(
2000 HIMC hIMC, DWORD dwIndex,
2001 LPCVOID lpComp, DWORD dwCompLen,
2002 LPCVOID lpRead, DWORD dwReadLen)
2003 {
2004 DWORD comp_len;
2005 DWORD read_len;
2006 WCHAR *CompBuffer = NULL;
2007 WCHAR *ReadBuffer = NULL;
2008 BOOL rc;
2009 InputContextData *data = (InputContextData*)hIMC;
2010
2011 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2012 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2013
2014 if (!data)
2015 return FALSE;
2016
2017 if (!is_himc_ime_unicode(data))
2018 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2019 dwCompLen, lpRead, dwReadLen);
2020
2021 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2022 if (comp_len)
2023 {
2024 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2025 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2026 }
2027
2028 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2029 if (read_len)
2030 {
2031 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2032 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2033 }
2034
2035 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2036 ReadBuffer, read_len);
2037
2038 HeapFree(GetProcessHeap(), 0, CompBuffer);
2039 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2040
2041 return rc;
2042 }
2043
2044 /***********************************************************************
2045 * ImmSetCompositionStringW (IMM32.@)
2046 */
2047 BOOL WINAPI ImmSetCompositionStringW(
2048 HIMC hIMC, DWORD dwIndex,
2049 LPCVOID lpComp, DWORD dwCompLen,
2050 LPCVOID lpRead, DWORD dwReadLen)
2051 {
2052 DWORD comp_len;
2053 DWORD read_len;
2054 CHAR *CompBuffer = NULL;
2055 CHAR *ReadBuffer = NULL;
2056 BOOL rc;
2057 InputContextData *data = (InputContextData*)hIMC;
2058
2059 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2060 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2061
2062 if (!data)
2063 return FALSE;
2064
2065 if (is_himc_ime_unicode(data))
2066 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2067 dwCompLen, lpRead, dwReadLen);
2068
2069 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2070 NULL);
2071 if (comp_len)
2072 {
2073 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2074 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2075 NULL, NULL);
2076 }
2077
2078 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2079 NULL);
2080 if (read_len)
2081 {
2082 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2083 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2084 NULL, NULL);
2085 }
2086
2087 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2088 ReadBuffer, read_len);
2089
2090 HeapFree(GetProcessHeap(), 0, CompBuffer);
2091 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2092
2093 return rc;
2094 }
2095
2096 /***********************************************************************
2097 * ImmSetCompositionWindow (IMM32.@)
2098 */
2099 BOOL WINAPI ImmSetCompositionWindow(
2100 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2101 {
2102 BOOL reshow = FALSE;
2103 InputContextData *data = (InputContextData*)hIMC;
2104
2105 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2106 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2107 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2108 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2109
2110 if (!data)
2111 return FALSE;
2112
2113 data->IMC.cfCompForm = *lpCompForm;
2114
2115 if (IsWindowVisible(IMM_GetThreadData()->hwndDefault))
2116 {
2117 reshow = TRUE;
2118 ShowWindow(IMM_GetThreadData()->hwndDefault,SW_HIDE);
2119 }
2120
2121 /* FIXME: this is a partial stub */
2122
2123 if (reshow)
2124 ShowWindow(IMM_GetThreadData()->hwndDefault,SW_SHOWNOACTIVATE);
2125
2126 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2127 return TRUE;
2128 }
2129
2130 /***********************************************************************
2131 * ImmSetConversionStatus (IMM32.@)
2132 */
2133 BOOL WINAPI ImmSetConversionStatus(
2134 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2135 {
2136 DWORD oldConversion, oldSentence;
2137 InputContextData *data = (InputContextData*)hIMC;
2138
2139 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2140
2141 if (!data)
2142 return FALSE;
2143
2144 if ( fdwConversion != data->IMC.fdwConversion )
2145 {
2146 oldConversion = data->IMC.fdwConversion;
2147 data->IMC.fdwConversion = fdwConversion;
2148 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2149 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2150 }
2151 if ( fdwSentence != data->IMC.fdwSentence )
2152 {
2153 oldSentence = data->IMC.fdwSentence;
2154 data->IMC.fdwSentence = fdwSentence;
2155 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2156 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2157 }
2158
2159 return TRUE;
2160 }
2161
2162 /***********************************************************************
2163 * ImmSetOpenStatus (IMM32.@)
2164 */
2165 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2166 {
2167 InputContextData *data = (InputContextData*)hIMC;
2168
2169 TRACE("%p %d\n", hIMC, fOpen);
2170
2171 if (!data)
2172 return FALSE;
2173
2174 if (data->imeWnd == NULL)
2175 {
2176 /* create the ime window */
2177 data->imeWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2178 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2179 0, data->immKbd->hIME, 0);
2180 SetWindowLongW(data->imeWnd, IMMGWL_IMC, (LONG)data);
2181 IMM_GetThreadData()->hwndDefault = data->imeWnd;
2182 }
2183
2184 if (!fOpen != !data->IMC.fOpen)
2185 {
2186 data->IMC.fOpen = fOpen;
2187 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2188 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2189 }
2190
2191 return TRUE;
2192 }
2193
2194 /***********************************************************************
2195 * ImmSetStatusWindowPos (IMM32.@)
2196 */
2197 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2198 {
2199 InputContextData *data = (InputContextData*)hIMC;
2200
2201 TRACE("(%p, %p)\n", hIMC, lpptPos);
2202
2203 if (!data || !lpptPos)
2204 return FALSE;
2205
2206 TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2207
2208 data->IMC.ptStatusWndPos = *lpptPos;
2209 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2210 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2211
2212 return TRUE;
2213 }
2214
2215 /***********************************************************************
2216 * ImmCreateSoftKeyboard(IMM32.@)
2217 */
2218 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2219 {
2220 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2221 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2222 return 0;
2223 }
2224
2225 /***********************************************************************
2226 * ImmDestroySoftKeyboard(IMM32.@)
2227 */
2228 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2229 {
2230 FIXME("(%p): stub\n", hSoftWnd);
2231 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2232 return FALSE;
2233 }
2234
2235 /***********************************************************************
2236 * ImmShowSoftKeyboard(IMM32.@)
2237 */
2238 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2239 {
2240 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2241 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2242 return FALSE;
2243 }
2244
2245 /***********************************************************************
2246 * ImmSimulateHotKey (IMM32.@)
2247 */
2248 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2249 {
2250 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2251 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2252 return FALSE;
2253 }
2254
2255 /***********************************************************************
2256 * ImmUnregisterWordA (IMM32.@)
2257 */
2258 BOOL WINAPI ImmUnregisterWordA(
2259 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2260 {
2261 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2262 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2263 debugstr_a(lpszUnregister));
2264 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2265 {
2266 if (!is_kbd_ime_unicode(immHkl))
2267 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2268 (LPCWSTR)lpszUnregister);
2269 else
2270 {
2271 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2272 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2273 BOOL rc;
2274
2275 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2276 HeapFree(GetProcessHeap(),0,lpszwReading);
2277 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2278 return rc;
2279 }
2280 }
2281 else
2282 return FALSE;
2283 }
2284
2285 /***********************************************************************
2286 * ImmUnregisterWordW (IMM32.@)
2287 */
2288 BOOL WINAPI ImmUnregisterWordW(
2289 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2290 {
2291 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2292 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2293 debugstr_w(lpszUnregister));
2294 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2295 {
2296 if (is_kbd_ime_unicode(immHkl))
2297 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2298 else
2299 {
2300 LPSTR lpszaReading = strdupWtoA(lpszReading);
2301 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2302 BOOL rc;
2303
2304 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2305 (LPCWSTR)lpszaUnregister);
2306 HeapFree(GetProcessHeap(),0,lpszaReading);
2307 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2308 return rc;
2309 }
2310 }
2311 else
2312 return FALSE;
2313 }
2314
2315 /***********************************************************************
2316 * ImmGetImeMenuItemsA (IMM32.@)
2317 */
2318 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2319 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2320 DWORD dwSize)
2321 {
2322 InputContextData *data = (InputContextData*)hIMC;
2323 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2324 lpImeParentMenu, lpImeMenu, dwSize);
2325 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2326 {
2327 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2328 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2329 (IMEMENUITEMINFOW*)lpImeParentMenu,
2330 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2331 else
2332 {
2333 IMEMENUITEMINFOW lpImeParentMenuW;
2334 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2335 DWORD rc;
2336
2337 if (lpImeParentMenu)
2338 parent = &lpImeParentMenuW;
2339 if (lpImeMenu)
2340 {
2341 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2342 dwSize = count * sizeof(IMEMENUITEMINFOW);
2343 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2344 }
2345 else
2346 lpImeMenuW = NULL;
2347
2348 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2349 parent, lpImeMenuW, dwSize);
2350
2351 if (lpImeParentMenu)
2352 {
2353 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2354 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2355 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2356 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2357 NULL, NULL);
2358 }
2359 if (lpImeMenu && rc)
2360 {
2361 int i;
2362 for (i = 0; i < rc; i++)
2363 {
2364 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2365 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2366 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2367 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2368 NULL, NULL);
2369 }
2370 }
2371 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2372 return rc;
2373 }
2374 }
2375 else
2376 return 0;
2377 }
2378
2379 /***********************************************************************
2380 * ImmGetImeMenuItemsW (IMM32.@)
2381 */
2382 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2383 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2384 DWORD dwSize)
2385 {
2386 InputContextData *data = (InputContextData*)hIMC;
2387 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2388 lpImeParentMenu, lpImeMenu, dwSize);
2389 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2390 {
2391 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2392 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2393 lpImeParentMenu, lpImeMenu, dwSize);
2394 else
2395 {
2396 IMEMENUITEMINFOA lpImeParentMenuA;
2397 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2398 DWORD rc;
2399
2400 if (lpImeParentMenu)
2401 parent = &lpImeParentMenuA;
2402 if (lpImeMenu)
2403 {
2404 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2405 dwSize = count * sizeof(IMEMENUITEMINFOA);
2406 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2407 }
2408 else
2409 lpImeMenuA = NULL;
2410
2411 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2412 (IMEMENUITEMINFOW*)parent,
2413 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2414
2415 if (lpImeParentMenu)
2416 {
2417 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2418 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2419 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2420 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2421 }
2422 if (lpImeMenu && rc)
2423 {
2424 int i;
2425 for (i = 0; i < rc; i++)
2426 {
2427 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2428 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2429 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2430 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2431 }
2432 }
2433 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2434 return rc;
2435 }
2436 }
2437 else
2438 return 0;
2439 }
2440
2441 /***********************************************************************
2442 * ImmLockIMC(IMM32.@)
2443 */
2444 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2445 {
2446 InputContextData *data = (InputContextData*)hIMC;
2447
2448 if (!data)
2449 return NULL;
2450 data->dwLock++;
2451 return &data->IMC;
2452 }
2453
2454 /***********************************************************************
2455 * ImmUnlockIMC(IMM32.@)
2456 */
2457 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2458 {
2459 InputContextData *data = (InputContextData*)hIMC;
2460 data->dwLock--;
2461 return (data->dwLock!=0);
2462 }
2463
2464 /***********************************************************************
2465 * ImmGetIMCLockCount(IMM32.@)
2466 */
2467 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2468 {
2469 InputContextData *data = (InputContextData*)hIMC;
2470 return data->dwLock;
2471 }
2472
2473 /***********************************************************************
2474 * ImmCreateIMCC(IMM32.@)
2475 */
2476 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2477 {
2478 IMCCInternal *internal;
2479 int real_size = size + sizeof(IMCCInternal);
2480
2481 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2482 if (internal == NULL)
2483 return NULL;
2484
2485 internal->dwSize = size;
2486 return (HIMCC)internal;
2487 }
2488
2489 /***********************************************************************
2490 * ImmDestroyIMCC(IMM32.@)
2491 */
2492 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2493 {
2494 HeapFree(GetProcessHeap(),0,block);
2495 return NULL;
2496 }
2497
2498 /***********************************************************************
2499 * ImmLockIMCC(IMM32.@)
2500 */
2501 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2502 {
2503 IMCCInternal *internal;
2504 internal = (IMCCInternal*) imcc;
2505
2506 internal->dwLock ++;
2507 return internal + 1;
2508 }
2509
2510 /***********************************************************************
2511 * ImmUnlockIMCC(IMM32.@)
2512 */
2513 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2514 {
2515 IMCCInternal *internal;
2516 internal = (IMCCInternal*) imcc;
2517
2518 internal->dwLock --;
2519 return (internal->dwLock!=0);
2520 }
2521
2522 /***********************************************************************
2523 * ImmGetIMCCLockCount(IMM32.@)
2524 */
2525 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2526 {
2527 IMCCInternal *internal;
2528 internal = (IMCCInternal*) imcc;
2529
2530 return internal->dwLock;
2531 }
2532
2533 /***********************************************************************
2534 * ImmReSizeIMCC(IMM32.@)
2535 */
2536 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2537 {
2538 IMCCInternal *internal,*newone;
2539 int real_size = size + sizeof(IMCCInternal);
2540
2541 internal = (IMCCInternal*) imcc;
2542
2543 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2544 newone->dwSize = size;
2545
2546 return newone;
2547 }
2548
2549 /***********************************************************************
2550 * ImmGetIMCCSize(IMM32.@)
2551 */
2552 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2553 {
2554 IMCCInternal *internal;
2555 internal = (IMCCInternal*) imcc;
2556
2557 return internal->dwSize;
2558 }
2559
2560 /***********************************************************************
2561 * ImmGenerateMessage(IMM32.@)
2562 */
2563 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2564 {
2565 InputContextData *data = (InputContextData*)hIMC;
2566
2567 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2568 if (data->IMC.dwNumMsgBuf > 0)
2569 {
2570 LPTRANSMSG lpTransMsg;
2571 INT i;
2572
2573 lpTransMsg = (LPTRANSMSG)ImmLockIMCC(data->IMC.hMsgBuf);
2574 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2575 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2576
2577 ImmUnlockIMCC(data->IMC.hMsgBuf);
2578
2579 data->IMC.dwNumMsgBuf = 0;
2580 }
2581
2582 return TRUE;
2583 }
2584
2585 /***********************************************************************
2586 * ImmTranslateMessage(IMM32.@)
2587 * ( Undocumented, call internally and from user32.dll )
2588 */
2589 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2590 {
2591 InputContextData *data;
2592 HIMC imc = ImmGetContext(hwnd);
2593 BYTE state[256];
2594 UINT scancode;
2595 LPVOID list = 0;
2596 UINT msg_count;
2597 UINT uVirtKey;
2598 static const int list_count = 10;
2599
2600 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2601
2602 if (imc)
2603 data = (InputContextData*)imc;
2604 else
2605 return FALSE;
2606
2607 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2608 return FALSE;
2609
2610 GetKeyboardState(state);
2611 scancode = lKeyData >> 0x10 & 0xff;
2612
2613 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2614 ((DWORD*)list)[0] = list_count;
2615
2616 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2617 {
2618 WCHAR chr;
2619
2620 if (!is_himc_ime_unicode(data))
2621 ToAscii(data->lastVK, scancode, state, &chr, 0);
2622 else
2623 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2624 uVirtKey = MAKELONG(data->lastVK,chr);
2625 }
2626 else
2627 uVirtKey = data->lastVK;
2628
2629 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2630 TRACE("%i messages generated\n",msg_count);
2631 if (msg_count && msg_count <= list_count)
2632 {
2633 int i;
2634 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2635
2636 for (i = 0; i < msg_count; i++)
2637 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2638 }
2639 else if (msg_count > list_count)
2640 ImmGenerateMessage(imc);
2641
2642 HeapFree(GetProcessHeap(),0,list);
2643
2644 data->lastVK = VK_PROCESSKEY;
2645
2646 return (msg_count > 0);
2647 }
2648
2649 /***********************************************************************
2650 * ImmProcessKey(IMM32.@)
2651 * ( Undocumented, called from user32.dll )
2652 */
2653 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2654 {
2655 InputContextData *data;
2656 HIMC imc = ImmGetContext(hwnd);
2657 BYTE state[256];
2658
2659 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2660
2661 if (imc)
2662 data = (InputContextData*)imc;
2663 else
2664 return FALSE;
2665
2666 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
2667 return FALSE;
2668
2669 GetKeyboardState(state);
2670 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
2671 {
2672 data->lastVK = vKey;
2673 return TRUE;
2674 }
2675
2676 data->lastVK = VK_PROCESSKEY;
2677 return FALSE;
2678 }
2679
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.