push 2f3ca95c4974ba229fa47d638b3044f50788f3bd
[wine/hacks.git] / dlls / imm32 / imm.c
blob14178c3d237b58401256b6a8eab3711e60f15db3
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','l','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 %p\n",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;
659 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)GetKeyboardLayout(0));
661 new_context->immKbd->uSelected++;
662 TRACE("Created context %p\n",new_context);
664 return new_context;
667 static BOOL IMM_DestroyContext(HIMC hIMC)
669 InputContextData *data = hIMC;
671 TRACE("Destroying %p\n",hIMC);
673 if (hIMC)
675 data->immKbd->uSelected --;
676 data->immKbd->pImeSelect(hIMC, FALSE);
677 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
679 if (IMM_GetThreadData()->hwndDefault == data->imeWnd)
680 IMM_GetThreadData()->hwndDefault = NULL;
681 DestroyWindow(data->imeWnd);
683 ImmDestroyIMCC(data->IMC.hCompStr);
684 ImmDestroyIMCC(data->IMC.hCandInfo);
685 ImmDestroyIMCC(data->IMC.hGuideLine);
686 ImmDestroyIMCC(data->IMC.hPrivate);
687 ImmDestroyIMCC(data->IMC.hMsgBuf);
689 HeapFree(GetProcessHeap(),0,data);
691 return TRUE;
694 /***********************************************************************
695 * ImmDestroyContext (IMM32.@)
697 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
699 if (hIMC != IMM_GetThreadData()->defaultContext)
700 return IMM_DestroyContext(hIMC);
701 else
702 return FALSE;
705 /***********************************************************************
706 * ImmDisableIME (IMM32.@)
708 BOOL WINAPI ImmDisableIME(DWORD idThread)
710 FIXME("(%d): stub\n", idThread);
711 return TRUE;
714 /***********************************************************************
715 * ImmEnumRegisterWordA (IMM32.@)
717 UINT WINAPI ImmEnumRegisterWordA(
718 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
719 LPCSTR lpszReading, DWORD dwStyle,
720 LPCSTR lpszRegister, LPVOID lpData)
722 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
723 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
724 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
725 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
727 if (!is_kbd_ime_unicode(immHkl))
728 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
729 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
730 else
732 LPWSTR lpszwReading = strdupAtoW(lpszReading);
733 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
734 BOOL rc;
736 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
737 lpszwReading, dwStyle, lpszwRegister,
738 lpData);
740 HeapFree(GetProcessHeap(),0,lpszwReading);
741 HeapFree(GetProcessHeap(),0,lpszwRegister);
742 return rc;
745 else
746 return 0;
749 /***********************************************************************
750 * ImmEnumRegisterWordW (IMM32.@)
752 UINT WINAPI ImmEnumRegisterWordW(
753 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
754 LPCWSTR lpszReading, DWORD dwStyle,
755 LPCWSTR lpszRegister, LPVOID lpData)
757 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
758 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
759 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
760 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
762 if (is_kbd_ime_unicode(immHkl))
763 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
764 lpszRegister, lpData);
765 else
767 LPSTR lpszaReading = strdupWtoA(lpszReading);
768 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
769 BOOL rc;
771 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
772 dwStyle, (LPCWSTR)lpszaRegister, lpData);
774 HeapFree(GetProcessHeap(),0,lpszaReading);
775 HeapFree(GetProcessHeap(),0,lpszaRegister);
776 return rc;
779 else
780 return 0;
783 static inline BOOL EscapeRequiresWA(UINT uEscape)
785 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
786 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
787 uEscape == IME_ESC_IME_NAME ||
788 uEscape == IME_ESC_GETHELPFILENAME)
789 return TRUE;
790 return FALSE;
793 /***********************************************************************
794 * ImmEscapeA (IMM32.@)
796 LRESULT WINAPI ImmEscapeA(
797 HKL hKL, HIMC hIMC,
798 UINT uEscape, LPVOID lpData)
800 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
801 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
803 if (immHkl->hIME && immHkl->pImeEscape)
805 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
806 return immHkl->pImeEscape(hIMC,uEscape,lpData);
807 else
809 WCHAR buffer[81]; /* largest required buffer should be 80 */
810 LRESULT rc;
811 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
813 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
814 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
816 else
818 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
819 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
821 return rc;
824 else
825 return 0;
828 /***********************************************************************
829 * ImmEscapeW (IMM32.@)
831 LRESULT WINAPI ImmEscapeW(
832 HKL hKL, HIMC hIMC,
833 UINT uEscape, LPVOID lpData)
835 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
836 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
838 if (immHkl->hIME && immHkl->pImeEscape)
840 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
841 return immHkl->pImeEscape(hIMC,uEscape,lpData);
842 else
844 CHAR buffer[81]; /* largest required buffer should be 80 */
845 LRESULT rc;
846 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
848 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
849 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
851 else
853 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
854 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
856 return rc;
859 else
860 return 0;
863 /***********************************************************************
864 * ImmGetCandidateListA (IMM32.@)
866 DWORD WINAPI ImmGetCandidateListA(
867 HIMC hIMC, DWORD dwIndex,
868 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
870 InputContextData *data = hIMC;
871 LPCANDIDATEINFO candinfo;
872 LPCANDIDATELIST candlist;
873 DWORD ret = 0;
875 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
877 if (!data || !data->IMC.hCandInfo)
878 return 0;
880 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
881 if ( dwIndex >= candinfo->dwCount ||
882 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
883 goto done;
885 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
886 if ( !candlist->dwSize || !candlist->dwCount )
887 goto done;
889 if ( !is_himc_ime_unicode(data) )
891 ret = candlist->dwSize;
892 if ( lpCandList && dwBufLen >= ret )
893 memcpy(lpCandList, candlist, ret);
895 else
896 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
898 done:
899 ImmUnlockIMCC(data->IMC.hCandInfo);
900 return ret;
903 /***********************************************************************
904 * ImmGetCandidateListCountA (IMM32.@)
906 DWORD WINAPI ImmGetCandidateListCountA(
907 HIMC hIMC, LPDWORD lpdwListCount)
909 InputContextData *data = hIMC;
910 LPCANDIDATEINFO candinfo;
911 DWORD ret, count;
913 TRACE("%p, %p\n", hIMC, lpdwListCount);
915 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
916 return 0;
918 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
920 *lpdwListCount = count = candinfo->dwCount;
922 if ( !is_himc_ime_unicode(data) )
923 ret = candinfo->dwSize;
924 else
926 ret = sizeof(CANDIDATEINFO);
927 while ( count-- )
928 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
931 ImmUnlockIMCC(data->IMC.hCandInfo);
932 return ret;
935 /***********************************************************************
936 * ImmGetCandidateListCountW (IMM32.@)
938 DWORD WINAPI ImmGetCandidateListCountW(
939 HIMC hIMC, LPDWORD lpdwListCount)
941 InputContextData *data = hIMC;
942 LPCANDIDATEINFO candinfo;
943 DWORD ret, count;
945 TRACE("%p, %p\n", hIMC, lpdwListCount);
947 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
948 return 0;
950 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
952 *lpdwListCount = count = candinfo->dwCount;
954 if ( is_himc_ime_unicode(data) )
955 ret = candinfo->dwSize;
956 else
958 ret = sizeof(CANDIDATEINFO);
959 while ( count-- )
960 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
963 ImmUnlockIMCC(data->IMC.hCandInfo);
964 return ret;
967 /***********************************************************************
968 * ImmGetCandidateListW (IMM32.@)
970 DWORD WINAPI ImmGetCandidateListW(
971 HIMC hIMC, DWORD dwIndex,
972 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
974 InputContextData *data = hIMC;
975 LPCANDIDATEINFO candinfo;
976 LPCANDIDATELIST candlist;
977 DWORD ret = 0;
979 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
981 if (!data || !data->IMC.hCandInfo)
982 return 0;
984 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
985 if ( dwIndex >= candinfo->dwCount ||
986 dwIndex >= (sizeof(candinfo->dwOffset) / sizeof(DWORD)) )
987 goto done;
989 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
990 if ( !candlist->dwSize || !candlist->dwCount )
991 goto done;
993 if ( is_himc_ime_unicode(data) )
995 ret = candlist->dwSize;
996 if ( lpCandList && dwBufLen >= ret )
997 memcpy(lpCandList, candlist, ret);
999 else
1000 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1002 done:
1003 ImmUnlockIMCC(data->IMC.hCandInfo);
1004 return ret;
1007 /***********************************************************************
1008 * ImmGetCandidateWindow (IMM32.@)
1010 BOOL WINAPI ImmGetCandidateWindow(
1011 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1013 InputContextData *data = hIMC;
1015 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1017 if (!data || !lpCandidate)
1018 return FALSE;
1020 if ( dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
1021 return FALSE;
1023 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1025 return TRUE;
1028 /***********************************************************************
1029 * ImmGetCompositionFontA (IMM32.@)
1031 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1033 LOGFONTW lfW;
1034 BOOL rc;
1036 TRACE("(%p, %p):\n", hIMC, lplf);
1038 rc = ImmGetCompositionFontW(hIMC,&lfW);
1039 if (!rc || !lplf)
1040 return FALSE;
1042 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1043 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1044 LF_FACESIZE, NULL, NULL);
1045 return TRUE;
1048 /***********************************************************************
1049 * ImmGetCompositionFontW (IMM32.@)
1051 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1053 InputContextData *data = hIMC;
1055 TRACE("(%p, %p):\n", hIMC, lplf);
1057 if (!data || !lplf)
1058 return FALSE;
1060 *lplf = data->IMC.lfFont.W;
1062 return TRUE;
1066 /* Helpers for the GetCompositionString functions */
1068 static INT CopyCompStringIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE target, INT tlen,
1069 BOOL unicode )
1071 INT rc;
1073 if (is_himc_ime_unicode(data) && !unicode)
1074 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)source, slen, (LPSTR)target, tlen, NULL, NULL);
1075 else if (!is_himc_ime_unicode(data) && unicode)
1076 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)source, slen, (LPWSTR)target, tlen) * sizeof(WCHAR);
1077 else
1079 int dlen = (unicode)?sizeof(WCHAR):sizeof(CHAR);
1080 memcpy( target, source, min(slen,tlen)*dlen);
1081 rc = slen*dlen;
1084 return rc;
1087 static INT CopyCompAttrIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1088 LPBYTE target, INT tlen, BOOL unicode )
1090 INT rc;
1092 if (is_himc_ime_unicode(data) && !unicode)
1094 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, sslen, NULL, 0, NULL, NULL);
1095 if (tlen)
1097 const BYTE *src = source;
1098 LPBYTE dst = target;
1099 int i, j = 0, k = 0;
1101 if (rc < tlen)
1102 tlen = rc;
1103 for (i = 0; i < sslen; ++i)
1105 int len;
1107 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)ssource + i, 1,
1108 NULL, 0, NULL, NULL);
1109 for (; len > 0; --len)
1111 dst[j++] = src[k];
1113 if (j >= tlen)
1114 goto end;
1116 ++k;
1118 end:
1119 rc = j;
1122 else if (!is_himc_ime_unicode(data) && unicode)
1124 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, sslen, NULL, 0);
1125 if (tlen)
1127 const BYTE *src = source;
1128 LPBYTE dst = target;
1129 int i, j = 0;
1131 if (rc < tlen)
1132 tlen = rc;
1133 for (i = 0; i < sslen; ++i)
1135 if (IsDBCSLeadByte(((LPSTR)ssource)[i]))
1136 continue;
1138 dst[j++] = src[i];
1140 if (j >= tlen)
1141 break;
1143 rc = j;
1146 else
1148 memcpy( target, source, min(slen,tlen));
1149 rc = slen;
1152 return rc;
1155 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource, INT sslen,
1156 LPBYTE target, INT tlen, BOOL unicode )
1158 INT rc;
1160 if (is_himc_ime_unicode(data) && !unicode)
1162 if (tlen)
1164 int i;
1166 if (slen < tlen)
1167 tlen = slen;
1168 tlen /= sizeof (DWORD);
1169 for (i = 0; i < tlen; ++i)
1171 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1172 ((DWORD *)source)[i],
1173 NULL, 0,
1174 NULL, NULL);
1176 rc = sizeof (DWORD) * i;
1178 else
1179 rc = slen;
1181 else if (!is_himc_ime_unicode(data) && unicode)
1183 if (tlen)
1185 int i;
1187 if (slen < tlen)
1188 tlen = slen;
1189 tlen /= sizeof (DWORD);
1190 for (i = 0; i < tlen; ++i)
1192 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1193 ((DWORD *)source)[i],
1194 NULL, 0);
1196 rc = sizeof (DWORD) * i;
1198 else
1199 rc = slen;
1201 else
1203 memcpy( target, source, min(slen,tlen));
1204 rc = slen;
1207 return rc;
1210 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1212 int rc;
1214 if (is_himc_ime_unicode(data) && !unicode)
1216 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1218 else if (!is_himc_ime_unicode(data) && unicode)
1220 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1222 else
1223 rc = offset;
1225 return rc;
1228 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1229 DWORD dwBufLen, BOOL unicode)
1231 LONG rc = 0;
1232 InputContextData *data = hIMC;
1233 LPCOMPOSITIONSTRING compstr;
1234 LPBYTE compdata;
1236 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1238 if (!data)
1239 return FALSE;
1241 if (!data->IMC.hCompStr)
1242 return FALSE;
1244 compdata = ImmLockIMCC(data->IMC.hCompStr);
1245 compstr = (LPCOMPOSITIONSTRING)compdata;
1247 switch (dwIndex)
1249 case GCS_RESULTSTR:
1250 TRACE("GCS_RESULTSTR\n");
1251 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1252 break;
1253 case GCS_COMPSTR:
1254 TRACE("GCS_COMPSTR\n");
1255 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1256 break;
1257 case GCS_COMPATTR:
1258 TRACE("GCS_COMPATTR\n");
1259 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1260 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1261 lpBuf, dwBufLen, unicode);
1262 break;
1263 case GCS_COMPCLAUSE:
1264 TRACE("GCS_COMPCLAUSE\n");
1265 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1266 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1267 lpBuf, dwBufLen, unicode);
1268 break;
1269 case GCS_RESULTCLAUSE:
1270 TRACE("GCS_RESULTCLAUSE\n");
1271 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1272 compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen,
1273 lpBuf, dwBufLen, unicode);
1274 break;
1275 case GCS_RESULTREADSTR:
1276 TRACE("GCS_RESULTREADSTR\n");
1277 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1278 break;
1279 case GCS_RESULTREADCLAUSE:
1280 TRACE("GCS_RESULTREADCLAUSE\n");
1281 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1282 compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen,
1283 lpBuf, dwBufLen, unicode);
1284 break;
1285 case GCS_COMPREADSTR:
1286 TRACE("GCS_COMPREADSTR\n");
1287 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1288 break;
1289 case GCS_COMPREADATTR:
1290 TRACE("GCS_COMPREADATTR\n");
1291 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1292 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1293 lpBuf, dwBufLen, unicode);
1294 break;
1295 case GCS_COMPREADCLAUSE:
1296 TRACE("GCS_COMPREADCLAUSE\n");
1297 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1298 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1299 lpBuf, dwBufLen, unicode);
1300 break;
1301 case GCS_CURSORPOS:
1302 TRACE("GCS_CURSORPOS\n");
1303 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1304 break;
1305 case GCS_DELTASTART:
1306 TRACE("GCS_DELTASTART\n");
1307 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1308 break;
1309 default:
1310 FIXME("Unhandled index 0x%x\n",dwIndex);
1311 break;
1314 ImmUnlockIMCC(data->IMC.hCompStr);
1316 return rc;
1319 /***********************************************************************
1320 * ImmGetCompositionStringA (IMM32.@)
1322 LONG WINAPI ImmGetCompositionStringA(
1323 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1325 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1329 /***********************************************************************
1330 * ImmGetCompositionStringW (IMM32.@)
1332 LONG WINAPI ImmGetCompositionStringW(
1333 HIMC hIMC, DWORD dwIndex,
1334 LPVOID lpBuf, DWORD dwBufLen)
1336 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1339 /***********************************************************************
1340 * ImmGetCompositionWindow (IMM32.@)
1342 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1344 InputContextData *data = hIMC;
1346 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1348 if (!data)
1349 return FALSE;
1351 *lpCompForm = data->IMC.cfCompForm;
1352 return 1;
1355 /***********************************************************************
1356 * ImmGetContext (IMM32.@)
1359 HIMC WINAPI ImmGetContext(HWND hWnd)
1361 HIMC rc = NULL;
1363 TRACE("%p\n", hWnd);
1364 if (!IMM_GetThreadData()->defaultContext)
1365 IMM_GetThreadData()->defaultContext = ImmCreateContext();
1367 rc = GetPropW(hWnd,szwWineIMCProperty);
1368 if (rc == (HIMC)-1)
1369 rc = NULL;
1370 else if (rc == NULL)
1371 rc = IMM_GetThreadData()->defaultContext;
1373 if (rc)
1375 InputContextData *data = rc;
1376 data->IMC.hWnd = hWnd;
1378 TRACE("returning %p\n", rc);
1380 return rc;
1383 /***********************************************************************
1384 * ImmGetConversionListA (IMM32.@)
1386 DWORD WINAPI ImmGetConversionListA(
1387 HKL hKL, HIMC hIMC,
1388 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1389 DWORD dwBufLen, UINT uFlag)
1391 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1392 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1393 dwBufLen, uFlag);
1394 if (immHkl->hIME && immHkl->pImeConversionList)
1396 if (!is_kbd_ime_unicode(immHkl))
1397 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1398 else
1400 LPCANDIDATELIST lpwDst;
1401 DWORD ret = 0, len;
1402 LPWSTR pwSrc = strdupAtoW(pSrc);
1404 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1405 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1406 if ( lpwDst )
1408 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1409 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1410 HeapFree(GetProcessHeap(), 0, lpwDst);
1412 HeapFree(GetProcessHeap(), 0, pwSrc);
1414 return ret;
1417 else
1418 return 0;
1421 /***********************************************************************
1422 * ImmGetConversionListW (IMM32.@)
1424 DWORD WINAPI ImmGetConversionListW(
1425 HKL hKL, HIMC hIMC,
1426 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1427 DWORD dwBufLen, UINT uFlag)
1429 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1430 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1431 dwBufLen, uFlag);
1432 if (immHkl->hIME && immHkl->pImeConversionList)
1434 if (is_kbd_ime_unicode(immHkl))
1435 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1436 else
1438 LPCANDIDATELIST lpaDst;
1439 DWORD ret = 0, len;
1440 LPSTR paSrc = strdupWtoA(pSrc);
1442 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1443 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1444 if ( lpaDst )
1446 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1447 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1448 HeapFree(GetProcessHeap(), 0, lpaDst);
1450 HeapFree(GetProcessHeap(), 0, paSrc);
1452 return ret;
1455 else
1456 return 0;
1459 /***********************************************************************
1460 * ImmGetConversionStatus (IMM32.@)
1462 BOOL WINAPI ImmGetConversionStatus(
1463 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1465 InputContextData *data = hIMC;
1467 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1469 if (!data)
1470 return FALSE;
1472 if (lpfdwConversion)
1473 *lpfdwConversion = data->IMC.fdwConversion;
1474 if (lpfdwSentence)
1475 *lpfdwSentence = data->IMC.fdwSentence;
1477 return TRUE;
1480 /***********************************************************************
1481 * ImmGetDefaultIMEWnd (IMM32.@)
1483 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1485 TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault);
1486 return IMM_GetThreadData()->hwndDefault;
1489 /***********************************************************************
1490 * ImmGetDescriptionA (IMM32.@)
1492 UINT WINAPI ImmGetDescriptionA(
1493 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1495 WCHAR *buf;
1496 DWORD len;
1498 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1500 /* find out how many characters in the unicode buffer */
1501 len = ImmGetDescriptionW( hKL, NULL, 0 );
1503 /* allocate a buffer of that size */
1504 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1505 if( !buf )
1506 return 0;
1508 /* fetch the unicode buffer */
1509 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1511 /* convert it back to ASCII */
1512 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1513 lpszDescription, uBufLen, NULL, NULL );
1515 HeapFree( GetProcessHeap(), 0, buf );
1517 return len;
1520 /***********************************************************************
1521 * ImmGetDescriptionW (IMM32.@)
1523 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1525 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1527 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1529 if (!uBufLen) return lstrlenW( name );
1530 lstrcpynW( lpszDescription, name, uBufLen );
1531 return lstrlenW( lpszDescription );
1534 /***********************************************************************
1535 * ImmGetGuideLineA (IMM32.@)
1537 DWORD WINAPI ImmGetGuideLineA(
1538 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1540 FIXME("(%p, %d, %s, %d): stub\n",
1541 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1543 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1544 return 0;
1547 /***********************************************************************
1548 * ImmGetGuideLineW (IMM32.@)
1550 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1552 FIXME("(%p, %d, %s, %d): stub\n",
1553 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1555 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1556 return 0;
1559 /***********************************************************************
1560 * ImmGetIMEFileNameA (IMM32.@)
1562 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1564 LPWSTR bufW = NULL;
1565 UINT wBufLen = uBufLen;
1566 UINT rc;
1568 if (uBufLen && lpszFileName)
1569 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1570 else /* We need this to get the number of byte required */
1572 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1573 wBufLen = MAX_PATH;
1576 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1578 if (rc > 0)
1580 if (uBufLen && lpszFileName)
1581 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1582 uBufLen, NULL, NULL);
1583 else /* get the length */
1584 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1585 NULL);
1588 HeapFree(GetProcessHeap(),0,bufW);
1589 return rc;
1592 /***********************************************************************
1593 * ImmGetIMEFileNameW (IMM32.@)
1595 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1597 HKEY hkey;
1598 DWORD length;
1599 DWORD rc;
1600 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1602 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1603 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1604 if (rc != ERROR_SUCCESS)
1606 SetLastError(rc);
1607 return 0;
1610 length = 0;
1611 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1613 if (rc != ERROR_SUCCESS)
1615 RegCloseKey(hkey);
1616 SetLastError(rc);
1617 return 0;
1619 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1621 RegCloseKey(hkey);
1622 if (lpszFileName)
1624 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1625 return 0;
1627 else
1628 return length / sizeof(WCHAR);
1631 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1633 RegCloseKey(hkey);
1635 return length / sizeof(WCHAR);
1638 /***********************************************************************
1639 * ImmGetOpenStatus (IMM32.@)
1641 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1643 InputContextData *data = hIMC;
1645 if (!data)
1646 return FALSE;
1647 FIXME("(%p): semi-stub\n", hIMC);
1649 return data->IMC.fOpen;
1652 /***********************************************************************
1653 * ImmGetProperty (IMM32.@)
1655 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1657 DWORD rc = 0;
1658 ImmHkl *kbd;
1660 TRACE("(%p, %d)\n", hKL, fdwIndex);
1661 kbd = IMM_GetImmHkl(hKL);
1663 if (kbd && kbd->hIME)
1665 switch (fdwIndex)
1667 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1668 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1669 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1670 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1671 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1672 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1673 case IGP_UI: rc = 0; break;
1674 default: rc = 0;
1677 return rc;
1680 /***********************************************************************
1681 * ImmGetRegisterWordStyleA (IMM32.@)
1683 UINT WINAPI ImmGetRegisterWordStyleA(
1684 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1686 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1687 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1688 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1690 if (!is_kbd_ime_unicode(immHkl))
1691 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1692 else
1694 STYLEBUFW sbw;
1695 UINT rc;
1697 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1698 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1699 lpStyleBuf->szDescription, 32, NULL, NULL);
1700 lpStyleBuf->dwStyle = sbw.dwStyle;
1701 return rc;
1704 else
1705 return 0;
1708 /***********************************************************************
1709 * ImmGetRegisterWordStyleW (IMM32.@)
1711 UINT WINAPI ImmGetRegisterWordStyleW(
1712 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1714 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1715 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1716 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1718 if (is_kbd_ime_unicode(immHkl))
1719 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1720 else
1722 STYLEBUFA sba;
1723 UINT rc;
1725 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1726 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1727 lpStyleBuf->szDescription, 32);
1728 lpStyleBuf->dwStyle = sba.dwStyle;
1729 return rc;
1732 else
1733 return 0;
1736 /***********************************************************************
1737 * ImmGetStatusWindowPos (IMM32.@)
1739 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
1741 InputContextData *data = hIMC;
1743 TRACE("(%p, %p)\n", hIMC, lpptPos);
1745 if (!data || !lpptPos)
1746 return FALSE;
1748 *lpptPos = data->IMC.ptStatusWndPos;
1750 return TRUE;
1753 /***********************************************************************
1754 * ImmGetVirtualKey (IMM32.@)
1756 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
1758 OSVERSIONINFOA version;
1759 InputContextData *data = ImmGetContext( hWnd );
1760 TRACE("%p\n", hWnd);
1762 if ( data )
1763 return data->lastVK;
1765 GetVersionExA( &version );
1766 switch(version.dwPlatformId)
1768 case VER_PLATFORM_WIN32_WINDOWS:
1769 return VK_PROCESSKEY;
1770 case VER_PLATFORM_WIN32_NT:
1771 return 0;
1772 default:
1773 FIXME("%d not supported\n",version.dwPlatformId);
1774 return VK_PROCESSKEY;
1778 /***********************************************************************
1779 * ImmInstallIMEA (IMM32.@)
1781 HKL WINAPI ImmInstallIMEA(
1782 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
1784 LPWSTR lpszwIMEFileName;
1785 LPWSTR lpszwLayoutText;
1786 HKL hkl;
1788 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
1789 debugstr_a(lpszLayoutText));
1791 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
1792 lpszwLayoutText = strdupAtoW(lpszLayoutText);
1794 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
1796 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
1797 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
1798 return hkl;
1801 /***********************************************************************
1802 * ImmInstallIMEW (IMM32.@)
1804 HKL WINAPI ImmInstallIMEW(
1805 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
1807 INT lcid = GetUserDefaultLCID();
1808 INT count;
1809 HKL hkl;
1810 DWORD rc;
1811 HKEY hkey;
1812 WCHAR regKey[sizeof(szImeRegFmt)/sizeof(WCHAR)+8];
1814 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
1815 debugstr_w(lpszLayoutText));
1817 /* Start with 2. e001 will be blank and so default to the wine internal IME */
1818 count = 2;
1820 while (count < 0xfff)
1822 DWORD disposition = 0;
1824 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
1825 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
1827 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
1828 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
1829 break;
1830 else if (rc == ERROR_SUCCESS)
1831 RegCloseKey(hkey);
1833 count++;
1836 if (count == 0xfff)
1838 WARN("Unable to find slot to install IME\n");
1839 return 0;
1842 if (rc == ERROR_SUCCESS)
1844 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (LPBYTE)lpszIMEFileName,
1845 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
1846 if (rc == ERROR_SUCCESS)
1847 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (LPBYTE)lpszLayoutText,
1848 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
1849 RegCloseKey(hkey);
1850 return hkl;
1852 else
1854 WARN("Unable to set IME registry values\n");
1855 return 0;
1859 /***********************************************************************
1860 * ImmIsIME (IMM32.@)
1862 BOOL WINAPI ImmIsIME(HKL hKL)
1864 ImmHkl *ptr;
1865 TRACE("(%p):\n", hKL);
1866 ptr = IMM_GetImmHkl(hKL);
1867 return (ptr && ptr->hIME);
1870 /***********************************************************************
1871 * ImmIsUIMessageA (IMM32.@)
1873 BOOL WINAPI ImmIsUIMessageA(
1874 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1876 BOOL rc = FALSE;
1878 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
1879 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1880 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1881 (msg == WM_MSIME_SERVICE) ||
1882 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1883 (msg == WM_MSIME_MOUSE) ||
1884 (msg == WM_MSIME_RECONVERTREQUEST) ||
1885 (msg == WM_MSIME_RECONVERT) ||
1886 (msg == WM_MSIME_QUERYPOSITION) ||
1887 (msg == WM_MSIME_DOCUMENTFEED))
1890 if (!IMM_GetThreadData()->hwndDefault)
1891 ImmGetDefaultIMEWnd(NULL);
1893 if (hWndIME == NULL)
1894 PostMessageA(IMM_GetThreadData()->hwndDefault, msg, wParam, lParam);
1896 rc = TRUE;
1898 return rc;
1901 /***********************************************************************
1902 * ImmIsUIMessageW (IMM32.@)
1904 BOOL WINAPI ImmIsUIMessageW(
1905 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
1907 BOOL rc = FALSE;
1908 TRACE("(%p, %d, %ld, %ld):\n", hWndIME, msg, wParam, lParam);
1909 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
1910 (msg >= WM_IME_SETCONTEXT && msg <= WM_IME_KEYUP) ||
1911 (msg == WM_MSIME_SERVICE) ||
1912 (msg == WM_MSIME_RECONVERTOPTIONS) ||
1913 (msg == WM_MSIME_MOUSE) ||
1914 (msg == WM_MSIME_RECONVERTREQUEST) ||
1915 (msg == WM_MSIME_RECONVERT) ||
1916 (msg == WM_MSIME_QUERYPOSITION) ||
1917 (msg == WM_MSIME_DOCUMENTFEED))
1918 rc = TRUE;
1919 return rc;
1922 /***********************************************************************
1923 * ImmNotifyIME (IMM32.@)
1925 BOOL WINAPI ImmNotifyIME(
1926 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
1928 InputContextData *data = hIMC;
1930 TRACE("(%p, %d, %d, %d)\n",
1931 hIMC, dwAction, dwIndex, dwValue);
1933 if (!data || ! data->immKbd->pNotifyIME)
1934 return FALSE;
1936 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
1939 /***********************************************************************
1940 * ImmRegisterWordA (IMM32.@)
1942 BOOL WINAPI ImmRegisterWordA(
1943 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
1945 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1946 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
1947 debugstr_a(lpszRegister));
1948 if (immHkl->hIME && immHkl->pImeRegisterWord)
1950 if (!is_kbd_ime_unicode(immHkl))
1951 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
1952 (LPCWSTR)lpszRegister);
1953 else
1955 LPWSTR lpszwReading = strdupAtoW(lpszReading);
1956 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
1957 BOOL rc;
1959 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
1960 HeapFree(GetProcessHeap(),0,lpszwReading);
1961 HeapFree(GetProcessHeap(),0,lpszwRegister);
1962 return rc;
1965 else
1966 return FALSE;
1969 /***********************************************************************
1970 * ImmRegisterWordW (IMM32.@)
1972 BOOL WINAPI ImmRegisterWordW(
1973 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
1975 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1976 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
1977 debugstr_w(lpszRegister));
1978 if (immHkl->hIME && immHkl->pImeRegisterWord)
1980 if (is_kbd_ime_unicode(immHkl))
1981 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
1982 else
1984 LPSTR lpszaReading = strdupWtoA(lpszReading);
1985 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
1986 BOOL rc;
1988 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
1989 (LPCWSTR)lpszaRegister);
1990 HeapFree(GetProcessHeap(),0,lpszaReading);
1991 HeapFree(GetProcessHeap(),0,lpszaRegister);
1992 return rc;
1995 else
1996 return FALSE;
1999 /***********************************************************************
2000 * ImmReleaseContext (IMM32.@)
2002 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2004 static int shown = 0;
2006 if (!shown) {
2007 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2008 shown = 1;
2010 return TRUE;
2013 /***********************************************************************
2014 * ImmRequestMessageA(IMM32.@)
2016 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2018 InputContextData *data = hIMC;
2020 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2022 if (data && IsWindow(data->IMC.hWnd))
2023 return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2025 return 0;
2028 /***********************************************************************
2029 * ImmRequestMessageW(IMM32.@)
2031 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2033 InputContextData *data = hIMC;
2035 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2037 if (data && IsWindow(data->IMC.hWnd))
2038 return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2040 return 0;
2043 /***********************************************************************
2044 * ImmSetCandidateWindow (IMM32.@)
2046 BOOL WINAPI ImmSetCandidateWindow(
2047 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2049 InputContextData *data = hIMC;
2051 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2053 if (!data || !lpCandidate)
2054 return FALSE;
2056 TRACE("\t%x, %x, (%i,%i), (%i,%i - %i,%i)\n",
2057 lpCandidate->dwIndex, lpCandidate->dwStyle,
2058 lpCandidate->ptCurrentPos.x, lpCandidate->ptCurrentPos.y,
2059 lpCandidate->rcArea.top, lpCandidate->rcArea.left,
2060 lpCandidate->rcArea.bottom, lpCandidate->rcArea.right);
2062 if ( lpCandidate->dwIndex >= (sizeof(data->IMC.cfCandForm) / sizeof(CANDIDATEFORM)) )
2063 return FALSE;
2065 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2066 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2067 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2069 return TRUE;
2072 /***********************************************************************
2073 * ImmSetCompositionFontA (IMM32.@)
2075 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2077 InputContextData *data = hIMC;
2078 TRACE("(%p, %p)\n", hIMC, lplf);
2080 if (!data || !lplf)
2081 return FALSE;
2083 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2084 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2085 LF_FACESIZE);
2086 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2087 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2089 return TRUE;
2092 /***********************************************************************
2093 * ImmSetCompositionFontW (IMM32.@)
2095 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2097 InputContextData *data = hIMC;
2098 TRACE("(%p, %p)\n", hIMC, lplf);
2100 if (!data || !lplf)
2101 return FALSE;
2103 data->IMC.lfFont.W = *lplf;
2104 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2105 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2107 return TRUE;
2110 /***********************************************************************
2111 * ImmSetCompositionStringA (IMM32.@)
2113 BOOL WINAPI ImmSetCompositionStringA(
2114 HIMC hIMC, DWORD dwIndex,
2115 LPCVOID lpComp, DWORD dwCompLen,
2116 LPCVOID lpRead, DWORD dwReadLen)
2118 DWORD comp_len;
2119 DWORD read_len;
2120 WCHAR *CompBuffer = NULL;
2121 WCHAR *ReadBuffer = NULL;
2122 BOOL rc;
2123 InputContextData *data = hIMC;
2125 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2126 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2128 if (!data)
2129 return FALSE;
2131 if (!is_himc_ime_unicode(data))
2132 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2133 dwCompLen, lpRead, dwReadLen);
2135 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2136 if (comp_len)
2138 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2139 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2142 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2143 if (read_len)
2145 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2146 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2149 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2150 ReadBuffer, read_len);
2152 HeapFree(GetProcessHeap(), 0, CompBuffer);
2153 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2155 return rc;
2158 /***********************************************************************
2159 * ImmSetCompositionStringW (IMM32.@)
2161 BOOL WINAPI ImmSetCompositionStringW(
2162 HIMC hIMC, DWORD dwIndex,
2163 LPCVOID lpComp, DWORD dwCompLen,
2164 LPCVOID lpRead, DWORD dwReadLen)
2166 DWORD comp_len;
2167 DWORD read_len;
2168 CHAR *CompBuffer = NULL;
2169 CHAR *ReadBuffer = NULL;
2170 BOOL rc;
2171 InputContextData *data = hIMC;
2173 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2174 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2176 if (!data)
2177 return FALSE;
2179 if (is_himc_ime_unicode(data))
2180 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2181 dwCompLen, lpRead, dwReadLen);
2183 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2184 NULL);
2185 if (comp_len)
2187 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2188 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2189 NULL, NULL);
2192 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2193 NULL);
2194 if (read_len)
2196 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2197 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2198 NULL, NULL);
2201 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2202 ReadBuffer, read_len);
2204 HeapFree(GetProcessHeap(), 0, CompBuffer);
2205 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2207 return rc;
2210 /***********************************************************************
2211 * ImmSetCompositionWindow (IMM32.@)
2213 BOOL WINAPI ImmSetCompositionWindow(
2214 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2216 BOOL reshow = FALSE;
2217 InputContextData *data = hIMC;
2219 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2220 TRACE("\t%x, (%i,%i), (%i,%i - %i,%i)\n",lpCompForm->dwStyle,
2221 lpCompForm->ptCurrentPos.x, lpCompForm->ptCurrentPos.y, lpCompForm->rcArea.top,
2222 lpCompForm->rcArea.left, lpCompForm->rcArea.bottom, lpCompForm->rcArea.right);
2224 if (!data)
2225 return FALSE;
2227 data->IMC.cfCompForm = *lpCompForm;
2229 if (IsWindowVisible(IMM_GetThreadData()->hwndDefault))
2231 reshow = TRUE;
2232 ShowWindow(IMM_GetThreadData()->hwndDefault,SW_HIDE);
2235 /* FIXME: this is a partial stub */
2237 if (reshow)
2238 ShowWindow(IMM_GetThreadData()->hwndDefault,SW_SHOWNOACTIVATE);
2240 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2241 return TRUE;
2244 /***********************************************************************
2245 * ImmSetConversionStatus (IMM32.@)
2247 BOOL WINAPI ImmSetConversionStatus(
2248 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2250 DWORD oldConversion, oldSentence;
2251 InputContextData *data = hIMC;
2253 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2255 if (!data)
2256 return FALSE;
2258 if ( fdwConversion != data->IMC.fdwConversion )
2260 oldConversion = data->IMC.fdwConversion;
2261 data->IMC.fdwConversion = fdwConversion;
2262 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2263 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2265 if ( fdwSentence != data->IMC.fdwSentence )
2267 oldSentence = data->IMC.fdwSentence;
2268 data->IMC.fdwSentence = fdwSentence;
2269 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2270 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2273 return TRUE;
2276 /***********************************************************************
2277 * ImmSetOpenStatus (IMM32.@)
2279 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2281 InputContextData *data = hIMC;
2283 TRACE("%p %d\n", hIMC, fOpen);
2285 if (!data)
2286 return FALSE;
2288 if (data->imeWnd == NULL)
2290 /* create the ime window */
2291 data->imeWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2292 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2293 0, data->immKbd->hIME, 0);
2294 SetWindowLongW(data->imeWnd, IMMGWL_IMC, (LONG)data);
2295 IMM_GetThreadData()->hwndDefault = data->imeWnd;
2298 if (!fOpen != !data->IMC.fOpen)
2300 data->IMC.fOpen = fOpen;
2301 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2302 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2305 return TRUE;
2308 /***********************************************************************
2309 * ImmSetStatusWindowPos (IMM32.@)
2311 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2313 InputContextData *data = hIMC;
2315 TRACE("(%p, %p)\n", hIMC, lpptPos);
2317 if (!data || !lpptPos)
2318 return FALSE;
2320 TRACE("\t(%i,%i)\n", lpptPos->x, lpptPos->y);
2322 data->IMC.ptStatusWndPos = *lpptPos;
2323 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2324 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2326 return TRUE;
2329 /***********************************************************************
2330 * ImmCreateSoftKeyboard(IMM32.@)
2332 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2334 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2335 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2336 return 0;
2339 /***********************************************************************
2340 * ImmDestroySoftKeyboard(IMM32.@)
2342 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2344 FIXME("(%p): stub\n", hSoftWnd);
2345 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2346 return FALSE;
2349 /***********************************************************************
2350 * ImmShowSoftKeyboard(IMM32.@)
2352 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2354 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2355 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2356 return FALSE;
2359 /***********************************************************************
2360 * ImmSimulateHotKey (IMM32.@)
2362 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2364 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2365 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2366 return FALSE;
2369 /***********************************************************************
2370 * ImmUnregisterWordA (IMM32.@)
2372 BOOL WINAPI ImmUnregisterWordA(
2373 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2375 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2376 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2377 debugstr_a(lpszUnregister));
2378 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2380 if (!is_kbd_ime_unicode(immHkl))
2381 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2382 (LPCWSTR)lpszUnregister);
2383 else
2385 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2386 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2387 BOOL rc;
2389 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2390 HeapFree(GetProcessHeap(),0,lpszwReading);
2391 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2392 return rc;
2395 else
2396 return FALSE;
2399 /***********************************************************************
2400 * ImmUnregisterWordW (IMM32.@)
2402 BOOL WINAPI ImmUnregisterWordW(
2403 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2405 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2406 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2407 debugstr_w(lpszUnregister));
2408 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2410 if (is_kbd_ime_unicode(immHkl))
2411 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2412 else
2414 LPSTR lpszaReading = strdupWtoA(lpszReading);
2415 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2416 BOOL rc;
2418 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2419 (LPCWSTR)lpszaUnregister);
2420 HeapFree(GetProcessHeap(),0,lpszaReading);
2421 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2422 return rc;
2425 else
2426 return FALSE;
2429 /***********************************************************************
2430 * ImmGetImeMenuItemsA (IMM32.@)
2432 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2433 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2434 DWORD dwSize)
2436 InputContextData *data = hIMC;
2437 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2438 lpImeParentMenu, lpImeMenu, dwSize);
2439 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2441 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2442 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2443 (IMEMENUITEMINFOW*)lpImeParentMenu,
2444 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2445 else
2447 IMEMENUITEMINFOW lpImeParentMenuW;
2448 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2449 DWORD rc;
2451 if (lpImeParentMenu)
2452 parent = &lpImeParentMenuW;
2453 if (lpImeMenu)
2455 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2456 dwSize = count * sizeof(IMEMENUITEMINFOW);
2457 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2459 else
2460 lpImeMenuW = NULL;
2462 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2463 parent, lpImeMenuW, dwSize);
2465 if (lpImeParentMenu)
2467 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2468 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2469 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2470 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2471 NULL, NULL);
2473 if (lpImeMenu && rc)
2475 unsigned int i;
2476 for (i = 0; i < rc; i++)
2478 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2479 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2480 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2481 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2482 NULL, NULL);
2485 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2486 return rc;
2489 else
2490 return 0;
2493 /***********************************************************************
2494 * ImmGetImeMenuItemsW (IMM32.@)
2496 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2497 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2498 DWORD dwSize)
2500 InputContextData *data = hIMC;
2501 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2502 lpImeParentMenu, lpImeMenu, dwSize);
2503 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2505 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2506 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2507 lpImeParentMenu, lpImeMenu, dwSize);
2508 else
2510 IMEMENUITEMINFOA lpImeParentMenuA;
2511 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2512 DWORD rc;
2514 if (lpImeParentMenu)
2515 parent = &lpImeParentMenuA;
2516 if (lpImeMenu)
2518 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2519 dwSize = count * sizeof(IMEMENUITEMINFOA);
2520 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2522 else
2523 lpImeMenuA = NULL;
2525 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2526 (IMEMENUITEMINFOW*)parent,
2527 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2529 if (lpImeParentMenu)
2531 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2532 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2533 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2534 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2536 if (lpImeMenu && rc)
2538 unsigned int i;
2539 for (i = 0; i < rc; i++)
2541 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2542 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2543 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2544 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2547 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2548 return rc;
2551 else
2552 return 0;
2555 /***********************************************************************
2556 * ImmLockIMC(IMM32.@)
2558 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2560 InputContextData *data = hIMC;
2562 if (!data)
2563 return NULL;
2564 data->dwLock++;
2565 return &data->IMC;
2568 /***********************************************************************
2569 * ImmUnlockIMC(IMM32.@)
2571 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2573 InputContextData *data = hIMC;
2574 data->dwLock--;
2575 return (data->dwLock!=0);
2578 /***********************************************************************
2579 * ImmGetIMCLockCount(IMM32.@)
2581 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2583 InputContextData *data = hIMC;
2584 return data->dwLock;
2587 /***********************************************************************
2588 * ImmCreateIMCC(IMM32.@)
2590 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2592 IMCCInternal *internal;
2593 int real_size = size + sizeof(IMCCInternal);
2595 internal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, real_size);
2596 if (internal == NULL)
2597 return NULL;
2599 internal->dwSize = size;
2600 return internal;
2603 /***********************************************************************
2604 * ImmDestroyIMCC(IMM32.@)
2606 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2608 HeapFree(GetProcessHeap(),0,block);
2609 return NULL;
2612 /***********************************************************************
2613 * ImmLockIMCC(IMM32.@)
2615 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2617 IMCCInternal *internal;
2618 internal = imcc;
2620 internal->dwLock ++;
2621 return internal + 1;
2624 /***********************************************************************
2625 * ImmUnlockIMCC(IMM32.@)
2627 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2629 IMCCInternal *internal;
2630 internal = imcc;
2632 internal->dwLock --;
2633 return (internal->dwLock!=0);
2636 /***********************************************************************
2637 * ImmGetIMCCLockCount(IMM32.@)
2639 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2641 IMCCInternal *internal;
2642 internal = imcc;
2644 return internal->dwLock;
2647 /***********************************************************************
2648 * ImmReSizeIMCC(IMM32.@)
2650 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2652 IMCCInternal *internal,*newone;
2653 int real_size = size + sizeof(IMCCInternal);
2655 internal = imcc;
2657 newone = HeapReAlloc(GetProcessHeap(), 0, internal, real_size);
2658 newone->dwSize = size;
2660 return newone;
2663 /***********************************************************************
2664 * ImmGetIMCCSize(IMM32.@)
2666 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2668 IMCCInternal *internal;
2669 internal = imcc;
2671 return internal->dwSize;
2674 /***********************************************************************
2675 * ImmGenerateMessage(IMM32.@)
2677 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2679 InputContextData *data = hIMC;
2681 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
2682 if (data->IMC.dwNumMsgBuf > 0)
2684 LPTRANSMSG lpTransMsg;
2685 DWORD i;
2687 lpTransMsg = ImmLockIMCC(data->IMC.hMsgBuf);
2688 for (i = 0; i < data->IMC.dwNumMsgBuf; i++)
2689 ImmInternalPostIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
2691 ImmUnlockIMCC(data->IMC.hMsgBuf);
2693 data->IMC.dwNumMsgBuf = 0;
2696 return TRUE;
2699 /***********************************************************************
2700 * ImmTranslateMessage(IMM32.@)
2701 * ( Undocumented, call internally and from user32.dll )
2703 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
2705 InputContextData *data;
2706 HIMC imc = ImmGetContext(hwnd);
2707 BYTE state[256];
2708 UINT scancode;
2709 LPVOID list = 0;
2710 UINT msg_count;
2711 UINT uVirtKey;
2712 static const DWORD list_count = 10;
2714 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
2716 if (imc)
2717 data = imc;
2718 else
2719 return FALSE;
2721 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
2722 return FALSE;
2724 GetKeyboardState(state);
2725 scancode = lKeyData >> 0x10 & 0xff;
2727 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
2728 ((DWORD*)list)[0] = list_count;
2730 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
2732 WCHAR chr;
2734 if (!is_himc_ime_unicode(data))
2735 ToAscii(data->lastVK, scancode, state, &chr, 0);
2736 else
2737 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
2738 uVirtKey = MAKELONG(data->lastVK,chr);
2740 else
2741 uVirtKey = data->lastVK;
2743 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
2744 TRACE("%i messages generated\n",msg_count);
2745 if (msg_count && msg_count <= list_count)
2747 UINT i;
2748 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
2750 for (i = 0; i < msg_count; i++)
2751 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
2753 else if (msg_count > list_count)
2754 ImmGenerateMessage(imc);
2756 HeapFree(GetProcessHeap(),0,list);
2758 data->lastVK = VK_PROCESSKEY;
2760 return (msg_count > 0);
2763 /***********************************************************************
2764 * ImmProcessKey(IMM32.@)
2765 * ( Undocumented, called from user32.dll )
2767 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
2769 InputContextData *data;
2770 HIMC imc = ImmGetContext(hwnd);
2771 BYTE state[256];
2773 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
2775 if (imc)
2776 data = imc;
2777 else
2778 return FALSE;
2780 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
2781 return FALSE;
2783 GetKeyboardState(state);
2784 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
2786 data->lastVK = vKey;
2787 return TRUE;
2790 data->lastVK = VK_PROCESSKEY;
2791 return FALSE;