ntdll: Load .so builtin modules without using libwine.
[wine/zf.git] / dlls / imm32 / imm.c
blob5f68c1d27ddb6d6d0096691ac22fc28e6fcb780b
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 #define IMM_INIT_MAGIC 0x19650412
40 BOOL WINAPI User32InitializeImmEntryTable(DWORD);
42 typedef struct _tagImmHkl{
43 struct list entry;
44 HKL hkl;
45 HMODULE hIME;
46 IMEINFO imeInfo;
47 WCHAR imeClassName[17]; /* 16 character max */
48 ULONG uSelected;
49 HWND UIWnd;
51 /* Function Pointers */
52 BOOL (WINAPI *pImeInquire)(IMEINFO *, WCHAR *, const WCHAR *);
53 BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *);
54 BOOL (WINAPI *pImeDestroy)(UINT);
55 LRESULT (WINAPI *pImeEscape)(HIMC, UINT, void *);
56 BOOL (WINAPI *pImeSelect)(HIMC, BOOL);
57 BOOL (WINAPI *pImeSetActiveContext)(HIMC, BOOL);
58 UINT (WINAPI *pImeToAsciiEx)(UINT, UINT, const BYTE *, DWORD *, UINT, HIMC);
59 BOOL (WINAPI *pNotifyIME)(HIMC, DWORD, DWORD, DWORD);
60 BOOL (WINAPI *pImeRegisterWord)(const WCHAR *, DWORD, const WCHAR *);
61 BOOL (WINAPI *pImeUnregisterWord)(const WCHAR *, DWORD, const WCHAR *);
62 UINT (WINAPI *pImeEnumRegisterWord)(REGISTERWORDENUMPROCW, const WCHAR *, DWORD, const WCHAR *, void *);
63 BOOL (WINAPI *pImeSetCompositionString)(HIMC, DWORD, const void *, DWORD, const void *, DWORD);
64 DWORD (WINAPI *pImeConversionList)(HIMC, const WCHAR *, CANDIDATELIST *, DWORD, UINT);
65 BOOL (WINAPI *pImeProcessKey)(HIMC, UINT, LPARAM, const BYTE *);
66 UINT (WINAPI *pImeGetRegisterWordStyle)(UINT, STYLEBUFW *);
67 DWORD (WINAPI *pImeGetImeMenuItems)(HIMC, DWORD, DWORD, IMEMENUITEMINFOW *, IMEMENUITEMINFOW *, DWORD);
68 } ImmHkl;
70 typedef struct tagInputContextData
72 DWORD dwLock;
73 INPUTCONTEXT IMC;
74 DWORD threadID;
76 ImmHkl *immKbd;
77 UINT lastVK;
78 BOOL threadDefault;
79 DWORD magic;
80 } InputContextData;
82 #define WINE_IMC_VALID_MAGIC 0x56434D49
84 typedef struct _tagTRANSMSG {
85 UINT message;
86 WPARAM wParam;
87 LPARAM lParam;
88 } TRANSMSG, *LPTRANSMSG;
90 typedef struct _tagIMMThreadData {
91 struct list entry;
92 DWORD threadID;
93 HIMC defaultContext;
94 HWND hwndDefault;
95 BOOL disableIME;
96 DWORD windowRefs;
97 } IMMThreadData;
99 static struct list ImmHklList = LIST_INIT(ImmHklList);
100 static struct list ImmThreadDataList = LIST_INIT(ImmThreadDataList);
102 static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
104 static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
105 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
106 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};
108 static const WCHAR szwIME[] = {'I','M','E',0};
109 static const WCHAR szwDefaultIME[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
111 static CRITICAL_SECTION threaddata_cs;
112 static CRITICAL_SECTION_DEBUG critsect_debug =
114 0, 0, &threaddata_cs,
115 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
116 0, 0, { (DWORD_PTR)(__FILE__ ": threaddata_cs") }
118 static CRITICAL_SECTION threaddata_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
119 static BOOL disable_ime;
121 static inline BOOL is_himc_ime_unicode(const InputContextData *data)
123 return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
126 static inline BOOL is_kbd_ime_unicode(const ImmHkl *hkl)
128 return !!(hkl->imeInfo.fdwProperty & IME_PROP_UNICODE);
131 static BOOL IMM_DestroyContext(HIMC hIMC);
132 static InputContextData* get_imc_data(HIMC hIMC);
134 static inline WCHAR *strdupAtoW( const char *str )
136 WCHAR *ret = NULL;
137 if (str)
139 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
140 if ((ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
141 MultiByteToWideChar( CP_ACP, 0, str, -1, ret, len );
143 return ret;
146 static inline CHAR *strdupWtoA( const WCHAR *str )
148 CHAR *ret = NULL;
149 if (str)
151 DWORD len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
152 if ((ret = HeapAlloc( GetProcessHeap(), 0, len )))
153 WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
155 return ret;
158 static DWORD convert_candidatelist_WtoA(
159 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
161 DWORD ret, i, len;
163 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
164 if ( lpDst && dwBufLen > 0 )
166 *lpDst = *lpSrc;
167 lpDst->dwOffset[0] = ret;
170 for ( i = 0; i < lpSrc->dwCount; i++)
172 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
174 if ( lpDst && dwBufLen > 0 )
176 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
178 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1,
179 (LPSTR)dest, dwBufLen, NULL, NULL);
181 if ( i + 1 < lpSrc->dwCount )
182 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(char);
183 dwBufLen -= len * sizeof(char);
185 else
186 len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)src, -1, NULL, 0, NULL, NULL);
188 ret += len * sizeof(char);
191 if ( lpDst )
192 lpDst->dwSize = ret;
194 return ret;
197 static DWORD convert_candidatelist_AtoW(
198 LPCANDIDATELIST lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen)
200 DWORD ret, i, len;
202 ret = FIELD_OFFSET( CANDIDATELIST, dwOffset[lpSrc->dwCount] );
203 if ( lpDst && dwBufLen > 0 )
205 *lpDst = *lpSrc;
206 lpDst->dwOffset[0] = ret;
209 for ( i = 0; i < lpSrc->dwCount; i++)
211 LPBYTE src = (LPBYTE)lpSrc + lpSrc->dwOffset[i];
213 if ( lpDst && dwBufLen > 0 )
215 LPBYTE dest = (LPBYTE)lpDst + lpDst->dwOffset[i];
217 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1,
218 (LPWSTR)dest, dwBufLen);
220 if ( i + 1 < lpSrc->dwCount )
221 lpDst->dwOffset[i+1] = lpDst->dwOffset[i] + len * sizeof(WCHAR);
222 dwBufLen -= len * sizeof(WCHAR);
224 else
225 len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)src, -1, NULL, 0);
227 ret += len * sizeof(WCHAR);
230 if ( lpDst )
231 lpDst->dwSize = ret;
233 return ret;
236 static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD thread)
238 IMMThreadData *data;
239 DWORD process;
241 if (hwnd)
243 if (!(thread = GetWindowThreadProcessId(hwnd, &process))) return NULL;
244 if (process != GetCurrentProcessId()) return NULL;
246 else if (thread)
248 HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, FALSE, thread);
249 if (!h) return NULL;
250 process = GetProcessIdOfThread(h);
251 CloseHandle(h);
252 if (process != GetCurrentProcessId()) return NULL;
254 else
255 thread = GetCurrentThreadId();
257 EnterCriticalSection(&threaddata_cs);
258 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
259 if (data->threadID == thread) return data;
261 data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
262 data->threadID = thread;
263 list_add_head(&ImmThreadDataList,&data->entry);
264 TRACE("Thread Data Created (%x)\n",thread);
265 return data;
268 static BOOL IMM_IsDefaultContext(HIMC imc)
270 InputContextData *data = get_imc_data(imc);
272 if (!data)
273 return FALSE;
275 return data->threadDefault;
278 static void IMM_FreeThreadData(void)
280 IMMThreadData *data;
282 EnterCriticalSection(&threaddata_cs);
283 LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
285 if (data->threadID == GetCurrentThreadId())
287 list_remove(&data->entry);
288 LeaveCriticalSection(&threaddata_cs);
289 IMM_DestroyContext(data->defaultContext);
290 HeapFree(GetProcessHeap(),0,data);
291 TRACE("Thread Data Destroyed\n");
292 return;
295 LeaveCriticalSection(&threaddata_cs);
298 static HMODULE load_graphics_driver(void)
300 static const WCHAR display_device_guid_propW[] = {
301 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
302 'd','e','v','i','c','e','_','g','u','i','d',0 };
303 static const WCHAR key_pathW[] = {
304 'S','y','s','t','e','m','\\',
305 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
306 'C','o','n','t','r','o','l','\\',
307 'V','i','d','e','o','\\','{',0};
308 static const WCHAR displayW[] = {'}','\\','0','0','0','0',0};
309 static const WCHAR driverW[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
311 HMODULE ret = 0;
312 HKEY hkey;
313 DWORD size;
314 WCHAR path[MAX_PATH];
315 WCHAR key[ARRAY_SIZE( key_pathW ) + ARRAY_SIZE( displayW ) + 40];
316 UINT guid_atom = HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW ));
318 if (!guid_atom) return 0;
319 memcpy( key, key_pathW, sizeof(key_pathW) );
320 if (!GlobalGetAtomNameW( guid_atom, key + lstrlenW(key), 40 )) return 0;
321 lstrcatW( key, displayW );
322 if (RegOpenKeyW( HKEY_LOCAL_MACHINE, key, &hkey )) return 0;
323 size = sizeof(path);
324 if (!RegQueryValueExW( hkey, driverW, NULL, NULL, (BYTE *)path, &size )) ret = LoadLibraryW( path );
325 RegCloseKey( hkey );
326 TRACE( "%s %p\n", debugstr_w(path), ret );
327 return ret;
330 /* ImmHkl loading and freeing */
331 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
332 static ImmHkl *IMM_GetImmHkl(HKL hkl)
334 ImmHkl *ptr;
335 WCHAR filename[MAX_PATH];
337 TRACE("Seeking ime for keyboard %p\n",hkl);
339 LIST_FOR_EACH_ENTRY(ptr, &ImmHklList, ImmHkl, entry)
341 if (ptr->hkl == hkl)
342 return ptr;
344 /* not found... create it */
346 ptr = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ImmHkl));
348 ptr->hkl = hkl;
349 if (ImmGetIMEFileNameW(hkl, filename, MAX_PATH)) ptr->hIME = LoadLibraryW(filename);
350 if (!ptr->hIME) ptr->hIME = load_graphics_driver();
351 if (ptr->hIME)
353 LOAD_FUNCPTR(ImeInquire);
354 if (!ptr->pImeInquire || !ptr->pImeInquire(&ptr->imeInfo, ptr->imeClassName, NULL))
356 FreeLibrary(ptr->hIME);
357 ptr->hIME = NULL;
359 else
361 LOAD_FUNCPTR(ImeDestroy);
362 LOAD_FUNCPTR(ImeSelect);
363 if (!ptr->pImeSelect || !ptr->pImeDestroy)
365 FreeLibrary(ptr->hIME);
366 ptr->hIME = NULL;
368 else
370 LOAD_FUNCPTR(ImeConfigure);
371 LOAD_FUNCPTR(ImeEscape);
372 LOAD_FUNCPTR(ImeSetActiveContext);
373 LOAD_FUNCPTR(ImeToAsciiEx);
374 LOAD_FUNCPTR(NotifyIME);
375 LOAD_FUNCPTR(ImeRegisterWord);
376 LOAD_FUNCPTR(ImeUnregisterWord);
377 LOAD_FUNCPTR(ImeEnumRegisterWord);
378 LOAD_FUNCPTR(ImeSetCompositionString);
379 LOAD_FUNCPTR(ImeConversionList);
380 LOAD_FUNCPTR(ImeProcessKey);
381 LOAD_FUNCPTR(ImeGetRegisterWordStyle);
382 LOAD_FUNCPTR(ImeGetImeMenuItems);
383 /* make sure our classname is WCHAR */
384 if (!is_kbd_ime_unicode(ptr))
386 WCHAR bufW[17];
387 MultiByteToWideChar(CP_ACP, 0, (LPSTR)ptr->imeClassName,
388 -1, bufW, 17);
389 lstrcpyW(ptr->imeClassName, bufW);
394 list_add_head(&ImmHklList,&ptr->entry);
396 return ptr;
398 #undef LOAD_FUNCPTR
400 HWND WINAPI __wine_get_ui_window(HKL hkl)
402 ImmHkl *immHkl = IMM_GetImmHkl(hkl);
403 return immHkl->UIWnd;
406 static void IMM_FreeAllImmHkl(void)
408 ImmHkl *ptr,*cursor2;
410 LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
412 list_remove(&ptr->entry);
413 if (ptr->hIME)
415 ptr->pImeDestroy(1);
416 FreeLibrary(ptr->hIME);
418 if (ptr->UIWnd)
419 DestroyWindow(ptr->UIWnd);
420 HeapFree(GetProcessHeap(),0,ptr);
424 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
426 TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
427 switch (fdwReason)
429 case DLL_PROCESS_ATTACH:
430 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
432 return FALSE;
434 break;
435 case DLL_THREAD_ATTACH:
436 break;
437 case DLL_THREAD_DETACH:
438 IMM_FreeThreadData();
439 break;
440 case DLL_PROCESS_DETACH:
441 if (lpReserved) break;
442 IMM_FreeThreadData();
443 IMM_FreeAllImmHkl();
444 break;
446 return TRUE;
449 /* for posting messages as the IME */
450 static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
452 HWND target = GetFocus();
453 if (!target)
454 PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
455 else
456 PostMessageW(target, msg, wParam, lParam);
459 /* for sending messages as the IME */
460 static void ImmInternalSendIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
462 HWND target = GetFocus();
463 if (!target)
464 SendMessageW(data->IMC.hWnd,msg,wParam,lParam);
465 else
466 SendMessageW(target, msg, wParam, lParam);
469 static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, LPARAM lParam)
471 HWND target;
473 target = data->IMC.hWnd;
474 if (!target) target = GetFocus();
476 if (target)
477 return SendMessageW(target, WM_IME_NOTIFY, notify, lParam);
479 return 0;
482 static HIMCC ImmCreateBlankCompStr(void)
484 HIMCC rc;
485 LPCOMPOSITIONSTRING ptr;
486 rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
487 ptr = ImmLockIMCC(rc);
488 memset(ptr,0,sizeof(COMPOSITIONSTRING));
489 ptr->dwSize = sizeof(COMPOSITIONSTRING);
490 ImmUnlockIMCC(rc);
491 return rc;
494 static InputContextData* get_imc_data(HIMC hIMC)
496 InputContextData *data = hIMC;
498 if (hIMC == NULL)
499 return NULL;
501 if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
503 SetLastError(ERROR_INVALID_HANDLE);
504 return NULL;
506 return data;
509 static HIMC get_default_context( HWND hwnd )
511 HIMC ret;
512 IMMThreadData* thread_data = IMM_GetThreadData( hwnd, 0 );
514 if (!thread_data) return 0;
516 if (thread_data->defaultContext)
518 ret = thread_data->defaultContext;
519 LeaveCriticalSection(&threaddata_cs);
520 return ret;
523 /* can't create a default context in another thread */
524 if (thread_data->threadID != GetCurrentThreadId())
526 LeaveCriticalSection(&threaddata_cs);
527 return 0;
530 LeaveCriticalSection(&threaddata_cs);
532 ret = ImmCreateContext();
533 if (!ret) return 0;
534 ((InputContextData*)ret)->threadDefault = TRUE;
536 /* thread_data is in the current thread so we can assume it's still valid */
537 EnterCriticalSection(&threaddata_cs);
539 if (thread_data->defaultContext) /* someone beat us */
541 IMM_DestroyContext( ret );
542 ret = thread_data->defaultContext;
544 else thread_data->defaultContext = ret;
546 LeaveCriticalSection(&threaddata_cs);
547 return ret;
550 static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
552 InputContextData *data;
554 if (hWnd)
556 DWORD thread = GetWindowThreadProcessId(hWnd, NULL);
557 if (thread != GetCurrentThreadId()) return TRUE;
559 data = get_imc_data(hIMC);
560 if (data && data->threadID != GetCurrentThreadId())
561 return TRUE;
563 return FALSE;
566 /***********************************************************************
567 * ImmAssociateContext (IMM32.@)
569 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
571 HIMC old = NULL;
572 InputContextData *data = get_imc_data(hIMC);
574 TRACE("(%p, %p):\n", hWnd, hIMC);
576 if(hIMC && !data)
577 return NULL;
580 * If already associated just return
582 if (hIMC && data->IMC.hWnd == hWnd)
583 return hIMC;
585 if (hIMC && IMM_IsCrossThreadAccess(hWnd, hIMC))
586 return NULL;
588 if (hWnd)
590 HIMC defaultContext = get_default_context( hWnd );
591 old = RemovePropW(hWnd,szwWineIMCProperty);
593 if (old == NULL)
594 old = defaultContext;
595 else if (old == (HIMC)-1)
596 old = NULL;
598 if (hIMC != defaultContext)
600 if (hIMC == NULL) /* Meaning disable imm for that window*/
601 SetPropW(hWnd,szwWineIMCProperty,(HANDLE)-1);
602 else
603 SetPropW(hWnd,szwWineIMCProperty,hIMC);
606 if (old)
608 InputContextData *old_data = old;
609 if (old_data->IMC.hWnd == hWnd)
610 old_data->IMC.hWnd = NULL;
614 if (!hIMC)
615 return old;
617 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, FALSE, ISC_SHOWUIALL);
618 data->IMC.hWnd = hWnd;
619 SendMessageW(data->IMC.hWnd, WM_IME_SETCONTEXT, TRUE, ISC_SHOWUIALL);
621 return old;
626 * Helper function for ImmAssociateContextEx
628 static BOOL CALLBACK _ImmAssociateContextExEnumProc(HWND hwnd, LPARAM lParam)
630 HIMC hImc = (HIMC)lParam;
631 ImmAssociateContext(hwnd,hImc);
632 return TRUE;
635 /***********************************************************************
636 * ImmAssociateContextEx (IMM32.@)
638 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
640 TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
642 if (!hWnd)
643 return FALSE;
645 switch (dwFlags)
647 case 0:
648 ImmAssociateContext(hWnd,hIMC);
649 return TRUE;
650 case IACE_DEFAULT:
652 HIMC defaultContext = get_default_context( hWnd );
653 if (!defaultContext) return FALSE;
654 ImmAssociateContext(hWnd,defaultContext);
655 return TRUE;
657 case IACE_IGNORENOCONTEXT:
658 if (GetPropW(hWnd,szwWineIMCProperty))
659 ImmAssociateContext(hWnd,hIMC);
660 return TRUE;
661 case IACE_CHILDREN:
662 EnumChildWindows(hWnd,_ImmAssociateContextExEnumProc,(LPARAM)hIMC);
663 return TRUE;
664 default:
665 FIXME("Unknown dwFlags 0x%x\n",dwFlags);
666 return FALSE;
670 /***********************************************************************
671 * ImmConfigureIMEA (IMM32.@)
673 BOOL WINAPI ImmConfigureIMEA(
674 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
676 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
678 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
680 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
681 return FALSE;
683 if (immHkl->hIME && immHkl->pImeConfigure)
685 if (dwMode != IME_CONFIG_REGISTERWORD || !is_kbd_ime_unicode(immHkl))
686 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
687 else
689 REGISTERWORDW rww;
690 REGISTERWORDA *rwa = lpData;
691 BOOL rc;
693 rww.lpReading = strdupAtoW(rwa->lpReading);
694 rww.lpWord = strdupAtoW(rwa->lpWord);
695 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rww);
696 HeapFree(GetProcessHeap(),0,rww.lpReading);
697 HeapFree(GetProcessHeap(),0,rww.lpWord);
698 return rc;
701 else
702 return FALSE;
705 /***********************************************************************
706 * ImmConfigureIMEW (IMM32.@)
708 BOOL WINAPI ImmConfigureIMEW(
709 HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData)
711 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
713 TRACE("(%p, %p, %d, %p):\n", hKL, hWnd, dwMode, lpData);
715 if (dwMode == IME_CONFIG_REGISTERWORD && !lpData)
716 return FALSE;
718 if (immHkl->hIME && immHkl->pImeConfigure)
720 if (dwMode != IME_CONFIG_REGISTERWORD || is_kbd_ime_unicode(immHkl))
721 return immHkl->pImeConfigure(hKL,hWnd,dwMode,lpData);
722 else
724 REGISTERWORDW *rww = lpData;
725 REGISTERWORDA rwa;
726 BOOL rc;
728 rwa.lpReading = strdupWtoA(rww->lpReading);
729 rwa.lpWord = strdupWtoA(rww->lpWord);
730 rc = immHkl->pImeConfigure(hKL,hWnd,dwMode,&rwa);
731 HeapFree(GetProcessHeap(),0,rwa.lpReading);
732 HeapFree(GetProcessHeap(),0,rwa.lpWord);
733 return rc;
736 else
737 return FALSE;
740 /***********************************************************************
741 * ImmCreateContext (IMM32.@)
743 HIMC WINAPI ImmCreateContext(void)
745 InputContextData *new_context;
746 LPGUIDELINE gl;
747 LPCANDIDATEINFO ci;
748 int i;
750 new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
752 /* Load the IME */
753 new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
755 if (!new_context->immKbd->hIME)
757 TRACE("IME dll could not be loaded\n");
758 HeapFree(GetProcessHeap(),0,new_context);
759 return 0;
762 /* the HIMCCs are never NULL */
763 new_context->IMC.hCompStr = ImmCreateBlankCompStr();
764 new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
765 new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
766 ci = ImmLockIMCC(new_context->IMC.hCandInfo);
767 memset(ci,0,sizeof(CANDIDATEINFO));
768 ci->dwSize = sizeof(CANDIDATEINFO);
769 ImmUnlockIMCC(new_context->IMC.hCandInfo);
770 new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
771 gl = ImmLockIMCC(new_context->IMC.hGuideLine);
772 memset(gl,0,sizeof(GUIDELINE));
773 gl->dwSize = sizeof(GUIDELINE);
774 ImmUnlockIMCC(new_context->IMC.hGuideLine);
776 for (i = 0; i < ARRAY_SIZE(new_context->IMC.cfCandForm); i++)
777 new_context->IMC.cfCandForm[i].dwIndex = ~0u;
779 /* Initialize the IME Private */
780 new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
782 new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps;
783 new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps;
785 if (!new_context->immKbd->pImeSelect(new_context, TRUE))
787 TRACE("Selection of IME failed\n");
788 IMM_DestroyContext(new_context);
789 return 0;
791 new_context->threadID = GetCurrentThreadId();
792 SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd);
794 new_context->immKbd->uSelected++;
795 TRACE("Created context %p\n",new_context);
797 new_context->magic = WINE_IMC_VALID_MAGIC;
798 return new_context;
801 static BOOL IMM_DestroyContext(HIMC hIMC)
803 InputContextData *data = get_imc_data(hIMC);
805 TRACE("Destroying %p\n",hIMC);
807 if (!data)
808 return FALSE;
810 data->immKbd->uSelected --;
811 data->immKbd->pImeSelect(hIMC, FALSE);
812 SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd);
814 ImmDestroyIMCC(data->IMC.hCompStr);
815 ImmDestroyIMCC(data->IMC.hCandInfo);
816 ImmDestroyIMCC(data->IMC.hGuideLine);
817 ImmDestroyIMCC(data->IMC.hPrivate);
818 ImmDestroyIMCC(data->IMC.hMsgBuf);
820 data->magic = 0;
821 HeapFree(GetProcessHeap(),0,data);
823 return TRUE;
826 /***********************************************************************
827 * ImmDestroyContext (IMM32.@)
829 BOOL WINAPI ImmDestroyContext(HIMC hIMC)
831 if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
832 return IMM_DestroyContext(hIMC);
833 else
834 return FALSE;
837 /***********************************************************************
838 * ImmDisableIME (IMM32.@)
840 BOOL WINAPI ImmDisableIME(DWORD idThread)
842 if (idThread == (DWORD)-1)
843 disable_ime = TRUE;
844 else {
845 IMMThreadData *thread_data = IMM_GetThreadData(NULL, idThread);
846 if (!thread_data) return FALSE;
847 thread_data->disableIME = TRUE;
848 LeaveCriticalSection(&threaddata_cs);
850 return TRUE;
853 /***********************************************************************
854 * ImmEnumRegisterWordA (IMM32.@)
856 UINT WINAPI ImmEnumRegisterWordA(
857 HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
858 LPCSTR lpszReading, DWORD dwStyle,
859 LPCSTR lpszRegister, LPVOID lpData)
861 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
862 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
863 debugstr_a(lpszReading), dwStyle, debugstr_a(lpszRegister), lpData);
864 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
866 if (!is_kbd_ime_unicode(immHkl))
867 return immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
868 (LPCWSTR)lpszReading, dwStyle, (LPCWSTR)lpszRegister, lpData);
869 else
871 LPWSTR lpszwReading = strdupAtoW(lpszReading);
872 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
873 BOOL rc;
875 rc = immHkl->pImeEnumRegisterWord((REGISTERWORDENUMPROCW)lpfnEnumProc,
876 lpszwReading, dwStyle, lpszwRegister,
877 lpData);
879 HeapFree(GetProcessHeap(),0,lpszwReading);
880 HeapFree(GetProcessHeap(),0,lpszwRegister);
881 return rc;
884 else
885 return 0;
888 /***********************************************************************
889 * ImmEnumRegisterWordW (IMM32.@)
891 UINT WINAPI ImmEnumRegisterWordW(
892 HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
893 LPCWSTR lpszReading, DWORD dwStyle,
894 LPCWSTR lpszRegister, LPVOID lpData)
896 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
897 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL, lpfnEnumProc,
898 debugstr_w(lpszReading), dwStyle, debugstr_w(lpszRegister), lpData);
899 if (immHkl->hIME && immHkl->pImeEnumRegisterWord)
901 if (is_kbd_ime_unicode(immHkl))
902 return immHkl->pImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
903 lpszRegister, lpData);
904 else
906 LPSTR lpszaReading = strdupWtoA(lpszReading);
907 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
908 BOOL rc;
910 rc = immHkl->pImeEnumRegisterWord(lpfnEnumProc, (LPCWSTR)lpszaReading,
911 dwStyle, (LPCWSTR)lpszaRegister, lpData);
913 HeapFree(GetProcessHeap(),0,lpszaReading);
914 HeapFree(GetProcessHeap(),0,lpszaRegister);
915 return rc;
918 else
919 return 0;
922 static inline BOOL EscapeRequiresWA(UINT uEscape)
924 if (uEscape == IME_ESC_GET_EUDC_DICTIONARY ||
925 uEscape == IME_ESC_SET_EUDC_DICTIONARY ||
926 uEscape == IME_ESC_IME_NAME ||
927 uEscape == IME_ESC_GETHELPFILENAME)
928 return TRUE;
929 return FALSE;
932 /***********************************************************************
933 * ImmEscapeA (IMM32.@)
935 LRESULT WINAPI ImmEscapeA(
936 HKL hKL, HIMC hIMC,
937 UINT uEscape, LPVOID lpData)
939 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
940 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
942 if (immHkl->hIME && immHkl->pImeEscape)
944 if (!EscapeRequiresWA(uEscape) || !is_kbd_ime_unicode(immHkl))
945 return immHkl->pImeEscape(hIMC,uEscape,lpData);
946 else
948 WCHAR buffer[81]; /* largest required buffer should be 80 */
949 LRESULT rc;
950 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
952 MultiByteToWideChar(CP_ACP,0,lpData,-1,buffer,81);
953 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
955 else
957 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
958 WideCharToMultiByte(CP_ACP,0,buffer,-1,lpData,80, NULL, NULL);
960 return rc;
963 else
964 return 0;
967 /***********************************************************************
968 * ImmEscapeW (IMM32.@)
970 LRESULT WINAPI ImmEscapeW(
971 HKL hKL, HIMC hIMC,
972 UINT uEscape, LPVOID lpData)
974 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
975 TRACE("(%p, %p, %d, %p):\n", hKL, hIMC, uEscape, lpData);
977 if (immHkl->hIME && immHkl->pImeEscape)
979 if (!EscapeRequiresWA(uEscape) || is_kbd_ime_unicode(immHkl))
980 return immHkl->pImeEscape(hIMC,uEscape,lpData);
981 else
983 CHAR buffer[81]; /* largest required buffer should be 80 */
984 LRESULT rc;
985 if (uEscape == IME_ESC_SET_EUDC_DICTIONARY)
987 WideCharToMultiByte(CP_ACP,0,lpData,-1,buffer,81, NULL, NULL);
988 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
990 else
992 rc = immHkl->pImeEscape(hIMC,uEscape,buffer);
993 MultiByteToWideChar(CP_ACP,0,buffer,-1,lpData,80);
995 return rc;
998 else
999 return 0;
1002 /***********************************************************************
1003 * ImmGetCandidateListA (IMM32.@)
1005 DWORD WINAPI ImmGetCandidateListA(
1006 HIMC hIMC, DWORD dwIndex,
1007 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1009 InputContextData *data = get_imc_data(hIMC);
1010 LPCANDIDATEINFO candinfo;
1011 LPCANDIDATELIST candlist;
1012 DWORD ret = 0;
1014 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1016 if (!data || !data->IMC.hCandInfo)
1017 return 0;
1019 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1020 if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset))
1021 goto done;
1023 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1024 if ( !candlist->dwSize || !candlist->dwCount )
1025 goto done;
1027 if ( !is_himc_ime_unicode(data) )
1029 ret = candlist->dwSize;
1030 if ( lpCandList && dwBufLen >= ret )
1031 memcpy(lpCandList, candlist, ret);
1033 else
1034 ret = convert_candidatelist_WtoA( candlist, lpCandList, dwBufLen);
1036 done:
1037 ImmUnlockIMCC(data->IMC.hCandInfo);
1038 return ret;
1041 /***********************************************************************
1042 * ImmGetCandidateListCountA (IMM32.@)
1044 DWORD WINAPI ImmGetCandidateListCountA(
1045 HIMC hIMC, LPDWORD lpdwListCount)
1047 InputContextData *data = get_imc_data(hIMC);
1048 LPCANDIDATEINFO candinfo;
1049 DWORD ret, count;
1051 TRACE("%p, %p\n", hIMC, lpdwListCount);
1053 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
1054 return 0;
1056 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1058 *lpdwListCount = count = candinfo->dwCount;
1060 if ( !is_himc_ime_unicode(data) )
1061 ret = candinfo->dwSize;
1062 else
1064 ret = sizeof(CANDIDATEINFO);
1065 while ( count-- )
1066 ret += ImmGetCandidateListA(hIMC, count, NULL, 0);
1069 ImmUnlockIMCC(data->IMC.hCandInfo);
1070 return ret;
1073 /***********************************************************************
1074 * ImmGetCandidateListCountW (IMM32.@)
1076 DWORD WINAPI ImmGetCandidateListCountW(
1077 HIMC hIMC, LPDWORD lpdwListCount)
1079 InputContextData *data = get_imc_data(hIMC);
1080 LPCANDIDATEINFO candinfo;
1081 DWORD ret, count;
1083 TRACE("%p, %p\n", hIMC, lpdwListCount);
1085 if (!data || !lpdwListCount || !data->IMC.hCandInfo)
1086 return 0;
1088 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1090 *lpdwListCount = count = candinfo->dwCount;
1092 if ( is_himc_ime_unicode(data) )
1093 ret = candinfo->dwSize;
1094 else
1096 ret = sizeof(CANDIDATEINFO);
1097 while ( count-- )
1098 ret += ImmGetCandidateListW(hIMC, count, NULL, 0);
1101 ImmUnlockIMCC(data->IMC.hCandInfo);
1102 return ret;
1105 /***********************************************************************
1106 * ImmGetCandidateListW (IMM32.@)
1108 DWORD WINAPI ImmGetCandidateListW(
1109 HIMC hIMC, DWORD dwIndex,
1110 LPCANDIDATELIST lpCandList, DWORD dwBufLen)
1112 InputContextData *data = get_imc_data(hIMC);
1113 LPCANDIDATEINFO candinfo;
1114 LPCANDIDATELIST candlist;
1115 DWORD ret = 0;
1117 TRACE("%p, %d, %p, %d\n", hIMC, dwIndex, lpCandList, dwBufLen);
1119 if (!data || !data->IMC.hCandInfo)
1120 return 0;
1122 candinfo = ImmLockIMCC(data->IMC.hCandInfo);
1123 if (dwIndex >= candinfo->dwCount || dwIndex >= ARRAY_SIZE(candinfo->dwOffset))
1124 goto done;
1126 candlist = (LPCANDIDATELIST)((LPBYTE)candinfo + candinfo->dwOffset[dwIndex]);
1127 if ( !candlist->dwSize || !candlist->dwCount )
1128 goto done;
1130 if ( is_himc_ime_unicode(data) )
1132 ret = candlist->dwSize;
1133 if ( lpCandList && dwBufLen >= ret )
1134 memcpy(lpCandList, candlist, ret);
1136 else
1137 ret = convert_candidatelist_AtoW( candlist, lpCandList, dwBufLen);
1139 done:
1140 ImmUnlockIMCC(data->IMC.hCandInfo);
1141 return ret;
1144 /***********************************************************************
1145 * ImmGetCandidateWindow (IMM32.@)
1147 BOOL WINAPI ImmGetCandidateWindow(
1148 HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
1150 InputContextData *data = get_imc_data(hIMC);
1152 TRACE("%p, %d, %p\n", hIMC, dwIndex, lpCandidate);
1154 if (!data || !lpCandidate)
1155 return FALSE;
1157 if (dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm))
1158 return FALSE;
1160 if (data->IMC.cfCandForm[dwIndex].dwIndex != dwIndex)
1161 return FALSE;
1163 *lpCandidate = data->IMC.cfCandForm[dwIndex];
1165 return TRUE;
1168 /***********************************************************************
1169 * ImmGetCompositionFontA (IMM32.@)
1171 BOOL WINAPI ImmGetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
1173 LOGFONTW lfW;
1174 BOOL rc;
1176 TRACE("(%p, %p):\n", hIMC, lplf);
1178 rc = ImmGetCompositionFontW(hIMC,&lfW);
1179 if (!rc || !lplf)
1180 return FALSE;
1182 memcpy(lplf,&lfW,sizeof(LOGFONTA));
1183 WideCharToMultiByte(CP_ACP, 0, lfW.lfFaceName, -1, lplf->lfFaceName,
1184 LF_FACESIZE, NULL, NULL);
1185 return TRUE;
1188 /***********************************************************************
1189 * ImmGetCompositionFontW (IMM32.@)
1191 BOOL WINAPI ImmGetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
1193 InputContextData *data = get_imc_data(hIMC);
1195 TRACE("(%p, %p):\n", hIMC, lplf);
1197 if (!data || !lplf)
1198 return FALSE;
1200 *lplf = data->IMC.lfFont.W;
1202 return TRUE;
1206 /* Helpers for the GetCompositionString functions */
1208 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
1209 length is always in bytes. */
1210 static INT CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT src_len, void *dst,
1211 INT dst_len, BOOL unicode)
1213 int char_size = unicode ? sizeof(WCHAR) : sizeof(char);
1214 INT ret;
1216 if (is_himc_ime_unicode(data) ^ unicode)
1218 if (unicode)
1219 ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len / sizeof(WCHAR));
1220 else
1221 ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, NULL, NULL);
1222 ret *= char_size;
1224 else
1226 if (dst_len)
1228 ret = min(src_len * char_size, dst_len);
1229 memcpy(dst, src, ret);
1231 else
1232 ret = src_len * char_size;
1235 return ret;
1238 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
1239 passed mode. String length is in characters, attributes are in byte arrays. */
1240 static INT CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE *src, INT src_len, const void *comp_string,
1241 INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
1243 union
1245 const void *str;
1246 const WCHAR *strW;
1247 const char *strA;
1248 } string;
1249 INT rc;
1251 string.str = comp_string;
1253 if (is_himc_ime_unicode(data) && !unicode)
1255 rc = WideCharToMultiByte(CP_ACP, 0, string.strW, str_len, NULL, 0, NULL, NULL);
1256 if (dst_len)
1258 int i, j = 0, k = 0;
1260 if (rc < dst_len)
1261 dst_len = rc;
1262 for (i = 0; i < str_len; ++i)
1264 int len;
1266 len = WideCharToMultiByte(CP_ACP, 0, string.strW + i, 1, NULL, 0, NULL, NULL);
1267 for (; len > 0; --len)
1269 dst[j++] = src[k];
1271 if (j >= dst_len)
1272 goto end;
1274 ++k;
1276 end:
1277 rc = j;
1280 else if (!is_himc_ime_unicode(data) && unicode)
1282 rc = MultiByteToWideChar(CP_ACP, 0, string.strA, str_len, NULL, 0);
1283 if (dst_len)
1285 int i, j = 0;
1287 if (rc < dst_len)
1288 dst_len = rc;
1289 for (i = 0; i < str_len; ++i)
1291 if (IsDBCSLeadByte(string.strA[i]))
1292 continue;
1294 dst[j++] = src[i];
1296 if (j >= dst_len)
1297 break;
1299 rc = j;
1302 else
1304 memcpy(dst, src, min(src_len, dst_len));
1305 rc = src_len;
1308 return rc;
1311 static INT CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
1312 LPBYTE target, INT tlen, BOOL unicode )
1314 INT rc;
1316 if (is_himc_ime_unicode(data) && !unicode)
1318 if (tlen)
1320 int i;
1322 if (slen < tlen)
1323 tlen = slen;
1324 tlen /= sizeof (DWORD);
1325 for (i = 0; i < tlen; ++i)
1327 ((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
1328 ((DWORD *)source)[i],
1329 NULL, 0,
1330 NULL, NULL);
1332 rc = sizeof (DWORD) * i;
1334 else
1335 rc = slen;
1337 else if (!is_himc_ime_unicode(data) && unicode)
1339 if (tlen)
1341 int i;
1343 if (slen < tlen)
1344 tlen = slen;
1345 tlen /= sizeof (DWORD);
1346 for (i = 0; i < tlen; ++i)
1348 ((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
1349 ((DWORD *)source)[i],
1350 NULL, 0);
1352 rc = sizeof (DWORD) * i;
1354 else
1355 rc = slen;
1357 else
1359 memcpy( target, source, min(slen,tlen));
1360 rc = slen;
1363 return rc;
1366 static INT CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
1368 int rc;
1370 if (is_himc_ime_unicode(data) && !unicode)
1372 rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
1374 else if (!is_himc_ime_unicode(data) && unicode)
1376 rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
1378 else
1379 rc = offset;
1381 return rc;
1384 static LONG ImmGetCompositionStringT( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
1385 DWORD dwBufLen, BOOL unicode)
1387 LONG rc = 0;
1388 InputContextData *data = get_imc_data(hIMC);
1389 LPCOMPOSITIONSTRING compstr;
1390 LPBYTE compdata;
1392 TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
1394 if (!data)
1395 return FALSE;
1397 if (!data->IMC.hCompStr)
1398 return FALSE;
1400 compdata = ImmLockIMCC(data->IMC.hCompStr);
1401 compstr = (LPCOMPOSITIONSTRING)compdata;
1403 switch (dwIndex)
1405 case GCS_RESULTSTR:
1406 TRACE("GCS_RESULTSTR\n");
1407 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
1408 break;
1409 case GCS_COMPSTR:
1410 TRACE("GCS_COMPSTR\n");
1411 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
1412 break;
1413 case GCS_COMPATTR:
1414 TRACE("GCS_COMPATTR\n");
1415 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
1416 compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
1417 lpBuf, dwBufLen, unicode);
1418 break;
1419 case GCS_COMPCLAUSE:
1420 TRACE("GCS_COMPCLAUSE\n");
1421 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
1422 compdata + compstr->dwCompStrOffset,
1423 lpBuf, dwBufLen, unicode);
1424 break;
1425 case GCS_RESULTCLAUSE:
1426 TRACE("GCS_RESULTCLAUSE\n");
1427 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
1428 compdata + compstr->dwResultStrOffset,
1429 lpBuf, dwBufLen, unicode);
1430 break;
1431 case GCS_RESULTREADSTR:
1432 TRACE("GCS_RESULTREADSTR\n");
1433 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
1434 break;
1435 case GCS_RESULTREADCLAUSE:
1436 TRACE("GCS_RESULTREADCLAUSE\n");
1437 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
1438 compdata + compstr->dwResultStrOffset,
1439 lpBuf, dwBufLen, unicode);
1440 break;
1441 case GCS_COMPREADSTR:
1442 TRACE("GCS_COMPREADSTR\n");
1443 rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
1444 break;
1445 case GCS_COMPREADATTR:
1446 TRACE("GCS_COMPREADATTR\n");
1447 rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
1448 compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
1449 lpBuf, dwBufLen, unicode);
1450 break;
1451 case GCS_COMPREADCLAUSE:
1452 TRACE("GCS_COMPREADCLAUSE\n");
1453 rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
1454 compdata + compstr->dwCompStrOffset,
1455 lpBuf, dwBufLen, unicode);
1456 break;
1457 case GCS_CURSORPOS:
1458 TRACE("GCS_CURSORPOS\n");
1459 rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
1460 break;
1461 case GCS_DELTASTART:
1462 TRACE("GCS_DELTASTART\n");
1463 rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
1464 break;
1465 default:
1466 FIXME("Unhandled index 0x%x\n",dwIndex);
1467 break;
1470 ImmUnlockIMCC(data->IMC.hCompStr);
1472 return rc;
1475 /***********************************************************************
1476 * ImmGetCompositionStringA (IMM32.@)
1478 LONG WINAPI ImmGetCompositionStringA(
1479 HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
1481 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
1485 /***********************************************************************
1486 * ImmGetCompositionStringW (IMM32.@)
1488 LONG WINAPI ImmGetCompositionStringW(
1489 HIMC hIMC, DWORD dwIndex,
1490 LPVOID lpBuf, DWORD dwBufLen)
1492 return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
1495 /***********************************************************************
1496 * ImmGetCompositionWindow (IMM32.@)
1498 BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
1500 InputContextData *data = get_imc_data(hIMC);
1502 TRACE("(%p, %p)\n", hIMC, lpCompForm);
1504 if (!data)
1505 return FALSE;
1507 *lpCompForm = data->IMC.cfCompForm;
1508 return TRUE;
1511 /***********************************************************************
1512 * ImmGetContext (IMM32.@)
1515 HIMC WINAPI ImmGetContext(HWND hWnd)
1517 HIMC rc;
1519 TRACE("%p\n", hWnd);
1521 if (!IsWindow(hWnd))
1523 SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1524 return NULL;
1527 rc = GetPropW(hWnd,szwWineIMCProperty);
1528 if (rc == (HIMC)-1)
1529 rc = NULL;
1530 else if (rc == NULL)
1531 rc = get_default_context( hWnd );
1533 if (rc)
1535 InputContextData *data = rc;
1536 data->IMC.hWnd = hWnd;
1539 TRACE("returning %p\n", rc);
1541 return rc;
1544 /***********************************************************************
1545 * ImmGetConversionListA (IMM32.@)
1547 DWORD WINAPI ImmGetConversionListA(
1548 HKL hKL, HIMC hIMC,
1549 LPCSTR pSrc, LPCANDIDATELIST lpDst,
1550 DWORD dwBufLen, UINT uFlag)
1552 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1553 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_a(pSrc), lpDst,
1554 dwBufLen, uFlag);
1555 if (immHkl->hIME && immHkl->pImeConversionList)
1557 if (!is_kbd_ime_unicode(immHkl))
1558 return immHkl->pImeConversionList(hIMC,(LPCWSTR)pSrc,lpDst,dwBufLen,uFlag);
1559 else
1561 LPCANDIDATELIST lpwDst;
1562 DWORD ret = 0, len;
1563 LPWSTR pwSrc = strdupAtoW(pSrc);
1565 len = immHkl->pImeConversionList(hIMC, pwSrc, NULL, 0, uFlag);
1566 lpwDst = HeapAlloc(GetProcessHeap(), 0, len);
1567 if ( lpwDst )
1569 immHkl->pImeConversionList(hIMC, pwSrc, lpwDst, len, uFlag);
1570 ret = convert_candidatelist_WtoA( lpwDst, lpDst, dwBufLen);
1571 HeapFree(GetProcessHeap(), 0, lpwDst);
1573 HeapFree(GetProcessHeap(), 0, pwSrc);
1575 return ret;
1578 else
1579 return 0;
1582 /***********************************************************************
1583 * ImmGetConversionListW (IMM32.@)
1585 DWORD WINAPI ImmGetConversionListW(
1586 HKL hKL, HIMC hIMC,
1587 LPCWSTR pSrc, LPCANDIDATELIST lpDst,
1588 DWORD dwBufLen, UINT uFlag)
1590 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1591 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL, hIMC, debugstr_w(pSrc), lpDst,
1592 dwBufLen, uFlag);
1593 if (immHkl->hIME && immHkl->pImeConversionList)
1595 if (is_kbd_ime_unicode(immHkl))
1596 return immHkl->pImeConversionList(hIMC,pSrc,lpDst,dwBufLen,uFlag);
1597 else
1599 LPCANDIDATELIST lpaDst;
1600 DWORD ret = 0, len;
1601 LPSTR paSrc = strdupWtoA(pSrc);
1603 len = immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, NULL, 0, uFlag);
1604 lpaDst = HeapAlloc(GetProcessHeap(), 0, len);
1605 if ( lpaDst )
1607 immHkl->pImeConversionList(hIMC, (LPCWSTR)paSrc, lpaDst, len, uFlag);
1608 ret = convert_candidatelist_AtoW( lpaDst, lpDst, dwBufLen);
1609 HeapFree(GetProcessHeap(), 0, lpaDst);
1611 HeapFree(GetProcessHeap(), 0, paSrc);
1613 return ret;
1616 else
1617 return 0;
1620 /***********************************************************************
1621 * ImmGetConversionStatus (IMM32.@)
1623 BOOL WINAPI ImmGetConversionStatus(
1624 HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence)
1626 InputContextData *data = get_imc_data(hIMC);
1628 TRACE("%p %p %p\n", hIMC, lpfdwConversion, lpfdwSentence);
1630 if (!data)
1631 return FALSE;
1633 if (lpfdwConversion)
1634 *lpfdwConversion = data->IMC.fdwConversion;
1635 if (lpfdwSentence)
1636 *lpfdwSentence = data->IMC.fdwSentence;
1638 return TRUE;
1641 static BOOL needs_ime_window(HWND hwnd)
1643 WCHAR classW[8];
1645 if (GetClassNameW(hwnd, classW, ARRAY_SIZE(classW)) && !lstrcmpW(classW, szwIME))
1646 return FALSE;
1647 if (GetClassLongPtrW(hwnd, GCL_STYLE) & CS_IME) return FALSE;
1649 return TRUE;
1652 /***********************************************************************
1653 * __wine_register_window (IMM32.@)
1655 BOOL WINAPI __wine_register_window(HWND hwnd)
1657 HWND new = NULL;
1658 IMMThreadData *thread_data;
1659 TRACE("(%p)\n", hwnd);
1661 if (!needs_ime_window(hwnd))
1662 return FALSE;
1664 thread_data = IMM_GetThreadData(hwnd, 0);
1665 if (!thread_data)
1666 return FALSE;
1668 if (thread_data->disableIME || disable_ime)
1670 TRACE("IME for this thread is disabled\n");
1671 LeaveCriticalSection(&threaddata_cs);
1672 return FALSE;
1674 thread_data->windowRefs++;
1675 TRACE("windowRefs=%u, hwndDefault=%p\n",
1676 thread_data->windowRefs, thread_data->hwndDefault);
1678 /* Create default IME window */
1679 if (thread_data->windowRefs == 1)
1681 /* Do not create the window inside of a critical section */
1682 LeaveCriticalSection(&threaddata_cs);
1683 new = CreateWindowExW( 0, szwIME, szwDefaultIME,
1684 WS_POPUP | WS_DISABLED | WS_CLIPSIBLINGS,
1685 0, 0, 1, 1, 0, 0, 0, 0);
1686 /* thread_data is in the current thread so we can assume it's still valid */
1687 EnterCriticalSection(&threaddata_cs);
1688 /* See if anyone beat us */
1689 if (thread_data->hwndDefault == NULL)
1691 thread_data->hwndDefault = new;
1692 new = NULL;
1693 TRACE("Default is %p\n", thread_data->hwndDefault);
1697 LeaveCriticalSection(&threaddata_cs);
1699 /* Clean up an unused new window outside of the critical section */
1700 if (new != NULL)
1701 DestroyWindow(new);
1702 return TRUE;
1705 /***********************************************************************
1706 * __wine_unregister_window (IMM32.@)
1708 void WINAPI __wine_unregister_window(HWND hwnd)
1710 HWND to_destroy = 0;
1711 IMMThreadData *thread_data;
1712 TRACE("(%p)\n", hwnd);
1714 thread_data = IMM_GetThreadData(hwnd, 0);
1715 if (!thread_data) return;
1717 thread_data->windowRefs--;
1718 TRACE("windowRefs=%u, hwndDefault=%p\n",
1719 thread_data->windowRefs, thread_data->hwndDefault);
1721 /* Destroy default IME window */
1722 if (thread_data->windowRefs == 0 && thread_data->hwndDefault)
1724 to_destroy = thread_data->hwndDefault;
1725 thread_data->hwndDefault = NULL;
1727 LeaveCriticalSection(&threaddata_cs);
1729 if (to_destroy) DestroyWindow( to_destroy );
1732 /***********************************************************************
1733 * ImmGetDefaultIMEWnd (IMM32.@)
1735 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
1737 HWND ret;
1738 IMMThreadData* thread_data = IMM_GetThreadData(hWnd, 0);
1739 if (!thread_data)
1740 return NULL;
1741 ret = thread_data->hwndDefault;
1742 LeaveCriticalSection(&threaddata_cs);
1743 TRACE("Default is %p\n",ret);
1744 return ret;
1747 /***********************************************************************
1748 * ImmGetDescriptionA (IMM32.@)
1750 UINT WINAPI ImmGetDescriptionA(
1751 HKL hKL, LPSTR lpszDescription, UINT uBufLen)
1753 WCHAR *buf;
1754 DWORD len;
1756 TRACE("%p %p %d\n", hKL, lpszDescription, uBufLen);
1758 /* find out how many characters in the unicode buffer */
1759 len = ImmGetDescriptionW( hKL, NULL, 0 );
1760 if (!len)
1761 return 0;
1763 /* allocate a buffer of that size */
1764 buf = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof (WCHAR) );
1765 if( !buf )
1766 return 0;
1768 /* fetch the unicode buffer */
1769 len = ImmGetDescriptionW( hKL, buf, len + 1 );
1771 /* convert it back to ASCII */
1772 len = WideCharToMultiByte( CP_ACP, 0, buf, len + 1,
1773 lpszDescription, uBufLen, NULL, NULL );
1775 HeapFree( GetProcessHeap(), 0, buf );
1777 if (len == 0)
1778 return 0;
1780 return len - 1;
1783 /***********************************************************************
1784 * ImmGetDescriptionW (IMM32.@)
1786 UINT WINAPI ImmGetDescriptionW(HKL hKL, LPWSTR lpszDescription, UINT uBufLen)
1788 static const WCHAR name[] = { 'W','i','n','e',' ','X','I','M',0 };
1790 FIXME("(%p, %p, %d): semi stub\n", hKL, lpszDescription, uBufLen);
1792 if (!hKL) return 0;
1793 if (!uBufLen) return lstrlenW( name );
1794 lstrcpynW( lpszDescription, name, uBufLen );
1795 return lstrlenW( lpszDescription );
1798 /***********************************************************************
1799 * ImmGetGuideLineA (IMM32.@)
1801 DWORD WINAPI ImmGetGuideLineA(
1802 HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
1804 FIXME("(%p, %d, %s, %d): stub\n",
1805 hIMC, dwIndex, debugstr_a(lpBuf), dwBufLen
1807 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1808 return 0;
1811 /***********************************************************************
1812 * ImmGetGuideLineW (IMM32.@)
1814 DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
1816 FIXME("(%p, %d, %s, %d): stub\n",
1817 hIMC, dwIndex, debugstr_w(lpBuf), dwBufLen
1819 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1820 return 0;
1823 /***********************************************************************
1824 * ImmGetIMEFileNameA (IMM32.@)
1826 UINT WINAPI ImmGetIMEFileNameA( HKL hKL, LPSTR lpszFileName, UINT uBufLen)
1828 LPWSTR bufW = NULL;
1829 UINT wBufLen = uBufLen;
1830 UINT rc;
1832 if (uBufLen && lpszFileName)
1833 bufW = HeapAlloc(GetProcessHeap(),0,uBufLen * sizeof(WCHAR));
1834 else /* We need this to get the number of byte required */
1836 bufW = HeapAlloc(GetProcessHeap(),0,MAX_PATH * sizeof(WCHAR));
1837 wBufLen = MAX_PATH;
1840 rc = ImmGetIMEFileNameW(hKL,bufW,wBufLen);
1842 if (rc > 0)
1844 if (uBufLen && lpszFileName)
1845 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, lpszFileName,
1846 uBufLen, NULL, NULL);
1847 else /* get the length */
1848 rc = WideCharToMultiByte(CP_ACP, 0, bufW, -1, NULL, 0, NULL,
1849 NULL);
1852 HeapFree(GetProcessHeap(),0,bufW);
1853 return rc;
1856 /***********************************************************************
1857 * ImmGetIMEFileNameW (IMM32.@)
1859 UINT WINAPI ImmGetIMEFileNameW(HKL hKL, LPWSTR lpszFileName, UINT uBufLen)
1861 HKEY hkey;
1862 DWORD length;
1863 DWORD rc;
1864 WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
1866 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hKL );
1867 rc = RegOpenKeyW( HKEY_LOCAL_MACHINE, regKey, &hkey);
1868 if (rc != ERROR_SUCCESS)
1870 SetLastError(rc);
1871 return 0;
1874 length = 0;
1875 rc = RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, NULL, &length);
1877 if (rc != ERROR_SUCCESS)
1879 RegCloseKey(hkey);
1880 SetLastError(rc);
1881 return 0;
1883 if (length > uBufLen * sizeof(WCHAR) || !lpszFileName)
1885 RegCloseKey(hkey);
1886 if (lpszFileName)
1888 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1889 return 0;
1891 else
1892 return length / sizeof(WCHAR);
1895 RegGetValueW(hkey, NULL, szImeFileW, RRF_RT_REG_SZ, NULL, lpszFileName, &length);
1897 RegCloseKey(hkey);
1899 return length / sizeof(WCHAR);
1902 /***********************************************************************
1903 * ImmGetOpenStatus (IMM32.@)
1905 BOOL WINAPI ImmGetOpenStatus(HIMC hIMC)
1907 InputContextData *data = get_imc_data(hIMC);
1908 static int i;
1910 if (!data)
1911 return FALSE;
1913 TRACE("(%p): semi-stub\n", hIMC);
1915 if (!i++)
1916 FIXME("(%p): semi-stub\n", hIMC);
1918 return data->IMC.fOpen;
1921 /***********************************************************************
1922 * ImmGetProperty (IMM32.@)
1924 DWORD WINAPI ImmGetProperty(HKL hKL, DWORD fdwIndex)
1926 DWORD rc = 0;
1927 ImmHkl *kbd;
1929 TRACE("(%p, %d)\n", hKL, fdwIndex);
1930 kbd = IMM_GetImmHkl(hKL);
1932 if (kbd && kbd->hIME)
1934 switch (fdwIndex)
1936 case IGP_PROPERTY: rc = kbd->imeInfo.fdwProperty; break;
1937 case IGP_CONVERSION: rc = kbd->imeInfo.fdwConversionCaps; break;
1938 case IGP_SENTENCE: rc = kbd->imeInfo.fdwSentenceCaps; break;
1939 case IGP_SETCOMPSTR: rc = kbd->imeInfo.fdwSCSCaps; break;
1940 case IGP_SELECT: rc = kbd->imeInfo.fdwSelectCaps; break;
1941 case IGP_GETIMEVERSION: rc = IMEVER_0400; break;
1942 case IGP_UI: rc = 0; break;
1943 default: rc = 0;
1946 return rc;
1949 /***********************************************************************
1950 * ImmGetRegisterWordStyleA (IMM32.@)
1952 UINT WINAPI ImmGetRegisterWordStyleA(
1953 HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
1955 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1956 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1957 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1959 if (!is_kbd_ime_unicode(immHkl))
1960 return immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)lpStyleBuf);
1961 else
1963 STYLEBUFW sbw;
1964 UINT rc;
1966 rc = immHkl->pImeGetRegisterWordStyle(nItem,&sbw);
1967 WideCharToMultiByte(CP_ACP, 0, sbw.szDescription, -1,
1968 lpStyleBuf->szDescription, 32, NULL, NULL);
1969 lpStyleBuf->dwStyle = sbw.dwStyle;
1970 return rc;
1973 else
1974 return 0;
1977 /***********************************************************************
1978 * ImmGetRegisterWordStyleW (IMM32.@)
1980 UINT WINAPI ImmGetRegisterWordStyleW(
1981 HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
1983 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
1984 TRACE("(%p, %d, %p):\n", hKL, nItem, lpStyleBuf);
1985 if (immHkl->hIME && immHkl->pImeGetRegisterWordStyle)
1987 if (is_kbd_ime_unicode(immHkl))
1988 return immHkl->pImeGetRegisterWordStyle(nItem,lpStyleBuf);
1989 else
1991 STYLEBUFA sba;
1992 UINT rc;
1994 rc = immHkl->pImeGetRegisterWordStyle(nItem,(LPSTYLEBUFW)&sba);
1995 MultiByteToWideChar(CP_ACP, 0, sba.szDescription, -1,
1996 lpStyleBuf->szDescription, 32);
1997 lpStyleBuf->dwStyle = sba.dwStyle;
1998 return rc;
2001 else
2002 return 0;
2005 /***********************************************************************
2006 * ImmGetStatusWindowPos (IMM32.@)
2008 BOOL WINAPI ImmGetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2010 InputContextData *data = get_imc_data(hIMC);
2012 TRACE("(%p, %p)\n", hIMC, lpptPos);
2014 if (!data || !lpptPos)
2015 return FALSE;
2017 *lpptPos = data->IMC.ptStatusWndPos;
2019 return TRUE;
2022 /***********************************************************************
2023 * ImmGetVirtualKey (IMM32.@)
2025 UINT WINAPI ImmGetVirtualKey(HWND hWnd)
2027 OSVERSIONINFOA version;
2028 InputContextData *data = ImmGetContext( hWnd );
2029 TRACE("%p\n", hWnd);
2031 if ( data )
2032 return data->lastVK;
2034 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
2035 GetVersionExA( &version );
2036 switch(version.dwPlatformId)
2038 case VER_PLATFORM_WIN32_WINDOWS:
2039 return VK_PROCESSKEY;
2040 case VER_PLATFORM_WIN32_NT:
2041 return 0;
2042 default:
2043 FIXME("%d not supported\n",version.dwPlatformId);
2044 return VK_PROCESSKEY;
2048 /***********************************************************************
2049 * ImmInstallIMEA (IMM32.@)
2051 HKL WINAPI ImmInstallIMEA(
2052 LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
2054 LPWSTR lpszwIMEFileName;
2055 LPWSTR lpszwLayoutText;
2056 HKL hkl;
2058 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName),
2059 debugstr_a(lpszLayoutText));
2061 lpszwIMEFileName = strdupAtoW(lpszIMEFileName);
2062 lpszwLayoutText = strdupAtoW(lpszLayoutText);
2064 hkl = ImmInstallIMEW(lpszwIMEFileName, lpszwLayoutText);
2066 HeapFree(GetProcessHeap(),0,lpszwIMEFileName);
2067 HeapFree(GetProcessHeap(),0,lpszwLayoutText);
2068 return hkl;
2071 /***********************************************************************
2072 * ImmInstallIMEW (IMM32.@)
2074 HKL WINAPI ImmInstallIMEW(
2075 LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
2077 INT lcid = GetUserDefaultLCID();
2078 INT count;
2079 HKL hkl;
2080 DWORD rc;
2081 HKEY hkey;
2082 WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
2084 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
2085 debugstr_w(lpszLayoutText));
2087 /* Start with 2. e001 will be blank and so default to the wine internal IME */
2088 count = 2;
2090 while (count < 0xfff)
2092 DWORD disposition = 0;
2094 hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
2095 wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
2097 rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
2098 if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
2099 break;
2100 else if (rc == ERROR_SUCCESS)
2101 RegCloseKey(hkey);
2103 count++;
2106 if (count == 0xfff)
2108 WARN("Unable to find slot to install IME\n");
2109 return 0;
2112 if (rc == ERROR_SUCCESS)
2114 rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
2115 (lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
2116 if (rc == ERROR_SUCCESS)
2117 rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
2118 (lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
2119 RegCloseKey(hkey);
2120 return hkl;
2122 else
2124 WARN("Unable to set IME registry values\n");
2125 return 0;
2129 /***********************************************************************
2130 * ImmIsIME (IMM32.@)
2132 BOOL WINAPI ImmIsIME(HKL hKL)
2134 ImmHkl *ptr;
2135 TRACE("(%p):\n", hKL);
2136 ptr = IMM_GetImmHkl(hKL);
2137 return (ptr && ptr->hIME);
2140 /***********************************************************************
2141 * ImmIsUIMessageA (IMM32.@)
2143 BOOL WINAPI ImmIsUIMessageA(
2144 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2146 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2147 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2148 (msg == WM_IME_SETCONTEXT) ||
2149 (msg == WM_IME_NOTIFY) ||
2150 (msg == WM_IME_COMPOSITIONFULL) ||
2151 (msg == WM_IME_SELECT) ||
2152 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2154 if (hWndIME)
2155 SendMessageA(hWndIME, msg, wParam, lParam);
2157 return TRUE;
2159 return FALSE;
2162 /***********************************************************************
2163 * ImmIsUIMessageW (IMM32.@)
2165 BOOL WINAPI ImmIsUIMessageW(
2166 HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
2168 TRACE("(%p, %x, %ld, %ld)\n", hWndIME, msg, wParam, lParam);
2169 if ((msg >= WM_IME_STARTCOMPOSITION && msg <= WM_IME_KEYLAST) ||
2170 (msg == WM_IME_SETCONTEXT) ||
2171 (msg == WM_IME_NOTIFY) ||
2172 (msg == WM_IME_COMPOSITIONFULL) ||
2173 (msg == WM_IME_SELECT) ||
2174 (msg == 0x287 /* FIXME: WM_IME_SYSTEM */))
2176 if (hWndIME)
2177 SendMessageW(hWndIME, msg, wParam, lParam);
2179 return TRUE;
2181 return FALSE;
2184 /***********************************************************************
2185 * ImmNotifyIME (IMM32.@)
2187 BOOL WINAPI ImmNotifyIME(
2188 HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)
2190 InputContextData *data = get_imc_data(hIMC);
2192 TRACE("(%p, %d, %d, %d)\n",
2193 hIMC, dwAction, dwIndex, dwValue);
2195 if (hIMC == NULL)
2197 SetLastError(ERROR_SUCCESS);
2198 return FALSE;
2201 if (!data || ! data->immKbd->pNotifyIME)
2203 return FALSE;
2206 return data->immKbd->pNotifyIME(hIMC,dwAction,dwIndex,dwValue);
2209 /***********************************************************************
2210 * ImmRegisterWordA (IMM32.@)
2212 BOOL WINAPI ImmRegisterWordA(
2213 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
2215 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2216 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2217 debugstr_a(lpszRegister));
2218 if (immHkl->hIME && immHkl->pImeRegisterWord)
2220 if (!is_kbd_ime_unicode(immHkl))
2221 return immHkl->pImeRegisterWord((LPCWSTR)lpszReading,dwStyle,
2222 (LPCWSTR)lpszRegister);
2223 else
2225 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2226 LPWSTR lpszwRegister = strdupAtoW(lpszRegister);
2227 BOOL rc;
2229 rc = immHkl->pImeRegisterWord(lpszwReading,dwStyle,lpszwRegister);
2230 HeapFree(GetProcessHeap(),0,lpszwReading);
2231 HeapFree(GetProcessHeap(),0,lpszwRegister);
2232 return rc;
2235 else
2236 return FALSE;
2239 /***********************************************************************
2240 * ImmRegisterWordW (IMM32.@)
2242 BOOL WINAPI ImmRegisterWordW(
2243 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
2245 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2246 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2247 debugstr_w(lpszRegister));
2248 if (immHkl->hIME && immHkl->pImeRegisterWord)
2250 if (is_kbd_ime_unicode(immHkl))
2251 return immHkl->pImeRegisterWord(lpszReading,dwStyle,lpszRegister);
2252 else
2254 LPSTR lpszaReading = strdupWtoA(lpszReading);
2255 LPSTR lpszaRegister = strdupWtoA(lpszRegister);
2256 BOOL rc;
2258 rc = immHkl->pImeRegisterWord((LPCWSTR)lpszaReading,dwStyle,
2259 (LPCWSTR)lpszaRegister);
2260 HeapFree(GetProcessHeap(),0,lpszaReading);
2261 HeapFree(GetProcessHeap(),0,lpszaRegister);
2262 return rc;
2265 else
2266 return FALSE;
2269 /***********************************************************************
2270 * ImmReleaseContext (IMM32.@)
2272 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
2274 static BOOL shown = FALSE;
2276 if (!shown) {
2277 FIXME("(%p, %p): stub\n", hWnd, hIMC);
2278 shown = TRUE;
2280 return TRUE;
2283 /***********************************************************************
2284 * ImmRequestMessageA(IMM32.@)
2286 LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2288 InputContextData *data = get_imc_data(hIMC);
2290 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2292 if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2294 SetLastError(ERROR_INVALID_HANDLE);
2295 return 0;
2298 /***********************************************************************
2299 * ImmRequestMessageW(IMM32.@)
2301 LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
2303 InputContextData *data = get_imc_data(hIMC);
2305 TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
2307 if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
2309 SetLastError(ERROR_INVALID_HANDLE);
2310 return 0;
2313 /***********************************************************************
2314 * ImmSetCandidateWindow (IMM32.@)
2316 BOOL WINAPI ImmSetCandidateWindow(
2317 HIMC hIMC, LPCANDIDATEFORM lpCandidate)
2319 InputContextData *data = get_imc_data(hIMC);
2321 TRACE("(%p, %p)\n", hIMC, lpCandidate);
2323 if (!data || !lpCandidate)
2324 return FALSE;
2326 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2327 return FALSE;
2329 TRACE("\t%x, %x, %s, %s\n",
2330 lpCandidate->dwIndex, lpCandidate->dwStyle,
2331 wine_dbgstr_point(&lpCandidate->ptCurrentPos),
2332 wine_dbgstr_rect(&lpCandidate->rcArea));
2334 if (lpCandidate->dwIndex >= ARRAY_SIZE(data->IMC.cfCandForm))
2335 return FALSE;
2337 data->IMC.cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
2338 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS);
2339 ImmInternalSendIMENotify(data, IMN_SETCANDIDATEPOS, 1 << lpCandidate->dwIndex);
2341 return TRUE;
2344 /***********************************************************************
2345 * ImmSetCompositionFontA (IMM32.@)
2347 BOOL WINAPI ImmSetCompositionFontA(HIMC hIMC, LPLOGFONTA lplf)
2349 InputContextData *data = get_imc_data(hIMC);
2350 TRACE("(%p, %p)\n", hIMC, lplf);
2352 if (!data || !lplf)
2354 SetLastError(ERROR_INVALID_HANDLE);
2355 return FALSE;
2358 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2359 return FALSE;
2361 memcpy(&data->IMC.lfFont.W,lplf,sizeof(LOGFONTA));
2362 MultiByteToWideChar(CP_ACP, 0, lplf->lfFaceName, -1, data->IMC.lfFont.W.lfFaceName,
2363 LF_FACESIZE);
2364 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2365 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2367 return TRUE;
2370 /***********************************************************************
2371 * ImmSetCompositionFontW (IMM32.@)
2373 BOOL WINAPI ImmSetCompositionFontW(HIMC hIMC, LPLOGFONTW lplf)
2375 InputContextData *data = get_imc_data(hIMC);
2376 TRACE("(%p, %p)\n", hIMC, lplf);
2378 if (!data || !lplf)
2380 SetLastError(ERROR_INVALID_HANDLE);
2381 return FALSE;
2384 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2385 return FALSE;
2387 data->IMC.lfFont.W = *lplf;
2388 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, 0, IMC_SETCOMPOSITIONFONT);
2389 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONFONT, 0);
2391 return TRUE;
2394 /***********************************************************************
2395 * ImmSetCompositionStringA (IMM32.@)
2397 BOOL WINAPI ImmSetCompositionStringA(
2398 HIMC hIMC, DWORD dwIndex,
2399 LPCVOID lpComp, DWORD dwCompLen,
2400 LPCVOID lpRead, DWORD dwReadLen)
2402 DWORD comp_len;
2403 DWORD read_len;
2404 WCHAR *CompBuffer = NULL;
2405 WCHAR *ReadBuffer = NULL;
2406 BOOL rc;
2407 InputContextData *data = get_imc_data(hIMC);
2409 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2410 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2412 if (!data)
2413 return FALSE;
2415 if (!(dwIndex == SCS_SETSTR ||
2416 dwIndex == SCS_CHANGEATTR ||
2417 dwIndex == SCS_CHANGECLAUSE ||
2418 dwIndex == SCS_SETRECONVERTSTRING ||
2419 dwIndex == SCS_QUERYRECONVERTSTRING))
2420 return FALSE;
2422 if (!is_himc_ime_unicode(data))
2423 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2424 dwCompLen, lpRead, dwReadLen);
2426 comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
2427 if (comp_len)
2429 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
2430 MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
2433 read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
2434 if (read_len)
2436 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
2437 MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
2440 rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
2441 ReadBuffer, read_len);
2443 HeapFree(GetProcessHeap(), 0, CompBuffer);
2444 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2446 return rc;
2449 /***********************************************************************
2450 * ImmSetCompositionStringW (IMM32.@)
2452 BOOL WINAPI ImmSetCompositionStringW(
2453 HIMC hIMC, DWORD dwIndex,
2454 LPCVOID lpComp, DWORD dwCompLen,
2455 LPCVOID lpRead, DWORD dwReadLen)
2457 DWORD comp_len;
2458 DWORD read_len;
2459 CHAR *CompBuffer = NULL;
2460 CHAR *ReadBuffer = NULL;
2461 BOOL rc;
2462 InputContextData *data = get_imc_data(hIMC);
2464 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2465 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
2467 if (!data)
2468 return FALSE;
2470 if (!(dwIndex == SCS_SETSTR ||
2471 dwIndex == SCS_CHANGEATTR ||
2472 dwIndex == SCS_CHANGECLAUSE ||
2473 dwIndex == SCS_SETRECONVERTSTRING ||
2474 dwIndex == SCS_QUERYRECONVERTSTRING))
2475 return FALSE;
2477 if (is_himc_ime_unicode(data))
2478 return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
2479 dwCompLen, lpRead, dwReadLen);
2481 comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
2482 NULL);
2483 if (comp_len)
2485 CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
2486 WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
2487 NULL, NULL);
2490 read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
2491 NULL);
2492 if (read_len)
2494 ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
2495 WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
2496 NULL, NULL);
2499 rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
2500 ReadBuffer, read_len);
2502 HeapFree(GetProcessHeap(), 0, CompBuffer);
2503 HeapFree(GetProcessHeap(), 0, ReadBuffer);
2505 return rc;
2508 /***********************************************************************
2509 * ImmSetCompositionWindow (IMM32.@)
2511 BOOL WINAPI ImmSetCompositionWindow(
2512 HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
2514 BOOL reshow = FALSE;
2515 InputContextData *data = get_imc_data(hIMC);
2517 TRACE("(%p, %p)\n", hIMC, lpCompForm);
2518 if (lpCompForm)
2519 TRACE("\t%x, %s, %s\n", lpCompForm->dwStyle,
2520 wine_dbgstr_point(&lpCompForm->ptCurrentPos),
2521 wine_dbgstr_rect(&lpCompForm->rcArea));
2523 if (!data)
2525 SetLastError(ERROR_INVALID_HANDLE);
2526 return FALSE;
2529 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2530 return FALSE;
2532 data->IMC.cfCompForm = *lpCompForm;
2534 if (IsWindowVisible(data->immKbd->UIWnd))
2536 reshow = TRUE;
2537 ShowWindow(data->immKbd->UIWnd,SW_HIDE);
2540 /* FIXME: this is a partial stub */
2542 if (reshow)
2543 ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE);
2545 ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
2546 return TRUE;
2549 /***********************************************************************
2550 * ImmSetConversionStatus (IMM32.@)
2552 BOOL WINAPI ImmSetConversionStatus(
2553 HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)
2555 DWORD oldConversion, oldSentence;
2556 InputContextData *data = get_imc_data(hIMC);
2558 TRACE("%p %d %d\n", hIMC, fdwConversion, fdwSentence);
2560 if (!data)
2562 SetLastError(ERROR_INVALID_HANDLE);
2563 return FALSE;
2566 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2567 return FALSE;
2569 if ( fdwConversion != data->IMC.fdwConversion )
2571 oldConversion = data->IMC.fdwConversion;
2572 data->IMC.fdwConversion = fdwConversion;
2573 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldConversion, IMC_SETCONVERSIONMODE);
2574 ImmInternalSendIMENotify(data, IMN_SETCONVERSIONMODE, 0);
2576 if ( fdwSentence != data->IMC.fdwSentence )
2578 oldSentence = data->IMC.fdwSentence;
2579 data->IMC.fdwSentence = fdwSentence;
2580 ImmNotifyIME(hIMC, NI_CONTEXTUPDATED, oldSentence, IMC_SETSENTENCEMODE);
2581 ImmInternalSendIMENotify(data, IMN_SETSENTENCEMODE, 0);
2584 return TRUE;
2587 /***********************************************************************
2588 * ImmSetOpenStatus (IMM32.@)
2590 BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
2592 InputContextData *data = get_imc_data(hIMC);
2594 TRACE("%p %d\n", hIMC, fOpen);
2596 if (!data)
2598 SetLastError(ERROR_INVALID_HANDLE);
2599 return FALSE;
2602 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2603 return FALSE;
2605 if (data->immKbd->UIWnd == NULL)
2607 /* create the ime window */
2608 data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
2609 data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
2610 0, data->immKbd->hIME, 0);
2611 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2613 else if (fOpen)
2614 SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
2616 if (!fOpen != !data->IMC.fOpen)
2618 data->IMC.fOpen = fOpen;
2619 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
2620 ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
2623 return TRUE;
2626 /***********************************************************************
2627 * ImmSetStatusWindowPos (IMM32.@)
2629 BOOL WINAPI ImmSetStatusWindowPos(HIMC hIMC, LPPOINT lpptPos)
2631 InputContextData *data = get_imc_data(hIMC);
2633 TRACE("(%p, %p)\n", hIMC, lpptPos);
2635 if (!data || !lpptPos)
2637 SetLastError(ERROR_INVALID_HANDLE);
2638 return FALSE;
2641 if (IMM_IsCrossThreadAccess(NULL, hIMC))
2642 return FALSE;
2644 TRACE("\t%s\n", wine_dbgstr_point(lpptPos));
2646 data->IMC.ptStatusWndPos = *lpptPos;
2647 ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETSTATUSWINDOWPOS);
2648 ImmInternalSendIMENotify(data, IMN_SETSTATUSWINDOWPOS, 0);
2650 return TRUE;
2653 /***********************************************************************
2654 * ImmCreateSoftKeyboard(IMM32.@)
2656 HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
2658 FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
2659 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2660 return 0;
2663 /***********************************************************************
2664 * ImmDestroySoftKeyboard(IMM32.@)
2666 BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
2668 FIXME("(%p): stub\n", hSoftWnd);
2669 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2670 return FALSE;
2673 /***********************************************************************
2674 * ImmShowSoftKeyboard(IMM32.@)
2676 BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
2678 FIXME("(%p, %d): stub\n", hSoftWnd, nCmdShow);
2679 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2680 return FALSE;
2683 /***********************************************************************
2684 * ImmSimulateHotKey (IMM32.@)
2686 BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
2688 FIXME("(%p, %d): stub\n", hWnd, dwHotKeyID);
2689 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2690 return FALSE;
2693 /***********************************************************************
2694 * ImmUnregisterWordA (IMM32.@)
2696 BOOL WINAPI ImmUnregisterWordA(
2697 HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
2699 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2700 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_a(lpszReading), dwStyle,
2701 debugstr_a(lpszUnregister));
2702 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2704 if (!is_kbd_ime_unicode(immHkl))
2705 return immHkl->pImeUnregisterWord((LPCWSTR)lpszReading,dwStyle,
2706 (LPCWSTR)lpszUnregister);
2707 else
2709 LPWSTR lpszwReading = strdupAtoW(lpszReading);
2710 LPWSTR lpszwUnregister = strdupAtoW(lpszUnregister);
2711 BOOL rc;
2713 rc = immHkl->pImeUnregisterWord(lpszwReading,dwStyle,lpszwUnregister);
2714 HeapFree(GetProcessHeap(),0,lpszwReading);
2715 HeapFree(GetProcessHeap(),0,lpszwUnregister);
2716 return rc;
2719 else
2720 return FALSE;
2723 /***********************************************************************
2724 * ImmUnregisterWordW (IMM32.@)
2726 BOOL WINAPI ImmUnregisterWordW(
2727 HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
2729 ImmHkl *immHkl = IMM_GetImmHkl(hKL);
2730 TRACE("(%p, %s, %d, %s):\n", hKL, debugstr_w(lpszReading), dwStyle,
2731 debugstr_w(lpszUnregister));
2732 if (immHkl->hIME && immHkl->pImeUnregisterWord)
2734 if (is_kbd_ime_unicode(immHkl))
2735 return immHkl->pImeUnregisterWord(lpszReading,dwStyle,lpszUnregister);
2736 else
2738 LPSTR lpszaReading = strdupWtoA(lpszReading);
2739 LPSTR lpszaUnregister = strdupWtoA(lpszUnregister);
2740 BOOL rc;
2742 rc = immHkl->pImeUnregisterWord((LPCWSTR)lpszaReading,dwStyle,
2743 (LPCWSTR)lpszaUnregister);
2744 HeapFree(GetProcessHeap(),0,lpszaReading);
2745 HeapFree(GetProcessHeap(),0,lpszaUnregister);
2746 return rc;
2749 else
2750 return FALSE;
2753 /***********************************************************************
2754 * ImmGetImeMenuItemsA (IMM32.@)
2756 DWORD WINAPI ImmGetImeMenuItemsA( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2757 LPIMEMENUITEMINFOA lpImeParentMenu, LPIMEMENUITEMINFOA lpImeMenu,
2758 DWORD dwSize)
2760 InputContextData *data = get_imc_data(hIMC);
2761 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2762 lpImeParentMenu, lpImeMenu, dwSize);
2764 if (!data)
2766 SetLastError(ERROR_INVALID_HANDLE);
2767 return 0;
2770 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2772 if (!is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2773 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2774 (IMEMENUITEMINFOW*)lpImeParentMenu,
2775 (IMEMENUITEMINFOW*)lpImeMenu, dwSize);
2776 else
2778 IMEMENUITEMINFOW lpImeParentMenuW;
2779 IMEMENUITEMINFOW *lpImeMenuW, *parent = NULL;
2780 DWORD rc;
2782 if (lpImeParentMenu)
2783 parent = &lpImeParentMenuW;
2784 if (lpImeMenu)
2786 int count = dwSize / sizeof(LPIMEMENUITEMINFOA);
2787 dwSize = count * sizeof(IMEMENUITEMINFOW);
2788 lpImeMenuW = HeapAlloc(GetProcessHeap(), 0, dwSize);
2790 else
2791 lpImeMenuW = NULL;
2793 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2794 parent, lpImeMenuW, dwSize);
2796 if (lpImeParentMenu)
2798 memcpy(lpImeParentMenu,&lpImeParentMenuW,sizeof(IMEMENUITEMINFOA));
2799 lpImeParentMenu->hbmpItem = lpImeParentMenuW.hbmpItem;
2800 WideCharToMultiByte(CP_ACP, 0, lpImeParentMenuW.szString,
2801 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE,
2802 NULL, NULL);
2804 if (lpImeMenu && rc)
2806 unsigned int i;
2807 for (i = 0; i < rc; i++)
2809 memcpy(&lpImeMenu[i],&lpImeMenuW[1],sizeof(IMEMENUITEMINFOA));
2810 lpImeMenu[i].hbmpItem = lpImeMenuW[i].hbmpItem;
2811 WideCharToMultiByte(CP_ACP, 0, lpImeMenuW[i].szString,
2812 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE,
2813 NULL, NULL);
2816 HeapFree(GetProcessHeap(),0,lpImeMenuW);
2817 return rc;
2820 else
2821 return 0;
2824 /***********************************************************************
2825 * ImmGetImeMenuItemsW (IMM32.@)
2827 DWORD WINAPI ImmGetImeMenuItemsW( HIMC hIMC, DWORD dwFlags, DWORD dwType,
2828 LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu,
2829 DWORD dwSize)
2831 InputContextData *data = get_imc_data(hIMC);
2832 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC, dwFlags, dwType,
2833 lpImeParentMenu, lpImeMenu, dwSize);
2835 if (!data)
2837 SetLastError(ERROR_INVALID_HANDLE);
2838 return 0;
2841 if (data->immKbd->hIME && data->immKbd->pImeGetImeMenuItems)
2843 if (is_himc_ime_unicode(data) || (!lpImeParentMenu && !lpImeMenu))
2844 return data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2845 lpImeParentMenu, lpImeMenu, dwSize);
2846 else
2848 IMEMENUITEMINFOA lpImeParentMenuA;
2849 IMEMENUITEMINFOA *lpImeMenuA, *parent = NULL;
2850 DWORD rc;
2852 if (lpImeParentMenu)
2853 parent = &lpImeParentMenuA;
2854 if (lpImeMenu)
2856 int count = dwSize / sizeof(LPIMEMENUITEMINFOW);
2857 dwSize = count * sizeof(IMEMENUITEMINFOA);
2858 lpImeMenuA = HeapAlloc(GetProcessHeap(), 0, dwSize);
2860 else
2861 lpImeMenuA = NULL;
2863 rc = data->immKbd->pImeGetImeMenuItems(hIMC, dwFlags, dwType,
2864 (IMEMENUITEMINFOW*)parent,
2865 (IMEMENUITEMINFOW*)lpImeMenuA, dwSize);
2867 if (lpImeParentMenu)
2869 memcpy(lpImeParentMenu,&lpImeParentMenuA,sizeof(IMEMENUITEMINFOA));
2870 lpImeParentMenu->hbmpItem = lpImeParentMenuA.hbmpItem;
2871 MultiByteToWideChar(CP_ACP, 0, lpImeParentMenuA.szString,
2872 -1, lpImeParentMenu->szString, IMEMENUITEM_STRING_SIZE);
2874 if (lpImeMenu && rc)
2876 unsigned int i;
2877 for (i = 0; i < rc; i++)
2879 memcpy(&lpImeMenu[i],&lpImeMenuA[1],sizeof(IMEMENUITEMINFOA));
2880 lpImeMenu[i].hbmpItem = lpImeMenuA[i].hbmpItem;
2881 MultiByteToWideChar(CP_ACP, 0, lpImeMenuA[i].szString,
2882 -1, lpImeMenu[i].szString, IMEMENUITEM_STRING_SIZE);
2885 HeapFree(GetProcessHeap(),0,lpImeMenuA);
2886 return rc;
2889 else
2890 return 0;
2893 /***********************************************************************
2894 * ImmLockIMC(IMM32.@)
2896 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
2898 InputContextData *data = get_imc_data(hIMC);
2900 if (!data)
2901 return NULL;
2902 data->dwLock++;
2903 return &data->IMC;
2906 /***********************************************************************
2907 * ImmUnlockIMC(IMM32.@)
2909 BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
2911 InputContextData *data = get_imc_data(hIMC);
2913 if (!data)
2914 return FALSE;
2915 if (data->dwLock)
2916 data->dwLock--;
2917 return TRUE;
2920 /***********************************************************************
2921 * ImmGetIMCLockCount(IMM32.@)
2923 DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
2925 InputContextData *data = get_imc_data(hIMC);
2926 if (!data)
2927 return 0;
2928 return data->dwLock;
2931 /***********************************************************************
2932 * ImmCreateIMCC(IMM32.@)
2934 HIMCC WINAPI ImmCreateIMCC(DWORD size)
2936 return GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE, size);
2939 /***********************************************************************
2940 * ImmDestroyIMCC(IMM32.@)
2942 HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
2944 return GlobalFree(block);
2947 /***********************************************************************
2948 * ImmLockIMCC(IMM32.@)
2950 LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
2952 return GlobalLock(imcc);
2955 /***********************************************************************
2956 * ImmUnlockIMCC(IMM32.@)
2958 BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
2960 return GlobalUnlock(imcc);
2963 /***********************************************************************
2964 * ImmGetIMCCLockCount(IMM32.@)
2966 DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
2968 return GlobalFlags(imcc) & GMEM_LOCKCOUNT;
2971 /***********************************************************************
2972 * ImmReSizeIMCC(IMM32.@)
2974 HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
2976 return GlobalReAlloc(imcc, size, GMEM_ZEROINIT | GMEM_MOVEABLE);
2979 /***********************************************************************
2980 * ImmGetIMCCSize(IMM32.@)
2982 DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
2984 return GlobalSize(imcc);
2987 /***********************************************************************
2988 * ImmGenerateMessage(IMM32.@)
2990 BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
2992 InputContextData *data = get_imc_data(hIMC);
2994 if (!data)
2996 SetLastError(ERROR_INVALID_HANDLE);
2997 return FALSE;
3000 TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
3001 if (data->IMC.dwNumMsgBuf > 0)
3003 LPTRANSMSG lpTransMsg;
3004 HIMCC hMsgBuf;
3005 DWORD i, dwNumMsgBuf;
3007 /* We are going to detach our hMsgBuff so that if processing messages
3008 generates new messages they go into a new buffer */
3009 hMsgBuf = data->IMC.hMsgBuf;
3010 dwNumMsgBuf = data->IMC.dwNumMsgBuf;
3012 data->IMC.hMsgBuf = ImmCreateIMCC(0);
3013 data->IMC.dwNumMsgBuf = 0;
3015 lpTransMsg = ImmLockIMCC(hMsgBuf);
3016 for (i = 0; i < dwNumMsgBuf; i++)
3017 ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam);
3019 ImmUnlockIMCC(hMsgBuf);
3020 ImmDestroyIMCC(hMsgBuf);
3023 return TRUE;
3026 /***********************************************************************
3027 * ImmTranslateMessage(IMM32.@)
3028 * ( Undocumented, call internally and from user32.dll )
3030 BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
3032 InputContextData *data;
3033 HIMC imc = ImmGetContext(hwnd);
3034 BYTE state[256];
3035 UINT scancode;
3036 LPVOID list = 0;
3037 UINT msg_count;
3038 UINT uVirtKey;
3039 static const DWORD list_count = 10;
3041 TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
3043 if (imc)
3044 data = imc;
3045 else
3046 return FALSE;
3048 if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
3049 return FALSE;
3051 GetKeyboardState(state);
3052 scancode = lKeyData >> 0x10 & 0xff;
3054 list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) + sizeof(DWORD));
3055 ((DWORD*)list)[0] = list_count;
3057 if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
3059 WCHAR chr;
3061 if (!is_himc_ime_unicode(data))
3062 ToAscii(data->lastVK, scancode, state, &chr, 0);
3063 else
3064 ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0));
3065 uVirtKey = MAKELONG(data->lastVK,chr);
3067 else
3068 uVirtKey = data->lastVK;
3070 msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0, imc);
3071 TRACE("%i messages generated\n",msg_count);
3072 if (msg_count && msg_count <= list_count)
3074 UINT i;
3075 LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
3077 for (i = 0; i < msg_count; i++)
3078 ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam);
3080 else if (msg_count > list_count)
3081 ImmGenerateMessage(imc);
3083 HeapFree(GetProcessHeap(),0,list);
3085 data->lastVK = VK_PROCESSKEY;
3087 return (msg_count > 0);
3090 /***********************************************************************
3091 * ImmProcessKey(IMM32.@)
3092 * ( Undocumented, called from user32.dll )
3094 BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown)
3096 InputContextData *data;
3097 HIMC imc = ImmGetContext(hwnd);
3098 BYTE state[256];
3100 TRACE("%p %p %x %x %x\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown);
3102 if (imc)
3103 data = imc;
3104 else
3105 return FALSE;
3107 /* Make sure we are inputting to the correct keyboard */
3108 if (data->immKbd->hkl != hKL)
3110 ImmHkl *new_hkl = IMM_GetImmHkl(hKL);
3111 if (new_hkl)
3113 data->immKbd->pImeSelect(imc, FALSE);
3114 data->immKbd->uSelected--;
3115 data->immKbd = new_hkl;
3116 data->immKbd->pImeSelect(imc, TRUE);
3117 data->immKbd->uSelected++;
3119 else
3120 return FALSE;
3123 if (!data->immKbd->hIME || !data->immKbd->pImeProcessKey)
3124 return FALSE;
3126 GetKeyboardState(state);
3127 if (data->immKbd->pImeProcessKey(imc, vKey, lKeyData, state))
3129 data->lastVK = vKey;
3130 return TRUE;
3133 data->lastVK = VK_PROCESSKEY;
3134 return FALSE;
3137 /***********************************************************************
3138 * ImmDisableTextFrameService(IMM32.@)
3140 BOOL WINAPI ImmDisableTextFrameService(DWORD idThread)
3142 FIXME("Stub\n");
3143 return FALSE;
3146 /***********************************************************************
3147 * ImmEnumInputContext(IMM32.@)
3150 BOOL WINAPI ImmEnumInputContext(DWORD idThread, IMCENUMPROC lpfn, LPARAM lParam)
3152 FIXME("Stub\n");
3153 return FALSE;
3156 /***********************************************************************
3157 * ImmGetHotKey(IMM32.@)
3160 BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl)
3162 FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl);
3163 return FALSE;
3166 /***********************************************************************
3167 * ImmDisableLegacyIME(IMM32.@)
3169 BOOL WINAPI ImmDisableLegacyIME(void)
3171 FIXME("stub\n");
3172 return TRUE;