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
25 #define WIN32_NO_STATUS
31 #include <wine/debug.h>
36 #include <wine/list.h>
38 #include <ndk/umtypes.h>
39 #include <ndk/pstypes.h>
40 #include <ndk/rtlfuncs.h>
41 #include "../../../win32ss/include/ntuser.h"
42 #include "../../../win32ss/include/ntwin32.h"
43 #include <imm32_undoc.h>
46 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
48 #define IMM_INIT_MAGIC 0x19650412
49 #define IMM_INVALID_CANDFORM ULONG_MAX
51 #define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
52 #define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
53 #define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
55 #define REGKEY_KEYBOARD_LAYOUTS \
56 L"System\\CurrentControlSet\\Control\\Keyboard Layouts"
58 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM"
60 #define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
62 HMODULE g_hImm32Inst
= NULL
;
63 RTL_CRITICAL_SECTION g_csImeDpi
;
64 PIMEDPI g_pImeDpiList
= NULL
;
65 PSERVERINFO g_psi
= NULL
;
66 SHAREDINFO g_SharedInfo
= { NULL
};
67 BYTE g_bClientRegd
= FALSE
;
68 HANDLE g_hImm32Heap
= NULL
;
70 static BOOL APIENTRY
Imm32InitInstance(HMODULE hMod
)
80 status
= RtlInitializeCriticalSection(&g_csImeDpi
);
88 LPVOID APIENTRY
Imm32HeapAlloc(DWORD dwFlags
, DWORD dwBytes
)
92 g_hImm32Heap
= RtlGetProcessHeap();
93 if (g_hImm32Heap
== NULL
)
96 return HeapAlloc(g_hImm32Heap
, dwFlags
, dwBytes
);
99 static LPWSTR APIENTRY
Imm32WideFromAnsi(LPCSTR pszA
)
101 INT cch
= lstrlenA(pszA
);
102 LPWSTR pszW
= Imm32HeapAlloc(0, (cch
+ 1) * sizeof(WCHAR
));
105 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, pszA
, cch
, pszW
, cch
+ 1);
110 static LPSTR APIENTRY
Imm32AnsiFromWide(LPCWSTR pszW
)
112 INT cchW
= lstrlenW(pszW
);
113 INT cchA
= (cchW
+ 1) * sizeof(WCHAR
);
114 LPSTR pszA
= Imm32HeapAlloc(0, cchA
);
117 cchA
= WideCharToMultiByte(CP_ACP
, 0, pszW
, cchW
, pszA
, cchA
, NULL
, NULL
);
122 static inline BOOL
Imm32IsCrossThreadAccess(HIMC hIMC
)
124 DWORD dwImeThreadId
= NtUserQueryInputContext(hIMC
, 1);
125 DWORD dwThreadId
= GetCurrentThreadId();
126 return (dwImeThreadId
!= dwThreadId
);
129 static VOID APIENTRY
Imm32FreeImeDpi(PIMEDPI pImeDpi
, BOOL bDestroy
)
131 if (pImeDpi
->hInst
== NULL
)
134 pImeDpi
->ImeDestroy(0);
135 FreeLibrary(pImeDpi
->hInst
);
136 pImeDpi
->hInst
= NULL
;
140 Imm32NotifyAction(HIMC hIMC
, HWND hwnd
, DWORD dwAction
, DWORD_PTR dwIndex
, DWORD_PTR dwValue
,
141 DWORD_PTR dwCommand
, DWORD_PTR dwData
)
149 dwLayout
= NtUserQueryInputContext(hIMC
, 1);
152 /* find keyboard layout and lock it */
153 hKL
= GetKeyboardLayout(dwLayout
);
154 pImeDpi
= ImmLockImeDpi(hKL
);
158 pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
160 ImmUnlockImeDpi(pImeDpi
); /* unlock */
165 if (hwnd
&& dwCommand
)
166 SendMessageW(hwnd
, WM_IME_NOTIFY
, dwCommand
, dwData
);
171 static PIMEDPI APIENTRY
Imm32FindImeDpi(HKL hKL
)
175 RtlEnterCriticalSection(&g_csImeDpi
);
176 for (pImeDpi
= g_pImeDpiList
; pImeDpi
!= NULL
; pImeDpi
= pImeDpi
->pNext
)
178 if (pImeDpi
->hKL
== hKL
)
181 RtlLeaveCriticalSection(&g_csImeDpi
);
186 static BOOL
Imm32GetSystemLibraryPath(LPWSTR pszPath
, DWORD cchPath
, LPCWSTR pszFileName
)
188 if (!pszFileName
[0] || !GetSystemDirectoryW(pszPath
, cchPath
))
190 StringCchCatW(pszPath
, cchPath
, L
"\\");
191 StringCchCatW(pszPath
, cchPath
, pszFileName
);
195 static BOOL APIENTRY
Imm32InquireIme(PIMEDPI pImeDpi
)
199 DWORD dwSysInfoFlags
= 0; // TODO: ???
200 LPIMEINFO pImeInfo
= &pImeDpi
->ImeInfo
;
202 // TODO: NtUserGetThreadState(THREADSTATE_UNKNOWN16);
204 if (!IS_IME_HKL(pImeDpi
->hKL
))
206 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
) &&
207 pImeDpi
->CtfImeInquireExW
)
214 if (!pImeDpi
->ImeInquire(pImeInfo
, szUIClass
, dwSysInfoFlags
))
217 szUIClass
[_countof(szUIClass
) - 1] = 0;
219 if (pImeInfo
->dwPrivateDataSize
== 0)
220 pImeInfo
->dwPrivateDataSize
= 4;
222 #define VALID_IME_PROP (IME_PROP_AT_CARET | \
223 IME_PROP_SPECIAL_UI | \
224 IME_PROP_CANDLIST_START_FROM_1 | \
226 IME_PROP_COMPLETE_ON_UNSELECT | \
227 IME_PROP_END_UNLOAD | \
228 IME_PROP_KBD_CHAR_FIRST | \
229 IME_PROP_IGNORE_UPKEYS | \
230 IME_PROP_NEED_ALTKEY | \
231 IME_PROP_NO_KEYS_ON_CLOSE | \
232 IME_PROP_ACCEPT_WIDE_VKEY)
233 #define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
235 IME_CMODE_KATAKANA | \
236 IME_CMODE_LANGUAGE | \
237 IME_CMODE_FULLSHAPE | \
239 IME_CMODE_CHARCODE | \
240 IME_CMODE_HANJACONVERT | \
241 IME_CMODE_SOFTKBD | \
242 IME_CMODE_NOCONVERSION | \
246 #define VALID_SMODE_CAPS (IME_SMODE_NONE | \
247 IME_SMODE_PLAURALCLAUSE | \
248 IME_SMODE_SINGLECONVERT | \
249 IME_SMODE_AUTOMATIC | \
250 IME_SMODE_PHRASEPREDICT | \
251 IME_SMODE_CONVERSATION)
252 #define VALID_UI_CAPS (UI_CAP_2700 | \
256 #define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \
258 SCS_CAP_SETRECONVERTSTRING)
259 #define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
261 if (pImeInfo
->fdwProperty
& ~VALID_IME_PROP
)
263 if (pImeInfo
->fdwConversionCaps
& ~VALID_CMODE_CAPS
)
265 if (pImeInfo
->fdwSentenceCaps
& ~VALID_SMODE_CAPS
)
267 if (pImeInfo
->fdwUICaps
& ~VALID_UI_CAPS
)
269 if (pImeInfo
->fdwSCSCaps
& ~VALID_SCS_CAPS
)
271 if (pImeInfo
->fdwSelectCaps
& ~VALID_SELECT_CAPS
)
274 #undef VALID_IME_PROP
275 #undef VALID_CMODE_CAPS
276 #undef VALID_SMODE_CAPS
278 #undef VALID_SCS_CAPS
279 #undef VALID_SELECT_CAPS
281 if (pImeInfo
->fdwProperty
& IME_PROP_UNICODE
)
283 StringCchCopyW(pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
), szUIClass
);
287 if (pImeDpi
->uCodePage
!= GetACP() && pImeDpi
->uCodePage
)
290 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, (LPSTR
)szUIClass
, -1,
291 pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
));
294 return GetClassInfoW(pImeDpi
->hInst
, pImeDpi
->szUIClass
, &wcW
);
297 static BOOL APIENTRY
Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx
, PIMEDPI pImeDpi
)
299 WCHAR szPath
[MAX_PATH
];
303 if (!Imm32GetSystemLibraryPath(szPath
, _countof(szPath
), pImeInfoEx
->wszImeFile
))
306 hIME
= GetModuleHandleW(szPath
);
309 hIME
= LoadLibraryW(szPath
);
312 ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath
);
316 pImeDpi
->hInst
= hIME
;
318 #define DEFINE_IME_ENTRY(type, name, params, extended) \
320 fn = GetProcAddress(hIME, #name); \
321 if (fn) pImeDpi->name = (FN_##name)fn; \
322 else if (!extended) goto Failed; \
324 #include "../../../win32ss/include/imetable.h"
325 #undef DEFINE_IME_ENTRY
327 if (!Imm32InquireIme(pImeDpi
))
329 ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
333 if (pImeInfoEx
->fLoadFlag
)
336 NtUserSetImeOwnerWindow(pImeInfoEx
, TRUE
);
340 FreeLibrary(pImeDpi
->hInst
);
341 pImeDpi
->hInst
= NULL
;
345 static PIMEDPI APIENTRY
Ime32LoadImeDpi(HKL hKL
, BOOL bLock
)
349 PIMEDPI pImeDpiNew
, pImeDpiFound
;
353 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
) ||
354 ImeInfoEx
.fLoadFlag
== 1)
359 pImeDpiNew
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(IMEDPI
));
360 if (pImeDpiNew
== NULL
)
363 pImeDpiNew
->hKL
= hKL
;
366 if (TranslateCharsetInfo((LPDWORD
)(DWORD_PTR
)lcid
, &ci
, TCI_SRCLOCALE
))
367 uCodePage
= ci
.ciACP
;
370 pImeDpiNew
->uCodePage
= uCodePage
;
372 if (!Imm32LoadImeInfo(&ImeInfoEx
, pImeDpiNew
))
374 HeapFree(g_hImm32Heap
, 0, pImeDpiNew
);
378 RtlEnterCriticalSection(&g_csImeDpi
);
380 pImeDpiFound
= Imm32FindImeDpi(hKL
);
384 pImeDpiFound
->dwFlags
&= ~IMEDPI_FLAG_LOCKED
;
386 RtlLeaveCriticalSection(&g_csImeDpi
);
388 Imm32FreeImeDpi(pImeDpiNew
, FALSE
);
389 HeapFree(g_hImm32Heap
, 0, pImeDpiNew
);
396 pImeDpiNew
->dwFlags
|= IMEDPI_FLAG_LOCKED
;
397 pImeDpiNew
->cLockObj
= 1;
400 pImeDpiNew
->pNext
= g_pImeDpiList
;
401 g_pImeDpiList
= pImeDpiNew
;
403 RtlLeaveCriticalSection(&g_csImeDpi
);
408 /***********************************************************************
409 * ImmLoadIME (IMM32.@)
411 BOOL WINAPI
ImmLoadIME(HKL hKL
)
413 PW32CLIENTINFO pInfo
;
416 if (!IS_IME_HKL(hKL
))
418 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
421 pInfo
= (PW32CLIENTINFO
)(NtCurrentTeb()->Win32ClientInfo
);
422 if ((pInfo
->W32ClientInfo
[0] & 2))
426 pImeDpi
= Imm32FindImeDpi(hKL
);
428 pImeDpi
= Ime32LoadImeDpi(hKL
, FALSE
);
429 return (pImeDpi
!= NULL
);
432 PIMEDPI APIENTRY
ImmLockOrLoadImeDpi(HKL hKL
)
434 PW32CLIENTINFO pInfo
;
437 if (!IS_IME_HKL(hKL
))
439 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
442 pInfo
= (PW32CLIENTINFO
)(NtCurrentTeb()->Win32ClientInfo
);
443 if ((pInfo
->W32ClientInfo
[0] & 2))
447 pImeDpi
= ImmLockImeDpi(hKL
);
449 pImeDpi
= Ime32LoadImeDpi(hKL
, TRUE
);
453 /***********************************************************************
454 * ImmLoadLayout (IMM32.@)
456 HKL WINAPI
ImmLoadLayout(HKL hKL
, PIMEINFOEX pImeInfoEx
)
459 UNICODE_STRING UnicodeString
;
460 HKEY hLayoutKey
= NULL
, hLayoutsKey
= NULL
;
463 WCHAR szLayout
[MAX_PATH
];
465 TRACE("(%p, %p)\n", hKL
, pImeInfoEx
);
467 if (IS_IME_HKL(hKL
) ||
468 !g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
) ||
469 ((PW32CLIENTINFO
)NtCurrentTeb()->Win32ClientInfo
)->W32ClientInfo
[0] & 2)
471 UnicodeString
.Buffer
= szLayout
;
472 UnicodeString
.MaximumLength
= sizeof(szLayout
);
473 Status
= RtlIntegerToUnicodeString((DWORD_PTR
)hKL
, 16, &UnicodeString
);
474 if (!NT_SUCCESS(Status
))
477 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_KEYBOARD_LAYOUTS
, &hLayoutsKey
);
481 error
= RegOpenKeyW(hLayoutsKey
, szLayout
, &hLayoutKey
);
485 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_IMM
, &hLayoutKey
);
490 ERR("RegOpenKeyW error: 0x%08lX\n", error
);
495 cbData
= sizeof(pImeInfoEx
->wszImeFile
);
496 error
= RegQueryValueExW(hLayoutKey
, L
"Ime File", 0, 0,
497 (LPBYTE
)pImeInfoEx
->wszImeFile
, &cbData
);
502 RegCloseKey(hLayoutKey
);
504 RegCloseKey(hLayoutsKey
);
508 typedef struct _tagImmHkl
{
513 WCHAR imeClassName
[17]; /* 16 character max */
517 /* Function Pointers */
518 BOOL (WINAPI
*pImeInquire
)(IMEINFO
*, WCHAR
*, const WCHAR
*);
519 BOOL (WINAPI
*pImeConfigure
)(HKL
, HWND
, DWORD
, void *);
520 BOOL (WINAPI
*pImeDestroy
)(UINT
);
521 LRESULT (WINAPI
*pImeEscape
)(HIMC
, UINT
, void *);
522 BOOL (WINAPI
*pImeSelect
)(HIMC
, BOOL
);
523 BOOL (WINAPI
*pImeSetActiveContext
)(HIMC
, BOOL
);
524 UINT (WINAPI
*pImeToAsciiEx
)(UINT
, UINT
, const BYTE
*, DWORD
*, UINT
, HIMC
);
525 BOOL (WINAPI
*pNotifyIME
)(HIMC
, DWORD
, DWORD
, DWORD
);
526 BOOL (WINAPI
*pImeRegisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
527 BOOL (WINAPI
*pImeUnregisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
528 UINT (WINAPI
*pImeEnumRegisterWord
)(REGISTERWORDENUMPROCW
, const WCHAR
*, DWORD
, const WCHAR
*, void *);
529 BOOL (WINAPI
*pImeSetCompositionString
)(HIMC
, DWORD
, const void *, DWORD
, const void *, DWORD
);
530 DWORD (WINAPI
*pImeConversionList
)(HIMC
, const WCHAR
*, CANDIDATELIST
*, DWORD
, UINT
);
531 BOOL (WINAPI
*pImeProcessKey
)(HIMC
, UINT
, LPARAM
, const BYTE
*);
532 UINT (WINAPI
*pImeGetRegisterWordStyle
)(UINT
, STYLEBUFW
*);
533 DWORD (WINAPI
*pImeGetImeMenuItems
)(HIMC
, DWORD
, DWORD
, IMEMENUITEMINFOW
*, IMEMENUITEMINFOW
*, DWORD
);
536 typedef struct tagInputContextData
548 #define WINE_IMC_VALID_MAGIC 0x56434D49
550 typedef struct _tagTRANSMSG
{
554 } TRANSMSG
, *LPTRANSMSG
;
556 typedef struct _tagIMMThreadData
{
565 static struct list ImmHklList
= LIST_INIT(ImmHklList
);
566 static struct list ImmThreadDataList
= LIST_INIT(ImmThreadDataList
);
568 static const WCHAR szwWineIMCProperty
[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
570 static const WCHAR szImeFileW
[] = {'I','m','e',' ','F','i','l','e',0};
571 static const WCHAR szLayoutTextW
[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
572 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};
574 static const WCHAR szwIME
[] = {'I','M','E',0};
575 static const WCHAR szwDefaultIME
[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
577 static CRITICAL_SECTION threaddata_cs
;
578 static CRITICAL_SECTION_DEBUG critsect_debug
=
580 0, 0, &threaddata_cs
,
581 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
582 0, 0, { (DWORD_PTR
)(__FILE__
": threaddata_cs") }
584 static CRITICAL_SECTION threaddata_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
586 static inline BOOL
is_himc_ime_unicode(const InputContextData
*data
)
588 return !!(data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
591 static inline BOOL
is_kbd_ime_unicode(const ImmHkl
*hkl
)
593 return !!(hkl
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
596 static InputContextData
* get_imc_data(HIMC hIMC
);
598 static inline WCHAR
*strdupAtoW( const char *str
)
603 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
604 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
605 MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
610 static inline CHAR
*strdupWtoA( const WCHAR
*str
)
615 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
616 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
617 WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
622 static HMODULE
load_graphics_driver(void)
624 static const WCHAR display_device_guid_propW
[] = {
625 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
626 'd','e','v','i','c','e','_','g','u','i','d',0 };
627 static const WCHAR key_pathW
[] = {
628 'S','y','s','t','e','m','\\',
629 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
630 'C','o','n','t','r','o','l','\\',
631 'V','i','d','e','o','\\','{',0};
632 static const WCHAR displayW
[] = {'}','\\','0','0','0','0',0};
633 static const WCHAR driverW
[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
638 WCHAR path
[MAX_PATH
];
639 WCHAR key
[ARRAY_SIZE( key_pathW
) + ARRAY_SIZE( displayW
) + 40];
640 UINT guid_atom
= HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW
));
642 if (!guid_atom
) return 0;
643 memcpy( key
, key_pathW
, sizeof(key_pathW
) );
644 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
645 lstrcatW( key
, displayW
);
646 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
648 if (!RegQueryValueExW( hkey
, driverW
, NULL
, NULL
, (BYTE
*)path
, &size
)) ret
= LoadLibraryW( path
);
650 TRACE( "%s %p\n", debugstr_w(path
), ret
);
654 /* ImmHkl loading and freeing */
655 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
656 static ImmHkl
*IMM_GetImmHkl(HKL hkl
)
659 WCHAR filename
[MAX_PATH
];
661 TRACE("Seeking ime for keyboard %p\n",hkl
);
663 LIST_FOR_EACH_ENTRY(ptr
, &ImmHklList
, ImmHkl
, entry
)
668 /* not found... create it */
670 ptr
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ImmHkl
));
673 if (ImmGetIMEFileNameW(hkl
, filename
, MAX_PATH
)) ptr
->hIME
= LoadLibraryW(filename
);
674 if (!ptr
->hIME
) ptr
->hIME
= load_graphics_driver();
677 LOAD_FUNCPTR(ImeInquire
);
678 if (!ptr
->pImeInquire
|| !ptr
->pImeInquire(&ptr
->imeInfo
, ptr
->imeClassName
, NULL
))
680 FreeLibrary(ptr
->hIME
);
685 LOAD_FUNCPTR(ImeDestroy
);
686 LOAD_FUNCPTR(ImeSelect
);
687 if (!ptr
->pImeSelect
|| !ptr
->pImeDestroy
)
689 FreeLibrary(ptr
->hIME
);
694 LOAD_FUNCPTR(ImeConfigure
);
695 LOAD_FUNCPTR(ImeEscape
);
696 LOAD_FUNCPTR(ImeSetActiveContext
);
697 LOAD_FUNCPTR(ImeToAsciiEx
);
698 LOAD_FUNCPTR(NotifyIME
);
699 LOAD_FUNCPTR(ImeRegisterWord
);
700 LOAD_FUNCPTR(ImeUnregisterWord
);
701 LOAD_FUNCPTR(ImeEnumRegisterWord
);
702 LOAD_FUNCPTR(ImeSetCompositionString
);
703 LOAD_FUNCPTR(ImeConversionList
);
704 LOAD_FUNCPTR(ImeProcessKey
);
705 LOAD_FUNCPTR(ImeGetRegisterWordStyle
);
706 LOAD_FUNCPTR(ImeGetImeMenuItems
);
707 /* make sure our classname is WCHAR */
708 if (!is_kbd_ime_unicode(ptr
))
711 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ptr
->imeClassName
,
713 lstrcpyW(ptr
->imeClassName
, bufW
);
718 list_add_head(&ImmHklList
,&ptr
->entry
);
724 /* for posting messages as the IME */
725 static void ImmInternalPostIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
727 HWND target
= GetFocus();
729 PostMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
731 PostMessageW(target
, msg
, wParam
, lParam
);
734 /* for sending messages as the IME */
735 static void ImmInternalSendIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
737 HWND target
= GetFocus();
739 SendMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
741 SendMessageW(target
, msg
, wParam
, lParam
);
744 static InputContextData
* get_imc_data(HIMC hIMC
)
746 InputContextData
*data
= (InputContextData
*)hIMC
;
751 if(IsBadReadPtr(data
, sizeof(InputContextData
)) || data
->magic
!= WINE_IMC_VALID_MAGIC
)
753 SetLastError(ERROR_INVALID_HANDLE
);
759 static HIMC
get_default_context( HWND hwnd
)
761 FIXME("Don't use this function\n");
765 static BOOL
IMM_IsCrossThreadAccess(HWND hWnd
, HIMC hIMC
)
767 InputContextData
*data
;
771 DWORD thread
= GetWindowThreadProcessId(hWnd
, NULL
);
772 if (thread
!= GetCurrentThreadId()) return TRUE
;
774 data
= get_imc_data(hIMC
);
775 if (data
&& data
->threadID
!= GetCurrentThreadId())
781 /***********************************************************************
782 * ImmAssociateContext (IMM32.@)
784 HIMC WINAPI
ImmAssociateContext(HWND hWnd
, HIMC hIMC
)
787 InputContextData
*data
= get_imc_data(hIMC
);
789 TRACE("(%p, %p):\n", hWnd
, hIMC
);
795 * If already associated just return
797 if (hIMC
&& data
->IMC
.hWnd
== hWnd
)
800 if (hIMC
&& IMM_IsCrossThreadAccess(hWnd
, hIMC
))
805 HIMC defaultContext
= get_default_context( hWnd
);
806 old
= RemovePropW(hWnd
,szwWineIMCProperty
);
809 old
= defaultContext
;
810 else if (old
== (HIMC
)-1)
813 if (hIMC
!= defaultContext
)
815 if (hIMC
== NULL
) /* Meaning disable imm for that window*/
816 SetPropW(hWnd
,szwWineIMCProperty
,(HANDLE
)-1);
818 SetPropW(hWnd
,szwWineIMCProperty
,hIMC
);
823 InputContextData
*old_data
= (InputContextData
*)old
;
824 if (old_data
->IMC
.hWnd
== hWnd
)
825 old_data
->IMC
.hWnd
= NULL
;
832 if(GetActiveWindow() == data
->IMC
.hWnd
)
834 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, FALSE
, ISC_SHOWUIALL
);
835 data
->IMC
.hWnd
= hWnd
;
836 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, TRUE
, ISC_SHOWUIALL
);
844 * Helper function for ImmAssociateContextEx
846 static BOOL CALLBACK
_ImmAssociateContextExEnumProc(HWND hwnd
, LPARAM lParam
)
848 HIMC hImc
= (HIMC
)lParam
;
849 ImmAssociateContext(hwnd
,hImc
);
853 /***********************************************************************
854 * ImmAssociateContextEx (IMM32.@)
856 BOOL WINAPI
ImmAssociateContextEx(HWND hWnd
, HIMC hIMC
, DWORD dwFlags
)
858 TRACE("(%p, %p, 0x%x):\n", hWnd
, hIMC
, dwFlags
);
866 ImmAssociateContext(hWnd
,hIMC
);
870 HIMC defaultContext
= get_default_context( hWnd
);
871 if (!defaultContext
) return FALSE
;
872 ImmAssociateContext(hWnd
,defaultContext
);
875 case IACE_IGNORENOCONTEXT
:
876 if (GetPropW(hWnd
,szwWineIMCProperty
))
877 ImmAssociateContext(hWnd
,hIMC
);
880 EnumChildWindows(hWnd
,_ImmAssociateContextExEnumProc
,(LPARAM
)hIMC
);
883 FIXME("Unknown dwFlags 0x%x\n",dwFlags
);
888 /***********************************************************************
889 * ImmConfigureIMEA (IMM32.@)
891 BOOL WINAPI
ImmConfigureIMEA(
892 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
894 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
896 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
898 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
901 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
903 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| !is_kbd_ime_unicode(immHkl
))
904 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
908 REGISTERWORDA
*rwa
= lpData
;
911 rww
.lpReading
= strdupAtoW(rwa
->lpReading
);
912 rww
.lpWord
= strdupAtoW(rwa
->lpWord
);
913 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rww
);
914 HeapFree(GetProcessHeap(),0,rww
.lpReading
);
915 HeapFree(GetProcessHeap(),0,rww
.lpWord
);
923 /***********************************************************************
924 * ImmConfigureIMEW (IMM32.@)
926 BOOL WINAPI
ImmConfigureIMEW(
927 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
929 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
931 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
933 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
936 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
938 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| is_kbd_ime_unicode(immHkl
))
939 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
942 REGISTERWORDW
*rww
= lpData
;
946 rwa
.lpReading
= strdupWtoA(rww
->lpReading
);
947 rwa
.lpWord
= strdupWtoA(rww
->lpWord
);
948 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rwa
);
949 HeapFree(GetProcessHeap(),0,rwa
.lpReading
);
950 HeapFree(GetProcessHeap(),0,rwa
.lpWord
);
958 /***********************************************************************
959 * ImmCreateContext (IMM32.@)
961 HIMC WINAPI
ImmCreateContext(void)
963 PCLIENTIMC pClientImc
;
968 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
971 pClientImc
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
972 if (pClientImc
== NULL
)
975 hIMC
= NtUserCreateInputContext(pClientImc
);
978 HeapFree(g_hImm32Heap
, 0, pClientImc
);
982 RtlInitializeCriticalSection(&pClientImc
->cs
);
983 pClientImc
->unknown
= NtUserGetThreadState(THREADSTATE_UNKNOWN13
);
987 static VOID APIENTRY
Imm32CleanupContextExtra(LPINPUTCONTEXT pIC
)
989 FIXME("We have to do something do here");
992 static PCLIENTIMC APIENTRY
Imm32FindClientImc(HIMC hIMC
)
998 BOOL APIENTRY
Imm32CleanupContext(HIMC hIMC
, HKL hKL
, BOOL bKeep
)
1002 PCLIENTIMC pClientImc
;
1004 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
) || hIMC
== NULL
)
1007 FIXME("We have do something to do here\n");
1008 pClientImc
= Imm32FindClientImc(hIMC
);
1012 if (pClientImc
->hImc
== NULL
)
1014 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN1
;
1015 ImmUnlockClientImc(pClientImc
);
1017 return NtUserDestroyInputContext(hIMC
);
1021 pIC
= ImmLockIMC(hIMC
);
1024 ImmUnlockClientImc(pClientImc
);
1028 FIXME("We have do something to do here\n");
1030 if (pClientImc
->hKL
== hKL
)
1032 pImeDpi
= ImmLockImeDpi(hKL
);
1033 if (pImeDpi
!= NULL
)
1035 if (IS_IME_HKL(hKL
))
1037 pImeDpi
->ImeSelect(hIMC
, FALSE
);
1039 else if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
1041 FIXME("We have do something to do here\n");
1043 ImmUnlockImeDpi(pImeDpi
);
1045 pClientImc
->hKL
= NULL
;
1048 ImmDestroyIMCC(pIC
->hPrivate
);
1049 ImmDestroyIMCC(pIC
->hMsgBuf
);
1050 ImmDestroyIMCC(pIC
->hGuideLine
);
1051 ImmDestroyIMCC(pIC
->hCandInfo
);
1052 ImmDestroyIMCC(pIC
->hCompStr
);
1054 Imm32CleanupContextExtra(pIC
);
1058 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN1
;
1059 ImmUnlockClientImc(pClientImc
);
1062 return NtUserDestroyInputContext(hIMC
);
1067 /***********************************************************************
1068 * ImmDestroyContext (IMM32.@)
1070 BOOL WINAPI
ImmDestroyContext(HIMC hIMC
)
1074 TRACE("(%p)\n", hIMC
);
1076 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
1079 if (Imm32IsCrossThreadAccess(hIMC
))
1082 hKL
= GetKeyboardLayout(0);
1083 return Imm32CleanupContext(hIMC
, hKL
, FALSE
);
1086 /***********************************************************************
1087 * ImmDisableIME (IMM32.@)
1089 BOOL WINAPI
ImmDisableIME(DWORD dwThreadId
)
1091 return NtUserDisableThreadIme(dwThreadId
);
1095 * These functions absorb the difference between Ansi and Wide.
1097 typedef struct ENUM_WORD_A2W
1099 REGISTERWORDENUMPROCW lpfnEnumProc
;
1102 } ENUM_WORD_A2W
, *LPENUM_WORD_A2W
;
1104 typedef struct ENUM_WORD_W2A
1106 REGISTERWORDENUMPROCA lpfnEnumProc
;
1109 } ENUM_WORD_W2A
, *LPENUM_WORD_W2A
;
1112 Imm32EnumWordProcA2W(LPCSTR pszReadingA
, DWORD dwStyle
, LPCSTR pszRegisterA
, LPVOID lpData
)
1115 LPENUM_WORD_A2W lpEnumData
= lpData
;
1116 LPWSTR pszReadingW
= NULL
, pszRegisterW
= NULL
;
1120 pszReadingW
= Imm32WideFromAnsi(pszReadingA
);
1121 if (pszReadingW
== NULL
)
1127 pszRegisterW
= Imm32WideFromAnsi(pszRegisterA
);
1128 if (pszRegisterW
== NULL
)
1132 ret
= lpEnumData
->lpfnEnumProc(pszReadingW
, dwStyle
, pszRegisterW
, lpEnumData
->lpData
);
1133 lpEnumData
->ret
= ret
;
1137 HeapFree(g_hImm32Heap
, 0, pszReadingW
);
1139 HeapFree(g_hImm32Heap
, 0, pszRegisterW
);
1144 Imm32EnumWordProcW2A(LPCWSTR pszReadingW
, DWORD dwStyle
, LPCWSTR pszRegisterW
, LPVOID lpData
)
1147 LPENUM_WORD_W2A lpEnumData
= lpData
;
1148 LPSTR pszReadingA
= NULL
, pszRegisterA
= NULL
;
1152 pszReadingA
= Imm32AnsiFromWide(pszReadingW
);
1153 if (pszReadingW
== NULL
)
1159 pszRegisterA
= Imm32AnsiFromWide(pszRegisterW
);
1160 if (pszRegisterA
== NULL
)
1164 ret
= lpEnumData
->lpfnEnumProc(pszReadingA
, dwStyle
, pszRegisterA
, lpEnumData
->lpData
);
1165 lpEnumData
->ret
= ret
;
1169 HeapFree(g_hImm32Heap
, 0, pszReadingA
);
1171 HeapFree(g_hImm32Heap
, 0, pszRegisterA
);
1175 /***********************************************************************
1176 * ImmEnumRegisterWordA (IMM32.@)
1178 UINT WINAPI
ImmEnumRegisterWordA(
1179 HKL hKL
, REGISTERWORDENUMPROCA lpfnEnumProc
,
1180 LPCSTR lpszReading
, DWORD dwStyle
,
1181 LPCSTR lpszRegister
, LPVOID lpData
)
1184 LPWSTR pszReadingW
= NULL
, pszRegisterW
= NULL
;
1185 ENUM_WORD_W2A EnumDataW2A
;
1188 TRACE("(%p, %p, %s, 0x%lX, %s, %p)", hKL
, lpfnEnumProc
, debugstr_a(lpszReading
),
1189 dwStyle
, debugstr_a(lpszRegister
), lpData
);
1191 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
1195 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
1197 ret
= pImeDpi
->ImeEnumRegisterWord(lpfnEnumProc
, lpszReading
, dwStyle
,
1198 lpszRegister
, lpData
);
1199 ImmUnlockImeDpi(pImeDpi
);
1205 pszReadingW
= Imm32WideFromAnsi(lpszReading
);
1206 if (pszReadingW
== NULL
)
1212 pszRegisterW
= Imm32WideFromAnsi(lpszRegister
);
1213 if (pszRegisterW
== NULL
)
1217 EnumDataW2A
.lpfnEnumProc
= lpfnEnumProc
;
1218 EnumDataW2A
.lpData
= lpData
;
1219 EnumDataW2A
.ret
= 0;
1220 pImeDpi
->ImeEnumRegisterWord(Imm32EnumWordProcW2A
, pszReadingW
, dwStyle
,
1221 pszRegisterW
, &EnumDataW2A
);
1222 ret
= EnumDataW2A
.ret
;
1226 HeapFree(g_hImm32Heap
, 0, pszReadingW
);
1228 HeapFree(g_hImm32Heap
, 0, pszRegisterW
);
1229 ImmUnlockImeDpi(pImeDpi
);
1233 /***********************************************************************
1234 * ImmEnumRegisterWordW (IMM32.@)
1236 UINT WINAPI
ImmEnumRegisterWordW(
1237 HKL hKL
, REGISTERWORDENUMPROCW lpfnEnumProc
,
1238 LPCWSTR lpszReading
, DWORD dwStyle
,
1239 LPCWSTR lpszRegister
, LPVOID lpData
)
1242 LPSTR pszReadingA
= NULL
, pszRegisterA
= NULL
;
1243 ENUM_WORD_A2W EnumDataA2W
;
1246 TRACE("(%p, %p, %s, 0x%lX, %s, %p)", hKL
, lpfnEnumProc
, debugstr_w(lpszReading
),
1247 dwStyle
, debugstr_w(lpszRegister
), lpData
);
1249 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
1253 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
1255 ret
= pImeDpi
->ImeEnumRegisterWord(lpfnEnumProc
, lpszReading
, dwStyle
,
1256 lpszRegister
, lpData
);
1257 ImmUnlockImeDpi(pImeDpi
);
1263 pszReadingA
= Imm32AnsiFromWide(lpszReading
);
1264 if (pszReadingA
== NULL
)
1270 pszRegisterA
= Imm32AnsiFromWide(lpszRegister
);
1271 if (pszRegisterA
== NULL
)
1275 EnumDataA2W
.lpfnEnumProc
= lpfnEnumProc
;
1276 EnumDataA2W
.lpData
= lpData
;
1277 EnumDataA2W
.ret
= 0;
1278 pImeDpi
->ImeEnumRegisterWord(Imm32EnumWordProcA2W
, pszReadingA
, dwStyle
,
1279 pszRegisterA
, &EnumDataA2W
);
1280 ret
= EnumDataA2W
.ret
;
1284 HeapFree(g_hImm32Heap
, 0, pszReadingA
);
1286 HeapFree(g_hImm32Heap
, 0, pszRegisterA
);
1287 ImmUnlockImeDpi(pImeDpi
);
1291 static inline BOOL
EscapeRequiresWA(UINT uEscape
)
1293 if (uEscape
== IME_ESC_GET_EUDC_DICTIONARY
||
1294 uEscape
== IME_ESC_SET_EUDC_DICTIONARY
||
1295 uEscape
== IME_ESC_IME_NAME
||
1296 uEscape
== IME_ESC_GETHELPFILENAME
)
1301 /***********************************************************************
1302 * ImmEscapeA (IMM32.@)
1304 LRESULT WINAPI
ImmEscapeA(
1306 UINT uEscape
, LPVOID lpData
)
1308 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1309 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1311 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1313 if (!EscapeRequiresWA(uEscape
) || !is_kbd_ime_unicode(immHkl
))
1314 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1317 WCHAR buffer
[81]; /* largest required buffer should be 80 */
1319 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1321 MultiByteToWideChar(CP_ACP
,0,lpData
,-1,buffer
,81);
1322 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1326 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1327 WideCharToMultiByte(CP_ACP
,0,buffer
,-1,lpData
,80, NULL
, NULL
);
1336 /***********************************************************************
1337 * ImmEscapeW (IMM32.@)
1339 LRESULT WINAPI
ImmEscapeW(
1341 UINT uEscape
, LPVOID lpData
)
1343 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1344 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1346 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1348 if (!EscapeRequiresWA(uEscape
) || is_kbd_ime_unicode(immHkl
))
1349 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1352 CHAR buffer
[81]; /* largest required buffer should be 80 */
1354 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1356 WideCharToMultiByte(CP_ACP
,0,lpData
,-1,buffer
,81, NULL
, NULL
);
1357 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1361 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1362 MultiByteToWideChar(CP_ACP
,0,buffer
,-1,lpData
,80);
1371 static PCLIENTIMC APIENTRY
Imm32GetClientImcCache(void)
1373 // FIXME: Do something properly here
1377 static DWORD APIENTRY
Imm32AllocAndBuildHimcList(DWORD dwThreadId
, HIMC
**pphList
)
1379 #define INITIAL_COUNT 0x40
1380 #define MAX_RETRY 10
1382 DWORD dwCount
= INITIAL_COUNT
, cRetry
= 0;
1385 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
1386 if (phNewList
== NULL
)
1389 Status
= NtUserBuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
1390 while (Status
== STATUS_BUFFER_TOO_SMALL
)
1392 HeapFree(g_hImm32Heap
, 0, phNewList
);
1393 if (cRetry
++ >= MAX_RETRY
)
1396 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
1397 if (phNewList
== NULL
)
1400 Status
= NtUserBuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
1403 if (NT_ERROR(Status
) || !dwCount
)
1405 HeapFree(g_hImm32Heap
, 0, phNewList
);
1409 *pphList
= phNewList
;
1411 #undef INITIAL_COUNT
1415 static BOOL APIENTRY
Imm32ImeNonImeToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
, LANGID LangID
)
1423 if (!IS_IME_HKL(hKL
) || LOWORD(hKL
) != LangID
)
1425 FIXME("We have to do something here\n");
1429 pIC
= ImmLockIMC(hIMC
);
1438 ImmSetOpenStatus(hIMC
, TRUE
);
1442 FIXME("We have to do something here\n");
1446 static BOOL APIENTRY
Imm32CShapeToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1450 DWORD dwConversion
, dwSentence
;
1452 if (hWnd
== NULL
|| !IS_IME_HKL(hKL
))
1455 pIC
= ImmLockIMC(hIMC
);
1462 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_FULLSHAPE
);
1463 dwSentence
= pIC
->fdwSentence
;
1469 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1471 ImmSetOpenStatus(hIMC
, TRUE
);
1476 static BOOL APIENTRY
Imm32CSymbolToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1480 DWORD dwConversion
, dwSentence
;
1482 if (hWnd
== NULL
|| !IS_IME_HKL(hKL
))
1485 pIC
= ImmLockIMC(hIMC
);
1492 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_SYMBOL
);
1493 dwSentence
= pIC
->fdwSentence
;
1499 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1501 ImmSetOpenStatus(hIMC
, TRUE
);
1506 static BOOL APIENTRY
Imm32JCloseOpen(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1510 if (ImmIsIME(hKL
) && LOWORD(hKL
) == LANGID_JAPANESE
)
1512 fOpen
= ImmGetOpenStatus(hIMC
);
1513 ImmSetOpenStatus(hIMC
, !fOpen
);
1517 FIXME("We have to do something here\n");
1521 static BOOL APIENTRY
Imm32KShapeToggle(HIMC hIMC
)
1524 DWORD dwConversion
, dwSentence
;
1526 pIC
= ImmLockIMC(hIMC
);
1530 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_FULLSHAPE
);
1531 dwSentence
= pIC
->fdwSentence
;
1532 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1534 if (pIC
->fdwConversion
& (IME_CMODE_FULLSHAPE
| IME_CMODE_NATIVE
))
1535 ImmSetOpenStatus(hIMC
, TRUE
);
1537 ImmSetOpenStatus(hIMC
, FALSE
);
1543 static BOOL APIENTRY
Imm32KHanjaConvert(HIMC hIMC
)
1546 DWORD dwConversion
, dwSentence
;
1548 pIC
= ImmLockIMC(hIMC
);
1552 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_HANJACONVERT
);
1553 dwSentence
= pIC
->fdwSentence
;
1556 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1560 static BOOL APIENTRY
Imm32KEnglish(HIMC hIMC
)
1563 DWORD dwConversion
, dwSentence
;
1566 pIC
= ImmLockIMC(hIMC
);
1570 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_NATIVE
);
1571 dwSentence
= pIC
->fdwSentence
;
1572 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1574 fOpen
= ((pIC
->fdwConversion
& (IME_CMODE_FULLSHAPE
| IME_CMODE_NATIVE
)) != 0);
1575 ImmSetOpenStatus(hIMC
, fOpen
);
1581 static BOOL APIENTRY
Imm32ProcessHotKey(HWND hWnd
, HIMC hIMC
, HKL hKL
, DWORD dwHotKeyID
)
1586 if (hIMC
&& Imm32IsCrossThreadAccess(hIMC
))
1591 case IME_CHOTKEY_IME_NONIME_TOGGLE
:
1592 return Imm32ImeNonImeToggle(hIMC
, hKL
, hWnd
, LANGID_CHINESE_SIMPLIFIED
);
1594 case IME_CHOTKEY_SHAPE_TOGGLE
:
1595 return Imm32CShapeToggle(hIMC
, hKL
, hWnd
);
1597 case IME_CHOTKEY_SYMBOL_TOGGLE
:
1598 return Imm32CSymbolToggle(hIMC
, hKL
, hWnd
);
1600 case IME_JHOTKEY_CLOSE_OPEN
:
1601 return Imm32JCloseOpen(hIMC
, hKL
, hWnd
);
1603 case IME_KHOTKEY_SHAPE_TOGGLE
:
1604 return Imm32KShapeToggle(hIMC
);
1606 case IME_KHOTKEY_HANJACONVERT
:
1607 return Imm32KHanjaConvert(hIMC
);
1609 case IME_KHOTKEY_ENGLISH
:
1610 return Imm32KEnglish(hIMC
);
1612 case IME_THOTKEY_IME_NONIME_TOGGLE
:
1613 return Imm32ImeNonImeToggle(hIMC
, hKL
, hWnd
, LANGID_CHINESE_TRADITIONAL
);
1615 case IME_THOTKEY_SHAPE_TOGGLE
:
1616 return Imm32CShapeToggle(hIMC
, hKL
, hWnd
);
1618 case IME_THOTKEY_SYMBOL_TOGGLE
:
1619 return Imm32CSymbolToggle(hIMC
, hKL
, hWnd
);
1625 if (dwHotKeyID
< IME_HOTKEY_PRIVATE_FIRST
|| IME_HOTKEY_PRIVATE_LAST
< dwHotKeyID
)
1628 pImeDpi
= ImmLockImeDpi(hKL
);
1629 if (pImeDpi
== NULL
)
1632 ret
= (BOOL
)pImeDpi
->ImeEscape(hIMC
, IME_ESC_PRIVATE_HOTKEY
, &dwHotKeyID
);
1633 ImmUnlockImeDpi(pImeDpi
);
1637 /***********************************************************************
1638 * ImmLockClientImc (IMM32.@)
1640 PCLIENTIMC WINAPI
ImmLockClientImc(HIMC hImc
)
1642 PCLIENTIMC pClientImc
;
1644 TRACE("(%p)\n", hImc
);
1649 pClientImc
= Imm32GetClientImcCache();
1652 pClientImc
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
1656 RtlInitializeCriticalSection(&pClientImc
->cs
);
1657 pClientImc
->unknown
= NtUserGetThreadState(THREADSTATE_UNKNOWN13
);
1659 if (!NtUserUpdateInputContext(hImc
, 0, pClientImc
))
1661 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1665 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN2
;
1669 if (pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN1
)
1673 InterlockedIncrement(&pClientImc
->cLockObj
);
1677 /***********************************************************************
1678 * ImmUnlockClientImc (IMM32.@)
1680 VOID WINAPI
ImmUnlockClientImc(PCLIENTIMC pClientImc
)
1685 TRACE("(%p)\n", pClientImc
);
1687 cLocks
= InterlockedDecrement(&pClientImc
->cLockObj
);
1688 if (cLocks
!= 0 || !(pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN1
))
1691 hImc
= pClientImc
->hImc
;
1695 RtlDeleteCriticalSection(&pClientImc
->cs
);
1696 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1699 static DWORD APIENTRY
1700 CandidateListWideToAnsi(const CANDIDATELIST
*pWideCL
, LPCANDIDATELIST pAnsiCL
, DWORD dwBufLen
,
1704 DWORD dwSize
, dwIndex
, cbGot
, cbLeft
;
1709 /* calculate total ansi size */
1710 if (pWideCL
->dwCount
> 0)
1712 dwSize
= sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1713 for (dwIndex
= 0; dwIndex
< pWideCL
->dwCount
; ++dwIndex
)
1715 pbWide
= (const BYTE
*)pWideCL
+ pWideCL
->dwOffset
[dwIndex
];
1716 cbGot
= WideCharToMultiByte(uCodePage
, 0, (LPCWSTR
)pbWide
, -1, NULL
, 0,
1717 NULL
, &bUsedDefault
);
1723 dwSize
= sizeof(CANDIDATELIST
);
1726 dwSize
= ROUNDUP4(dwSize
);
1729 if (dwBufLen
< dwSize
)
1733 pAnsiCL
->dwSize
= dwBufLen
;
1734 pAnsiCL
->dwStyle
= pWideCL
->dwStyle
;
1735 pAnsiCL
->dwCount
= pWideCL
->dwCount
;
1736 pAnsiCL
->dwSelection
= pWideCL
->dwSelection
;
1737 pAnsiCL
->dwPageStart
= pWideCL
->dwPageStart
;
1738 pAnsiCL
->dwPageSize
= pWideCL
->dwPageSize
;
1740 pibOffsets
= pAnsiCL
->dwOffset
;
1741 if (pWideCL
->dwCount
> 0)
1743 pibOffsets
[0] = sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1744 cbLeft
= dwBufLen
- pibOffsets
[0];
1746 for (dwIndex
= 0; dwIndex
< pWideCL
->dwCount
; ++dwIndex
)
1748 pbWide
= (const BYTE
*)pWideCL
+ pWideCL
->dwOffset
[dwIndex
];
1749 pbAnsi
= (LPBYTE
)pAnsiCL
+ pibOffsets
[dwIndex
];
1751 /* convert to ansi */
1752 cbGot
= WideCharToMultiByte(uCodePage
, 0, (LPCWSTR
)pbWide
, -1,
1753 (LPSTR
)pbAnsi
, cbLeft
, NULL
, &bUsedDefault
);
1756 if (dwIndex
< pWideCL
->dwCount
- 1)
1757 pibOffsets
[dwIndex
+ 1] = pibOffsets
[dwIndex
] + cbGot
;
1762 pibOffsets
[0] = sizeof(CANDIDATELIST
);
1768 static DWORD APIENTRY
1769 CandidateListAnsiToWide(const CANDIDATELIST
*pAnsiCL
, LPCANDIDATELIST pWideCL
, DWORD dwBufLen
,
1772 DWORD dwSize
, dwIndex
, cchGot
, cbGot
, cbLeft
;
1777 /* calculate total wide size */
1778 if (pAnsiCL
->dwCount
> 0)
1780 dwSize
= sizeof(CANDIDATELIST
) + ((pAnsiCL
->dwCount
- 1) * sizeof(DWORD
));
1781 for (dwIndex
= 0; dwIndex
< pAnsiCL
->dwCount
; ++dwIndex
)
1783 pbAnsi
= (const BYTE
*)pAnsiCL
+ pAnsiCL
->dwOffset
[dwIndex
];
1784 cchGot
= MultiByteToWideChar(uCodePage
, MB_PRECOMPOSED
, (LPCSTR
)pbAnsi
, -1, NULL
, 0);
1785 dwSize
+= cchGot
* sizeof(WCHAR
);
1790 dwSize
= sizeof(CANDIDATELIST
);
1793 dwSize
= ROUNDUP4(dwSize
);
1796 if (dwBufLen
< dwSize
)
1800 pWideCL
->dwSize
= dwBufLen
;
1801 pWideCL
->dwStyle
= pAnsiCL
->dwStyle
;
1802 pWideCL
->dwCount
= pAnsiCL
->dwCount
;
1803 pWideCL
->dwSelection
= pAnsiCL
->dwSelection
;
1804 pWideCL
->dwPageStart
= pAnsiCL
->dwPageStart
;
1805 pWideCL
->dwPageSize
= pAnsiCL
->dwPageSize
;
1807 pibOffsets
= pWideCL
->dwOffset
;
1808 if (pAnsiCL
->dwCount
> 0)
1810 pibOffsets
[0] = sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1811 cbLeft
= dwBufLen
- pibOffsets
[0];
1813 for (dwIndex
= 0; dwIndex
< pAnsiCL
->dwCount
; ++dwIndex
)
1815 pbAnsi
= (const BYTE
*)pAnsiCL
+ pAnsiCL
->dwOffset
[dwIndex
];
1816 pbWide
= (LPBYTE
)pWideCL
+ pibOffsets
[dwIndex
];
1818 /* convert to wide */
1819 cchGot
= MultiByteToWideChar(uCodePage
, MB_PRECOMPOSED
, (LPCSTR
)pbAnsi
, -1,
1820 (LPWSTR
)pbWide
, cbLeft
/ sizeof(WCHAR
));
1821 cbGot
= cchGot
* sizeof(WCHAR
);
1824 if (dwIndex
+ 1 < pAnsiCL
->dwCount
)
1825 pibOffsets
[dwIndex
+ 1] = pibOffsets
[dwIndex
] + cbGot
;
1830 pibOffsets
[0] = sizeof(CANDIDATELIST
);
1836 static DWORD APIENTRY
1837 ImmGetCandidateListAW(HIMC hIMC
, DWORD dwIndex
, LPCANDIDATELIST lpCandList
, DWORD dwBufLen
,
1842 PCLIENTIMC pClientImc
;
1843 LPCANDIDATEINFO pCI
;
1844 LPCANDIDATELIST pCL
;
1847 pClientImc
= ImmLockClientImc(hIMC
);
1851 pIC
= ImmLockIMC(hIMC
);
1854 ImmUnlockClientImc(pClientImc
);
1858 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
1862 ImmUnlockClientImc(pClientImc
);
1866 if (pCI
->dwSize
< sizeof(CANDIDATEINFO
) || pCI
->dwCount
<= dwIndex
)
1869 /* get required size */
1870 pCL
= (LPCANDIDATELIST
)((LPBYTE
)pCI
+ pCI
->dwOffset
[dwIndex
]);
1873 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1874 dwSize
= CandidateListAnsiToWide(pCL
, NULL
, 0, CP_ACP
);
1876 dwSize
= pCL
->dwSize
;
1880 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1881 dwSize
= pCL
->dwSize
;
1883 dwSize
= CandidateListWideToAnsi(pCL
, NULL
, 0, CP_ACP
);
1886 if (dwBufLen
!= 0 && dwSize
!= 0)
1888 if (lpCandList
== NULL
|| dwBufLen
< dwSize
)
1894 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1895 CandidateListAnsiToWide(pCL
, lpCandList
, dwSize
, CP_ACP
);
1897 RtlCopyMemory(lpCandList
, pCL
, dwSize
);
1901 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1902 RtlCopyMemory(lpCandList
, pCL
, dwSize
);
1904 CandidateListWideToAnsi(pCL
, lpCandList
, dwSize
, CP_ACP
);
1911 ImmUnlockIMCC(pIC
->hCandInfo
);
1913 ImmUnlockClientImc(pClientImc
);
1917 DWORD APIENTRY
ImmGetCandidateListCountAW(HIMC hIMC
, LPDWORD lpdwListCount
, BOOL bAnsi
)
1919 DWORD ret
= 0, cbGot
, dwIndex
;
1920 PCLIENTIMC pClientImc
;
1922 const CANDIDATEINFO
*pCI
;
1924 const CANDIDATELIST
*pCL
;
1925 const DWORD
*pdwOffsets
;
1927 if (lpdwListCount
== NULL
)
1932 pClientImc
= ImmLockClientImc(hIMC
);
1933 if (pClientImc
== NULL
)
1936 pIC
= ImmLockIMC(hIMC
);
1939 ImmUnlockClientImc(pClientImc
);
1943 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
1947 ImmUnlockClientImc(pClientImc
);
1951 if (pCI
->dwSize
< sizeof(CANDIDATEINFO
))
1954 *lpdwListCount
= pCI
->dwCount
; /* the number of candidate lists */
1956 /* calculate total size of candidate lists */
1959 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1961 ret
= ROUNDUP4(pCI
->dwPrivateSize
);
1962 pdwOffsets
= pCI
->dwOffset
;
1963 for (dwIndex
= 0; dwIndex
< pCI
->dwCount
; ++dwIndex
)
1965 pb
= (const BYTE
*)pCI
+ pdwOffsets
[dwIndex
];
1966 pCL
= (const CANDIDATELIST
*)pb
;
1967 cbGot
= CandidateListWideToAnsi(pCL
, NULL
, 0, CP_ACP
);
1978 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1984 ret
= ROUNDUP4(pCI
->dwPrivateSize
);
1985 pdwOffsets
= pCI
->dwOffset
;
1986 for (dwIndex
= 0; dwIndex
< pCI
->dwCount
; ++dwIndex
)
1988 pb
= (const BYTE
*)pCI
+ pdwOffsets
[dwIndex
];
1989 pCL
= (const CANDIDATELIST
*)pb
;
1990 cbGot
= CandidateListAnsiToWide(pCL
, NULL
, 0, CP_ACP
);
1997 ImmUnlockIMCC(pIC
->hCandInfo
);
1999 ImmUnlockClientImc(pClientImc
);
2003 /***********************************************************************
2004 * ImmGetCandidateListA (IMM32.@)
2006 DWORD WINAPI
ImmGetCandidateListA(
2007 HIMC hIMC
, DWORD dwIndex
,
2008 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
2010 return ImmGetCandidateListAW(hIMC
, dwIndex
, lpCandList
, dwBufLen
, TRUE
);
2013 /***********************************************************************
2014 * ImmGetCandidateListCountA (IMM32.@)
2016 DWORD WINAPI
ImmGetCandidateListCountA(
2017 HIMC hIMC
, LPDWORD lpdwListCount
)
2019 return ImmGetCandidateListCountAW(hIMC
, lpdwListCount
, TRUE
);
2022 /***********************************************************************
2023 * ImmGetCandidateListCountW (IMM32.@)
2025 DWORD WINAPI
ImmGetCandidateListCountW(
2026 HIMC hIMC
, LPDWORD lpdwListCount
)
2028 return ImmGetCandidateListCountAW(hIMC
, lpdwListCount
, FALSE
);
2031 /***********************************************************************
2032 * ImmGetCandidateListW (IMM32.@)
2034 DWORD WINAPI
ImmGetCandidateListW(
2035 HIMC hIMC
, DWORD dwIndex
,
2036 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
2038 return ImmGetCandidateListAW(hIMC
, dwIndex
, lpCandList
, dwBufLen
, FALSE
);
2041 /***********************************************************************
2042 * ImmGetCandidateWindow (IMM32.@)
2044 BOOL WINAPI
ImmGetCandidateWindow(
2045 HIMC hIMC
, DWORD dwIndex
, LPCANDIDATEFORM lpCandidate
)
2049 LPCANDIDATEFORM pCF
;
2051 TRACE("(%p, %lu, %p)\n", hIMC
, dwIndex
, lpCandidate
);
2053 pIC
= ImmLockIMC(hIMC
);
2057 pCF
= &pIC
->cfCandForm
[dwIndex
];
2058 if (pCF
->dwIndex
!= IMM_INVALID_CANDFORM
)
2060 *lpCandidate
= *pCF
;
2068 static VOID APIENTRY
LogFontAnsiToWide(const LOGFONTA
*plfA
, LPLOGFONTW plfW
)
2071 RtlCopyMemory(plfW
, plfA
, offsetof(LOGFONTA
, lfFaceName
));
2072 StringCchLengthA(plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), &cch
);
2073 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, plfA
->lfFaceName
, (INT
)cch
,
2074 plfW
->lfFaceName
, _countof(plfW
->lfFaceName
));
2075 if (cch
> _countof(plfW
->lfFaceName
) - 1)
2076 cch
= _countof(plfW
->lfFaceName
) - 1;
2077 plfW
->lfFaceName
[cch
] = 0;
2080 static VOID APIENTRY
LogFontWideToAnsi(const LOGFONTW
*plfW
, LPLOGFONTA plfA
)
2083 RtlCopyMemory(plfA
, plfW
, offsetof(LOGFONTW
, lfFaceName
));
2084 StringCchLengthW(plfW
->lfFaceName
, _countof(plfW
->lfFaceName
), &cch
);
2085 cch
= WideCharToMultiByte(CP_ACP
, 0, plfW
->lfFaceName
, (INT
)cch
,
2086 plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), NULL
, NULL
);
2087 if (cch
> _countof(plfA
->lfFaceName
) - 1)
2088 cch
= _countof(plfA
->lfFaceName
) - 1;
2089 plfA
->lfFaceName
[cch
] = 0;
2092 /***********************************************************************
2093 * ImmGetCompositionFontA (IMM32.@)
2095 BOOL WINAPI
ImmGetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
2097 PCLIENTIMC pClientImc
;
2098 BOOL ret
= FALSE
, bWide
;
2101 TRACE("(%p, %p)\n", hIMC
, lplf
);
2103 pClientImc
= ImmLockClientImc(hIMC
);
2104 if (pClientImc
== NULL
)
2107 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
2108 ImmUnlockClientImc(pClientImc
);
2110 pIC
= ImmLockIMC(hIMC
);
2114 if (pIC
->fdwInit
& INIT_LOGFONT
)
2117 LogFontWideToAnsi(&pIC
->lfFont
.W
, lplf
);
2119 *lplf
= pIC
->lfFont
.A
;
2128 /***********************************************************************
2129 * ImmGetCompositionFontW (IMM32.@)
2131 BOOL WINAPI
ImmGetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
2133 PCLIENTIMC pClientImc
;
2138 TRACE("(%p, %p)\n", hIMC
, lplf
);
2140 pClientImc
= ImmLockClientImc(hIMC
);
2141 if (pClientImc
== NULL
)
2144 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
2145 ImmUnlockClientImc(pClientImc
);
2147 pIC
= ImmLockIMC(hIMC
);
2151 if (pIC
->fdwInit
& INIT_LOGFONT
)
2154 *lplf
= pIC
->lfFont
.W
;
2156 LogFontAnsiToWide(&pIC
->lfFont
.A
, lplf
);
2166 /* Helpers for the GetCompositionString functions */
2168 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
2169 length is always in bytes. */
2170 static INT
CopyCompStringIMEtoClient(const InputContextData
*data
, const void *src
, INT src_len
, void *dst
,
2171 INT dst_len
, BOOL unicode
)
2173 int char_size
= unicode
? sizeof(WCHAR
) : sizeof(char);
2176 if (is_himc_ime_unicode(data
) ^ unicode
)
2179 ret
= MultiByteToWideChar(CP_ACP
, 0, src
, src_len
, dst
, dst_len
/ sizeof(WCHAR
));
2181 ret
= WideCharToMultiByte(CP_ACP
, 0, src
, src_len
, dst
, dst_len
, NULL
, NULL
);
2188 ret
= min(src_len
* char_size
, dst_len
);
2189 memcpy(dst
, src
, ret
);
2192 ret
= src_len
* char_size
;
2198 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
2199 passed mode. String length is in characters, attributes are in byte arrays. */
2200 static INT
CopyCompAttrIMEtoClient(const InputContextData
*data
, const BYTE
*src
, INT src_len
, const void *comp_string
,
2201 INT str_len
, BYTE
*dst
, INT dst_len
, BOOL unicode
)
2211 string
.str
= comp_string
;
2213 if (is_himc_ime_unicode(data
) && !unicode
)
2215 rc
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
, str_len
, NULL
, 0, NULL
, NULL
);
2218 int i
, j
= 0, k
= 0;
2222 for (i
= 0; i
< str_len
; ++i
)
2226 len
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
+ i
, 1, NULL
, 0, NULL
, NULL
);
2227 for (; len
> 0; --len
)
2240 else if (!is_himc_ime_unicode(data
) && unicode
)
2242 rc
= MultiByteToWideChar(CP_ACP
, 0, string
.strA
, str_len
, NULL
, 0);
2249 for (i
= 0; i
< str_len
; ++i
)
2251 if (IsDBCSLeadByte(string
.strA
[i
]))
2264 memcpy(dst
, src
, min(src_len
, dst_len
));
2271 static INT
CopyCompClauseIMEtoClient(InputContextData
*data
, LPBYTE source
, INT slen
, LPBYTE ssource
,
2272 LPBYTE target
, INT tlen
, BOOL unicode
)
2276 if (is_himc_ime_unicode(data
) && !unicode
)
2284 tlen
/= sizeof (DWORD
);
2285 for (i
= 0; i
< tlen
; ++i
)
2287 ((DWORD
*)target
)[i
] = WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
,
2288 ((DWORD
*)source
)[i
],
2292 rc
= sizeof (DWORD
) * i
;
2297 else if (!is_himc_ime_unicode(data
) && unicode
)
2305 tlen
/= sizeof (DWORD
);
2306 for (i
= 0; i
< tlen
; ++i
)
2308 ((DWORD
*)target
)[i
] = MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
,
2309 ((DWORD
*)source
)[i
],
2312 rc
= sizeof (DWORD
) * i
;
2319 memcpy( target
, source
, min(slen
,tlen
));
2326 static INT
CopyCompOffsetIMEtoClient(InputContextData
*data
, DWORD offset
, LPBYTE ssource
, BOOL unicode
)
2330 if (is_himc_ime_unicode(data
) && !unicode
)
2332 rc
= WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
, offset
, NULL
, 0, NULL
, NULL
);
2334 else if (!is_himc_ime_unicode(data
) && unicode
)
2336 rc
= MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
, offset
, NULL
, 0);
2344 static LONG
ImmGetCompositionStringT( HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
,
2345 DWORD dwBufLen
, BOOL unicode
)
2348 InputContextData
*data
= get_imc_data(hIMC
);
2349 LPCOMPOSITIONSTRING compstr
;
2352 TRACE("(%p, 0x%x, %p, %d)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2357 if (!data
->IMC
.hCompStr
)
2360 compdata
= ImmLockIMCC(data
->IMC
.hCompStr
);
2361 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
2366 TRACE("GCS_RESULTSTR\n");
2367 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultStrOffset
, compstr
->dwResultStrLen
, lpBuf
, dwBufLen
, unicode
);
2370 TRACE("GCS_COMPSTR\n");
2371 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
, lpBuf
, dwBufLen
, unicode
);
2374 TRACE("GCS_COMPATTR\n");
2375 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompAttrOffset
, compstr
->dwCompAttrLen
,
2376 compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
,
2377 lpBuf
, dwBufLen
, unicode
);
2379 case GCS_COMPCLAUSE
:
2380 TRACE("GCS_COMPCLAUSE\n");
2381 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompClauseOffset
,compstr
->dwCompClauseLen
,
2382 compdata
+ compstr
->dwCompStrOffset
,
2383 lpBuf
, dwBufLen
, unicode
);
2385 case GCS_RESULTCLAUSE
:
2386 TRACE("GCS_RESULTCLAUSE\n");
2387 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultClauseOffset
,compstr
->dwResultClauseLen
,
2388 compdata
+ compstr
->dwResultStrOffset
,
2389 lpBuf
, dwBufLen
, unicode
);
2391 case GCS_RESULTREADSTR
:
2392 TRACE("GCS_RESULTREADSTR\n");
2393 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultReadStrOffset
, compstr
->dwResultReadStrLen
, lpBuf
, dwBufLen
, unicode
);
2395 case GCS_RESULTREADCLAUSE
:
2396 TRACE("GCS_RESULTREADCLAUSE\n");
2397 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultReadClauseOffset
,compstr
->dwResultReadClauseLen
,
2398 compdata
+ compstr
->dwResultStrOffset
,
2399 lpBuf
, dwBufLen
, unicode
);
2401 case GCS_COMPREADSTR
:
2402 TRACE("GCS_COMPREADSTR\n");
2403 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
, lpBuf
, dwBufLen
, unicode
);
2405 case GCS_COMPREADATTR
:
2406 TRACE("GCS_COMPREADATTR\n");
2407 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompReadAttrOffset
, compstr
->dwCompReadAttrLen
,
2408 compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
,
2409 lpBuf
, dwBufLen
, unicode
);
2411 case GCS_COMPREADCLAUSE
:
2412 TRACE("GCS_COMPREADCLAUSE\n");
2413 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompReadClauseOffset
,compstr
->dwCompReadClauseLen
,
2414 compdata
+ compstr
->dwCompStrOffset
,
2415 lpBuf
, dwBufLen
, unicode
);
2418 TRACE("GCS_CURSORPOS\n");
2419 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwCursorPos
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
2421 case GCS_DELTASTART
:
2422 TRACE("GCS_DELTASTART\n");
2423 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwDeltaStart
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
2426 FIXME("Unhandled index 0x%x\n",dwIndex
);
2430 ImmUnlockIMCC(data
->IMC
.hCompStr
);
2435 /***********************************************************************
2436 * ImmGetCompositionStringA (IMM32.@)
2438 LONG WINAPI
ImmGetCompositionStringA(
2439 HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
)
2441 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
2445 /***********************************************************************
2446 * ImmGetCompositionStringW (IMM32.@)
2448 LONG WINAPI
ImmGetCompositionStringW(
2449 HIMC hIMC
, DWORD dwIndex
,
2450 LPVOID lpBuf
, DWORD dwBufLen
)
2452 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
2455 /***********************************************************************
2456 * ImmGetCompositionWindow (IMM32.@)
2458 BOOL WINAPI
ImmGetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
2463 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
2465 pIC
= ImmLockIMC(hIMC
);
2469 if (pIC
->fdwInit
& INIT_COMPFORM
)
2471 *lpCompForm
= pIC
->cfCompForm
;
2479 /***********************************************************************
2480 * ImmGetContext (IMM32.@)
2482 HIMC WINAPI
ImmGetContext(HWND hWnd
)
2486 TRACE("%p\n", hWnd
);
2488 if (!IsWindow(hWnd
))
2490 SetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2494 rc
= GetPropW(hWnd
,szwWineIMCProperty
);
2497 else if (rc
== NULL
)
2498 rc
= get_default_context( hWnd
);
2502 InputContextData
*data
= (InputContextData
*)rc
;
2503 data
->IMC
.hWnd
= hWnd
;
2506 TRACE("returning %p\n", rc
);
2511 /***********************************************************************
2512 * ImmGetConversionListA (IMM32.@)
2514 DWORD WINAPI
ImmGetConversionListA(
2516 LPCSTR pSrc
, LPCANDIDATELIST lpDst
,
2517 DWORD dwBufLen
, UINT uFlag
)
2521 LPWSTR pszSrcW
= NULL
;
2522 LPCANDIDATELIST pCL
= NULL
;
2525 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL
, hIMC
, debugstr_a(pSrc
),
2526 lpDst
, dwBufLen
, uFlag
);
2528 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
2529 if (pImeDpi
== NULL
)
2532 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
2534 ret
= pImeDpi
->ImeConversionList(hIMC
, pSrc
, lpDst
, dwBufLen
, uFlag
);
2535 ImmUnlockImeDpi(pImeDpi
);
2541 pszSrcW
= Imm32WideFromAnsi(pSrc
);
2542 if (pszSrcW
== NULL
)
2546 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcW
, NULL
, 0, uFlag
);
2550 pCL
= Imm32HeapAlloc(0, cb
);
2554 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcW
, pCL
, cb
, uFlag
);
2558 ret
= CandidateListWideToAnsi(pCL
, lpDst
, dwBufLen
, CP_ACP
);
2562 HeapFree(g_hImm32Heap
, 0, pszSrcW
);
2564 HeapFree(g_hImm32Heap
, 0, pCL
);
2565 ImmUnlockImeDpi(pImeDpi
);
2569 /***********************************************************************
2570 * ImmGetConversionListW (IMM32.@)
2572 DWORD WINAPI
ImmGetConversionListW(
2574 LPCWSTR pSrc
, LPCANDIDATELIST lpDst
,
2575 DWORD dwBufLen
, UINT uFlag
)
2580 LPCANDIDATELIST pCL
= NULL
;
2581 LPSTR pszSrcA
= NULL
;
2583 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL
, hIMC
, debugstr_w(pSrc
),
2584 lpDst
, dwBufLen
, uFlag
);
2586 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
2590 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
2592 ret
= pImeDpi
->ImeConversionList(hIMC
, pSrc
, lpDst
, dwBufLen
, uFlag
);
2593 ImmUnlockImeDpi(pImeDpi
);
2599 pszSrcA
= Imm32AnsiFromWide(pSrc
);
2600 if (pszSrcA
== NULL
)
2604 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcA
, NULL
, 0, uFlag
);
2608 pCL
= Imm32HeapAlloc(0, cb
);
2612 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcA
, pCL
, cb
, uFlag
);
2616 ret
= CandidateListAnsiToWide(pCL
, lpDst
, dwBufLen
, CP_ACP
);
2620 HeapFree(g_hImm32Heap
, 0, pszSrcA
);
2622 HeapFree(g_hImm32Heap
, 0, pCL
);
2623 ImmUnlockImeDpi(pImeDpi
);
2627 /***********************************************************************
2628 * ImmGetConversionStatus (IMM32.@)
2630 BOOL WINAPI
ImmGetConversionStatus(
2631 HIMC hIMC
, LPDWORD lpfdwConversion
, LPDWORD lpfdwSentence
)
2635 TRACE("(%p %p %p)\n", hIMC
, lpfdwConversion
, lpfdwSentence
);
2637 pIC
= ImmLockIMC(hIMC
);
2641 if (lpfdwConversion
)
2642 *lpfdwConversion
= pIC
->fdwConversion
;
2644 *lpfdwSentence
= pIC
->fdwSentence
;
2650 /***********************************************************************
2651 * ImmGetDefaultIMEWnd (IMM32.@)
2653 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
2655 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
2659 return (HWND
)NtUserGetThreadState(THREADSTATE_ACTIVEWINDOW
);
2661 return (HWND
)NtUserQueryWindow(hWnd
, QUERY_WINDOW_DEFAULT_IME
);
2664 /***********************************************************************
2665 * CtfImmIsCiceroEnabled (IMM32.@)
2667 BOOL WINAPI
CtfImmIsCiceroEnabled(VOID
)
2669 return (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
));
2672 /***********************************************************************
2673 * ImmGetDescriptionA (IMM32.@)
2675 UINT WINAPI
ImmGetDescriptionA(
2676 HKL hKL
, LPSTR lpszDescription
, UINT uBufLen
)
2681 TRACE("(%p,%p,%d)\n", hKL
, lpszDescription
, uBufLen
);
2683 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2686 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
2687 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeDescription
, (INT
)cch
,
2688 lpszDescription
, uBufLen
, NULL
, NULL
);
2690 lpszDescription
[cch
] = 0;
2694 /***********************************************************************
2695 * ImmGetDescriptionW (IMM32.@)
2697 UINT WINAPI
ImmGetDescriptionW(HKL hKL
, LPWSTR lpszDescription
, UINT uBufLen
)
2702 TRACE("(%p, %p, %d)\n", hKL
, lpszDescription
, uBufLen
);
2704 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2708 StringCchCopyW(lpszDescription
, uBufLen
, info
.wszImeDescription
);
2710 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
2714 static DWORD APIENTRY
2715 ImmGetGuideLineAW(HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
, BOOL bAnsi
)
2717 PCLIENTIMC pClientImc
;
2719 LPGUIDELINE pGuideLine
;
2721 LPVOID pvStr
, pvPrivate
;
2724 pClientImc
= ImmLockClientImc(hIMC
);
2728 pIC
= ImmLockIMC(hIMC
);
2731 ImmUnlockClientImc(pClientImc
);
2735 pGuideLine
= ImmLockIMCC(pIC
->hGuideLine
);
2739 ImmUnlockClientImc(pClientImc
);
2743 if (dwIndex
== GGL_LEVEL
)
2745 ret
= pGuideLine
->dwLevel
;
2749 if (dwIndex
== GGL_INDEX
)
2751 ret
= pGuideLine
->dwIndex
;
2755 if (dwIndex
== GGL_STRING
)
2757 pvStr
= (LPBYTE
)pGuideLine
+ pGuideLine
->dwStrOffset
;
2762 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2764 cb
= WideCharToMultiByte(CP_ACP
, 0, pvStr
, pGuideLine
->dwStrLen
,
2765 NULL
, 0, NULL
, &bUsedDefault
);
2769 cb
= pGuideLine
->dwStrLen
* sizeof(CHAR
);
2774 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2776 cb
= pGuideLine
->dwStrLen
* sizeof(WCHAR
);
2780 cb
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, pvStr
, pGuideLine
->dwStrLen
,
2781 NULL
, 0) * sizeof(WCHAR
);
2785 if (dwBufLen
== 0 || cb
== 0 || lpBuf
== NULL
|| dwBufLen
< cb
)
2791 /* store to buffer */
2794 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2796 ret
= WideCharToMultiByte(CP_ACP
, 0, pvStr
, pGuideLine
->dwStrLen
,
2797 lpBuf
, dwBufLen
, NULL
, &bUsedDefault
);
2803 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
))
2805 ret
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, pvStr
, pGuideLine
->dwStrLen
,
2806 lpBuf
, dwBufLen
) * sizeof(WCHAR
);
2811 RtlCopyMemory(lpBuf
, pvStr
, cb
);
2816 if (dwIndex
== GGL_PRIVATE
)
2818 pvPrivate
= (LPBYTE
)pGuideLine
+ pGuideLine
->dwPrivateOffset
;
2823 if ((pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2824 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2826 cb
= CandidateListWideToAnsi(pvPrivate
, NULL
, 0, CP_ACP
);
2830 cb
= pGuideLine
->dwPrivateSize
;
2835 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2836 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2838 cb
= CandidateListAnsiToWide(pvPrivate
, NULL
, 0, CP_ACP
);
2842 cb
= pGuideLine
->dwPrivateSize
;
2846 if (dwBufLen
== 0 || cb
== 0 || lpBuf
== NULL
|| dwBufLen
< cb
)
2852 /* store to buffer */
2855 if ((pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2856 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2858 ret
= CandidateListWideToAnsi(pvPrivate
, lpBuf
, cb
, CP_ACP
);
2864 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2865 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2867 ret
= CandidateListAnsiToWide(pvPrivate
, lpBuf
, cb
, CP_ACP
);
2872 RtlCopyMemory(lpBuf
, pvPrivate
, cb
);
2878 ImmUnlockIMCC(pIC
->hGuideLine
);
2880 ImmUnlockClientImc(pClientImc
);
2884 /***********************************************************************
2885 * ImmGetGuideLineA (IMM32.@)
2887 DWORD WINAPI
ImmGetGuideLineA(
2888 HIMC hIMC
, DWORD dwIndex
, LPSTR lpBuf
, DWORD dwBufLen
)
2890 TRACE("(%p, %lu, %p, %lu)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2891 return ImmGetGuideLineAW(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
2894 /***********************************************************************
2895 * ImmGetGuideLineW (IMM32.@)
2897 DWORD WINAPI
ImmGetGuideLineW(HIMC hIMC
, DWORD dwIndex
, LPWSTR lpBuf
, DWORD dwBufLen
)
2899 TRACE("(%p, %lu, %p, %lu)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2900 return ImmGetGuideLineAW(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
2903 /***********************************************************************
2904 * ImmGetIMEFileNameA (IMM32.@)
2906 UINT WINAPI
ImmGetIMEFileNameA( HKL hKL
, LPSTR lpszFileName
, UINT uBufLen
)
2912 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
2914 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2917 lpszFileName
[0] = 0;
2921 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
2923 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeFile
, (INT
)cch
,
2924 lpszFileName
, uBufLen
, NULL
, &bDefUsed
);
2928 if (cch
> uBufLen
- 1)
2931 lpszFileName
[cch
] = 0;
2935 /***********************************************************************
2936 * ImmGetIMEFileNameW (IMM32.@)
2938 UINT WINAPI
ImmGetIMEFileNameW(HKL hKL
, LPWSTR lpszFileName
, UINT uBufLen
)
2943 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
2945 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2948 lpszFileName
[0] = 0;
2952 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
2956 StringCchCopyNW(lpszFileName
, uBufLen
, info
.wszImeFile
, cch
);
2958 if (cch
> uBufLen
- 1)
2961 lpszFileName
[cch
] = 0;
2965 /***********************************************************************
2966 * ImmGetOpenStatus (IMM32.@)
2968 BOOL WINAPI
ImmGetOpenStatus(HIMC hIMC
)
2973 TRACE("(%p)\n", hIMC
);
2978 pIC
= ImmLockIMC(hIMC
);
2988 /***********************************************************************
2989 * ImmGetProperty (IMM32.@)
2991 DWORD WINAPI
ImmGetProperty(HKL hKL
, DWORD fdwIndex
)
2993 IMEINFOEX ImeInfoEx
;
2996 PIMEDPI pImeDpi
= NULL
;
2998 TRACE("(%p, %lu)\n", hKL
, fdwIndex
);
3000 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
))
3003 if (fdwIndex
== IGP_GETIMEVERSION
)
3004 return ImeInfoEx
.dwImeWinVersion
;
3006 if (ImeInfoEx
.fLoadFlag
!= 2)
3008 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3009 if (pImeDpi
== NULL
)
3012 pImeInfo
= &pImeDpi
->ImeInfo
;
3016 pImeInfo
= &ImeInfoEx
.ImeInfo
;
3021 case IGP_PROPERTY
: dwValue
= pImeInfo
->fdwProperty
; break;
3022 case IGP_CONVERSION
: dwValue
= pImeInfo
->fdwConversionCaps
; break;
3023 case IGP_SENTENCE
: dwValue
= pImeInfo
->fdwSentenceCaps
; break;
3024 case IGP_UI
: dwValue
= pImeInfo
->fdwUICaps
; break;
3025 case IGP_SETCOMPSTR
: dwValue
= pImeInfo
->fdwSCSCaps
; break;
3026 case IGP_SELECT
: dwValue
= pImeInfo
->fdwSelectCaps
; break;
3027 default: dwValue
= 0; break;
3031 ImmUnlockImeDpi(pImeDpi
);
3035 /***********************************************************************
3036 * ImmGetRegisterWordStyleA (IMM32.@)
3038 UINT WINAPI
ImmGetRegisterWordStyleA(
3039 HKL hKL
, UINT nItem
, LPSTYLEBUFA lpStyleBuf
)
3041 UINT iItem
, ret
= 0;
3044 LPSTYLEBUFW pSrcW
, pNewStylesW
= NULL
;
3048 TRACE("(%p, %u, %p)\n", hKL
, nItem
, lpStyleBuf
);
3050 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3054 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
3056 ret
= pImeDpi
->ImeGetRegisterWordStyle(nItem
, lpStyleBuf
);
3062 pNewStylesW
= Imm32HeapAlloc(0, nItem
* sizeof(STYLEBUFW
));
3067 ret
= pImeDpi
->ImeGetRegisterWordStyle(nItem
, pNewStylesW
);
3071 /* lpStyleBuf <-- pNewStylesW */
3072 for (iItem
= 0; iItem
< ret
; ++iItem
)
3074 pSrcW
= &pNewStylesW
[iItem
];
3075 pDestA
= &lpStyleBuf
[iItem
];
3076 pDestA
->dwStyle
= pSrcW
->dwStyle
;
3077 StringCchLengthW(pSrcW
->szDescription
, _countof(pSrcW
->szDescription
), &cchW
);
3078 cchA
= WideCharToMultiByte(CP_ACP
, MB_PRECOMPOSED
,
3079 pSrcW
->szDescription
, (INT
)cchW
,
3080 pDestA
->szDescription
, _countof(pDestA
->szDescription
),
3082 if (cchA
> _countof(pDestA
->szDescription
) - 1)
3083 cchA
= _countof(pDestA
->szDescription
) - 1;
3084 pDestA
->szDescription
[cchA
] = 0;
3090 HeapFree(g_hImm32Heap
, 0, pNewStylesW
);
3091 ImmUnlockImeDpi(pImeDpi
);
3095 /***********************************************************************
3096 * ImmGetRegisterWordStyleW (IMM32.@)
3098 UINT WINAPI
ImmGetRegisterWordStyleW(
3099 HKL hKL
, UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
3101 UINT iItem
, ret
= 0;
3103 LPSTYLEBUFA pSrcA
, pNewStylesA
= NULL
;
3108 TRACE("(%p, %u, %p)\n", hKL
, nItem
, lpStyleBuf
);
3110 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3114 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
3116 ret
= pImeDpi
->ImeGetRegisterWordStyle(nItem
, lpStyleBuf
);
3122 pNewStylesA
= Imm32HeapAlloc(0, nItem
* sizeof(STYLEBUFA
));
3127 ret
= pImeDpi
->ImeGetRegisterWordStyle(nItem
, pNewStylesA
);
3131 /* lpStyleBuf <-- pNewStylesA */
3132 for (iItem
= 0; iItem
< ret
; ++iItem
)
3134 pSrcA
= &pNewStylesA
[iItem
];
3135 pDestW
= &lpStyleBuf
[iItem
];
3136 pDestW
->dwStyle
= pSrcA
->dwStyle
;
3137 StringCchLengthA(pSrcA
->szDescription
, _countof(pSrcA
->szDescription
), &cchA
);
3138 cchW
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
,
3139 pSrcA
->szDescription
, (INT
)cchA
,
3140 pDestW
->szDescription
, _countof(pDestW
->szDescription
));
3141 if (cchW
> _countof(pDestW
->szDescription
) - 1)
3142 cchW
= _countof(pDestW
->szDescription
) - 1;
3143 pDestW
->szDescription
[cchW
] = 0;
3149 HeapFree(g_hImm32Heap
, 0, pNewStylesA
);
3150 ImmUnlockImeDpi(pImeDpi
);
3154 /***********************************************************************
3155 * ImmGetStatusWindowPos (IMM32.@)
3157 BOOL WINAPI
ImmGetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
3162 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
3164 pIC
= ImmLockIMC(hIMC
);
3168 ret
= !!(pIC
->fdwInit
& INIT_STATUSWNDPOS
);
3170 *lpptPos
= pIC
->ptStatusWndPos
;
3176 /***********************************************************************
3177 * ImmGetVirtualKey (IMM32.@)
3179 UINT WINAPI
ImmGetVirtualKey(HWND hWnd
)
3182 LPINPUTCONTEXTDX pIC
;
3183 UINT ret
= VK_PROCESSKEY
;
3185 TRACE("(%p)\n", hWnd
);
3187 hIMC
= ImmGetContext(hWnd
);
3188 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3199 /***********************************************************************
3200 * ImmInstallIMEA (IMM32.@)
3202 HKL WINAPI
ImmInstallIMEA(
3203 LPCSTR lpszIMEFileName
, LPCSTR lpszLayoutText
)
3206 LPWSTR pszFileNameW
= NULL
, pszLayoutTextW
= NULL
;
3208 TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName
), debugstr_a(lpszLayoutText
));
3210 pszFileNameW
= Imm32WideFromAnsi(lpszIMEFileName
);
3211 if (pszFileNameW
== NULL
)
3214 pszLayoutTextW
= Imm32WideFromAnsi(lpszLayoutText
);
3215 if (pszLayoutTextW
== NULL
)
3218 hKL
= ImmInstallIMEW(pszFileNameW
, pszLayoutTextW
);
3222 HeapFree(g_hImm32Heap
, 0, pszFileNameW
);
3224 HeapFree(g_hImm32Heap
, 0, pszLayoutTextW
);
3228 /***********************************************************************
3229 * ImmInstallIMEW (IMM32.@)
3231 HKL WINAPI
ImmInstallIMEW(
3232 LPCWSTR lpszIMEFileName
, LPCWSTR lpszLayoutText
)
3234 INT lcid
= GetUserDefaultLCID();
3239 WCHAR regKey
[ARRAY_SIZE(szImeRegFmt
)+8];
3241 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName
),
3242 debugstr_w(lpszLayoutText
));
3244 /* Start with 2. e001 will be blank and so default to the wine internal IME */
3247 while (count
< 0xfff)
3249 DWORD disposition
= 0;
3251 hkl
= (HKL
)MAKELPARAM( lcid
, 0xe000 | count
);
3252 wsprintfW( regKey
, szImeRegFmt
, (ULONG_PTR
)hkl
);
3254 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, regKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hkey
, &disposition
);
3255 if (rc
== ERROR_SUCCESS
&& disposition
== REG_CREATED_NEW_KEY
)
3257 else if (rc
== ERROR_SUCCESS
)
3265 WARN("Unable to find slot to install IME\n");
3269 if (rc
== ERROR_SUCCESS
)
3271 rc
= RegSetValueExW(hkey
, szImeFileW
, 0, REG_SZ
, (const BYTE
*)lpszIMEFileName
,
3272 (lstrlenW(lpszIMEFileName
) + 1) * sizeof(WCHAR
));
3273 if (rc
== ERROR_SUCCESS
)
3274 rc
= RegSetValueExW(hkey
, szLayoutTextW
, 0, REG_SZ
, (const BYTE
*)lpszLayoutText
,
3275 (lstrlenW(lpszLayoutText
) + 1) * sizeof(WCHAR
));
3281 WARN("Unable to set IME registry values\n");
3286 /***********************************************************************
3287 * ImmIsIME (IMM32.@)
3289 BOOL WINAPI
ImmIsIME(HKL hKL
)
3292 TRACE("(%p)\n", hKL
);
3293 return !!ImmGetImeInfoEx(&info
, ImeInfoExImeWindow
, &hKL
);
3296 static BOOL APIENTRY
3297 ImmIsUIMessageAW(HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
, BOOL bAnsi
)
3301 case WM_IME_STARTCOMPOSITION
: case WM_IME_ENDCOMPOSITION
:
3302 case WM_IME_COMPOSITION
: case WM_IME_SETCONTEXT
: case WM_IME_NOTIFY
:
3303 case WM_IME_COMPOSITIONFULL
: case WM_IME_SELECT
: case WM_IME_SYSTEM
:
3313 SendMessageA(hWndIME
, msg
, wParam
, lParam
);
3315 SendMessageW(hWndIME
, msg
, wParam
, lParam
);
3320 /***********************************************************************
3321 * ImmIsUIMessageA (IMM32.@)
3323 BOOL WINAPI
ImmIsUIMessageA(
3324 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
3326 TRACE("(%p, 0x%X, %p, %p)\n", hWndIME
, msg
, wParam
, lParam
);
3327 return ImmIsUIMessageAW(hWndIME
, msg
, wParam
, lParam
, TRUE
);
3330 /***********************************************************************
3331 * ImmIsUIMessageW (IMM32.@)
3333 BOOL WINAPI
ImmIsUIMessageW(
3334 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
3336 TRACE("(%p, 0x%X, %p, %p)\n", hWndIME
, msg
, wParam
, lParam
);
3337 return ImmIsUIMessageAW(hWndIME
, msg
, wParam
, lParam
, FALSE
);
3340 /***********************************************************************
3341 * ImmNotifyIME (IMM32.@)
3343 BOOL WINAPI
ImmNotifyIME(
3344 HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
3350 TRACE("(%p, %lu, %lu, %lu)\n", hIMC
, dwAction
, dwIndex
, dwValue
);
3352 if (hIMC
&& Imm32IsCrossThreadAccess(hIMC
))
3355 hKL
= GetKeyboardLayout(0);
3356 pImeDpi
= ImmLockImeDpi(hKL
);
3357 if (pImeDpi
== NULL
)
3360 ret
= pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
3361 ImmUnlockImeDpi(pImeDpi
);
3365 /***********************************************************************
3366 * ImmRegisterWordA (IMM32.@)
3368 BOOL WINAPI
ImmRegisterWordA(
3369 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszRegister
)
3373 LPWSTR pszReadingW
= NULL
, pszRegisterW
= NULL
;
3375 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
3376 debugstr_a(lpszRegister
));
3378 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3382 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
3384 ret
= pImeDpi
->ImeRegisterWord(lpszReading
, dwStyle
, lpszRegister
);
3385 ImmUnlockImeDpi(pImeDpi
);
3391 pszReadingW
= Imm32WideFromAnsi(lpszReading
);
3392 if (pszReadingW
== NULL
)
3398 pszRegisterW
= Imm32WideFromAnsi(lpszRegister
);
3399 if (pszRegisterW
== NULL
)
3403 ret
= pImeDpi
->ImeRegisterWord(pszReadingW
, dwStyle
, pszRegisterW
);
3407 HeapFree(g_hImm32Heap
, 0, pszReadingW
);
3409 HeapFree(g_hImm32Heap
, 0, pszRegisterW
);
3410 ImmUnlockImeDpi(pImeDpi
);
3414 /***********************************************************************
3415 * ImmRegisterWordW (IMM32.@)
3417 BOOL WINAPI
ImmRegisterWordW(
3418 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszRegister
)
3422 LPSTR pszReadingA
= NULL
, pszRegisterA
= NULL
;
3424 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
3425 debugstr_w(lpszRegister
));
3427 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3431 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
3433 ret
= pImeDpi
->ImeRegisterWord(lpszReading
, dwStyle
, lpszRegister
);
3434 ImmUnlockImeDpi(pImeDpi
);
3440 pszReadingA
= Imm32AnsiFromWide(lpszReading
);
3447 pszRegisterA
= Imm32AnsiFromWide(lpszRegister
);
3452 ret
= pImeDpi
->ImeRegisterWord(pszReadingA
, dwStyle
, pszRegisterA
);
3456 HeapFree(g_hImm32Heap
, 0, pszReadingA
);
3458 HeapFree(g_hImm32Heap
, 0, pszRegisterA
);
3459 ImmUnlockImeDpi(pImeDpi
);
3463 /***********************************************************************
3464 * ImmReleaseContext (IMM32.@)
3466 BOOL WINAPI
ImmReleaseContext(HWND hWnd
, HIMC hIMC
)
3468 static BOOL shown
= FALSE
;
3471 FIXME("(%p, %p): stub\n", hWnd
, hIMC
);
3477 /***********************************************************************
3478 * ImmRequestMessageA(IMM32.@)
3480 LRESULT WINAPI
ImmRequestMessageA(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
3482 InputContextData
*data
= get_imc_data(hIMC
);
3484 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
3486 if (data
) return SendMessageA(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
3488 SetLastError(ERROR_INVALID_HANDLE
);
3492 /***********************************************************************
3493 * ImmRequestMessageW(IMM32.@)
3495 LRESULT WINAPI
ImmRequestMessageW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
3497 InputContextData
*data
= get_imc_data(hIMC
);
3499 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
3501 if (data
) return SendMessageW(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
3503 SetLastError(ERROR_INVALID_HANDLE
);
3507 /***********************************************************************
3508 * ImmSetCandidateWindow (IMM32.@)
3510 BOOL WINAPI
ImmSetCandidateWindow(
3511 HIMC hIMC
, LPCANDIDATEFORM lpCandidate
)
3513 #define MAX_CANDIDATEFORM 4
3517 TRACE("(%p, %p)\n", hIMC
, lpCandidate
);
3519 if (lpCandidate
->dwIndex
>= MAX_CANDIDATEFORM
)
3522 if (Imm32IsCrossThreadAccess(hIMC
))
3525 pIC
= ImmLockIMC(hIMC
);
3530 pIC
->cfCandForm
[lpCandidate
->dwIndex
] = *lpCandidate
;
3534 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCANDIDATEPOS
,
3535 IMN_SETCANDIDATEPOS
, (1 << lpCandidate
->dwIndex
));
3537 #undef MAX_CANDIDATEFORM
3540 static VOID APIENTRY
WideToAnsiLogFont(const LOGFONTW
*plfW
, LPLOGFONTA plfA
)
3543 size_t cchW
, cchA
= _countof(plfA
->lfFaceName
);
3544 RtlCopyMemory(plfA
, plfW
, offsetof(LOGFONTA
, lfFaceName
));
3545 StringCchLengthW(plfW
->lfFaceName
, _countof(plfW
->lfFaceName
), &cchW
);
3546 cchA
= WideCharToMultiByte(CP_ACP
, 0, plfW
->lfFaceName
, (INT
)cchW
,
3547 plfA
->lfFaceName
, (INT
)cchA
, NULL
, &bUsedDef
);
3548 if (cchA
> _countof(plfA
->lfFaceName
) - 1)
3549 cchA
= _countof(plfA
->lfFaceName
) - 1;
3550 plfA
->lfFaceName
[cchA
] = 0;
3553 static VOID APIENTRY
AnsiToWideLogFont(const LOGFONTA
*plfA
, LPLOGFONTW plfW
)
3555 size_t cchA
, cchW
= _countof(plfW
->lfFaceName
);
3556 RtlCopyMemory(plfW
, plfA
, offsetof(LOGFONTW
, lfFaceName
));
3557 StringCchLengthA(plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), &cchA
);
3558 cchW
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, plfA
->lfFaceName
, (INT
)cchA
,
3559 plfW
->lfFaceName
, cchW
);
3560 if (cchW
> _countof(plfW
->lfFaceName
) - 1)
3561 cchW
= _countof(plfW
->lfFaceName
) - 1;
3562 plfW
->lfFaceName
[cchW
] = 0;
3565 /***********************************************************************
3566 * ImmSetCompositionFontA (IMM32.@)
3568 BOOL WINAPI
ImmSetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
3571 PCLIENTIMC pClientImc
;
3573 LPINPUTCONTEXTDX pIC
;
3578 TRACE("(%p, %p)\n", hIMC
, lplf
);
3580 if (Imm32IsCrossThreadAccess(hIMC
))
3583 pClientImc
= ImmLockClientImc(hIMC
);
3584 if (pClientImc
== NULL
)
3587 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
3588 ImmUnlockClientImc(pClientImc
);
3592 AnsiToWideLogFont(lplf
, &lfW
);
3593 return ImmSetCompositionFontW(hIMC
, &lfW
);
3596 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3600 pTeb
= NtCurrentTeb();
3601 if (pTeb
->Win32ClientInfo
[2] < 0x400)
3603 lcid
= GetSystemDefaultLCID();
3604 if (PRIMARYLANGID(lcid
) == LANG_JAPANESE
&& !(pIC
->dwUIFlags
& 2) &&
3605 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
3607 PostMessageA(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
3611 pIC
->lfFont
.A
= *lplf
;
3612 pIC
->fdwInit
|= INIT_LOGFONT
;
3617 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
3618 IMN_SETCOMPOSITIONFONT
, 0);
3622 /***********************************************************************
3623 * ImmSetCompositionFontW (IMM32.@)
3625 BOOL WINAPI
ImmSetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
3628 PCLIENTIMC pClientImc
;
3631 LPINPUTCONTEXTDX pIC
;
3635 TRACE("(%p, %p)\n", hIMC
, lplf
);
3637 if (Imm32IsCrossThreadAccess(hIMC
))
3640 pClientImc
= ImmLockClientImc(hIMC
);
3641 if (pClientImc
== NULL
)
3644 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
3645 ImmUnlockClientImc(pClientImc
);
3649 WideToAnsiLogFont(lplf
, &lfA
);
3650 return ImmSetCompositionFontA(hIMC
, &lfA
);
3653 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3657 pTeb
= NtCurrentTeb();
3658 if (pTeb
->Win32ClientInfo
[2] < 0x400)
3660 lcid
= GetSystemDefaultLCID();
3661 if (PRIMARYLANGID(lcid
) == LANG_JAPANESE
&&
3662 !(pIC
->dwUIFlags
& 2) &&
3663 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
3665 PostMessageW(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
3669 pIC
->lfFont
.W
= *lplf
;
3670 pIC
->fdwInit
|= INIT_LOGFONT
;
3675 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
3676 IMN_SETCOMPOSITIONFONT
, 0);
3680 /***********************************************************************
3681 * ImmSetCompositionStringA (IMM32.@)
3683 BOOL WINAPI
ImmSetCompositionStringA(
3684 HIMC hIMC
, DWORD dwIndex
,
3685 LPCVOID lpComp
, DWORD dwCompLen
,
3686 LPCVOID lpRead
, DWORD dwReadLen
)
3690 WCHAR
*CompBuffer
= NULL
;
3691 WCHAR
*ReadBuffer
= NULL
;
3693 InputContextData
*data
= get_imc_data(hIMC
);
3695 TRACE("(%p, %d, %p, %d, %p, %d):\n",
3696 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
3701 if (!(dwIndex
== SCS_SETSTR
||
3702 dwIndex
== SCS_CHANGEATTR
||
3703 dwIndex
== SCS_CHANGECLAUSE
||
3704 dwIndex
== SCS_SETRECONVERTSTRING
||
3705 dwIndex
== SCS_QUERYRECONVERTSTRING
))
3708 if (!is_himc_ime_unicode(data
))
3709 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
3710 dwCompLen
, lpRead
, dwReadLen
);
3712 comp_len
= MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0);
3715 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
* sizeof(WCHAR
));
3716 MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
);
3719 read_len
= MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0);
3722 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
* sizeof(WCHAR
));
3723 MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
);
3726 rc
= ImmSetCompositionStringW(hIMC
, dwIndex
, CompBuffer
, comp_len
,
3727 ReadBuffer
, read_len
);
3729 HeapFree(GetProcessHeap(), 0, CompBuffer
);
3730 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
3735 /***********************************************************************
3736 * ImmSetCompositionStringW (IMM32.@)
3738 BOOL WINAPI
ImmSetCompositionStringW(
3739 HIMC hIMC
, DWORD dwIndex
,
3740 LPCVOID lpComp
, DWORD dwCompLen
,
3741 LPCVOID lpRead
, DWORD dwReadLen
)
3745 CHAR
*CompBuffer
= NULL
;
3746 CHAR
*ReadBuffer
= NULL
;
3748 InputContextData
*data
= get_imc_data(hIMC
);
3750 TRACE("(%p, %d, %p, %d, %p, %d):\n",
3751 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
3756 if (!(dwIndex
== SCS_SETSTR
||
3757 dwIndex
== SCS_CHANGEATTR
||
3758 dwIndex
== SCS_CHANGECLAUSE
||
3759 dwIndex
== SCS_SETRECONVERTSTRING
||
3760 dwIndex
== SCS_QUERYRECONVERTSTRING
))
3763 if (is_himc_ime_unicode(data
))
3764 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
3765 dwCompLen
, lpRead
, dwReadLen
);
3767 comp_len
= WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0, NULL
,
3771 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
);
3772 WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
,
3776 read_len
= WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0, NULL
,
3780 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
);
3781 WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
,
3785 rc
= ImmSetCompositionStringA(hIMC
, dwIndex
, CompBuffer
, comp_len
,
3786 ReadBuffer
, read_len
);
3788 HeapFree(GetProcessHeap(), 0, CompBuffer
);
3789 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
3794 /***********************************************************************
3795 * ImmSetCompositionWindow (IMM32.@)
3797 BOOL WINAPI
ImmSetCompositionWindow(
3798 HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
3803 if (Imm32IsCrossThreadAccess(hIMC
))
3806 pIC
= ImmLockIMC(hIMC
);
3810 pIC
->cfCompForm
= *lpCompForm
;
3811 pIC
->fdwInit
|= INIT_COMPFORM
;
3817 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
3818 IMC_SETCOMPOSITIONWINDOW
, IMN_SETCOMPOSITIONWINDOW
, 0);
3822 /***********************************************************************
3823 * ImmSetConversionStatus (IMM32.@)
3825 BOOL WINAPI
ImmSetConversionStatus(
3826 HIMC hIMC
, DWORD fdwConversion
, DWORD fdwSentence
)
3830 DWORD dwOldConversion
, dwOldSentence
;
3831 BOOL fConversionChange
= FALSE
, fSentenceChange
= FALSE
;
3834 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC
, fdwConversion
, fdwSentence
);
3836 hKL
= GetKeyboardLayout(0);
3837 if (!IS_IME_HKL(hKL
))
3839 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
3846 if (Imm32IsCrossThreadAccess(hIMC
))
3849 pIC
= ImmLockIMC(hIMC
);
3853 if (pIC
->fdwConversion
!= fdwConversion
)
3855 dwOldConversion
= pIC
->fdwConversion
;
3856 pIC
->fdwConversion
= fdwConversion
;
3857 fConversionChange
= TRUE
;
3860 if (pIC
->fdwSentence
!= fdwSentence
)
3862 dwOldSentence
= pIC
->fdwSentence
;
3863 pIC
->fdwSentence
= fdwSentence
;
3864 fSentenceChange
= TRUE
;
3870 if (fConversionChange
)
3872 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldConversion
,
3873 IMC_SETCONVERSIONMODE
, IMN_SETCONVERSIONMODE
, 0);
3874 NtUserNotifyIMEStatus(hWnd
, hIMC
, fdwConversion
);
3877 if (fSentenceChange
)
3879 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldSentence
,
3880 IMC_SETSENTENCEMODE
, IMN_SETSENTENCEMODE
, 0);
3886 /***********************************************************************
3887 * ImmLockImeDpi (IMM32.@)
3889 PIMEDPI WINAPI
ImmLockImeDpi(HKL hKL
)
3891 PIMEDPI pImeDpi
= NULL
;
3893 TRACE("(%p)\n", hKL
);
3895 RtlEnterCriticalSection(&g_csImeDpi
);
3898 for (pImeDpi
= g_pImeDpiList
; pImeDpi
; pImeDpi
= pImeDpi
->pNext
)
3900 if (pImeDpi
->hKL
== hKL
) /* found */
3902 /* lock if possible */
3903 if (pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
)
3906 ++(pImeDpi
->cLockObj
);
3911 RtlLeaveCriticalSection(&g_csImeDpi
);
3915 /***********************************************************************
3916 * ImmUnlockImeDpi (IMM32.@)
3918 VOID WINAPI
ImmUnlockImeDpi(PIMEDPI pImeDpi
)
3922 TRACE("(%p)\n", pImeDpi
);
3924 if (pImeDpi
== NULL
)
3927 RtlEnterCriticalSection(&g_csImeDpi
);
3930 --(pImeDpi
->cLockObj
);
3931 if (pImeDpi
->cLockObj
!= 0)
3933 RtlLeaveCriticalSection(&g_csImeDpi
);
3937 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
) == 0)
3939 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_LOCKED
) == 0 ||
3940 (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_END_UNLOAD
) == 0)
3942 RtlLeaveCriticalSection(&g_csImeDpi
);
3947 /* Remove from list */
3948 for (ppEntry
= &g_pImeDpiList
; *ppEntry
; ppEntry
= &((*ppEntry
)->pNext
))
3950 if (*ppEntry
== pImeDpi
) /* found */
3952 *ppEntry
= pImeDpi
->pNext
;
3957 Imm32FreeImeDpi(pImeDpi
, TRUE
);
3958 HeapFree(g_hImm32Heap
, 0, pImeDpi
);
3960 RtlLeaveCriticalSection(&g_csImeDpi
);
3963 /***********************************************************************
3964 * ImmSetOpenStatus (IMM32.@)
3966 BOOL WINAPI
ImmSetOpenStatus(HIMC hIMC
, BOOL fOpen
)
3971 BOOL bHasChange
= FALSE
;
3973 TRACE("(%p, %d)\n", hIMC
, fOpen
);
3975 if (Imm32IsCrossThreadAccess(hIMC
))
3978 pIC
= ImmLockIMC(hIMC
);
3982 if (pIC
->fOpen
!= fOpen
)
3986 dwConversion
= pIC
->fdwConversion
;
3994 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
3995 IMC_SETOPENSTATUS
, IMN_SETOPENSTATUS
, 0);
3996 NtUserNotifyIMEStatus(hWnd
, hIMC
, dwConversion
);
4002 /***********************************************************************
4003 * ImmSetStatusWindowPos (IMM32.@)
4005 BOOL WINAPI
ImmSetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
4010 TRACE("(%p, {%ld, %ld})\n", hIMC
, lpptPos
->x
, lpptPos
->y
);
4012 if (Imm32IsCrossThreadAccess(hIMC
))
4015 pIC
= ImmLockIMC(hIMC
);
4020 pIC
->ptStatusWndPos
= *lpptPos
;
4021 pIC
->fdwInit
|= INIT_STATUSWNDPOS
;
4025 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
4026 IMC_SETSTATUSWINDOWPOS
, IMN_SETSTATUSWINDOWPOS
, 0);
4030 /***********************************************************************
4031 * ImmCreateSoftKeyboard(IMM32.@)
4033 HWND WINAPI
ImmCreateSoftKeyboard(UINT uType
, UINT hOwner
, int x
, int y
)
4035 FIXME("(%d, %d, %d, %d): stub\n", uType
, hOwner
, x
, y
);
4036 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4040 /***********************************************************************
4041 * ImmDestroySoftKeyboard(IMM32.@)
4043 BOOL WINAPI
ImmDestroySoftKeyboard(HWND hSoftWnd
)
4045 TRACE("(%p)\n", hSoftWnd
);
4046 return DestroyWindow(hSoftWnd
);
4049 /***********************************************************************
4050 * ImmShowSoftKeyboard(IMM32.@)
4052 BOOL WINAPI
ImmShowSoftKeyboard(HWND hSoftWnd
, int nCmdShow
)
4054 TRACE("(%p, %d)\n", hSoftWnd
, nCmdShow
);
4056 return ShowWindow(hSoftWnd
, nCmdShow
);
4060 /***********************************************************************
4061 * ImmSimulateHotKey (IMM32.@)
4063 BOOL WINAPI
ImmSimulateHotKey(HWND hWnd
, DWORD dwHotKeyID
)
4070 TRACE("(%p, 0x%lX)\n", hWnd
, dwHotKeyID
);
4072 hIMC
= ImmGetContext(hWnd
);
4073 dwThreadId
= GetWindowThreadProcessId(hWnd
, NULL
);
4074 hKL
= GetKeyboardLayout(dwThreadId
);
4075 ret
= Imm32ProcessHotKey(hWnd
, hIMC
, hKL
, dwHotKeyID
);
4076 ImmReleaseContext(hWnd
, hIMC
);
4080 /***********************************************************************
4081 * ImmUnregisterWordA (IMM32.@)
4083 BOOL WINAPI
ImmUnregisterWordA(
4084 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszUnregister
)
4088 LPWSTR pszReadingW
= NULL
, pszUnregisterW
= NULL
;
4090 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
4091 debugstr_a(lpszUnregister
));
4093 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
4094 if (pImeDpi
== NULL
)
4097 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
4099 ret
= pImeDpi
->ImeUnregisterWord(lpszReading
, dwStyle
, lpszUnregister
);
4100 ImmUnlockImeDpi(pImeDpi
);
4106 pszReadingW
= Imm32WideFromAnsi(lpszReading
);
4107 if (pszReadingW
== NULL
)
4113 pszUnregisterW
= Imm32WideFromAnsi(lpszUnregister
);
4114 if (pszUnregisterW
== NULL
)
4118 ret
= pImeDpi
->ImeUnregisterWord(pszReadingW
, dwStyle
, pszUnregisterW
);
4122 HeapFree(g_hImm32Heap
, 0, pszReadingW
);
4124 HeapFree(g_hImm32Heap
, 0, pszUnregisterW
);
4125 ImmUnlockImeDpi(pImeDpi
);
4129 /***********************************************************************
4130 * ImmUnregisterWordW (IMM32.@)
4132 BOOL WINAPI
ImmUnregisterWordW(
4133 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszUnregister
)
4137 LPSTR pszReadingA
= NULL
, pszUnregisterA
= NULL
;
4139 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
4140 debugstr_w(lpszUnregister
));
4142 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
4146 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
4148 ret
= pImeDpi
->ImeUnregisterWord(lpszReading
, dwStyle
, lpszUnregister
);
4149 ImmUnlockImeDpi(pImeDpi
);
4155 pszReadingA
= Imm32AnsiFromWide(lpszReading
);
4162 pszUnregisterA
= Imm32AnsiFromWide(lpszUnregister
);
4163 if (!pszUnregisterA
)
4167 ret
= pImeDpi
->ImeUnregisterWord(pszReadingA
, dwStyle
, pszUnregisterA
);
4171 HeapFree(g_hImm32Heap
, 0, pszReadingA
);
4173 HeapFree(g_hImm32Heap
, 0, pszUnregisterA
);
4174 ImmUnlockImeDpi(pImeDpi
);
4178 /***********************************************************************
4179 * ImmGetImeMenuItemsA (IMM32.@)
4181 DWORD WINAPI
ImmGetImeMenuItemsA( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
4182 LPIMEMENUITEMINFOA lpImeParentMenu
, LPIMEMENUITEMINFOA lpImeMenu
,
4185 InputContextData
*data
= get_imc_data(hIMC
);
4186 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
4187 lpImeParentMenu
, lpImeMenu
, dwSize
);
4191 SetLastError(ERROR_INVALID_HANDLE
);
4195 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
4197 if (!is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
4198 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4199 (IMEMENUITEMINFOW
*)lpImeParentMenu
,
4200 (IMEMENUITEMINFOW
*)lpImeMenu
, dwSize
);
4203 IMEMENUITEMINFOW lpImeParentMenuW
;
4204 IMEMENUITEMINFOW
*lpImeMenuW
, *parent
= NULL
;
4207 if (lpImeParentMenu
)
4208 parent
= &lpImeParentMenuW
;
4211 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOA
);
4212 dwSize
= count
* sizeof(IMEMENUITEMINFOW
);
4213 lpImeMenuW
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
4218 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4219 parent
, lpImeMenuW
, dwSize
);
4221 if (lpImeParentMenu
)
4223 memcpy(lpImeParentMenu
,&lpImeParentMenuW
,sizeof(IMEMENUITEMINFOA
));
4224 lpImeParentMenu
->hbmpItem
= lpImeParentMenuW
.hbmpItem
;
4225 WideCharToMultiByte(CP_ACP
, 0, lpImeParentMenuW
.szString
,
4226 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
,
4229 if (lpImeMenu
&& rc
)
4232 for (i
= 0; i
< rc
; i
++)
4234 memcpy(&lpImeMenu
[i
],&lpImeMenuW
[1],sizeof(IMEMENUITEMINFOA
));
4235 lpImeMenu
[i
].hbmpItem
= lpImeMenuW
[i
].hbmpItem
;
4236 WideCharToMultiByte(CP_ACP
, 0, lpImeMenuW
[i
].szString
,
4237 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
,
4241 HeapFree(GetProcessHeap(),0,lpImeMenuW
);
4249 /***********************************************************************
4250 * ImmGetImeMenuItemsW (IMM32.@)
4252 DWORD WINAPI
ImmGetImeMenuItemsW( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
4253 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
4256 InputContextData
*data
= get_imc_data(hIMC
);
4257 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
4258 lpImeParentMenu
, lpImeMenu
, dwSize
);
4262 SetLastError(ERROR_INVALID_HANDLE
);
4266 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
4268 if (is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
4269 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4270 lpImeParentMenu
, lpImeMenu
, dwSize
);
4273 IMEMENUITEMINFOA lpImeParentMenuA
;
4274 IMEMENUITEMINFOA
*lpImeMenuA
, *parent
= NULL
;
4277 if (lpImeParentMenu
)
4278 parent
= &lpImeParentMenuA
;
4281 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOW
);
4282 dwSize
= count
* sizeof(IMEMENUITEMINFOA
);
4283 lpImeMenuA
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
4288 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4289 (IMEMENUITEMINFOW
*)parent
,
4290 (IMEMENUITEMINFOW
*)lpImeMenuA
, dwSize
);
4292 if (lpImeParentMenu
)
4294 memcpy(lpImeParentMenu
,&lpImeParentMenuA
,sizeof(IMEMENUITEMINFOA
));
4295 lpImeParentMenu
->hbmpItem
= lpImeParentMenuA
.hbmpItem
;
4296 MultiByteToWideChar(CP_ACP
, 0, lpImeParentMenuA
.szString
,
4297 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
);
4299 if (lpImeMenu
&& rc
)
4302 for (i
= 0; i
< rc
; i
++)
4304 memcpy(&lpImeMenu
[i
],&lpImeMenuA
[1],sizeof(IMEMENUITEMINFOA
));
4305 lpImeMenu
[i
].hbmpItem
= lpImeMenuA
[i
].hbmpItem
;
4306 MultiByteToWideChar(CP_ACP
, 0, lpImeMenuA
[i
].szString
,
4307 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
);
4310 HeapFree(GetProcessHeap(),0,lpImeMenuA
);
4318 /***********************************************************************
4319 * ImmLockIMC(IMM32.@)
4321 LPINPUTCONTEXT WINAPI
ImmLockIMC(HIMC hIMC
)
4323 InputContextData
*data
= get_imc_data(hIMC
);
4331 /***********************************************************************
4332 * ImmUnlockIMC(IMM32.@)
4334 BOOL WINAPI
ImmUnlockIMC(HIMC hIMC
)
4336 PCLIENTIMC pClientImc
;
4339 pClientImc
= ImmLockClientImc(hIMC
);
4340 if (pClientImc
== NULL
)
4343 hClientImc
= pClientImc
->hImc
;
4345 LocalUnlock(hClientImc
);
4347 InterlockedDecrement(&pClientImc
->cLockObj
);
4348 ImmUnlockClientImc(pClientImc
);
4352 /***********************************************************************
4353 * ImmGetIMCLockCount(IMM32.@)
4355 DWORD WINAPI
ImmGetIMCLockCount(HIMC hIMC
)
4359 PCLIENTIMC pClientImc
;
4361 pClientImc
= ImmLockClientImc(hIMC
);
4362 if (pClientImc
== NULL
)
4366 hClientImc
= pClientImc
->hImc
;
4368 ret
= (LocalFlags(hClientImc
) & LMEM_LOCKCOUNT
);
4370 ImmUnlockClientImc(pClientImc
);
4374 /***********************************************************************
4375 * ImmCreateIMCC(IMM32.@)
4377 HIMCC WINAPI
ImmCreateIMCC(DWORD size
)
4381 return LocalAlloc(LHND
, size
);
4384 /***********************************************************************
4385 * ImmDestroyIMCC(IMM32.@)
4387 HIMCC WINAPI
ImmDestroyIMCC(HIMCC block
)
4390 return LocalFree(block
);
4394 /***********************************************************************
4395 * ImmLockIMCC(IMM32.@)
4397 LPVOID WINAPI
ImmLockIMCC(HIMCC imcc
)
4400 return LocalLock(imcc
);
4404 /***********************************************************************
4405 * ImmUnlockIMCC(IMM32.@)
4407 BOOL WINAPI
ImmUnlockIMCC(HIMCC imcc
)
4410 return LocalUnlock(imcc
);
4414 /***********************************************************************
4415 * ImmGetIMCCLockCount(IMM32.@)
4417 DWORD WINAPI
ImmGetIMCCLockCount(HIMCC imcc
)
4419 return LocalFlags(imcc
) & LMEM_LOCKCOUNT
;
4422 /***********************************************************************
4423 * ImmReSizeIMCC(IMM32.@)
4425 HIMCC WINAPI
ImmReSizeIMCC(HIMCC imcc
, DWORD size
)
4429 return LocalReAlloc(imcc
, size
, LHND
);
4432 /***********************************************************************
4433 * ImmGetIMCCSize(IMM32.@)
4435 DWORD WINAPI
ImmGetIMCCSize(HIMCC imcc
)
4438 return LocalSize(imcc
);
4442 /***********************************************************************
4443 * ImmGenerateMessage(IMM32.@)
4445 BOOL WINAPI
ImmGenerateMessage(HIMC hIMC
)
4447 InputContextData
*data
= get_imc_data(hIMC
);
4451 SetLastError(ERROR_INVALID_HANDLE
);
4455 TRACE("%i messages queued\n",data
->IMC
.dwNumMsgBuf
);
4456 if (data
->IMC
.dwNumMsgBuf
> 0)
4458 LPTRANSMSG lpTransMsg
;
4460 DWORD i
, dwNumMsgBuf
;
4462 /* We are going to detach our hMsgBuff so that if processing messages
4463 generates new messages they go into a new buffer */
4464 hMsgBuf
= data
->IMC
.hMsgBuf
;
4465 dwNumMsgBuf
= data
->IMC
.dwNumMsgBuf
;
4467 data
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
4468 data
->IMC
.dwNumMsgBuf
= 0;
4470 lpTransMsg
= ImmLockIMCC(hMsgBuf
);
4471 for (i
= 0; i
< dwNumMsgBuf
; i
++)
4472 ImmInternalSendIMEMessage(data
, lpTransMsg
[i
].message
, lpTransMsg
[i
].wParam
, lpTransMsg
[i
].lParam
);
4474 ImmUnlockIMCC(hMsgBuf
);
4475 ImmDestroyIMCC(hMsgBuf
);
4481 /***********************************************************************
4482 * ImmTranslateMessage(IMM32.@)
4483 * ( Undocumented, call internally and from user32.dll )
4485 BOOL WINAPI
ImmTranslateMessage(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lKeyData
)
4487 InputContextData
*data
;
4488 HIMC imc
= ImmGetContext(hwnd
);
4494 static const DWORD list_count
= 10;
4496 TRACE("%p %x %x %x\n",hwnd
, msg
, (UINT
)wParam
, (UINT
)lKeyData
);
4499 data
= (InputContextData
*)imc
;
4503 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeToAsciiEx
)
4506 GetKeyboardState(state
);
4507 scancode
= lKeyData
>> 0x10 & 0xff;
4509 list
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, list_count
* sizeof(TRANSMSG
) + sizeof(DWORD
));
4510 ((DWORD
*)list
)[0] = list_count
;
4512 if (data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_KBD_CHAR_FIRST
)
4516 if (!is_himc_ime_unicode(data
))
4517 ToAscii(data
->lastVK
, scancode
, state
, &chr
, 0);
4519 ToUnicodeEx(data
->lastVK
, scancode
, state
, &chr
, 1, 0, GetKeyboardLayout(0));
4520 uVirtKey
= MAKELONG(data
->lastVK
,chr
);
4523 uVirtKey
= data
->lastVK
;
4525 msg_count
= data
->immKbd
->pImeToAsciiEx(uVirtKey
, scancode
, state
, list
, 0, imc
);
4526 TRACE("%i messages generated\n",msg_count
);
4527 if (msg_count
&& msg_count
<= list_count
)
4530 LPTRANSMSG msgs
= (LPTRANSMSG
)((LPBYTE
)list
+ sizeof(DWORD
));
4532 for (i
= 0; i
< msg_count
; i
++)
4533 ImmInternalPostIMEMessage(data
, msgs
[i
].message
, msgs
[i
].wParam
, msgs
[i
].lParam
);
4535 else if (msg_count
> list_count
)
4536 ImmGenerateMessage(imc
);
4538 HeapFree(GetProcessHeap(),0,list
);
4540 data
->lastVK
= VK_PROCESSKEY
;
4542 return (msg_count
> 0);
4545 /***********************************************************************
4546 * ImmProcessKey(IMM32.@)
4547 * ( Undocumented, called from user32.dll )
4549 BOOL WINAPI
ImmProcessKey(HWND hwnd
, HKL hKL
, UINT vKey
, LPARAM lKeyData
, DWORD unknown
)
4551 InputContextData
*data
;
4552 HIMC imc
= ImmGetContext(hwnd
);
4555 TRACE("%p %p %x %x %x\n",hwnd
, hKL
, vKey
, (UINT
)lKeyData
, unknown
);
4558 data
= (InputContextData
*)imc
;
4562 /* Make sure we are inputting to the correct keyboard */
4563 if (data
->immKbd
->hkl
!= hKL
)
4565 ImmHkl
*new_hkl
= IMM_GetImmHkl(hKL
);
4568 data
->immKbd
->pImeSelect(imc
, FALSE
);
4569 data
->immKbd
->uSelected
--;
4570 data
->immKbd
= new_hkl
;
4571 data
->immKbd
->pImeSelect(imc
, TRUE
);
4572 data
->immKbd
->uSelected
++;
4578 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeProcessKey
)
4581 GetKeyboardState(state
);
4582 if (data
->immKbd
->pImeProcessKey(imc
, vKey
, lKeyData
, state
))
4584 data
->lastVK
= vKey
;
4588 data
->lastVK
= VK_PROCESSKEY
;
4592 /***********************************************************************
4593 * ImmDisableTextFrameService(IMM32.@)
4595 BOOL WINAPI
ImmDisableTextFrameService(DWORD dwThreadId
)
4601 /***********************************************************************
4602 * ImmEnumInputContext(IMM32.@)
4604 BOOL WINAPI
ImmEnumInputContext(DWORD dwThreadId
, IMCENUMPROC lpfn
, LPARAM lParam
)
4607 DWORD dwIndex
, dwCount
;
4611 TRACE("(%lu, %p, %p)\n", dwThreadId
, lpfn
, lParam
);
4613 dwCount
= Imm32AllocAndBuildHimcList(dwThreadId
, &phList
);
4617 for (dwIndex
= 0; dwIndex
< dwCount
; ++dwIndex
)
4619 hIMC
= phList
[dwIndex
];
4620 ret
= (*lpfn
)(hIMC
, lParam
);
4625 HeapFree(g_hImm32Heap
, 0, phList
);
4629 /***********************************************************************
4630 * ImmGetHotKey(IMM32.@)
4633 ImmGetHotKey(IN DWORD dwHotKey
,
4634 OUT LPUINT lpuModifiers
,
4638 TRACE("%lx, %p, %p, %p\n", dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
4639 if (lpuModifiers
&& lpuVKey
)
4640 return NtUserGetImeHotKey(dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
4644 /***********************************************************************
4645 * ImmDisableLegacyIME(IMM32.@)
4647 BOOL WINAPI
ImmDisableLegacyIME(void)
4653 /***********************************************************************
4654 * ImmSetActiveContext(IMM32.@)
4656 BOOL WINAPI
ImmSetActiveContext(HWND hwnd
, HIMC hIMC
, BOOL fFlag
)
4658 FIXME("(%p, %p, %d): stub\n", hwnd
, hIMC
, fFlag
);
4662 /***********************************************************************
4663 * ImmSetActiveContextConsoleIME(IMM32.@)
4665 BOOL WINAPI
ImmSetActiveContextConsoleIME(HWND hwnd
, BOOL fFlag
)
4668 TRACE("(%p, %d)\n", hwnd
, fFlag
);
4670 hIMC
= ImmGetContext(hwnd
);
4672 return ImmSetActiveContext(hwnd
, hIMC
, fFlag
);
4676 /***********************************************************************
4677 * ImmRegisterClient(IMM32.@)
4678 * ( Undocumented, called from user32.dll )
4680 BOOL WINAPI
ImmRegisterClient(PSHAREDINFO ptr
, HINSTANCE hMod
)
4682 g_SharedInfo
= *ptr
;
4683 g_psi
= g_SharedInfo
.psi
;
4684 return Imm32InitInstance(hMod
);
4687 /***********************************************************************
4688 * CtfImmIsTextFrameServiceDisabled(IMM32.@)
4690 BOOL WINAPI
CtfImmIsTextFrameServiceDisabled(VOID
)
4692 PTEB pTeb
= NtCurrentTeb();
4693 if (((PW32CLIENTINFO
)pTeb
->Win32ClientInfo
)->CI_flags
& CI_TFSDISABLED
)
4698 /***********************************************************************
4699 * ImmGetImeInfoEx (IMM32.@)
4702 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx
,
4703 IMEINFOEXCLASS SearchType
,
4706 BOOL bDisabled
= FALSE
;
4712 case ImeInfoExKeyboardLayout
:
4715 case ImeInfoExImeWindow
:
4716 bDisabled
= CtfImmIsTextFrameServiceDisabled();
4717 SearchType
= ImeInfoExKeyboardLayout
;
4720 case ImeInfoExImeFileName
:
4721 StringCchCopyW(pImeInfoEx
->wszImeFile
, _countof(pImeInfoEx
->wszImeFile
),
4726 hKL
= *(HKL
*)pvSearchKey
;
4727 pImeInfoEx
->hkl
= hKL
;
4729 if (!IS_IME_HKL(hKL
))
4731 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
4733 pTeb
= NtCurrentTeb();
4734 if (((PW32CLIENTINFO
)pTeb
->Win32ClientInfo
)->W32ClientInfo
[0] & 2)
4743 return NtUserGetImeInfoEx(pImeInfoEx
, SearchType
);
4746 BOOL WINAPI
User32InitializeImmEntryTable(DWORD
);
4748 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpReserved
)
4754 TRACE("(%p, 0x%X, %p)\n", hinstDLL
, fdwReason
, lpReserved
);
4758 case DLL_PROCESS_ATTACH
:
4759 //Imm32GenerateRandomSeed(hinstDLL, 1, lpReserved); // Non-sense
4760 if (!Imm32InitInstance(hinstDLL
))
4762 ERR("Imm32InitInstance failed\n");
4765 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC
))
4767 ERR("User32InitializeImmEntryTable failed\n");
4772 case DLL_THREAD_ATTACH
:
4775 case DLL_THREAD_DETACH
:
4776 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
4779 pTeb
= NtCurrentTeb();
4780 if (pTeb
->Win32ThreadInfo
== NULL
)
4783 hKL
= GetKeyboardLayout(0);
4784 // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
4785 hIMC
= (HIMC
)NtUserGetThreadState(4);
4786 Imm32CleanupContext(hIMC
, hKL
, TRUE
);
4789 case DLL_PROCESS_DETACH
:
4790 RtlDeleteCriticalSection(&g_csImeDpi
);