push bf834a7eef2241618d351018da1587a7ae2466d1
[wine/hacks.git] / dlls / imm32 / imm.c
blob74d71d9c3e5b1a2de82ced3f8e20c1d23ecca46e
1 /*
2 * IMM32 library
4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
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.
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.
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
22 #include <stdarg.h>
23 #include <stdio.h>
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"
37 WINE_DEFAULT_DEBUG_CHANNEL(imm);
39 typedef struct tagIMCCInternal
41 DWORD dwLock;
42 DWORD dwSize;
43 } IMCCInternal;
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;
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
74 typedef struct tagInputContextData
76 DWORD dwLock;
77 INPUTCONTEXT IMC;
79 ImmHkl *immKbd;
80 HWND imeWnd;
81 UINT lastVK;
82 } InputContextData;
84 typedef struct _tagTRANSMSG {
85 UINT message;
86 WPARAM wParam;
87 LPARAM lParam;
88 } TRANSMSG, *LPTRANSMSG;
90 typedef struct _tagIMMThreadData {
91 HIMC defaultContext;
92 HWND hwndDefault;
93 } IMMThreadData;
95 static DWORD tlsIndex = 0;
96 static struct list ImmHklList = LIST_INIT(ImmHklList);
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;
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};
109 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
110 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
111 static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','x',0};
114 #define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
115 #define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
117 static BOOL IMM_DestroyContext(HIMC hIMC);
119 static inline WCHAR *strdupAtoW( const char *str )
121 WCHAR *ret = NULL;
122 if (str)
124 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
125 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
126 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
128 return ret;
131 static inline CHAR *strdupWtoA( const WCHAR *str )
133 CHAR *ret = NULL;
134 if (str)
136 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
137 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
138 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
140 return ret;
143 static DWORD convert_candidatelist_WtoA(
144 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
146 DWORD ret, i, len;
148 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
149 if ( lpDst && dwBufLen > 0 )
151 *lpDst = *lpSrc;
152 lpDst->dwOffset[0] = ret;
155 for ( i = 0; i < lpSrc->dwCount; i++)
157 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
159 if ( lpDst && dwBufLen > 0 )
161 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
163 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1,
164 (LPSTR)dest, dwBufLen, NULL, NULL);
166 if ( i + 1 < lpSrc->dwCount )
167 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
168 dwBufLen -= len * sizeof(char);
170 else
171 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL);
173 ret += len * sizeof(char);
176 if ( lpDst )
177 lpDst->dwSize = ret;
179 return ret;
182 static DWORD convert_candidatelist_AtoW(
183 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
185 DWORD ret, i, len;
187 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
188 if ( lpDst && dwBufLen > 0 )
190 *lpDst = *lpSrc;
191 lpDst->dwOffset[0] = ret;
194 for ( i = 0; i < lpSrc->dwCount; i++)
196 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
198 if ( lpDst && dwBufLen > 0 )
200 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
202 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1,
203 (LPWSTR)dest, dwBufLen);
205 if ( i + 1 < lpSrc->dwCount )
206 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
207 dwBufLen -= len * sizeof(WCHAR);
209 else
210 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
212 ret += len * sizeof(WCHAR);
215 if ( lpDst )
216 lpDst->dwSize = ret;
218 return ret;
221 static IMMThreadData* IMM_GetThreadData(void)
223 return TlsGetValue(tlsIndex);
226 static void IMM_InitThreadData(void)
228 IMMThreadData* data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
229 sizeof(IMMThreadData));
230 TlsSetValue(tlsIndex,data);
232 TRACE("Thread Data Created\n");
235 static void IMM_FreeThreadData(void)
237 IMMThreadData* data = TlsGetValue(tlsIndex);
238 IMM_DestroyContext(data->defaultContext);
239 DestroyWindow(data->hwndDefault);
240 HeapFree(GetProcessHeap(),0,data);
241 TRACE("Thread Data Destroyed\n");
244 static HMODULE LoadDefaultWineIME(void)
246 char buffer[MAX_PATH], libname[32], *name, *next;
247 HMODULE module = 0;
248 HKEY hkey;
250 TRACE("Attempting to fall back to wine default IME\n");
252 strcpy( buffer, "x11" ); /* default value */
253 /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
254 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
256 DWORD type, count = sizeof(buffer);
257 RegQueryValueExA( hkey, "Ime", 0, &type, (LPBYTE) buffer, &count );
258 RegCloseKey( hkey );
261 name = buffer;
262 while (name)
264 next = strchr( name, ',' );
265 if (next) *next++ = 0;
267 snprintf( libname, sizeof(libname), "wine%s.drv", name );
268 if ((module = LoadLibraryA( libname )) != 0) break;
269 name = next;
272 return module;
275 /* ImmHkl loading and freeing */
276 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
277 static ImmHkl *IMM_GetImmHkl(HKL hkl)
279 ImmHkl *ptr;
280 WCHAR filename[MAX_PATH];
282 TRACE("Seeking ime for keyboard 0x%x\n",(unsigned)hkl);
284 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
286 if (ptr->hkl == hkl)
287 return ptr;
289 /* not found... create it */
291 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
293 ptr->hkl = hkl;
294 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
295 if (!ptr->hIME)
296 ptr->hIME = LoadDefaultWineIME();
297 if (ptr->hIME)
299 LOAD_FUNCPTR(ImeInquire);
300 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
302 FreeLibrary(ptr->hIME);
303 ptr->hIME = NULL;
305 else
307 LOAD_FUNCPTR(ImeDestroy);
308 LOAD_FUNCPTR(ImeSelect);
309 if (!ptr->pImeSelect || !ptr->pImeDestroy)
311 FreeLibrary(ptr->hIME);
312 ptr->hIME = NULL;
314 else
316 LOAD_FUNCPTR(ImeConfigure);
317 LOAD_FUNCPTR(ImeEscape);
318 LOAD_FUNCPTR(ImeSetActiveContext);
319 LOAD_FUNCPTR(ImeToAsciiEx);
320 LOAD_FUNCPTR(NotifyIME);
321 LOAD_FUNCPTR(ImeRegisterWord);
322 LOAD_FUNCPTR(ImeUnregisterWord);
323 LOAD_FUNCPTR(ImeEnumRegisterWord);
324 LOAD_FUNCPTR(ImeSetCompositionString);
325 LOAD_FUNCPTR(ImeConversionList);
326 LOAD_FUNCPTR(ImeProcessKey);
327 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
328 LOAD_FUNCPTR(ImeGetImeMenuItems);
329 /* make sure our classname is WCHAR */
330 if (!is_kbd_ime_unicode(ptr))
332 WCHAR bufW[17];
333 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
334 -1, bufW, 17);
335 lstrcpyW(ptr->imeClassName, bufW);
340 list_add_head(&ImmHklList,&ptr->entry);
342 return ptr;
344 #undef LOAD_FUNCPTR
346 static void IMM_FreeAllImmHkl(void)
348 ImmHkl *ptr,*cursor2;
350 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
352 list_remove(&ptr->entry);
353 if (ptr->hIME)
355 ptr->pImeDestroy(1);
356 FreeLibrary(ptr->hIME);
358 HeapFree(GetProcessHeap(),0,ptr);
362 static void IMM_RegisterMessages(void)
364 WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService");
365 WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions");
366 WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation");
367 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest");
368 WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert");
369 WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition");
370 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
373 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
375 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
376 switch (fdwReason)
378 case DLL_PROCESS_ATTACH:
379 IMM_RegisterMessages();
380 tlsIndex = TlsAlloc();
381 IMM_InitThreadData();
382 break;
383 case DLL_THREAD_ATTACH:
384 IMM_InitThreadData();
385 break;
386 case DLL_THREAD_DETACH:
387 IMM_FreeThreadData();
388 break;
389 case DLL_PROCESS_DETACH:
390 IMM_FreeThreadData();
391 IMM_FreeAllImmHkl();
392 TlsFree(tlsIndex);
393 break;
395 return TRUE;
398 /* for posting messages as the IME */
399 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
401 HWND target = GetFocus();
402 if (!target)
403 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
404 else
405 PostMessageW(target, msg, wParam, lParam);
408 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
410 HWND target;
412 target = data->IMC.hWnd;
413 if (!target) target = GetFocus();
415 if (target)
416 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
418 return 0;
421 static HIMCC ImmCreateBlankCompStr(void)
423 HIMCC rc;
424 LPCOMPOSITIONSTRING ptr;
425 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
426 ptr = ImmLockIMCC(rc);
427 memset(ptr,0,sizeof(COMPOSITIONSTRING));
428 ptr->dwSize = sizeof(COMPOSITIONSTRING);
429 ImmUnlockIMCC(rc);
430 return rc;
433 /***********************************************************************
434 * ImmAssociateContext (IMM32.@)
436 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
438 HIMC old = NULL;
439 InputContextData *data = hIMC;
441 TRACE("(%p, %p):\n", hWnd, hIMC);
443 if (!IMM_GetThreadData()->defaultContext)
444 IMM_GetThreadData()->defaultContext = ImmCreateContext();
447 * If already associated just return
449 if (hIMC && data->IMC.hWnd == hWnd)
450 return hIMC;
452 if (hWnd)
454 old = RemovePropW(hWnd,szwWineIMCProperty);
456 if (old == NULL)
457 old = IMM_GetThreadData()->defaultContext;
458 else if (old == (HIMC)-1)
459 old = NULL;
461 if (hIMC != IMM_GetThreadData()->defaultContext)
463 if (hIMC == NULL) /* Meaning disable imm for that window*/
464 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
465 else
466 SetPropW(hWnd,szwWineIMCProperty,hIMC);
469 if (old)
471 InputContextData *old_data = old;
472 if (old_data->IMC.hWnd == hWnd)
473 old_data->IMC.hWnd = NULL;
477 if (!hIMC)
478 return old;
480 if (IsWindow(data->IMC.hWnd))
483 * Post a message that your context is switching
485 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
488 data->IMC.hWnd = hWnd;
490 if (IsWindow(data->IMC.hWnd))
493 * Post a message that your context is switching
495 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
498 return old;
503 * Helper function for ImmAssociateContextEx
505 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
507 HIMC hImc = (HIMC)lParam;
508 ImmAssociateContext(hwnd,hImc);
509 return TRUE;
512 /***********************************************************************
513 * ImmAssociateContextEx (IMM32.@)
515 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
517 TRACE("(%p, %p, %d): stub\n", hWnd, hIMC, dwFlags);
519 if (!IMM_GetThreadData()->defaultContext)
520 IMM_GetThreadData()->defaultContext = ImmCreateContext();
522 if (dwFlags == IACE_DEFAULT)
524 ImmAssociateContext(hWnd,IMM_GetThreadData()->defaultContext);
525 return TRUE;
527 else if (dwFlags == IACE_IGNORENOCONTEXT)
529 if (GetPropW(hWnd,szwWineIMCProperty) > 0)
530 ImmAssociateContext(hWnd,hIMC);
531 return TRUE;
533 else if (dwFlags == IACE_CHILDREN)
535 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC);
536 return TRUE;
538 else
540 ERR("Unknown dwFlags 0x%x\n",dwFlags);
541 return FALSE;
545 /***********************************************************************
546 * ImmConfigureIMEA (IMM32.@)
548 BOOL WINAPI ImmConfigureIMEA(
549 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
551 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
553 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
555 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
556 return FALSE;
558 if (immHkl->hIME && immHkl->pImeConfigure)
560 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
561 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
562 else
564 REGISTERWORDW rww;
565 REGISTERWORDA *rwa = lpData;
566 BOOL rc;
568 rww.lpReading = strdupAtoW(rwa->lpReading);
569 rww.lpWord = strdupAtoW(rwa->lpWord);
570 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
571 HeapFree(GetProcessHeap(),0,rww.lpReading);
572 HeapFree(GetProcessHeap(),0,rww.lpWord);
573 return rc;
576 else
577 return FALSE;
580 /***********************************************************************
581 * ImmConfigureIMEW (IMM32.@)
583 BOOL WINAPI ImmConfigureIMEW(
584 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
586 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
588 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
590 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
591 return FALSE;
593 if (immHkl->hIME && immHkl->pImeConfigure)
595 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
596 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
597 else
599 REGISTERWORDW *rww = lpData;
600 REGISTERWORDA rwa;
601 BOOL rc;
603 rwa.lpReading = strdupWtoA(rww->lpReading);
604 rwa.lpWord = strdupWtoA(rww->lpWord);
605 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
606 HeapFree(GetProcessHeap(),0,rwa.lpReading);
607 HeapFree(GetProcessHeap(),0,rwa.lpWord);
608 return rc;
611 else
612 return FALSE;
615 /***********************************************************************
616 * ImmCreateContext (IMM32.@)
618 HIMC WINAPI ImmCreateContext(void)
620 InputContextData *new_context;
621 LPGUIDELINE gl;
622 LPCANDIDATEINFO ci;
624 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
626 /* Load the IME */
627 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
629 if (!new_context->immKbd->hIME)
631 TRACE("IME dll could not be loaded\n");
632 HeapFree(GetProcessHeap(),0,new_context);
633 return 0;
636 /* the HIMCCs are never NULL */
637 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
638 new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
639 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
640 ci = ImmLockIMCC(new_context->IMC.hCandInfo);
641 memset(ci,0,sizeof(CANDIDATEINFO));
642 ci->dwSize = sizeof(CANDIDATEINFO);
643 ImmUnlockIMCC(new_context->IMC.hCandInfo);
644 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
645 gl = ImmLockIMCC(new_context->IMC.hGuideLine);
646 memset(gl,0,sizeof(GUIDELINE));
647 gl->dwSize = sizeof(GUIDELINE);
648 ImmUnlockIMCC(new_context->IMC.hGuideLine);
650 /* Initialize the IME Private */
651 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
653 if (!new_context->immKbd->pImeSelect(new_context, TRUE))
655 TRACE("Selection of IME failed\n");
656 IMM_DestroyContext(new_context);
657 return 0;
660 new_context->immKbd->uSelected++;
661 TRACE("Created context 0x%x\n",(UINT)new_context);
663 return new_context;
666 static BOOL IMM_DestroyContext(HIMC hIMC)
668 InputContextData *data = hIMC;
670 TRACE("Destroying %p\n",hIMC);
672 if (hIMC)
674 data->immKbd->uSelected --;
675 data->immKbd->pImeSelect(hIMC, FALSE);
677 if (IMM_GetThreadData()->hwndDefault == data->imeWnd)
678 IMM_GetThreadData()->hwndDefault = NULL;
679 DestroyWindow(data->imeWnd);
681 ImmDestroyIMCC(data->IMC.hCompStr);
682 ImmDestroyIMCC(data->IMC.hCandInfo);
683 ImmDestroyIMCC(data->IMC.hGuideLine);
684 ImmDestroyIMCC(data->IMC.hPrivate);
685 ImmDestroyIMCC(data->IMC.hMsgBuf);
687 HeapFree(GetProcessHeap(),0,data);
689 return TRUE;
692 /***********************************************************************
693 * ImmDestroyContext (IMM32.@)
695 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
697 if (hIMC != IMM_GetThreadData()->defaultContext)
698 return IMM_DestroyContext(hIMC);
699 else
700 return FALSE;
703 /***********************************************************************
704 * ImmDisableIME (IMM32.@)
706 BOOL WINAPI ImmDisableIME(DWORD idThread)
708 FIXME("(%d): stub\n", idThread);
709 return TRUE;
712 /***********************************************************************
713 * ImmEnumRegisterWordA (IMM32.@)
715 UINT WINAPI ImmEnumRegisterWordA(
716 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
717 LPCSTR lpszReading, DWORD dwStyle,
718 LPCSTR lpszRegister, LPVOID lpData)
720 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
721 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
722 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
723 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
725 if (!is_kbd_ime_unicode(immHkl))
726 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
727 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
728 else
730 LPWSTR lpszwReading = strdupAtoW(lpszReading);
731 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
732 BOOL rc;
734 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
735 lpszwReading, dwStyle, lpszwRegister,
736 lpData);
738 HeapFree(GetProcessHeap(),0,lpszwReading);
739 HeapFree(GetProcessHeap(),0,lpszwRegister);
740 return rc;
743 else
744 return 0;
747 /***********************************************************************
748 * ImmEnumRegisterWordW (IMM32.@)
750 UINT WINAPI ImmEnumRegisterWordW(
751 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
752 LPCWSTR lpszReading, DWORD dwStyle,
753 LPCWSTR lpszRegister, LPVOID lpData)
755 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
756 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
757 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
758 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
760 if (is_kbd_ime_unicode(immHkl))
761 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
762 lpszRegister, lpData);
763 else
765 LPSTR lpszaReading = strdupWtoA(lpszReading);
766 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
767 BOOL rc;
769 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
770 dwStyle, (LPCWSTR)lpszaRegister, lpData);
772 HeapFree(GetProcessHeap(),0,lpszaReading);
773 HeapFree(GetProcessHeap(),0,lpszaRegister);
774 return rc;
777 else
778 return 0;
781 static inline BOOL EscapeRequiresWA(UINT uEscape)
783 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
784 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
785 uEscape == IME_ESC_IME_NAME ||
786 uEscape == IME_ESC_GETHELPFILENAME)
787 return TRUE;
788 return FALSE;
791 /***********************************************************************
792 * ImmEscapeA (IMM32.@)
794 LRESULT WINAPI ImmEscapeA(
795 HKL hKL, HIMC hIMC,
796 UINT uEscape, LPVOID lpData)
798 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
799 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
801 if (immHkl->hIME && immHkl->pImeEscape)
803 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
804 return immHkl->pImeEscape(hIMC,uEscape,lpData);
805 else
807 WCHAR buffer[81]; /* largest required buffer should be 80 */
808 LRESULT rc;
809 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
811 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
812 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
814 else
816 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
817 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
819 return rc;
822 else
823 return 0;
826 /***********************************************************************
827 * ImmEscapeW (IMM32.@)
829 LRESULT WINAPI ImmEscapeW(
830 HKL hKL, HIMC hIMC,
831 UINT uEscape, LPVOID lpData)
833 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
834 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
836 if (immHkl->hIME && immHkl->pImeEscape)
838 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
839 return immHkl->pImeEscape(hIMC,uEscape,lpData);
840 else
842 CHAR buffer[81]; /* largest required buffer should be 80 */
843 LRESULT rc;
844 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
846 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
847 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
849 else
851 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
852 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
854 return rc;
857 else
858 return 0;
861 /***********************************************************************
862 * ImmGetCandidateListA (IMM32.@)
864 DWORD WINAPI ImmGetCandidateListA(
865 HIMC hIMC, DWORD dwIndex,
866 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
868 InputContextData *data = hIMC;
869 LPCANDIDATEINFO candinfo;
870 LPCANDIDATELIST candlist;
871 DWORD ret = 0;
873 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
875 if (!data || !data->IMC.hCandInfo)
876 return 0;
878 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
879 if ( dwIndex >= candinfo->dwCount ||
880 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
881 goto done;
883 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
884 if ( !candlist->dwSize || !candlist->dwCount )
885 goto done;
887 if ( !is_himc_ime_unicode(data) )
889 ret = candlist->dwSize;
890 if ( lpCandList && dwBufLen >= ret )
891 memcpy(lpCandList, candlist, ret);
893 else
894 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
896 done:
897 ImmUnlockIMCC(data->IMC.hCandInfo);
898 return ret;
901 /***********************************************************************
902 * ImmGetCandidateListCountA (IMM32.@)
904 DWORD WINAPI ImmGetCandidateListCountA(
905 HIMC hIMC, LPDWORD lpdwListCount)
907 InputContextData *data = hIMC;
908 LPCANDIDATEINFO candinfo;
909 DWORD ret, count;
911 TRACE("%p, %p\n", hIMC, lpdwListCount);
913 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
914 return 0;
916 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
918 *lpdwListCount = count = candinfo->dwCount;
920 if ( !is_himc_ime_unicode(data) )
921 ret = candinfo->dwSize;
922 else
924 ret = sizeof(CANDIDATEINFO);
925 while ( count-- )
926 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
929 ImmUnlockIMCC(data->IMC.hCandInfo);
930 return ret;
933 /***********************************************************************
934 * ImmGetCandidateListCountW (IMM32.@)
936 DWORD WINAPI ImmGetCandidateListCountW(
937 HIMC hIMC, LPDWORD lpdwListCount)
939 InputContextData *data = hIMC;
940 LPCANDIDATEINFO candinfo;
941 DWORD ret, count;
943 TRACE("%p, %p\n", hIMC, lpdwListCount);
945 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
946 return 0;
948 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
950 *lpdwListCount = count = candinfo->dwCount;
952 if ( is_himc_ime_unicode(data) )
953 ret = candinfo->dwSize;
954 else
956 ret = sizeof(CANDIDATEINFO);
957 while ( count-- )
958 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
961 ImmUnlockIMCC(data->IMC.hCandInfo);
962 return ret;
965 /***********************************************************************
966 * ImmGetCandidateListW (IMM32.@)
968 DWORD WINAPI ImmGetCandidateListW(
969 HIMC hIMC, DWORD dwIndex,
970 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
972 InputContextData *data = hIMC;
973 LPCANDIDATEINFO candinfo;
974 LPCANDIDATELIST candlist;
975 DWORD ret = 0;
977 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
979 if (!data || !data->IMC.hCandInfo)
980 return 0;
982 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
983 if ( dwIndex >= candinfo->dwCount ||
984 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
985 goto done;
987 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
988 if ( !candlist->dwSize || !candlist->dwCount )
989 goto done;
991 if ( is_himc_ime_unicode(data) )
993 ret = candlist->dwSize;
994 if ( lpCandList && dwBufLen >= ret )
995 memcpy(lpCandList, candlist, ret);
997 else
998 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1000 done:
1001 ImmUnlockIMCC(data->IMC.hCandInfo);
1002 return ret;
1005 /***********************************************************************
1006 * ImmGetCandidateWindow (IMM32.@)
1008 BOOL WINAPI ImmGetCandidateWindow(
1009 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1011 InputContextData *data = hIMC;
1013 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1015 if (!data || !lpCandidate)
1016 return FALSE;
1018 if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1019 return FALSE;
1021 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1023 return TRUE;
1026 /***********************************************************************
1027 * ImmGetCompositionFontA (IMM32.@)
1029 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1031 LOGFONTW lfW;
1032 BOOL rc;
1034 TRACE("(%p, %p):\n", hIMC, lplf);
1036 rc = ImmGetCompositionFontW(hIMC,&lfW);
1037 if (!rc || !lplf)
1038 return FALSE;
1040 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1041 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1042 LF_FACESIZE, NULL, NULL);
1043 return TRUE;
1046 /***********************************************************************
1047 * ImmGetCompositionFontW (IMM32.@)
1049 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1051 InputContextData *data = hIMC;
1053 TRACE("(%p, %p):\n", hIMC, lplf);
1055 if (!data || !lplf)
1056 return FALSE;
1058 *lplf = data->IMC.lfFont.W;
1060 return TRUE;
1064 /* Helpers for the GetCompositionString functions */
1066 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1067 BOOL unicode )
1069 INT rc;
1071 if (is_himc_ime_unicode(data) && !unicode)
1072 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1073 else if (!is_himc_ime_unicode(data) && unicode)
1074 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1075 else
1077 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1078 memcpy( target, source, min(slen,tlen)*dlen);
1079 rc = slen*dlen;
1082 return rc;
1085 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1086 LPBYTE target, INT tlen, BOOL unicode )
1088 INT rc;
1090 if (is_himc_ime_unicode(data) && !unicode)
1092 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1093 if (tlen)
1095 const BYTE *src = source;
1096 LPBYTE dst = target;
1097 int i, j = 0, k = 0;
1099 if (rc < tlen)
1100 tlen = rc;
1101 for (i = 0; i < sslen; ++i)
1103 int len;
1105 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1106 NULL, 0, NULL, NULL);
1107 for (; len > 0; --len)
1109 dst[j++] = src[k];
1111 if (j >= tlen)
1112 goto end;
1114 ++k;
1116 end:
1117 rc = j;
1120 else if (!is_himc_ime_unicode(data) && unicode)
1122 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1123 if (tlen)
1125 const BYTE *src = source;
1126 LPBYTE dst = target;
1127 int i, j = 0;
1129 if (rc < tlen)
1130 tlen = rc;
1131 for (i = 0; i < sslen; ++i)
1133 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1134 continue;
1136 dst[j++] = src[i];
1138 if (j >= tlen)
1139 break;
1141 rc = j;
1144 else
1146 memcpy( target, source, min(slen,tlen));
1147 rc = slen;
1150 return rc;
1153 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1154 LPBYTE target, INT tlen, BOOL unicode )
1156 INT rc;
1158 if (is_himc_ime_unicode(data) && !unicode)
1160 if (tlen)
1162 int i;
1164 if (slen < tlen)
1165 tlen = slen;
1166 tlen /= sizeof (DWORD);
1167 for (i = 0; i < tlen; ++i)
1169 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1170 ((DWORD *)source)[i],
1171 NULL, 0,
1172 NULL, NULL);
1174 rc = sizeof (DWORD) * i;
1176 else
1177 rc = slen;
1179 else if (!is_himc_ime_unicode(data) && unicode)
1181 if (tlen)
1183 int i;
1185 if (slen < tlen)
1186 tlen = slen;
1187 tlen /= sizeof (DWORD);
1188 for (i = 0; i < tlen; ++i)
1190 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1191 ((DWORD *)source)[i],
1192 NULL, 0);
1194 rc = sizeof (DWORD) * i;
1196 else
1197 rc = slen;
1199 else
1201 memcpy( target, source, min(slen,tlen));
1202 rc = slen;
1205 return rc;
1208 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1210 int rc;
1212 if (is_himc_ime_unicode(data) && !unicode)
1214 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1216 else if (!is_himc_ime_unicode(data) && unicode)
1218 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1220 else
1221 rc = offset;
1223 return rc;
1226 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1227 DWORD dwBufLen, BOOL unicode)
1229 LONG rc = 0;
1230 InputContextData *data = hIMC;
1231 LPCOMPOSITIONSTRING compstr;
1232 LPBYTE compdata;
1234 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1236 if (!data)
1237 return FALSE;
1239 if (!data->IMC.hCompStr)
1240 return FALSE;
1242 compdata = ImmLockIMCC(data->IMC.hCompStr);
1243 compstr = (LPCOMPOSITIONSTRING)compdata;
1245 switch (dwIndex)
1247 case GCS_RESULTSTR:
1248 TRACE("GCS_RESULTSTR\n");
1249 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1250 break;
1251 case GCS_COMPSTR:
1252 TRACE("GCS_COMPSTR\n");
1253 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1254 break;
1255 case GCS_COMPATTR:
1256 TRACE("GCS_COMPATTR\n");
1257 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1258 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1259 lpBuf, dwBufLen, unicode);
1260 break;
1261 case GCS_COMPCLAUSE:
1262 TRACE("GCS_COMPCLAUSE\n");
1263 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1264 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1265 lpBuf, dwBufLen, unicode);
1266 break;
1267 case GCS_RESULTCLAUSE:
1268 TRACE("GCS_RESULTCLAUSE\n");
1269 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1270 compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen,
1271 lpBuf, dwBufLen, unicode);
1272 break;
1273 case GCS_RESULTREADSTR:
1274 TRACE("GCS_RESULTREADSTR\n");
1275 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1276 break;
1277 case GCS_RESULTREADCLAUSE:
1278 TRACE("GCS_RESULTREADCLAUSE\n");
1279 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1280 compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen,
1281 lpBuf, dwBufLen, unicode);
1282 break;
1283 case GCS_COMPREADSTR:
1284 TRACE("GCS_COMPREADSTR\n");
1285 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1286 break;
1287 case GCS_COMPREADATTR:
1288 TRACE("GCS_COMPREADATTR\n");
1289 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1290 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1291 lpBuf, dwBufLen, unicode);
1292 break;
1293 case GCS_COMPREADCLAUSE:
1294 TRACE("GCS_COMPREADCLAUSE\n");
1295 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1296 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1297 lpBuf, dwBufLen, unicode);
1298 break;
1299 case GCS_CURSORPOS:
1300 TRACE("GCS_CURSORPOS\n");
1301 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1302 break;
1303 case GCS_DELTASTART:
1304 TRACE("GCS_DELTASTART\n");
1305 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1306 break;
1307 default:
1308 FIXME("Unhandled index 0x%x\n",dwIndex);
1309 break;
1312 ImmUnlockIMCC(data->IMC.hCompStr);
1314 return rc;
1317 /***********************************************************************
1318 * ImmGetCompositionStringA (IMM32.@)
1320 LONG WINAPI ImmGetCompositionStringA(
1321 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1323 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1327 /***********************************************************************
1328 * ImmGetCompositionStringW (IMM32.@)
1330 LONG WINAPI ImmGetCompositionStringW(
1331 HIMC hIMC, DWORD dwIndex,
1332 LPVOID lpBuf, DWORD dwBufLen)
1334 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1337 /***********************************************************************
1338 * ImmGetCompositionWindow (IMM32.@)
1340 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1342 InputContextData *data = hIMC;
1344 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1346 if (!data)
1347 return FALSE;
1349 *lpCompForm = data->IMC.cfCompForm;
1350 return 1;
1353 /***********************************************************************
1354 * ImmGetContext (IMM32.@)
1357 HIMC WINAPI ImmGetContext(HWND hWnd)
1359 HIMC rc = NULL;
1361 TRACE("%p\n", hWnd);
1362 if (!IMM_GetThreadData()->defaultContext)
1363 IMM_GetThreadData()->defaultContext = ImmCreateContext();
1365 rc = GetPropW(hWnd,szwWineIMCProperty);
1366 if (rc == (HIMC)-1)
1367 rc = NULL;
1368 else if (rc == NULL)
1369 rc = IMM_GetThreadData()->defaultContext;
1371 if (rc)
1373 InputContextData *data = rc;
1374 data->IMC.hWnd = hWnd;
1376 TRACE("returning %p\n", rc);
1378 return rc;
1381 /***********************************************************************
1382 * ImmGetConversionListA (IMM32.@)
1384 DWORD WINAPI ImmGetConversionListA(
1385 HKL hKL, HIMC hIMC,
1386 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1387 DWORD dwBufLen, UINT uFlag)
1389 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1390 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1391 dwBufLen, uFlag);
1392 if (immHkl->hIME && immHkl->pImeConversionList)
1394 if (!is_kbd_ime_unicode(immHkl))
1395 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1396 else
1398 LPCANDIDATELIST lpwDst;
1399 DWORD ret = 0, len;
1400 LPWSTR pwSrc = strdupAtoW(pSrc);
1402 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1403 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1404 if ( lpwDst )
1406 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1407 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1408 HeapFree(GetProcessHeap(), 0, lpwDst);
1410 HeapFree(GetProcessHeap(), 0, pwSrc);
1412 return ret;
1415 else
1416 return 0;
1419 /***********************************************************************
1420 * ImmGetConversionListW (IMM32.@)
1422 DWORD WINAPI ImmGetConversionListW(
1423 HKL hKL, HIMC hIMC,
1424 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1425 DWORD dwBufLen, UINT uFlag)
1427 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1428 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1429 dwBufLen, uFlag);
1430 if (immHkl->hIME && immHkl->pImeConversionList)
1432 if (is_kbd_ime_unicode(immHkl))
1433 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1434 else
1436 LPCANDIDATELIST lpaDst;
1437 DWORD ret = 0, len;
1438 LPSTR paSrc = strdupWtoA(pSrc);
1440 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1441 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1442 if ( lpaDst )
1444 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1445 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1446 HeapFree(GetProcessHeap(), 0, lpaDst);
1448 HeapFree(GetProcessHeap(), 0, paSrc);
1450 return ret;
1453 else
1454 return 0;
1457 /***********************************************************************
1458 * ImmGetConversionStatus (IMM32.@)
1460 BOOL WINAPI ImmGetConversionStatus(
1461 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1463 InputContextData *data = hIMC;
1465 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1467 if (!data)
1468 return FALSE;
1470 if (lpfdwConversion)
1471 *lpfdwConversion = data->IMC.fdwConversion;
1472 if (lpfdwSentence)
1473 *lpfdwSentence = data->IMC.fdwSentence;
1475 return TRUE;
1478 /***********************************************************************
1479 * ImmGetDefaultIMEWnd (IMM32.@)
1481 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1483 TRACE("Default is %x\n",(unsigned)IMM_GetThreadData()->hwndDefault);
1484 return IMM_GetThreadData()->hwndDefault;
1487 /***********************************************************************
1488 * ImmGetDescriptionA (IMM32.@)
1490 UINT WINAPI ImmGetDescriptionA(
1491 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1493 WCHAR *buf;
1494 DWORD len;
1496 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1498 /* find out how many characters in the unicode buffer */
1499 len = ImmGetDescriptionW( hKL, NULL, 0 );
1501 /* allocate a buffer of that size */
1502 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1503 if( !buf )
1504 return 0;
1506 /* fetch the unicode buffer */
1507 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1509 /* convert it back to ASCII */
1510 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1511 lpszDescription, uBufLen, NULL, NULL );
1513 HeapFree( GetProcessHeap(), 0, buf );
1515 return len;
1518 /***********************************************************************
1519 * ImmGetDescriptionW (IMM32.@)
1521 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1523 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1525 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1527 if (!uBufLen) return lstrlenW( name );
1528 lstrcpynW( lpszDescription, name, uBufLen );
1529 return lstrlenW( lpszDescription );
1532 /***********************************************************************
1533 * ImmGetGuideLineA (IMM32.@)
1535 DWORD WINAPI ImmGetGuideLineA(
1536 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1538 FIXME("(%p, %d, %s, %d): stub\n",
1539 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1541 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1542 return 0;
1545 /***********************************************************************
1546 * ImmGetGuideLineW (IMM32.@)
1548 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1550 FIXME("(%p, %d, %s, %d): stub\n",
1551 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1553 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1554 return 0;
1557 /***********************************************************************
1558 * ImmGetIMEFileNameA (IMM32.@)
1560 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1562 LPWSTR bufW = NULL;
1563 UINT wBufLen = uBufLen;
1564 UINT rc;
1566 if (uBufLen && lpszFileName)
1567 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1568 else /* We need this to get the number of byte required */
1570 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1571 wBufLen = MAX_PATH;
1574 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1576 if (rc > 0)
1578 if (uBufLen && lpszFileName)
1579 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1580 uBufLen, NULL, NULL);
1581 else /* get the length */
1582 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1583 NULL);
1586 HeapFree(GetProcessHeap(),0,bufW);
1587 return rc;
1590 /***********************************************************************
1591 * ImmGetIMEFileNameW (IMM32.@)
1593 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1595 HKEY hkey;
1596 DWORD length;
1597 DWORD rc;
1598 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1600 wsprintfW( regKey, szImeRegFmt, (unsigned)hKL );
1601 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1602 if (rc != ERROR_SUCCESS)
1604 SetLastError(rc);
1605 return 0;
1608 length = 0;
1609 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1611 if (rc != ERROR_SUCCESS)
1613 RegCloseKey(hkey);
1614 SetLastError(rc);
1615 return 0;
1617 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1619 RegCloseKey(hkey);
1620 if (lpszFileName)
1622 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1623 return 0;
1625 else
1626 return length / sizeof(WCHAR);
1629 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1631 RegCloseKey(hkey);
1633 return length / sizeof(WCHAR);
1636 /***********************************************************************
1637 * ImmGetOpenStatus (IMM32.@)
1639 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1641 InputContextData *data = hIMC;
1643 if (!data)
1644 return FALSE;
1645 FIXME("(%p): semi-stub\n", hIMC);
1647 return data->IMC.fOpen;
1650 /***********************************************************************
1651 * ImmGetProperty (IMM32.@)
1653 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1655 DWORD rc = 0;
1656 ImmHkl *kbd;
1658 TRACE("(%p, %d)\n", hKL, fdwIndex);
1659 kbd = IMM_GetImmHkl(hKL);
1661 if (kbd && kbd->hIME)
1663 switch (fdwIndex)
1665 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1666 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1667 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1668 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1669 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1670 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1671 case IGP_UI: rc = 0; break;
1672 default: rc = 0;
1675 return rc;
1678 /***********************************************************************
1679 * ImmGetRegisterWordStyleA (IMM32.@)
1681 UINT WINAPI ImmGetRegisterWordStyleA(
1682 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1684 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1685 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1686 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1688 if (!is_kbd_ime_unicode(immHkl))
1689 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1690 else
1692 STYLEBUFW sbw;
1693 UINT rc;
1695 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1696 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1697 lpStyleBuf->szDescription, 32, NULL, NULL);
1698 lpStyleBuf->dwStyle = sbw.dwStyle;
1699 return rc;
1702 else
1703 return 0;
1706 /***********************************************************************
1707 * ImmGetRegisterWordStyleW (IMM32.@)
1709 UINT WINAPI ImmGetRegisterWordStyleW(
1710 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1712 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1713 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1714 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1716 if (is_kbd_ime_unicode(immHkl))
1717 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1718 else
1720 STYLEBUFA sba;
1721 UINT rc;
1723 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1724 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1725 lpStyleBuf->szDescription, 32);
1726 lpStyleBuf->dwStyle = sba.dwStyle;
1727 return rc;
1730 else
1731 return 0;
1734 /***********************************************************************
1735 * ImmGetStatusWindowPos (IMM32.@)
1737 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1739 InputContextData *data = hIMC;
1741 TRACE("(%p, %p)\n", hIMC, lpptPos);
1743 if (!data || !lpptPos)
1744 return FALSE;
1746 *lpptPos = data->IMC.ptStatusWndPos;
1748 return TRUE;
1751 /***********************************************************************
1752 * ImmGetVirtualKey (IMM32.@)
1754 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1756 OSVERSIONINFOA version;
1757 InputContextData *data = ImmGetContext( hWnd );
1758 TRACE("%p\n", hWnd);
1760 if ( data )
1761 return data->lastVK;
1763 GetVersionExA( &version );
1764 switch(version.dwPlatformId)
1766 case VER_PLATFORM_WIN32_WINDOWS:
1767 return VK_PROCESSKEY;
1768 case VER_PLATFORM_WIN32_NT:
1769 return 0;
1770 default:
1771 FIXME("%d not supported\n",version.dwPlatformId);
1772 return VK_PROCESSKEY;
1776 /***********************************************************************
1777 * ImmInstallIMEA (IMM32.@)
1779 HKL WINAPI ImmInstallIMEA(
1780 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1782 LPWSTR lpszwIMEFileName;
1783 LPWSTR lpszwLayoutText;
1784 HKL hkl;
1786 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
1787 debugstr_a(lpszLayoutText));
1789 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
1790 lpszwLayoutText = strdupAtoW(lpszLayoutText);
1792 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
1794 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
1795 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
1796 return hkl;
1799 /***********************************************************************
1800 * ImmInstallIMEW (IMM32.@)
1802 HKL WINAPI ImmInstallIMEW(
1803 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1805 INT lcid = GetUserDefaultLCID();
1806 INT count;
1807 HKL hkl;
1808 DWORD rc;
1809 HKEY hkey;
1810 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1812 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
1813 debugstr_w(lpszLayoutText));
1815 /* Start with 2. e001 will be blank and so default to the wine internal IME */
1816 count = 2;
1818 while (count < 0xfff)
1820 DWORD disposition = 0;
1822 hkl = (HKL)(((0xe000|count)<<16) | lcid);
1823 wsprintfW( regKey, szImeRegFmt, (unsigned)hkl);
1825 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
1826 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
1827 break;
1828 else if (rc == ERROR_SUCCESS)
1829 RegCloseKey(hkey);
1831 count++;
1834 if (count == 0xfff)
1836 WARN("Unable to find slot to install IME\n");
1837 return 0;
1840 if (rc == ERROR_SUCCESS)
1842 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (LPBYTE)lpszIMEFileName,
1843 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
1844 if (rc == ERROR_SUCCESS)
1845 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (LPBYTE)lpszLayoutText,
1846 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
1847 RegCloseKey(hkey);
1848 return hkl;
1850 else
1852 WARN("Unable to set IME registry values\n");
1853 return 0;
1857 /***********************************************************************
1858 * ImmIsIME (IMM32.@)
1860 BOOL WINAPI ImmIsIME(HKL hKL)
1862 ImmHkl *ptr;
1863 TRACE("(%p):\n", hKL);
1864 ptr = IMM_GetImmHkl(hKL);
1865 return (ptr && ptr->hIME);
1868 /***********************************************************************
1869 * ImmIsUIMessageA (IMM32.@)
1871 BOOL WINAPI ImmIsUIMessageA(
1872 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1874 BOOL rc = FALSE;
1876 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1877 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1878 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1879 (msg == WM_MSIME_SERVICE) ||
1880 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1881 (msg == WM_MSIME_MOUSE) ||
1882 (msg == WM_MSIME_RECONVERTREQUEST) ||
1883 (msg == WM_MSIME_RECONVERT) ||
1884 (msg == WM_MSIME_QUERYPOSITION) ||
1885 (msg == WM_MSIME_DOCUMENTFEED))
1888 if (!IMM_GetThreadData()->hwndDefault)
1889 ImmGetDefaultIMEWnd(NULL);
1891 if (hWndIME == NULL)
1892 PostMessageA(IMM_GetThreadData()->hwndDefault, msg, wParam, lParam);
1894 rc = TRUE;
1896 return rc;
1899 /***********************************************************************
1900 * ImmIsUIMessageW (IMM32.@)
1902 BOOL WINAPI ImmIsUIMessageW(
1903 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1905 BOOL rc = FALSE;
1906 TRACE("(%p, %d, %ld, %ld):\n", hWndIME, msg, wParam, lParam);
1907 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1908 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1909 (msg == WM_MSIME_SERVICE) ||
1910 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1911 (msg == WM_MSIME_MOUSE) ||
1912 (msg == WM_MSIME_RECONVERTREQUEST) ||
1913 (msg == WM_MSIME_RECONVERT) ||
1914 (msg == WM_MSIME_QUERYPOSITION) ||
1915 (msg == WM_MSIME_DOCUMENTFEED))
1916 rc = TRUE;
1917 return rc;
1920 /***********************************************************************
1921 * ImmNotifyIME (IMM32.@)
1923 BOOL WINAPI ImmNotifyIME(
1924 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1926 InputContextData *data = hIMC;
1928 TRACE("(%p, %d, %d, %d)\n",
1929 hIMC, dwAction, dwIndex, dwValue);
1931 if (!data || ! data->immKbd->pNotifyIME)
1932 return FALSE;
1934 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
1937 /***********************************************************************
1938 * ImmRegisterWordA (IMM32.@)
1940 BOOL WINAPI ImmRegisterWordA(
1941 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1943 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1944 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
1945 debugstr_a(lpszRegister));
1946 if (immHkl->hIME && immHkl->pImeRegisterWord)
1948 if (!is_kbd_ime_unicode(immHkl))
1949 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
1950 (LPCWSTR)lpszRegister);
1951 else
1953 LPWSTR lpszwReading = strdupAtoW(lpszReading);
1954 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
1955 BOOL rc;
1957 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
1958 HeapFree(GetProcessHeap(),0,lpszwReading);
1959 HeapFree(GetProcessHeap(),0,lpszwRegister);
1960 return rc;
1963 else
1964 return FALSE;
1967 /***********************************************************************
1968 * ImmRegisterWordW (IMM32.@)
1970 BOOL WINAPI ImmRegisterWordW(
1971 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1973 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1974 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
1975 debugstr_w(lpszRegister));
1976 if (immHkl->hIME && immHkl->pImeRegisterWord)
1978 if (is_kbd_ime_unicode(immHkl))
1979 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
1980 else
1982 LPSTR lpszaReading = strdupWtoA(lpszReading);
1983 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
1984 BOOL rc;
1986 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
1987 (LPCWSTR)lpszaRegister);
1988 HeapFree(GetProcessHeap(),0,lpszaReading);
1989 HeapFree(GetProcessHeap(),0,lpszaRegister);
1990 return rc;
1993 else
1994 return FALSE;
1997 /***********************************************************************
1998 * ImmReleaseContext (IMM32.@)
2000 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2002 static int shown = 0;
2004 if (!shown) {
2005 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2006 shown = 1;
2008 return TRUE;
2011 /***********************************************************************
2012 * ImmRequestMessageA(IMM32.@)
2014 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2016 InputContextData *data = hIMC;
2018 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2020 if (data && IsWindow(data->IMC.hWnd))
2021 return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2023 return 0;
2026 /***********************************************************************
2027 * ImmRequestMessageW(IMM32.@)
2029 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2031 InputContextData *data = hIMC;
2033 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2035 if (data && IsWindow(data->IMC.hWnd))
2036 return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2038 return 0;
2041 /***********************************************************************
2042 * ImmSetCandidateWindow (IMM32.@)
2044 BOOL WINAPI ImmSetCandidateWindow(
2045 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2047 InputContextData *data = hIMC;
2049 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2051 if (!data || !lpCandidate)
2052 return FALSE;
2054 TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
2055 lpCandidate->dwIndex, lpCandidate->dwStyle,
2056 lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
2057 lpCandidate->rcArea.top, lpCandidate->rcArea.left,
2058 lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
2060 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
2061 return FALSE;
2063 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2064 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2065 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2067 return TRUE;
2070 /***********************************************************************
2071 * ImmSetCompositionFontA (IMM32.@)
2073 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2075 InputContextData *data = hIMC;
2076 TRACE("(%p, %p)\n", hIMC, lplf);
2078 if (!data || !lplf)
2079 return FALSE;
2081 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2082 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2083 LF_FACESIZE);
2084 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2085 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2087 return TRUE;
2090 /***********************************************************************
2091 * ImmSetCompositionFontW (IMM32.@)
2093 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2095 InputContextData *data = hIMC;
2096 TRACE("(%p, %p)\n", hIMC, lplf);
2098 if (!data || !lplf)
2099 return FALSE;
2101 data->IMC.lfFont.W = *lplf;
2102 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2103 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2105 return TRUE;
2108 /***********************************************************************
2109 * ImmSetCompositionStringA (IMM32.@)
2111 BOOL WINAPI ImmSetCompositionStringA(
2112 HIMC hIMC, DWORD dwIndex,
2113 LPCVOID lpComp, DWORD dwCompLen,
2114 LPCVOID lpRead, DWORD dwReadLen)
2116 DWORD comp_len;
2117 DWORD read_len;
2118 WCHAR *CompBuffer = NULL;
2119 WCHAR *ReadBuffer = NULL;
2120 BOOL rc;
2121 InputContextData *data = hIMC;
2123 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2124 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2126 if (!data)
2127 return FALSE;
2129 if (!is_himc_ime_unicode(data))
2130 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2131 dwCompLen, lpRead, dwReadLen);
2133 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2134 if (comp_len)
2136 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2137 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2140 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2141 if (read_len)
2143 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2144 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2147 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2148 ReadBuffer, read_len);
2150 HeapFree(GetProcessHeap(), 0, CompBuffer);
2151 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2153 return rc;
2156 /***********************************************************************
2157 * ImmSetCompositionStringW (IMM32.@)
2159 BOOL WINAPI ImmSetCompositionStringW(
2160 HIMC hIMC, DWORD dwIndex,
2161 LPCVOID lpComp, DWORD dwCompLen,
2162 LPCVOID lpRead, DWORD dwReadLen)
2164 DWORD comp_len;
2165 DWORD read_len;
2166 CHAR *CompBuffer = NULL;
2167 CHAR *ReadBuffer = NULL;
2168 BOOL rc;
2169 InputContextData *data = hIMC;
2171 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2172 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2174 if (!data)
2175 return FALSE;
2177 if (is_himc_ime_unicode(data))
2178 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2179 dwCompLen, lpRead, dwReadLen);
2181 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2182 NULL);
2183 if (comp_len)
2185 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2186 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2187 NULL, NULL);
2190 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2191 NULL);
2192 if (read_len)
2194 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2195 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2196 NULL, NULL);
2199 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2200 ReadBuffer, read_len);
2202 HeapFree(GetProcessHeap(), 0, CompBuffer);
2203 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2205 return rc;
2208 /***********************************************************************
2209 * ImmSetCompositionWindow (IMM32.@)
2211 BOOL WINAPI ImmSetCompositionWindow(
2212 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2214 BOOL reshow = FALSE;
2215 InputContextData *data = hIMC;
2217 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2218 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2219 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2220 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2222 if (!data)
2223 return FALSE;
2225 data->IMC.cfCompForm = *lpCompForm;
2227 if (IsWindowVisible(IMM_GetThreadData()->hwndDefault))
2229 reshow = TRUE;
2230 ShowWindow(IMM_GetThreadData()->hwndDefault,SW_HIDE);
2233 /* FIXME: this is a partial stub */
2235 if (reshow)
2236 ShowWindow(IMM_GetThreadData()->hwndDefault,SW_SHOWNOACTIVATE);
2238 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2239 return TRUE;
2242 /***********************************************************************
2243 * ImmSetConversionStatus (IMM32.@)
2245 BOOL WINAPI ImmSetConversionStatus(
2246 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2248 DWORD oldConversion, oldSentence;
2249 InputContextData *data = hIMC;
2251 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2253 if (!data)
2254 return FALSE;
2256 if ( fdwConversion != data->IMC.fdwConversion )
2258 oldConversion = data->IMC.fdwConversion;
2259 data->IMC.fdwConversion = fdwConversion;
2260 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2261 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2263 if ( fdwSentence != data->IMC.fdwSentence )
2265 oldSentence = data->IMC.fdwSentence;
2266 data->IMC.fdwSentence = fdwSentence;
2267 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2268 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2271 return TRUE;
2274 /***********************************************************************
2275 * ImmSetOpenStatus (IMM32.@)
2277 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2279 InputContextData *data = hIMC;
2281 TRACE("%p %d\n", hIMC, fOpen);
2283 if (!data)
2284 return FALSE;
2286 if (data->imeWnd == NULL)
2288 /* create the ime window */
2289 data->imeWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2290 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2291 0, data->immKbd->hIME, 0);
2292 SetWindowLongW(data->imeWnd, IMMGWL_IMC, (LONG)data);
2293 IMM_GetThreadData()->hwndDefault = data->imeWnd;
2296 if (!fOpen != !data->IMC.fOpen)
2298 data->IMC.fOpen = fOpen;
2299 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2300 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2303 return TRUE;
2306 /***********************************************************************
2307 * ImmSetStatusWindowPos (IMM32.@)
2309 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2311 InputContextData *data = hIMC;
2313 TRACE("(%p, %p)\n", hIMC, lpptPos);
2315 if (!data || !lpptPos)
2316 return FALSE;
2318 TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2320 data->IMC.ptStatusWndPos = *lpptPos;
2321 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2322 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2324 return TRUE;
2327 /***********************************************************************
2328 * ImmCreateSoftKeyboard(IMM32.@)
2330 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2332 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2333 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2334 return 0;
2337 /***********************************************************************
2338 * ImmDestroySoftKeyboard(IMM32.@)
2340 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2342 FIXME("(%p): stub\n", hSoftWnd);
2343 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2344 return FALSE;
2347 /***********************************************************************
2348 * ImmShowSoftKeyboard(IMM32.@)
2350 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2352 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2353 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2354 return FALSE;
2357 /***********************************************************************
2358 * ImmSimulateHotKey (IMM32.@)
2360 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2362 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2363 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2364 return FALSE;
2367 /***********************************************************************
2368 * ImmUnregisterWordA (IMM32.@)
2370 BOOL WINAPI ImmUnregisterWordA(
2371 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2373 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2374 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2375 debugstr_a(lpszUnregister));
2376 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2378 if (!is_kbd_ime_unicode(immHkl))
2379 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2380 (LPCWSTR)lpszUnregister);
2381 else
2383 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2384 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2385 BOOL rc;
2387 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2388 HeapFree(GetProcessHeap(),0,lpszwReading);
2389 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2390 return rc;
2393 else
2394 return FALSE;
2397 /***********************************************************************
2398 * ImmUnregisterWordW (IMM32.@)
2400 BOOL WINAPI ImmUnregisterWordW(
2401 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2403 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2404 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2405 debugstr_w(lpszUnregister));
2406 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2408 if (is_kbd_ime_unicode(immHkl))
2409 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2410 else
2412 LPSTR lpszaReading = strdupWtoA(lpszReading);
2413 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2414 BOOL rc;
2416 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2417 (LPCWSTR)lpszaUnregister);
2418 HeapFree(GetProcessHeap(),0,lpszaReading);
2419 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2420 return rc;
2423 else
2424 return FALSE;
2427 /***********************************************************************
2428 * ImmGetImeMenuItemsA (IMM32.@)
2430 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2431 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2432 DWORD dwSize)
2434 InputContextData *data = hIMC;
2435 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2436 lpImeParentMenu, lpImeMenu, dwSize);
2437 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2439 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2440 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2441 (IMEMENUITEMINFOW*)lpImeParentMenu,
2442 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2443 else
2445 IMEMENUITEMINFOW lpImeParentMenuW;
2446 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2447 DWORD rc;
2449 if (lpImeParentMenu)
2450 parent = &lpImeParentMenuW;
2451 if (lpImeMenu)
2453 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2454 dwSize = count * sizeof(IMEMENUITEMINFOW);
2455 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2457 else
2458 lpImeMenuW = NULL;
2460 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2461 parent, lpImeMenuW, dwSize);
2463 if (lpImeParentMenu)
2465 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2466 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2467 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2468 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2469 NULL, NULL);
2471 if (lpImeMenu && rc)
2473 unsigned int i;
2474 for (i = 0; i < rc; i++)
2476 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2477 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2478 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2479 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2480 NULL, NULL);
2483 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2484 return rc;
2487 else
2488 return 0;
2491 /***********************************************************************
2492 * ImmGetImeMenuItemsW (IMM32.@)
2494 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2495 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2496 DWORD dwSize)
2498 InputContextData *data = hIMC;
2499 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2500 lpImeParentMenu, lpImeMenu, dwSize);
2501 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2503 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2504 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2505 lpImeParentMenu, lpImeMenu, dwSize);
2506 else
2508 IMEMENUITEMINFOA lpImeParentMenuA;
2509 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2510 DWORD rc;
2512 if (lpImeParentMenu)
2513 parent = &lpImeParentMenuA;
2514 if (lpImeMenu)
2516 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2517 dwSize = count * sizeof(IMEMENUITEMINFOA);
2518 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2520 else
2521 lpImeMenuA = NULL;
2523 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2524 (IMEMENUITEMINFOW*)parent,
2525 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2527 if (lpImeParentMenu)
2529 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2530 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2531 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2532 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2534 if (lpImeMenu && rc)
2536 unsigned int i;
2537 for (i = 0; i < rc; i++)
2539 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2540 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2541 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2542 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2545 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2546 return rc;
2549 else
2550 return 0;
2553 /***********************************************************************
2554 * ImmLockIMC(IMM32.@)
2556 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2558 InputContextData *data = hIMC;
2560 if (!data)
2561 return NULL;
2562 data->dwLock++;
2563 return &data->IMC;
2566 /***********************************************************************
2567 * ImmUnlockIMC(IMM32.@)
2569 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2571 InputContextData *data = hIMC;
2572 data->dwLock--;
2573 return (data->dwLock!=0);
2576 /***********************************************************************
2577 * ImmGetIMCLockCount(IMM32.@)
2579 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2581 InputContextData *data = hIMC;
2582 return data->dwLock;
2585 /***********************************************************************
2586 * ImmCreateIMCC(IMM32.@)
2588 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2590 IMCCInternal *internal;
2591 int real_size = size + sizeof(IMCCInternal);
2593 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2594 if (internal == NULL)
2595 return NULL;
2597 internal->dwSize = size;
2598 return internal;
2601 /***********************************************************************
2602 * ImmDestroyIMCC(IMM32.@)
2604 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2606 HeapFree(GetProcessHeap(),0,block);
2607 return NULL;
2610 /***********************************************************************
2611 * ImmLockIMCC(IMM32.@)
2613 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2615 IMCCInternal *internal;
2616 internal = imcc;
2618 internal->dwLock ++;
2619 return internal + 1;
2622 /***********************************************************************
2623 * ImmUnlockIMCC(IMM32.@)
2625 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2627 IMCCInternal *internal;
2628 internal = imcc;
2630 internal->dwLock --;
2631 return (internal->dwLock!=0);
2634 /***********************************************************************
2635 * ImmGetIMCCLockCount(IMM32.@)
2637 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2639 IMCCInternal *internal;
2640 internal = imcc;
2642 return internal->dwLock;
2645 /***********************************************************************
2646 * ImmReSizeIMCC(IMM32.@)
2648 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2650 IMCCInternal *internal,*newone;
2651 int real_size = size + sizeof(IMCCInternal);
2653 internal = imcc;
2655 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2656 newone->dwSize = size;
2658 return newone;
2661 /***********************************************************************
2662 * ImmGetIMCCSize(IMM32.@)
2664 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2666 IMCCInternal *internal;
2667 internal = imcc;
2669 return internal->dwSize;
2672 /***********************************************************************
2673 * ImmGenerateMessage(IMM32.@)
2675 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2677 InputContextData *data = hIMC;
2679 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2680 if (data->IMC.dwNumMsgBuf > 0)
2682 LPTRANSMSG lpTransMsg;
2683 DWORD i;
2685 lpTransMsg = ImmLockIMCC(data->IMC.hMsgBuf);
2686 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2687 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2689 ImmUnlockIMCC(data->IMC.hMsgBuf);
2691 data->IMC.dwNumMsgBuf = 0;
2694 return TRUE;
2697 /***********************************************************************
2698 * ImmTranslateMessage(IMM32.@)
2699 * ( Undocumented, call internally and from user32.dll )
2701 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2703 InputContextData *data;
2704 HIMC imc = ImmGetContext(hwnd);
2705 BYTE state[256];
2706 UINT scancode;
2707 LPVOID list = 0;
2708 UINT msg_count;
2709 UINT uVirtKey;
2710 static const DWORD list_count = 10;
2712 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2714 if (imc)
2715 data = imc;
2716 else
2717 return FALSE;
2719 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2720 return FALSE;
2722 GetKeyboardState(state);
2723 scancode = lKeyData >> 0x10 & 0xff;
2725 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2726 ((DWORD*)list)[0] = list_count;
2728 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2730 WCHAR chr;
2732 if (!is_himc_ime_unicode(data))
2733 ToAscii(data->lastVK, scancode, state, &chr, 0);
2734 else
2735 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2736 uVirtKey = MAKELONG(data->lastVK,chr);
2738 else
2739 uVirtKey = data->lastVK;
2741 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2742 TRACE("%i messages generated\n",msg_count);
2743 if (msg_count && msg_count <= list_count)
2745 UINT i;
2746 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2748 for (i = 0; i < msg_count; i++)
2749 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2751 else if (msg_count > list_count)
2752 ImmGenerateMessage(imc);
2754 HeapFree(GetProcessHeap(),0,list);
2756 data->lastVK = VK_PROCESSKEY;
2758 return (msg_count > 0);
2761 /***********************************************************************
2762 * ImmProcessKey(IMM32.@)
2763 * ( Undocumented, called from user32.dll )
2765 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2767 InputContextData *data;
2768 HIMC imc = ImmGetContext(hwnd);
2769 BYTE state[256];
2771 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2773 if (imc)
2774 data = imc;
2775 else
2776 return FALSE;
2778 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
2779 return FALSE;
2781 GetKeyboardState(state);
2782 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
2784 data->lastVK = vKey;
2785 return TRUE;
2788 data->lastVK = VK_PROCESSKEY;
2789 return FALSE;