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 DWORD_PTR APIENTRY
Imm32QueryWindow(HWND hWnd
, DWORD Index
)
124 return NtUserQueryWindow(hWnd
, Index
);
127 static DWORD APIENTRY
128 Imm32UpdateInputContext(HIMC hIMC
, DWORD Unknown1
, PCLIENTIMC pClientImc
)
130 return NtUserUpdateInputContext(hIMC
, Unknown1
, pClientImc
);
133 static DWORD APIENTRY
Imm32QueryInputContext(HIMC hIMC
, DWORD dwUnknown2
)
135 return NtUserQueryInputContext(hIMC
, dwUnknown2
);
138 static inline BOOL
Imm32IsCrossThreadAccess(HIMC hIMC
)
140 DWORD dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
141 DWORD dwThreadId
= GetCurrentThreadId();
142 return (dwImeThreadId
!= dwThreadId
);
145 static DWORD APIENTRY
Imm32NotifyIMEStatus(HWND hwnd
, HIMC hIMC
, DWORD dwConversion
)
147 return NtUserNotifyIMEStatus(hwnd
, hIMC
, dwConversion
);
150 static HIMC APIENTRY
Imm32CreateInputContext(PCLIENTIMC pClientImc
)
152 return NtUserCreateInputContext(pClientImc
);
155 static BOOL APIENTRY
Imm32DestroyInputContext(HIMC hIMC
)
157 return NtUserDestroyInputContext(hIMC
);
160 DWORD_PTR APIENTRY
Imm32GetThreadState(DWORD Routine
)
162 return NtUserGetThreadState(Routine
);
165 static VOID APIENTRY
Imm32FreeImeDpi(PIMEDPI pImeDpi
, BOOL bDestroy
)
167 if (pImeDpi
->hInst
== NULL
)
170 pImeDpi
->ImeDestroy(0);
171 FreeLibrary(pImeDpi
->hInst
);
172 pImeDpi
->hInst
= NULL
;
176 Imm32NotifyAction(HIMC hIMC
, HWND hwnd
, DWORD dwAction
, DWORD_PTR dwIndex
, DWORD_PTR dwValue
,
177 DWORD_PTR dwCommand
, DWORD_PTR dwData
)
185 dwLayout
= Imm32QueryInputContext(hIMC
, 1);
188 /* find keyboard layout and lock it */
189 hKL
= GetKeyboardLayout(dwLayout
);
190 pImeDpi
= ImmLockImeDpi(hKL
);
194 pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
196 ImmUnlockImeDpi(pImeDpi
); /* unlock */
201 if (hwnd
&& dwCommand
)
202 SendMessageW(hwnd
, WM_IME_NOTIFY
, dwCommand
, dwData
);
207 static PIMEDPI APIENTRY
Imm32FindImeDpi(HKL hKL
)
211 RtlEnterCriticalSection(&g_csImeDpi
);
212 for (pImeDpi
= g_pImeDpiList
; pImeDpi
!= NULL
; pImeDpi
= pImeDpi
->pNext
)
214 if (pImeDpi
->hKL
== hKL
)
217 RtlLeaveCriticalSection(&g_csImeDpi
);
222 static BOOL
Imm32GetSystemLibraryPath(LPWSTR pszPath
, DWORD cchPath
, LPCWSTR pszFileName
)
224 if (!pszFileName
[0] || !GetSystemDirectoryW(pszPath
, cchPath
))
226 StringCchCatW(pszPath
, cchPath
, L
"\\");
227 StringCchCatW(pszPath
, cchPath
, pszFileName
);
231 DWORD APIENTRY
Imm32SetImeOwnerWindow(PIMEINFOEX pImeInfoEx
, BOOL fFlag
)
233 return NtUserSetImeOwnerWindow(pImeInfoEx
, fFlag
);
236 static BOOL APIENTRY
Imm32InquireIme(PIMEDPI pImeDpi
)
240 DWORD dwSysInfoFlags
= 0; // TODO: ???
241 LPIMEINFO pImeInfo
= &pImeDpi
->ImeInfo
;
243 // TODO: Imm32GetThreadState(THREADSTATE_UNKNOWN16);
245 if (!IS_IME_HKL(pImeDpi
->hKL
))
247 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
) &&
248 pImeDpi
->CtfImeInquireExW
)
255 if (!pImeDpi
->ImeInquire(pImeInfo
, szUIClass
, dwSysInfoFlags
))
258 szUIClass
[_countof(szUIClass
) - 1] = 0;
260 if (pImeInfo
->dwPrivateDataSize
== 0)
261 pImeInfo
->dwPrivateDataSize
= 4;
263 #define VALID_IME_PROP (IME_PROP_AT_CARET | \
264 IME_PROP_SPECIAL_UI | \
265 IME_PROP_CANDLIST_START_FROM_1 | \
267 IME_PROP_COMPLETE_ON_UNSELECT | \
268 IME_PROP_END_UNLOAD | \
269 IME_PROP_KBD_CHAR_FIRST | \
270 IME_PROP_IGNORE_UPKEYS | \
271 IME_PROP_NEED_ALTKEY | \
272 IME_PROP_NO_KEYS_ON_CLOSE | \
273 IME_PROP_ACCEPT_WIDE_VKEY)
274 #define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
276 IME_CMODE_KATAKANA | \
277 IME_CMODE_LANGUAGE | \
278 IME_CMODE_FULLSHAPE | \
280 IME_CMODE_CHARCODE | \
281 IME_CMODE_HANJACONVERT | \
282 IME_CMODE_SOFTKBD | \
283 IME_CMODE_NOCONVERSION | \
287 #define VALID_SMODE_CAPS (IME_SMODE_NONE | \
288 IME_SMODE_PLAURALCLAUSE | \
289 IME_SMODE_SINGLECONVERT | \
290 IME_SMODE_AUTOMATIC | \
291 IME_SMODE_PHRASEPREDICT | \
292 IME_SMODE_CONVERSATION)
293 #define VALID_UI_CAPS (UI_CAP_2700 | \
297 #define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \
299 SCS_CAP_SETRECONVERTSTRING)
300 #define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
302 if (pImeInfo
->fdwProperty
& ~VALID_IME_PROP
)
304 if (pImeInfo
->fdwConversionCaps
& ~VALID_CMODE_CAPS
)
306 if (pImeInfo
->fdwSentenceCaps
& ~VALID_SMODE_CAPS
)
308 if (pImeInfo
->fdwUICaps
& ~VALID_UI_CAPS
)
310 if (pImeInfo
->fdwSCSCaps
& ~VALID_SCS_CAPS
)
312 if (pImeInfo
->fdwSelectCaps
& ~VALID_SELECT_CAPS
)
315 #undef VALID_IME_PROP
316 #undef VALID_CMODE_CAPS
317 #undef VALID_SMODE_CAPS
319 #undef VALID_SCS_CAPS
320 #undef VALID_SELECT_CAPS
322 if (pImeInfo
->fdwProperty
& IME_PROP_UNICODE
)
324 StringCchCopyW(pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
), szUIClass
);
328 if (pImeDpi
->uCodePage
!= GetACP() && pImeDpi
->uCodePage
)
331 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, (LPSTR
)szUIClass
, -1,
332 pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
));
335 return GetClassInfoW(pImeDpi
->hInst
, pImeDpi
->szUIClass
, &wcW
);
338 static BOOL APIENTRY
Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx
, PIMEDPI pImeDpi
)
340 WCHAR szPath
[MAX_PATH
];
344 if (!Imm32GetSystemLibraryPath(szPath
, _countof(szPath
), pImeInfoEx
->wszImeFile
))
347 hIME
= GetModuleHandleW(szPath
);
350 hIME
= LoadLibraryW(szPath
);
353 ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath
);
357 pImeDpi
->hInst
= hIME
;
359 #define DEFINE_IME_ENTRY(type, name, params, extended) \
361 fn = GetProcAddress(hIME, #name); \
362 if (fn) pImeDpi->name = (FN_##name)fn; \
363 else if (!extended) goto Failed; \
365 #include "../../../win32ss/include/imetable.h"
366 #undef DEFINE_IME_ENTRY
368 if (!Imm32InquireIme(pImeDpi
))
370 ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
374 if (pImeInfoEx
->fLoadFlag
)
377 Imm32SetImeOwnerWindow(pImeInfoEx
, TRUE
);
381 FreeLibrary(pImeDpi
->hInst
);
382 pImeDpi
->hInst
= NULL
;
386 static PIMEDPI APIENTRY
Ime32LoadImeDpi(HKL hKL
, BOOL bLock
)
390 PIMEDPI pImeDpiNew
, pImeDpiFound
;
394 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
) ||
395 ImeInfoEx
.fLoadFlag
== 1)
400 pImeDpiNew
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(IMEDPI
));
401 if (pImeDpiNew
== NULL
)
404 pImeDpiNew
->hKL
= hKL
;
407 if (TranslateCharsetInfo((LPDWORD
)(DWORD_PTR
)lcid
, &ci
, TCI_SRCLOCALE
))
408 uCodePage
= ci
.ciACP
;
411 pImeDpiNew
->uCodePage
= uCodePage
;
413 if (!Imm32LoadImeInfo(&ImeInfoEx
, pImeDpiNew
))
415 HeapFree(g_hImm32Heap
, 0, pImeDpiNew
);
419 RtlEnterCriticalSection(&g_csImeDpi
);
421 pImeDpiFound
= Imm32FindImeDpi(hKL
);
425 pImeDpiFound
->dwFlags
&= ~IMEDPI_FLAG_LOCKED
;
427 RtlLeaveCriticalSection(&g_csImeDpi
);
429 Imm32FreeImeDpi(pImeDpiNew
, FALSE
);
430 HeapFree(g_hImm32Heap
, 0, pImeDpiNew
);
437 pImeDpiNew
->dwFlags
|= IMEDPI_FLAG_LOCKED
;
438 pImeDpiNew
->cLockObj
= 1;
441 pImeDpiNew
->pNext
= g_pImeDpiList
;
442 g_pImeDpiList
= pImeDpiNew
;
444 RtlLeaveCriticalSection(&g_csImeDpi
);
449 /***********************************************************************
450 * ImmLoadIME (IMM32.@)
452 BOOL WINAPI
ImmLoadIME(HKL hKL
)
454 PW32CLIENTINFO pInfo
;
457 if (!IS_IME_HKL(hKL
))
459 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
462 pInfo
= (PW32CLIENTINFO
)(NtCurrentTeb()->Win32ClientInfo
);
463 if ((pInfo
->W32ClientInfo
[0] & 2))
467 pImeDpi
= Imm32FindImeDpi(hKL
);
469 pImeDpi
= Ime32LoadImeDpi(hKL
, FALSE
);
470 return (pImeDpi
!= NULL
);
473 PIMEDPI APIENTRY
ImmLockOrLoadImeDpi(HKL hKL
)
475 PW32CLIENTINFO pInfo
;
478 if (!IS_IME_HKL(hKL
))
480 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
483 pInfo
= (PW32CLIENTINFO
)(NtCurrentTeb()->Win32ClientInfo
);
484 if ((pInfo
->W32ClientInfo
[0] & 2))
488 pImeDpi
= ImmLockImeDpi(hKL
);
490 pImeDpi
= Ime32LoadImeDpi(hKL
, TRUE
);
494 /***********************************************************************
495 * ImmLoadLayout (IMM32.@)
497 HKL WINAPI
ImmLoadLayout(HKL hKL
, PIMEINFOEX pImeInfoEx
)
500 UNICODE_STRING UnicodeString
;
501 HKEY hLayoutKey
= NULL
, hLayoutsKey
= NULL
;
504 WCHAR szLayout
[MAX_PATH
];
506 TRACE("(%p, %p)\n", hKL
, pImeInfoEx
);
508 if (IS_IME_HKL(hKL
) ||
509 !g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
) ||
510 ((PW32CLIENTINFO
)NtCurrentTeb()->Win32ClientInfo
)->W32ClientInfo
[0] & 2)
512 UnicodeString
.Buffer
= szLayout
;
513 UnicodeString
.MaximumLength
= sizeof(szLayout
);
514 Status
= RtlIntegerToUnicodeString((DWORD_PTR
)hKL
, 16, &UnicodeString
);
515 if (!NT_SUCCESS(Status
))
518 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_KEYBOARD_LAYOUTS
, &hLayoutsKey
);
522 error
= RegOpenKeyW(hLayoutsKey
, szLayout
, &hLayoutKey
);
526 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_IMM
, &hLayoutKey
);
531 ERR("RegOpenKeyW error: 0x%08lX\n", error
);
536 cbData
= sizeof(pImeInfoEx
->wszImeFile
);
537 error
= RegQueryValueExW(hLayoutKey
, L
"Ime File", 0, 0,
538 (LPBYTE
)pImeInfoEx
->wszImeFile
, &cbData
);
543 RegCloseKey(hLayoutKey
);
545 RegCloseKey(hLayoutsKey
);
549 typedef struct _tagImmHkl
{
554 WCHAR imeClassName
[17]; /* 16 character max */
558 /* Function Pointers */
559 BOOL (WINAPI
*pImeInquire
)(IMEINFO
*, WCHAR
*, const WCHAR
*);
560 BOOL (WINAPI
*pImeConfigure
)(HKL
, HWND
, DWORD
, void *);
561 BOOL (WINAPI
*pImeDestroy
)(UINT
);
562 LRESULT (WINAPI
*pImeEscape
)(HIMC
, UINT
, void *);
563 BOOL (WINAPI
*pImeSelect
)(HIMC
, BOOL
);
564 BOOL (WINAPI
*pImeSetActiveContext
)(HIMC
, BOOL
);
565 UINT (WINAPI
*pImeToAsciiEx
)(UINT
, UINT
, const BYTE
*, DWORD
*, UINT
, HIMC
);
566 BOOL (WINAPI
*pNotifyIME
)(HIMC
, DWORD
, DWORD
, DWORD
);
567 BOOL (WINAPI
*pImeRegisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
568 BOOL (WINAPI
*pImeUnregisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
569 UINT (WINAPI
*pImeEnumRegisterWord
)(REGISTERWORDENUMPROCW
, const WCHAR
*, DWORD
, const WCHAR
*, void *);
570 BOOL (WINAPI
*pImeSetCompositionString
)(HIMC
, DWORD
, const void *, DWORD
, const void *, DWORD
);
571 DWORD (WINAPI
*pImeConversionList
)(HIMC
, const WCHAR
*, CANDIDATELIST
*, DWORD
, UINT
);
572 BOOL (WINAPI
*pImeProcessKey
)(HIMC
, UINT
, LPARAM
, const BYTE
*);
573 UINT (WINAPI
*pImeGetRegisterWordStyle
)(UINT
, STYLEBUFW
*);
574 DWORD (WINAPI
*pImeGetImeMenuItems
)(HIMC
, DWORD
, DWORD
, IMEMENUITEMINFOW
*, IMEMENUITEMINFOW
*, DWORD
);
577 typedef struct tagInputContextData
589 #define WINE_IMC_VALID_MAGIC 0x56434D49
591 typedef struct _tagTRANSMSG
{
595 } TRANSMSG
, *LPTRANSMSG
;
597 typedef struct _tagIMMThreadData
{
606 static struct list ImmHklList
= LIST_INIT(ImmHklList
);
607 static struct list ImmThreadDataList
= LIST_INIT(ImmThreadDataList
);
609 static const WCHAR szwWineIMCProperty
[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
611 static const WCHAR szImeFileW
[] = {'I','m','e',' ','F','i','l','e',0};
612 static const WCHAR szLayoutTextW
[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
613 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};
615 static const WCHAR szwIME
[] = {'I','M','E',0};
616 static const WCHAR szwDefaultIME
[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
618 static CRITICAL_SECTION threaddata_cs
;
619 static CRITICAL_SECTION_DEBUG critsect_debug
=
621 0, 0, &threaddata_cs
,
622 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
623 0, 0, { (DWORD_PTR
)(__FILE__
": threaddata_cs") }
625 static CRITICAL_SECTION threaddata_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
626 static BOOL disable_ime
;
628 static inline BOOL
is_himc_ime_unicode(const InputContextData
*data
)
630 return !!(data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
633 static inline BOOL
is_kbd_ime_unicode(const ImmHkl
*hkl
)
635 return !!(hkl
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
638 static InputContextData
* get_imc_data(HIMC hIMC
);
640 static inline WCHAR
*strdupAtoW( const char *str
)
645 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
646 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
647 MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
652 static inline CHAR
*strdupWtoA( const WCHAR
*str
)
657 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
658 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
659 WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
664 static IMMThreadData
*IMM_GetThreadData(HWND hwnd
, DWORD thread
)
671 if (!(thread
= GetWindowThreadProcessId(hwnd
, &process
))) return NULL
;
672 if (process
!= GetCurrentProcessId()) return NULL
;
676 HANDLE h
= OpenThread(THREAD_QUERY_INFORMATION
, FALSE
, thread
);
678 process
= GetProcessIdOfThread(h
);
680 if (process
!= GetCurrentProcessId()) return NULL
;
683 thread
= GetCurrentThreadId();
685 EnterCriticalSection(&threaddata_cs
);
686 LIST_FOR_EACH_ENTRY(data
, &ImmThreadDataList
, IMMThreadData
, entry
)
687 if (data
->threadID
== thread
) return data
;
689 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
690 data
->threadID
= thread
;
691 list_add_head(&ImmThreadDataList
,&data
->entry
);
692 TRACE("Thread Data Created (%x)\n",thread
);
696 static HMODULE
load_graphics_driver(void)
698 static const WCHAR display_device_guid_propW
[] = {
699 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
700 'd','e','v','i','c','e','_','g','u','i','d',0 };
701 static const WCHAR key_pathW
[] = {
702 'S','y','s','t','e','m','\\',
703 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
704 'C','o','n','t','r','o','l','\\',
705 'V','i','d','e','o','\\','{',0};
706 static const WCHAR displayW
[] = {'}','\\','0','0','0','0',0};
707 static const WCHAR driverW
[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
712 WCHAR path
[MAX_PATH
];
713 WCHAR key
[ARRAY_SIZE( key_pathW
) + ARRAY_SIZE( displayW
) + 40];
714 UINT guid_atom
= HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW
));
716 if (!guid_atom
) return 0;
717 memcpy( key
, key_pathW
, sizeof(key_pathW
) );
718 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
719 lstrcatW( key
, displayW
);
720 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
722 if (!RegQueryValueExW( hkey
, driverW
, NULL
, NULL
, (BYTE
*)path
, &size
)) ret
= LoadLibraryW( path
);
724 TRACE( "%s %p\n", debugstr_w(path
), ret
);
728 /* ImmHkl loading and freeing */
729 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
730 static ImmHkl
*IMM_GetImmHkl(HKL hkl
)
733 WCHAR filename
[MAX_PATH
];
735 TRACE("Seeking ime for keyboard %p\n",hkl
);
737 LIST_FOR_EACH_ENTRY(ptr
, &ImmHklList
, ImmHkl
, entry
)
742 /* not found... create it */
744 ptr
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ImmHkl
));
747 if (ImmGetIMEFileNameW(hkl
, filename
, MAX_PATH
)) ptr
->hIME
= LoadLibraryW(filename
);
748 if (!ptr
->hIME
) ptr
->hIME
= load_graphics_driver();
751 LOAD_FUNCPTR(ImeInquire
);
752 if (!ptr
->pImeInquire
|| !ptr
->pImeInquire(&ptr
->imeInfo
, ptr
->imeClassName
, NULL
))
754 FreeLibrary(ptr
->hIME
);
759 LOAD_FUNCPTR(ImeDestroy
);
760 LOAD_FUNCPTR(ImeSelect
);
761 if (!ptr
->pImeSelect
|| !ptr
->pImeDestroy
)
763 FreeLibrary(ptr
->hIME
);
768 LOAD_FUNCPTR(ImeConfigure
);
769 LOAD_FUNCPTR(ImeEscape
);
770 LOAD_FUNCPTR(ImeSetActiveContext
);
771 LOAD_FUNCPTR(ImeToAsciiEx
);
772 LOAD_FUNCPTR(NotifyIME
);
773 LOAD_FUNCPTR(ImeRegisterWord
);
774 LOAD_FUNCPTR(ImeUnregisterWord
);
775 LOAD_FUNCPTR(ImeEnumRegisterWord
);
776 LOAD_FUNCPTR(ImeSetCompositionString
);
777 LOAD_FUNCPTR(ImeConversionList
);
778 LOAD_FUNCPTR(ImeProcessKey
);
779 LOAD_FUNCPTR(ImeGetRegisterWordStyle
);
780 LOAD_FUNCPTR(ImeGetImeMenuItems
);
781 /* make sure our classname is WCHAR */
782 if (!is_kbd_ime_unicode(ptr
))
785 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ptr
->imeClassName
,
787 lstrcpyW(ptr
->imeClassName
, bufW
);
792 list_add_head(&ImmHklList
,&ptr
->entry
);
798 HWND WINAPI
__wine_get_ui_window(HKL hkl
)
800 ImmHkl
*immHkl
= IMM_GetImmHkl(hkl
);
801 return immHkl
->UIWnd
;
804 /* for posting messages as the IME */
805 static void ImmInternalPostIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
807 HWND target
= GetFocus();
809 PostMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
811 PostMessageW(target
, msg
, wParam
, lParam
);
814 /* for sending messages as the IME */
815 static void ImmInternalSendIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
817 HWND target
= GetFocus();
819 SendMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
821 SendMessageW(target
, msg
, wParam
, lParam
);
824 static InputContextData
* get_imc_data(HIMC hIMC
)
826 InputContextData
*data
= hIMC
;
831 if(IsBadReadPtr(data
, sizeof(InputContextData
)) || data
->magic
!= WINE_IMC_VALID_MAGIC
)
833 SetLastError(ERROR_INVALID_HANDLE
);
839 static HIMC
get_default_context( HWND hwnd
)
841 FIXME("Don't use this function\n");
845 static BOOL
IMM_IsCrossThreadAccess(HWND hWnd
, HIMC hIMC
)
847 InputContextData
*data
;
851 DWORD thread
= GetWindowThreadProcessId(hWnd
, NULL
);
852 if (thread
!= GetCurrentThreadId()) return TRUE
;
854 data
= get_imc_data(hIMC
);
855 if (data
&& data
->threadID
!= GetCurrentThreadId())
861 /***********************************************************************
862 * ImmAssociateContext (IMM32.@)
864 HIMC WINAPI
ImmAssociateContext(HWND hWnd
, HIMC hIMC
)
867 InputContextData
*data
= get_imc_data(hIMC
);
869 TRACE("(%p, %p):\n", hWnd
, hIMC
);
875 * If already associated just return
877 if (hIMC
&& data
->IMC
.hWnd
== hWnd
)
880 if (hIMC
&& IMM_IsCrossThreadAccess(hWnd
, hIMC
))
885 HIMC defaultContext
= get_default_context( hWnd
);
886 old
= RemovePropW(hWnd
,szwWineIMCProperty
);
889 old
= defaultContext
;
890 else if (old
== (HIMC
)-1)
893 if (hIMC
!= defaultContext
)
895 if (hIMC
== NULL
) /* Meaning disable imm for that window*/
896 SetPropW(hWnd
,szwWineIMCProperty
,(HANDLE
)-1);
898 SetPropW(hWnd
,szwWineIMCProperty
,hIMC
);
903 InputContextData
*old_data
= old
;
904 if (old_data
->IMC
.hWnd
== hWnd
)
905 old_data
->IMC
.hWnd
= NULL
;
912 if(GetActiveWindow() == data
->IMC
.hWnd
)
914 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, FALSE
, ISC_SHOWUIALL
);
915 data
->IMC
.hWnd
= hWnd
;
916 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, TRUE
, ISC_SHOWUIALL
);
924 * Helper function for ImmAssociateContextEx
926 static BOOL CALLBACK
_ImmAssociateContextExEnumProc(HWND hwnd
, LPARAM lParam
)
928 HIMC hImc
= (HIMC
)lParam
;
929 ImmAssociateContext(hwnd
,hImc
);
933 /***********************************************************************
934 * ImmAssociateContextEx (IMM32.@)
936 BOOL WINAPI
ImmAssociateContextEx(HWND hWnd
, HIMC hIMC
, DWORD dwFlags
)
938 TRACE("(%p, %p, 0x%x):\n", hWnd
, hIMC
, dwFlags
);
946 ImmAssociateContext(hWnd
,hIMC
);
950 HIMC defaultContext
= get_default_context( hWnd
);
951 if (!defaultContext
) return FALSE
;
952 ImmAssociateContext(hWnd
,defaultContext
);
955 case IACE_IGNORENOCONTEXT
:
956 if (GetPropW(hWnd
,szwWineIMCProperty
))
957 ImmAssociateContext(hWnd
,hIMC
);
960 EnumChildWindows(hWnd
,_ImmAssociateContextExEnumProc
,(LPARAM
)hIMC
);
963 FIXME("Unknown dwFlags 0x%x\n",dwFlags
);
968 /***********************************************************************
969 * ImmConfigureIMEA (IMM32.@)
971 BOOL WINAPI
ImmConfigureIMEA(
972 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
974 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
976 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
978 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
981 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
983 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| !is_kbd_ime_unicode(immHkl
))
984 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
988 REGISTERWORDA
*rwa
= lpData
;
991 rww
.lpReading
= strdupAtoW(rwa
->lpReading
);
992 rww
.lpWord
= strdupAtoW(rwa
->lpWord
);
993 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rww
);
994 HeapFree(GetProcessHeap(),0,rww
.lpReading
);
995 HeapFree(GetProcessHeap(),0,rww
.lpWord
);
1003 /***********************************************************************
1004 * ImmConfigureIMEW (IMM32.@)
1006 BOOL WINAPI
ImmConfigureIMEW(
1007 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
1009 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1011 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
1013 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
1016 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
1018 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| is_kbd_ime_unicode(immHkl
))
1019 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
1022 REGISTERWORDW
*rww
= lpData
;
1026 rwa
.lpReading
= strdupWtoA(rww
->lpReading
);
1027 rwa
.lpWord
= strdupWtoA(rww
->lpWord
);
1028 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rwa
);
1029 HeapFree(GetProcessHeap(),0,rwa
.lpReading
);
1030 HeapFree(GetProcessHeap(),0,rwa
.lpWord
);
1038 /***********************************************************************
1039 * ImmCreateContext (IMM32.@)
1041 HIMC WINAPI
ImmCreateContext(void)
1043 PCLIENTIMC pClientImc
;
1048 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
1051 pClientImc
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
1052 if (pClientImc
== NULL
)
1055 hIMC
= Imm32CreateInputContext(pClientImc
);
1058 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1062 RtlInitializeCriticalSection(&pClientImc
->cs
);
1063 pClientImc
->unknown
= Imm32GetThreadState(THREADSTATE_UNKNOWN13
);
1067 static VOID APIENTRY
Imm32CleanupContextExtra(LPINPUTCONTEXT pIC
)
1069 FIXME("We have to do something do here");
1072 static PCLIENTIMC APIENTRY
Imm32FindClientImc(HIMC hIMC
)
1078 BOOL APIENTRY
Imm32CleanupContext(HIMC hIMC
, HKL hKL
, BOOL bKeep
)
1082 PCLIENTIMC pClientImc
;
1084 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
) || hIMC
== NULL
)
1087 FIXME("We have do something to do here\n");
1088 pClientImc
= Imm32FindClientImc(hIMC
);
1092 if (pClientImc
->hImc
== NULL
)
1094 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN1
;
1095 ImmUnlockClientImc(pClientImc
);
1097 return Imm32DestroyInputContext(hIMC
);
1101 pIC
= ImmLockIMC(hIMC
);
1104 ImmUnlockClientImc(pClientImc
);
1108 FIXME("We have do something to do here\n");
1110 if (pClientImc
->hKL
== hKL
)
1112 pImeDpi
= ImmLockImeDpi(hKL
);
1113 if (pImeDpi
!= NULL
)
1115 if (IS_IME_HKL(hKL
))
1117 pImeDpi
->ImeSelect(hIMC
, FALSE
);
1119 else if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
1121 FIXME("We have do something to do here\n");
1123 ImmUnlockImeDpi(pImeDpi
);
1125 pClientImc
->hKL
= NULL
;
1128 ImmDestroyIMCC(pIC
->hPrivate
);
1129 ImmDestroyIMCC(pIC
->hMsgBuf
);
1130 ImmDestroyIMCC(pIC
->hGuideLine
);
1131 ImmDestroyIMCC(pIC
->hCandInfo
);
1132 ImmDestroyIMCC(pIC
->hCompStr
);
1134 Imm32CleanupContextExtra(pIC
);
1138 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN1
;
1139 ImmUnlockClientImc(pClientImc
);
1142 return Imm32DestroyInputContext(hIMC
);
1147 /***********************************************************************
1148 * ImmDestroyContext (IMM32.@)
1150 BOOL WINAPI
ImmDestroyContext(HIMC hIMC
)
1154 TRACE("(%p)\n", hIMC
);
1156 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
1159 if (Imm32IsCrossThreadAccess(hIMC
))
1162 hKL
= GetKeyboardLayout(0);
1163 return Imm32CleanupContext(hIMC
, hKL
, FALSE
);
1166 /***********************************************************************
1167 * ImmDisableIME (IMM32.@)
1169 BOOL WINAPI
ImmDisableIME(DWORD dwThreadId
)
1171 return NtUserDisableThreadIme(dwThreadId
);
1174 /***********************************************************************
1175 * ImmEnumRegisterWordA (IMM32.@)
1177 UINT WINAPI
ImmEnumRegisterWordA(
1178 HKL hKL
, REGISTERWORDENUMPROCA lpfnEnumProc
,
1179 LPCSTR lpszReading
, DWORD dwStyle
,
1180 LPCSTR lpszRegister
, LPVOID lpData
)
1182 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1183 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL
, lpfnEnumProc
,
1184 debugstr_a(lpszReading
), dwStyle
, debugstr_a(lpszRegister
), lpData
);
1185 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
1187 if (!is_kbd_ime_unicode(immHkl
))
1188 return immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
1189 (LPCWSTR
)lpszReading
, dwStyle
, (LPCWSTR
)lpszRegister
, lpData
);
1192 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
1193 LPWSTR lpszwRegister
= strdupAtoW(lpszRegister
);
1196 rc
= immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
1197 lpszwReading
, dwStyle
, lpszwRegister
,
1200 HeapFree(GetProcessHeap(),0,lpszwReading
);
1201 HeapFree(GetProcessHeap(),0,lpszwRegister
);
1209 /***********************************************************************
1210 * ImmEnumRegisterWordW (IMM32.@)
1212 UINT WINAPI
ImmEnumRegisterWordW(
1213 HKL hKL
, REGISTERWORDENUMPROCW lpfnEnumProc
,
1214 LPCWSTR lpszReading
, DWORD dwStyle
,
1215 LPCWSTR lpszRegister
, LPVOID lpData
)
1217 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1218 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL
, lpfnEnumProc
,
1219 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
), lpData
);
1220 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
1222 if (is_kbd_ime_unicode(immHkl
))
1223 return immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, lpszReading
, dwStyle
,
1224 lpszRegister
, lpData
);
1227 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
1228 LPSTR lpszaRegister
= strdupWtoA(lpszRegister
);
1231 rc
= immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, (LPCWSTR
)lpszaReading
,
1232 dwStyle
, (LPCWSTR
)lpszaRegister
, lpData
);
1234 HeapFree(GetProcessHeap(),0,lpszaReading
);
1235 HeapFree(GetProcessHeap(),0,lpszaRegister
);
1243 static inline BOOL
EscapeRequiresWA(UINT uEscape
)
1245 if (uEscape
== IME_ESC_GET_EUDC_DICTIONARY
||
1246 uEscape
== IME_ESC_SET_EUDC_DICTIONARY
||
1247 uEscape
== IME_ESC_IME_NAME
||
1248 uEscape
== IME_ESC_GETHELPFILENAME
)
1253 /***********************************************************************
1254 * ImmEscapeA (IMM32.@)
1256 LRESULT WINAPI
ImmEscapeA(
1258 UINT uEscape
, LPVOID lpData
)
1260 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1261 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1263 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1265 if (!EscapeRequiresWA(uEscape
) || !is_kbd_ime_unicode(immHkl
))
1266 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1269 WCHAR buffer
[81]; /* largest required buffer should be 80 */
1271 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1273 MultiByteToWideChar(CP_ACP
,0,lpData
,-1,buffer
,81);
1274 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1278 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1279 WideCharToMultiByte(CP_ACP
,0,buffer
,-1,lpData
,80, NULL
, NULL
);
1288 /***********************************************************************
1289 * ImmEscapeW (IMM32.@)
1291 LRESULT WINAPI
ImmEscapeW(
1293 UINT uEscape
, LPVOID lpData
)
1295 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1296 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1298 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1300 if (!EscapeRequiresWA(uEscape
) || is_kbd_ime_unicode(immHkl
))
1301 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1304 CHAR buffer
[81]; /* largest required buffer should be 80 */
1306 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1308 WideCharToMultiByte(CP_ACP
,0,lpData
,-1,buffer
,81, NULL
, NULL
);
1309 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1313 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1314 MultiByteToWideChar(CP_ACP
,0,buffer
,-1,lpData
,80);
1323 static PCLIENTIMC APIENTRY
Imm32GetClientImcCache(void)
1325 // FIXME: Do something properly here
1329 static NTSTATUS APIENTRY
1330 Imm32BuildHimcList(DWORD dwThreadId
, DWORD dwCount
, HIMC
*phList
, LPDWORD pdwCount
)
1332 return NtUserBuildHimcList(dwThreadId
, dwCount
, phList
, pdwCount
);
1335 static DWORD APIENTRY
Imm32AllocAndBuildHimcList(DWORD dwThreadId
, HIMC
**pphList
)
1337 #define INITIAL_COUNT 0x40
1338 #define MAX_RETRY 10
1340 DWORD dwCount
= INITIAL_COUNT
, cRetry
= 0;
1343 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
1344 if (phNewList
== NULL
)
1347 Status
= Imm32BuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
1348 while (Status
== STATUS_BUFFER_TOO_SMALL
)
1350 HeapFree(g_hImm32Heap
, 0, phNewList
);
1351 if (cRetry
++ >= MAX_RETRY
)
1354 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
1355 if (phNewList
== NULL
)
1358 Status
= Imm32BuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
1361 if (NT_ERROR(Status
) || !dwCount
)
1363 HeapFree(g_hImm32Heap
, 0, phNewList
);
1367 *pphList
= phNewList
;
1369 #undef INITIAL_COUNT
1373 static BOOL APIENTRY
Imm32ImeNonImeToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
, LANGID LangID
)
1381 if (!IS_IME_HKL(hKL
) || LOWORD(hKL
) != LangID
)
1383 FIXME("We have to do something here\n");
1387 pIC
= ImmLockIMC(hIMC
);
1396 ImmSetOpenStatus(hIMC
, TRUE
);
1400 FIXME("We have to do something here\n");
1404 static BOOL APIENTRY
Imm32CShapeToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1408 DWORD dwConversion
, dwSentence
;
1410 if (hWnd
== NULL
|| !IS_IME_HKL(hKL
))
1413 pIC
= ImmLockIMC(hIMC
);
1420 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_FULLSHAPE
);
1421 dwSentence
= pIC
->fdwSentence
;
1427 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1429 ImmSetOpenStatus(hIMC
, TRUE
);
1434 static BOOL APIENTRY
Imm32CSymbolToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1438 DWORD dwConversion
, dwSentence
;
1440 if (hWnd
== NULL
|| !IS_IME_HKL(hKL
))
1443 pIC
= ImmLockIMC(hIMC
);
1450 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_SYMBOL
);
1451 dwSentence
= pIC
->fdwSentence
;
1457 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1459 ImmSetOpenStatus(hIMC
, TRUE
);
1464 static BOOL APIENTRY
Imm32JCloseOpen(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1468 if (ImmIsIME(hKL
) && LOWORD(hKL
) == LANGID_JAPANESE
)
1470 fOpen
= ImmGetOpenStatus(hIMC
);
1471 ImmSetOpenStatus(hIMC
, !fOpen
);
1475 FIXME("We have to do something here\n");
1479 static BOOL APIENTRY
Imm32KShapeToggle(HIMC hIMC
)
1482 DWORD dwConversion
, dwSentence
;
1484 pIC
= ImmLockIMC(hIMC
);
1488 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_FULLSHAPE
);
1489 dwSentence
= pIC
->fdwSentence
;
1490 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1492 if (pIC
->fdwConversion
& (IME_CMODE_FULLSHAPE
| IME_CMODE_NATIVE
))
1493 ImmSetOpenStatus(hIMC
, TRUE
);
1495 ImmSetOpenStatus(hIMC
, FALSE
);
1501 static BOOL APIENTRY
Imm32KHanjaConvert(HIMC hIMC
)
1504 DWORD dwConversion
, dwSentence
;
1506 pIC
= ImmLockIMC(hIMC
);
1510 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_HANJACONVERT
);
1511 dwSentence
= pIC
->fdwSentence
;
1514 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1518 static BOOL APIENTRY
Imm32KEnglish(HIMC hIMC
)
1521 DWORD dwConversion
, dwSentence
;
1524 pIC
= ImmLockIMC(hIMC
);
1528 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_NATIVE
);
1529 dwSentence
= pIC
->fdwSentence
;
1530 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1532 fOpen
= ((pIC
->fdwConversion
& (IME_CMODE_FULLSHAPE
| IME_CMODE_NATIVE
)) != 0);
1533 ImmSetOpenStatus(hIMC
, fOpen
);
1539 static BOOL APIENTRY
Imm32ProcessHotKey(HWND hWnd
, HIMC hIMC
, HKL hKL
, DWORD dwHotKeyID
)
1544 if (hIMC
&& Imm32IsCrossThreadAccess(hIMC
))
1549 case IME_CHOTKEY_IME_NONIME_TOGGLE
:
1550 return Imm32ImeNonImeToggle(hIMC
, hKL
, hWnd
, LANGID_CHINESE_SIMPLIFIED
);
1552 case IME_CHOTKEY_SHAPE_TOGGLE
:
1553 return Imm32CShapeToggle(hIMC
, hKL
, hWnd
);
1555 case IME_CHOTKEY_SYMBOL_TOGGLE
:
1556 return Imm32CSymbolToggle(hIMC
, hKL
, hWnd
);
1558 case IME_JHOTKEY_CLOSE_OPEN
:
1559 return Imm32JCloseOpen(hIMC
, hKL
, hWnd
);
1561 case IME_KHOTKEY_SHAPE_TOGGLE
:
1562 return Imm32KShapeToggle(hIMC
);
1564 case IME_KHOTKEY_HANJACONVERT
:
1565 return Imm32KHanjaConvert(hIMC
);
1567 case IME_KHOTKEY_ENGLISH
:
1568 return Imm32KEnglish(hIMC
);
1570 case IME_THOTKEY_IME_NONIME_TOGGLE
:
1571 return Imm32ImeNonImeToggle(hIMC
, hKL
, hWnd
, LANGID_CHINESE_TRADITIONAL
);
1573 case IME_THOTKEY_SHAPE_TOGGLE
:
1574 return Imm32CShapeToggle(hIMC
, hKL
, hWnd
);
1576 case IME_THOTKEY_SYMBOL_TOGGLE
:
1577 return Imm32CSymbolToggle(hIMC
, hKL
, hWnd
);
1583 if (dwHotKeyID
< IME_HOTKEY_PRIVATE_FIRST
|| IME_HOTKEY_PRIVATE_LAST
< dwHotKeyID
)
1586 pImeDpi
= ImmLockImeDpi(hKL
);
1587 if (pImeDpi
== NULL
)
1590 ret
= (BOOL
)pImeDpi
->ImeEscape(hIMC
, IME_ESC_PRIVATE_HOTKEY
, &dwHotKeyID
);
1591 ImmUnlockImeDpi(pImeDpi
);
1595 /***********************************************************************
1596 * ImmLockClientImc (IMM32.@)
1598 PCLIENTIMC WINAPI
ImmLockClientImc(HIMC hImc
)
1600 PCLIENTIMC pClientImc
;
1602 TRACE("(%p)\n", hImc
);
1607 pClientImc
= Imm32GetClientImcCache();
1610 pClientImc
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
1614 RtlInitializeCriticalSection(&pClientImc
->cs
);
1615 pClientImc
->unknown
= Imm32GetThreadState(THREADSTATE_UNKNOWN13
);
1617 if (!Imm32UpdateInputContext(hImc
, 0, pClientImc
))
1619 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1623 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN2
;
1627 if (pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN1
)
1631 InterlockedIncrement(&pClientImc
->cLockObj
);
1635 /***********************************************************************
1636 * ImmUnlockClientImc (IMM32.@)
1638 VOID WINAPI
ImmUnlockClientImc(PCLIENTIMC pClientImc
)
1643 TRACE("(%p)\n", pClientImc
);
1645 cLocks
= InterlockedDecrement(&pClientImc
->cLockObj
);
1646 if (cLocks
!= 0 || !(pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN1
))
1649 hImc
= pClientImc
->hImc
;
1653 RtlDeleteCriticalSection(&pClientImc
->cs
);
1654 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1657 static DWORD APIENTRY
1658 CandidateListWideToAnsi(const CANDIDATELIST
*pWideCL
, LPCANDIDATELIST pAnsiCL
, DWORD dwBufLen
,
1662 DWORD dwSize
, dwIndex
, cbGot
, cbLeft
;
1667 /* calculate total ansi size */
1668 if (pWideCL
->dwCount
> 0)
1670 dwSize
= sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1671 for (dwIndex
= 0; dwIndex
< pWideCL
->dwCount
; ++dwIndex
)
1673 pbWide
= (const BYTE
*)pWideCL
+ pWideCL
->dwOffset
[dwIndex
];
1674 cbGot
= WideCharToMultiByte(uCodePage
, 0, (LPCWSTR
)pbWide
, -1, NULL
, 0,
1675 NULL
, &bUsedDefault
);
1681 dwSize
= sizeof(CANDIDATELIST
);
1684 dwSize
= ROUNDUP4(dwSize
);
1687 if (dwBufLen
< dwSize
)
1691 pAnsiCL
->dwSize
= dwBufLen
;
1692 pAnsiCL
->dwStyle
= pWideCL
->dwStyle
;
1693 pAnsiCL
->dwCount
= pWideCL
->dwCount
;
1694 pAnsiCL
->dwSelection
= pWideCL
->dwSelection
;
1695 pAnsiCL
->dwPageStart
= pWideCL
->dwPageStart
;
1696 pAnsiCL
->dwPageSize
= pWideCL
->dwPageSize
;
1698 pibOffsets
= pAnsiCL
->dwOffset
;
1699 if (pWideCL
->dwCount
> 0)
1701 pibOffsets
[0] = sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1702 cbLeft
= dwBufLen
- pibOffsets
[0];
1704 for (dwIndex
= 0; dwIndex
< pWideCL
->dwCount
; ++dwIndex
)
1706 pbWide
= (const BYTE
*)pWideCL
+ pWideCL
->dwOffset
[dwIndex
];
1707 pbAnsi
= (LPBYTE
)pAnsiCL
+ pibOffsets
[dwIndex
];
1709 /* convert to ansi */
1710 cbGot
= WideCharToMultiByte(uCodePage
, 0, (LPCWSTR
)pbWide
, -1,
1711 (LPSTR
)pbAnsi
, cbLeft
, NULL
, &bUsedDefault
);
1714 if (dwIndex
< pWideCL
->dwCount
- 1)
1715 pibOffsets
[dwIndex
+ 1] = pibOffsets
[dwIndex
] + cbGot
;
1720 pibOffsets
[0] = sizeof(CANDIDATELIST
);
1726 static DWORD APIENTRY
1727 CandidateListAnsiToWide(const CANDIDATELIST
*pAnsiCL
, LPCANDIDATELIST pWideCL
, DWORD dwBufLen
,
1730 DWORD dwSize
, dwIndex
, cchGot
, cbGot
, cbLeft
;
1735 /* calculate total wide size */
1736 if (pAnsiCL
->dwCount
> 0)
1738 dwSize
= sizeof(CANDIDATELIST
) + ((pAnsiCL
->dwCount
- 1) * sizeof(DWORD
));
1739 for (dwIndex
= 0; dwIndex
< pAnsiCL
->dwCount
; ++dwIndex
)
1741 pbAnsi
= (const BYTE
*)pAnsiCL
+ pAnsiCL
->dwOffset
[dwIndex
];
1742 cchGot
= MultiByteToWideChar(uCodePage
, MB_PRECOMPOSED
, (LPCSTR
)pbAnsi
, -1, NULL
, 0);
1743 dwSize
+= cchGot
* sizeof(WCHAR
);
1748 dwSize
= sizeof(CANDIDATELIST
);
1751 dwSize
= ROUNDUP4(dwSize
);
1754 if (dwBufLen
< dwSize
)
1758 pWideCL
->dwSize
= dwBufLen
;
1759 pWideCL
->dwStyle
= pAnsiCL
->dwStyle
;
1760 pWideCL
->dwCount
= pAnsiCL
->dwCount
;
1761 pWideCL
->dwSelection
= pAnsiCL
->dwSelection
;
1762 pWideCL
->dwPageStart
= pAnsiCL
->dwPageStart
;
1763 pWideCL
->dwPageSize
= pAnsiCL
->dwPageSize
;
1765 pibOffsets
= pWideCL
->dwOffset
;
1766 if (pAnsiCL
->dwCount
> 0)
1768 pibOffsets
[0] = sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1769 cbLeft
= dwBufLen
- pibOffsets
[0];
1771 for (dwIndex
= 0; dwIndex
< pAnsiCL
->dwCount
; ++dwIndex
)
1773 pbAnsi
= (const BYTE
*)pAnsiCL
+ pAnsiCL
->dwOffset
[dwIndex
];
1774 pbWide
= (LPBYTE
)pWideCL
+ pibOffsets
[dwIndex
];
1776 /* convert to wide */
1777 cchGot
= MultiByteToWideChar(uCodePage
, MB_PRECOMPOSED
, (LPCSTR
)pbAnsi
, -1,
1778 (LPWSTR
)pbWide
, cbLeft
/ sizeof(WCHAR
));
1779 cbGot
= cchGot
* sizeof(WCHAR
);
1782 if (dwIndex
+ 1 < pAnsiCL
->dwCount
)
1783 pibOffsets
[dwIndex
+ 1] = pibOffsets
[dwIndex
] + cbGot
;
1788 pibOffsets
[0] = sizeof(CANDIDATELIST
);
1794 static DWORD APIENTRY
1795 ImmGetCandidateListAW(HIMC hIMC
, DWORD dwIndex
, LPCANDIDATELIST lpCandList
, DWORD dwBufLen
,
1800 PCLIENTIMC pClientImc
;
1801 LPCANDIDATEINFO pCI
;
1802 LPCANDIDATELIST pCL
;
1805 pClientImc
= ImmLockClientImc(hIMC
);
1809 pIC
= ImmLockIMC(hIMC
);
1812 ImmUnlockClientImc(pClientImc
);
1816 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
1820 ImmUnlockClientImc(pClientImc
);
1824 if (pCI
->dwSize
< sizeof(CANDIDATEINFO
) || pCI
->dwCount
<= dwIndex
)
1827 /* get required size */
1828 pCL
= (LPCANDIDATELIST
)((LPBYTE
)pCI
+ pCI
->dwOffset
[dwIndex
]);
1831 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1832 dwSize
= CandidateListAnsiToWide(pCL
, NULL
, 0, CP_ACP
);
1834 dwSize
= pCL
->dwSize
;
1838 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1839 dwSize
= pCL
->dwSize
;
1841 dwSize
= CandidateListWideToAnsi(pCL
, NULL
, 0, CP_ACP
);
1844 if (dwBufLen
!= 0 && dwSize
!= 0)
1846 if (lpCandList
== NULL
|| dwBufLen
< dwSize
)
1852 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1853 CandidateListAnsiToWide(pCL
, lpCandList
, dwSize
, CP_ACP
);
1855 RtlCopyMemory(lpCandList
, pCL
, dwSize
);
1859 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1860 RtlCopyMemory(lpCandList
, pCL
, dwSize
);
1862 CandidateListWideToAnsi(pCL
, lpCandList
, dwSize
, CP_ACP
);
1869 ImmUnlockIMCC(pIC
->hCandInfo
);
1871 ImmUnlockClientImc(pClientImc
);
1875 DWORD APIENTRY
ImmGetCandidateListCountAW(HIMC hIMC
, LPDWORD lpdwListCount
, BOOL bAnsi
)
1877 DWORD ret
= 0, cbGot
, dwIndex
;
1878 PCLIENTIMC pClientImc
;
1880 const CANDIDATEINFO
*pCI
;
1882 const CANDIDATELIST
*pCL
;
1883 const DWORD
*pdwOffsets
;
1885 if (lpdwListCount
== NULL
)
1890 pClientImc
= ImmLockClientImc(hIMC
);
1891 if (pClientImc
== NULL
)
1894 pIC
= ImmLockIMC(hIMC
);
1897 ImmUnlockClientImc(pClientImc
);
1901 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
1905 ImmUnlockClientImc(pClientImc
);
1909 if (pCI
->dwSize
< sizeof(CANDIDATEINFO
))
1912 *lpdwListCount
= pCI
->dwCount
; /* the number of candidate lists */
1914 /* calculate total size of candidate lists */
1917 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1919 ret
= ROUNDUP4(pCI
->dwPrivateSize
);
1920 pdwOffsets
= pCI
->dwOffset
;
1921 for (dwIndex
= 0; dwIndex
< pCI
->dwCount
; ++dwIndex
)
1923 pb
= (const BYTE
*)pCI
+ pdwOffsets
[dwIndex
];
1924 pCL
= (const CANDIDATELIST
*)pb
;
1925 cbGot
= CandidateListWideToAnsi(pCL
, NULL
, 0, CP_ACP
);
1936 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1942 ret
= ROUNDUP4(pCI
->dwPrivateSize
);
1943 pdwOffsets
= pCI
->dwOffset
;
1944 for (dwIndex
= 0; dwIndex
< pCI
->dwCount
; ++dwIndex
)
1946 pb
= (const BYTE
*)pCI
+ pdwOffsets
[dwIndex
];
1947 pCL
= (const CANDIDATELIST
*)pb
;
1948 cbGot
= CandidateListAnsiToWide(pCL
, NULL
, 0, CP_ACP
);
1955 ImmUnlockIMCC(pIC
->hCandInfo
);
1957 ImmUnlockClientImc(pClientImc
);
1961 /***********************************************************************
1962 * ImmGetCandidateListA (IMM32.@)
1964 DWORD WINAPI
ImmGetCandidateListA(
1965 HIMC hIMC
, DWORD dwIndex
,
1966 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1968 return ImmGetCandidateListAW(hIMC
, dwIndex
, lpCandList
, dwBufLen
, TRUE
);
1971 /***********************************************************************
1972 * ImmGetCandidateListCountA (IMM32.@)
1974 DWORD WINAPI
ImmGetCandidateListCountA(
1975 HIMC hIMC
, LPDWORD lpdwListCount
)
1977 return ImmGetCandidateListCountAW(hIMC
, lpdwListCount
, TRUE
);
1980 /***********************************************************************
1981 * ImmGetCandidateListCountW (IMM32.@)
1983 DWORD WINAPI
ImmGetCandidateListCountW(
1984 HIMC hIMC
, LPDWORD lpdwListCount
)
1986 return ImmGetCandidateListCountAW(hIMC
, lpdwListCount
, FALSE
);
1989 /***********************************************************************
1990 * ImmGetCandidateListW (IMM32.@)
1992 DWORD WINAPI
ImmGetCandidateListW(
1993 HIMC hIMC
, DWORD dwIndex
,
1994 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1996 return ImmGetCandidateListAW(hIMC
, dwIndex
, lpCandList
, dwBufLen
, FALSE
);
1999 /***********************************************************************
2000 * ImmGetCandidateWindow (IMM32.@)
2002 BOOL WINAPI
ImmGetCandidateWindow(
2003 HIMC hIMC
, DWORD dwIndex
, LPCANDIDATEFORM lpCandidate
)
2007 LPCANDIDATEFORM pCF
;
2009 TRACE("(%p, %lu, %p)\n", hIMC
, dwIndex
, lpCandidate
);
2011 pIC
= ImmLockIMC(hIMC
);
2015 pCF
= &pIC
->cfCandForm
[dwIndex
];
2016 if (pCF
->dwIndex
!= IMM_INVALID_CANDFORM
)
2018 *lpCandidate
= *pCF
;
2026 static VOID APIENTRY
LogFontAnsiToWide(const LOGFONTA
*plfA
, LPLOGFONTW plfW
)
2029 RtlCopyMemory(plfW
, plfA
, offsetof(LOGFONTA
, lfFaceName
));
2030 StringCchLengthA(plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), &cch
);
2031 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, plfA
->lfFaceName
, (INT
)cch
,
2032 plfW
->lfFaceName
, _countof(plfW
->lfFaceName
));
2033 if (cch
> _countof(plfW
->lfFaceName
) - 1)
2034 cch
= _countof(plfW
->lfFaceName
) - 1;
2035 plfW
->lfFaceName
[cch
] = 0;
2038 static VOID APIENTRY
LogFontWideToAnsi(const LOGFONTW
*plfW
, LPLOGFONTA plfA
)
2041 RtlCopyMemory(plfA
, plfW
, offsetof(LOGFONTW
, lfFaceName
));
2042 StringCchLengthW(plfW
->lfFaceName
, _countof(plfW
->lfFaceName
), &cch
);
2043 cch
= WideCharToMultiByte(CP_ACP
, 0, plfW
->lfFaceName
, (INT
)cch
,
2044 plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), NULL
, NULL
);
2045 if (cch
> _countof(plfA
->lfFaceName
) - 1)
2046 cch
= _countof(plfA
->lfFaceName
) - 1;
2047 plfA
->lfFaceName
[cch
] = 0;
2050 /***********************************************************************
2051 * ImmGetCompositionFontA (IMM32.@)
2053 BOOL WINAPI
ImmGetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
2055 PCLIENTIMC pClientImc
;
2056 BOOL ret
= FALSE
, bWide
;
2059 TRACE("(%p, %p)\n", hIMC
, lplf
);
2061 pClientImc
= ImmLockClientImc(hIMC
);
2062 if (pClientImc
== NULL
)
2065 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
2066 ImmUnlockClientImc(pClientImc
);
2068 pIC
= ImmLockIMC(hIMC
);
2072 if (pIC
->fdwInit
& INIT_LOGFONT
)
2075 LogFontWideToAnsi(&pIC
->lfFont
.W
, lplf
);
2077 *lplf
= pIC
->lfFont
.A
;
2086 /***********************************************************************
2087 * ImmGetCompositionFontW (IMM32.@)
2089 BOOL WINAPI
ImmGetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
2091 PCLIENTIMC pClientImc
;
2096 TRACE("(%p, %p)\n", hIMC
, lplf
);
2098 pClientImc
= ImmLockClientImc(hIMC
);
2099 if (pClientImc
== NULL
)
2102 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
2103 ImmUnlockClientImc(pClientImc
);
2105 pIC
= ImmLockIMC(hIMC
);
2109 if (pIC
->fdwInit
& INIT_LOGFONT
)
2112 *lplf
= pIC
->lfFont
.W
;
2114 LogFontAnsiToWide(&pIC
->lfFont
.A
, lplf
);
2124 /* Helpers for the GetCompositionString functions */
2126 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
2127 length is always in bytes. */
2128 static INT
CopyCompStringIMEtoClient(const InputContextData
*data
, const void *src
, INT src_len
, void *dst
,
2129 INT dst_len
, BOOL unicode
)
2131 int char_size
= unicode
? sizeof(WCHAR
) : sizeof(char);
2134 if (is_himc_ime_unicode(data
) ^ unicode
)
2137 ret
= MultiByteToWideChar(CP_ACP
, 0, src
, src_len
, dst
, dst_len
/ sizeof(WCHAR
));
2139 ret
= WideCharToMultiByte(CP_ACP
, 0, src
, src_len
, dst
, dst_len
, NULL
, NULL
);
2146 ret
= min(src_len
* char_size
, dst_len
);
2147 memcpy(dst
, src
, ret
);
2150 ret
= src_len
* char_size
;
2156 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
2157 passed mode. String length is in characters, attributes are in byte arrays. */
2158 static INT
CopyCompAttrIMEtoClient(const InputContextData
*data
, const BYTE
*src
, INT src_len
, const void *comp_string
,
2159 INT str_len
, BYTE
*dst
, INT dst_len
, BOOL unicode
)
2169 string
.str
= comp_string
;
2171 if (is_himc_ime_unicode(data
) && !unicode
)
2173 rc
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
, str_len
, NULL
, 0, NULL
, NULL
);
2176 int i
, j
= 0, k
= 0;
2180 for (i
= 0; i
< str_len
; ++i
)
2184 len
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
+ i
, 1, NULL
, 0, NULL
, NULL
);
2185 for (; len
> 0; --len
)
2198 else if (!is_himc_ime_unicode(data
) && unicode
)
2200 rc
= MultiByteToWideChar(CP_ACP
, 0, string
.strA
, str_len
, NULL
, 0);
2207 for (i
= 0; i
< str_len
; ++i
)
2209 if (IsDBCSLeadByte(string
.strA
[i
]))
2222 memcpy(dst
, src
, min(src_len
, dst_len
));
2229 static INT
CopyCompClauseIMEtoClient(InputContextData
*data
, LPBYTE source
, INT slen
, LPBYTE ssource
,
2230 LPBYTE target
, INT tlen
, BOOL unicode
)
2234 if (is_himc_ime_unicode(data
) && !unicode
)
2242 tlen
/= sizeof (DWORD
);
2243 for (i
= 0; i
< tlen
; ++i
)
2245 ((DWORD
*)target
)[i
] = WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
,
2246 ((DWORD
*)source
)[i
],
2250 rc
= sizeof (DWORD
) * i
;
2255 else if (!is_himc_ime_unicode(data
) && unicode
)
2263 tlen
/= sizeof (DWORD
);
2264 for (i
= 0; i
< tlen
; ++i
)
2266 ((DWORD
*)target
)[i
] = MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
,
2267 ((DWORD
*)source
)[i
],
2270 rc
= sizeof (DWORD
) * i
;
2277 memcpy( target
, source
, min(slen
,tlen
));
2284 static INT
CopyCompOffsetIMEtoClient(InputContextData
*data
, DWORD offset
, LPBYTE ssource
, BOOL unicode
)
2288 if (is_himc_ime_unicode(data
) && !unicode
)
2290 rc
= WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
, offset
, NULL
, 0, NULL
, NULL
);
2292 else if (!is_himc_ime_unicode(data
) && unicode
)
2294 rc
= MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
, offset
, NULL
, 0);
2302 static LONG
ImmGetCompositionStringT( HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
,
2303 DWORD dwBufLen
, BOOL unicode
)
2306 InputContextData
*data
= get_imc_data(hIMC
);
2307 LPCOMPOSITIONSTRING compstr
;
2310 TRACE("(%p, 0x%x, %p, %d)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2315 if (!data
->IMC
.hCompStr
)
2318 compdata
= ImmLockIMCC(data
->IMC
.hCompStr
);
2319 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
2324 TRACE("GCS_RESULTSTR\n");
2325 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultStrOffset
, compstr
->dwResultStrLen
, lpBuf
, dwBufLen
, unicode
);
2328 TRACE("GCS_COMPSTR\n");
2329 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
, lpBuf
, dwBufLen
, unicode
);
2332 TRACE("GCS_COMPATTR\n");
2333 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompAttrOffset
, compstr
->dwCompAttrLen
,
2334 compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
,
2335 lpBuf
, dwBufLen
, unicode
);
2337 case GCS_COMPCLAUSE
:
2338 TRACE("GCS_COMPCLAUSE\n");
2339 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompClauseOffset
,compstr
->dwCompClauseLen
,
2340 compdata
+ compstr
->dwCompStrOffset
,
2341 lpBuf
, dwBufLen
, unicode
);
2343 case GCS_RESULTCLAUSE
:
2344 TRACE("GCS_RESULTCLAUSE\n");
2345 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultClauseOffset
,compstr
->dwResultClauseLen
,
2346 compdata
+ compstr
->dwResultStrOffset
,
2347 lpBuf
, dwBufLen
, unicode
);
2349 case GCS_RESULTREADSTR
:
2350 TRACE("GCS_RESULTREADSTR\n");
2351 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultReadStrOffset
, compstr
->dwResultReadStrLen
, lpBuf
, dwBufLen
, unicode
);
2353 case GCS_RESULTREADCLAUSE
:
2354 TRACE("GCS_RESULTREADCLAUSE\n");
2355 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultReadClauseOffset
,compstr
->dwResultReadClauseLen
,
2356 compdata
+ compstr
->dwResultStrOffset
,
2357 lpBuf
, dwBufLen
, unicode
);
2359 case GCS_COMPREADSTR
:
2360 TRACE("GCS_COMPREADSTR\n");
2361 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
, lpBuf
, dwBufLen
, unicode
);
2363 case GCS_COMPREADATTR
:
2364 TRACE("GCS_COMPREADATTR\n");
2365 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompReadAttrOffset
, compstr
->dwCompReadAttrLen
,
2366 compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
,
2367 lpBuf
, dwBufLen
, unicode
);
2369 case GCS_COMPREADCLAUSE
:
2370 TRACE("GCS_COMPREADCLAUSE\n");
2371 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompReadClauseOffset
,compstr
->dwCompReadClauseLen
,
2372 compdata
+ compstr
->dwCompStrOffset
,
2373 lpBuf
, dwBufLen
, unicode
);
2376 TRACE("GCS_CURSORPOS\n");
2377 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwCursorPos
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
2379 case GCS_DELTASTART
:
2380 TRACE("GCS_DELTASTART\n");
2381 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwDeltaStart
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
2384 FIXME("Unhandled index 0x%x\n",dwIndex
);
2388 ImmUnlockIMCC(data
->IMC
.hCompStr
);
2393 /***********************************************************************
2394 * ImmGetCompositionStringA (IMM32.@)
2396 LONG WINAPI
ImmGetCompositionStringA(
2397 HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
)
2399 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
2403 /***********************************************************************
2404 * ImmGetCompositionStringW (IMM32.@)
2406 LONG WINAPI
ImmGetCompositionStringW(
2407 HIMC hIMC
, DWORD dwIndex
,
2408 LPVOID lpBuf
, DWORD dwBufLen
)
2410 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
2413 /***********************************************************************
2414 * ImmGetCompositionWindow (IMM32.@)
2416 BOOL WINAPI
ImmGetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
2421 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
2423 pIC
= ImmLockIMC(hIMC
);
2427 if (pIC
->fdwInit
& INIT_COMPFORM
)
2429 *lpCompForm
= pIC
->cfCompForm
;
2437 /***********************************************************************
2438 * ImmGetContext (IMM32.@)
2440 HIMC WINAPI
ImmGetContext(HWND hWnd
)
2444 TRACE("%p\n", hWnd
);
2446 if (!IsWindow(hWnd
))
2448 SetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2452 rc
= GetPropW(hWnd
,szwWineIMCProperty
);
2455 else if (rc
== NULL
)
2456 rc
= get_default_context( hWnd
);
2460 InputContextData
*data
= rc
;
2461 data
->IMC
.hWnd
= hWnd
;
2464 TRACE("returning %p\n", rc
);
2469 /***********************************************************************
2470 * ImmGetConversionListA (IMM32.@)
2472 DWORD WINAPI
ImmGetConversionListA(
2474 LPCSTR pSrc
, LPCANDIDATELIST lpDst
,
2475 DWORD dwBufLen
, UINT uFlag
)
2479 LPWSTR pszSrcW
= NULL
;
2480 LPCANDIDATELIST pCL
= NULL
;
2483 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL
, hIMC
, debugstr_a(pSrc
),
2484 lpDst
, dwBufLen
, uFlag
);
2486 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
2487 if (pImeDpi
== NULL
)
2490 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
2492 ret
= pImeDpi
->ImeConversionList(hIMC
, pSrc
, lpDst
, dwBufLen
, uFlag
);
2493 ImmUnlockImeDpi(pImeDpi
);
2499 pszSrcW
= Imm32WideFromAnsi(pSrc
);
2500 if (pszSrcW
== NULL
)
2504 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcW
, NULL
, 0, uFlag
);
2508 pCL
= Imm32HeapAlloc(0, cb
);
2512 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcW
, pCL
, cb
, uFlag
);
2516 ret
= CandidateListWideToAnsi(pCL
, lpDst
, dwBufLen
, CP_ACP
);
2520 HeapFree(g_hImm32Heap
, 0, pszSrcW
);
2522 HeapFree(g_hImm32Heap
, 0, pCL
);
2523 ImmUnlockImeDpi(pImeDpi
);
2527 /***********************************************************************
2528 * ImmGetConversionListW (IMM32.@)
2530 DWORD WINAPI
ImmGetConversionListW(
2532 LPCWSTR pSrc
, LPCANDIDATELIST lpDst
,
2533 DWORD dwBufLen
, UINT uFlag
)
2538 LPCANDIDATELIST pCL
= NULL
;
2539 LPSTR pszSrcA
= NULL
;
2541 TRACE("(%p, %p, %s, %p, %lu, 0x%lX)\n", hKL
, hIMC
, debugstr_w(pSrc
),
2542 lpDst
, dwBufLen
, uFlag
);
2544 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
2548 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
2550 ret
= pImeDpi
->ImeConversionList(hIMC
, pSrc
, lpDst
, dwBufLen
, uFlag
);
2551 ImmUnlockImeDpi(pImeDpi
);
2557 pszSrcA
= Imm32AnsiFromWide(pSrc
);
2558 if (pszSrcA
== NULL
)
2562 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcA
, NULL
, 0, uFlag
);
2566 pCL
= Imm32HeapAlloc(0, cb
);
2570 cb
= pImeDpi
->ImeConversionList(hIMC
, pszSrcA
, pCL
, cb
, uFlag
);
2574 ret
= CandidateListAnsiToWide(pCL
, lpDst
, dwBufLen
, CP_ACP
);
2578 HeapFree(g_hImm32Heap
, 0, pszSrcA
);
2580 HeapFree(g_hImm32Heap
, 0, pCL
);
2581 ImmUnlockImeDpi(pImeDpi
);
2585 /***********************************************************************
2586 * ImmGetConversionStatus (IMM32.@)
2588 BOOL WINAPI
ImmGetConversionStatus(
2589 HIMC hIMC
, LPDWORD lpfdwConversion
, LPDWORD lpfdwSentence
)
2593 TRACE("(%p %p %p)\n", hIMC
, lpfdwConversion
, lpfdwSentence
);
2595 pIC
= ImmLockIMC(hIMC
);
2599 if (lpfdwConversion
)
2600 *lpfdwConversion
= pIC
->fdwConversion
;
2602 *lpfdwSentence
= pIC
->fdwSentence
;
2608 static BOOL
needs_ime_window(HWND hwnd
)
2612 if (GetClassNameW(hwnd
, classW
, ARRAY_SIZE(classW
)) && !lstrcmpW(classW
, szwIME
))
2614 if (GetClassLongPtrW(hwnd
, GCL_STYLE
) & CS_IME
) return FALSE
;
2619 /***********************************************************************
2620 * __wine_register_window (IMM32.@)
2622 BOOL WINAPI
__wine_register_window(HWND hwnd
)
2625 IMMThreadData
*thread_data
;
2626 TRACE("(%p)\n", hwnd
);
2628 if (!needs_ime_window(hwnd
))
2631 thread_data
= IMM_GetThreadData(hwnd
, 0);
2635 if (thread_data
->disableIME
|| disable_ime
)
2637 TRACE("IME for this thread is disabled\n");
2638 LeaveCriticalSection(&threaddata_cs
);
2641 thread_data
->windowRefs
++;
2642 TRACE("windowRefs=%u, hwndDefault=%p\n",
2643 thread_data
->windowRefs
, thread_data
->hwndDefault
);
2645 /* Create default IME window */
2646 if (thread_data
->windowRefs
== 1)
2648 /* Do not create the window inside of a critical section */
2649 LeaveCriticalSection(&threaddata_cs
);
2650 new = CreateWindowExW( 0, szwIME
, szwDefaultIME
,
2651 WS_POPUP
| WS_DISABLED
| WS_CLIPSIBLINGS
,
2652 0, 0, 1, 1, 0, 0, 0, 0);
2653 /* thread_data is in the current thread so we can assume it's still valid */
2654 EnterCriticalSection(&threaddata_cs
);
2655 /* See if anyone beat us */
2656 if (thread_data
->hwndDefault
== NULL
)
2658 thread_data
->hwndDefault
= new;
2660 TRACE("Default is %p\n", thread_data
->hwndDefault
);
2664 LeaveCriticalSection(&threaddata_cs
);
2666 /* Clean up an unused new window outside of the critical section */
2672 /***********************************************************************
2673 * __wine_unregister_window (IMM32.@)
2675 void WINAPI
__wine_unregister_window(HWND hwnd
)
2677 HWND to_destroy
= 0;
2678 IMMThreadData
*thread_data
;
2679 TRACE("(%p)\n", hwnd
);
2681 thread_data
= IMM_GetThreadData(hwnd
, 0);
2682 if (!thread_data
) return;
2684 thread_data
->windowRefs
--;
2685 TRACE("windowRefs=%u, hwndDefault=%p\n",
2686 thread_data
->windowRefs
, thread_data
->hwndDefault
);
2688 /* Destroy default IME window */
2689 if (thread_data
->windowRefs
== 0 && thread_data
->hwndDefault
)
2691 to_destroy
= thread_data
->hwndDefault
;
2692 thread_data
->hwndDefault
= NULL
;
2694 LeaveCriticalSection(&threaddata_cs
);
2696 if (to_destroy
) DestroyWindow( to_destroy
);
2699 /***********************************************************************
2700 * ImmGetDefaultIMEWnd (IMM32.@)
2702 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
2704 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
2708 return (HWND
)Imm32GetThreadState(THREADSTATE_ACTIVEWINDOW
);
2710 return (HWND
)Imm32QueryWindow(hWnd
, QUERY_WINDOW_DEFAULT_IME
);
2713 /***********************************************************************
2714 * CtfImmIsCiceroEnabled (IMM32.@)
2716 BOOL WINAPI
CtfImmIsCiceroEnabled(VOID
)
2718 return (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
));
2721 /***********************************************************************
2722 * ImmGetDescriptionA (IMM32.@)
2724 UINT WINAPI
ImmGetDescriptionA(
2725 HKL hKL
, LPSTR lpszDescription
, UINT uBufLen
)
2730 TRACE("(%p,%p,%d)\n", hKL
, lpszDescription
, uBufLen
);
2732 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2735 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
2736 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeDescription
, (INT
)cch
,
2737 lpszDescription
, uBufLen
, NULL
, NULL
);
2739 lpszDescription
[cch
] = 0;
2743 /***********************************************************************
2744 * ImmGetDescriptionW (IMM32.@)
2746 UINT WINAPI
ImmGetDescriptionW(HKL hKL
, LPWSTR lpszDescription
, UINT uBufLen
)
2751 TRACE("(%p, %p, %d)\n", hKL
, lpszDescription
, uBufLen
);
2753 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2757 StringCchCopyW(lpszDescription
, uBufLen
, info
.wszImeDescription
);
2759 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
2763 static DWORD APIENTRY
2764 ImmGetGuideLineAW(HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
, BOOL bAnsi
)
2766 PCLIENTIMC pClientImc
;
2768 LPGUIDELINE pGuideLine
;
2770 LPVOID pvStr
, pvPrivate
;
2773 pClientImc
= ImmLockClientImc(hIMC
);
2777 pIC
= ImmLockIMC(hIMC
);
2780 ImmUnlockClientImc(pClientImc
);
2784 pGuideLine
= ImmLockIMCC(pIC
->hGuideLine
);
2788 ImmUnlockClientImc(pClientImc
);
2792 if (dwIndex
== GGL_LEVEL
)
2794 ret
= pGuideLine
->dwLevel
;
2798 if (dwIndex
== GGL_INDEX
)
2800 ret
= pGuideLine
->dwIndex
;
2804 if (dwIndex
== GGL_STRING
)
2806 pvStr
= (LPBYTE
)pGuideLine
+ pGuideLine
->dwStrOffset
;
2811 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2813 cb
= WideCharToMultiByte(CP_ACP
, 0, pvStr
, pGuideLine
->dwStrLen
,
2814 NULL
, 0, NULL
, &bUsedDefault
);
2818 cb
= pGuideLine
->dwStrLen
* sizeof(CHAR
);
2823 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2825 cb
= pGuideLine
->dwStrLen
* sizeof(WCHAR
);
2829 cb
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, pvStr
, pGuideLine
->dwStrLen
,
2830 NULL
, 0) * sizeof(WCHAR
);
2834 if (dwBufLen
== 0 || cb
== 0 || lpBuf
== NULL
|| dwBufLen
< cb
)
2840 /* store to buffer */
2843 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2845 ret
= WideCharToMultiByte(CP_ACP
, 0, pvStr
, pGuideLine
->dwStrLen
,
2846 lpBuf
, dwBufLen
, NULL
, &bUsedDefault
);
2852 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
))
2854 ret
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, pvStr
, pGuideLine
->dwStrLen
,
2855 lpBuf
, dwBufLen
) * sizeof(WCHAR
);
2860 RtlCopyMemory(lpBuf
, pvStr
, cb
);
2865 if (dwIndex
== GGL_PRIVATE
)
2867 pvPrivate
= (LPBYTE
)pGuideLine
+ pGuideLine
->dwPrivateOffset
;
2872 if ((pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2873 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2875 cb
= CandidateListWideToAnsi(pvPrivate
, NULL
, 0, CP_ACP
);
2879 cb
= pGuideLine
->dwPrivateSize
;
2884 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2885 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2887 cb
= CandidateListAnsiToWide(pvPrivate
, NULL
, 0, CP_ACP
);
2891 cb
= pGuideLine
->dwPrivateSize
;
2895 if (dwBufLen
== 0 || cb
== 0 || lpBuf
== NULL
|| dwBufLen
< cb
)
2901 /* store to buffer */
2904 if ((pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2905 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2907 ret
= CandidateListWideToAnsi(pvPrivate
, lpBuf
, cb
, CP_ACP
);
2913 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2914 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2916 ret
= CandidateListAnsiToWide(pvPrivate
, lpBuf
, cb
, CP_ACP
);
2921 RtlCopyMemory(lpBuf
, pvPrivate
, cb
);
2927 ImmUnlockIMCC(pIC
->hGuideLine
);
2929 ImmUnlockClientImc(pClientImc
);
2933 /***********************************************************************
2934 * ImmGetGuideLineA (IMM32.@)
2936 DWORD WINAPI
ImmGetGuideLineA(
2937 HIMC hIMC
, DWORD dwIndex
, LPSTR lpBuf
, DWORD dwBufLen
)
2939 TRACE("(%p, %lu, %p, %lu)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2940 return ImmGetGuideLineAW(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
2943 /***********************************************************************
2944 * ImmGetGuideLineW (IMM32.@)
2946 DWORD WINAPI
ImmGetGuideLineW(HIMC hIMC
, DWORD dwIndex
, LPWSTR lpBuf
, DWORD dwBufLen
)
2948 TRACE("(%p, %lu, %p, %lu)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2949 return ImmGetGuideLineAW(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
2952 /***********************************************************************
2953 * ImmGetIMEFileNameA (IMM32.@)
2955 UINT WINAPI
ImmGetIMEFileNameA( HKL hKL
, LPSTR lpszFileName
, UINT uBufLen
)
2961 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
2963 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2966 lpszFileName
[0] = 0;
2970 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
2972 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeFile
, (INT
)cch
,
2973 lpszFileName
, uBufLen
, NULL
, &bDefUsed
);
2977 if (cch
> uBufLen
- 1)
2980 lpszFileName
[cch
] = 0;
2984 /***********************************************************************
2985 * ImmGetIMEFileNameW (IMM32.@)
2987 UINT WINAPI
ImmGetIMEFileNameW(HKL hKL
, LPWSTR lpszFileName
, UINT uBufLen
)
2992 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
2994 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2997 lpszFileName
[0] = 0;
3001 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
3005 StringCchCopyNW(lpszFileName
, uBufLen
, info
.wszImeFile
, cch
);
3007 if (cch
> uBufLen
- 1)
3010 lpszFileName
[cch
] = 0;
3014 /***********************************************************************
3015 * ImmGetOpenStatus (IMM32.@)
3017 BOOL WINAPI
ImmGetOpenStatus(HIMC hIMC
)
3022 TRACE("(%p)\n", hIMC
);
3027 pIC
= ImmLockIMC(hIMC
);
3037 /***********************************************************************
3038 * ImmGetProperty (IMM32.@)
3040 DWORD WINAPI
ImmGetProperty(HKL hKL
, DWORD fdwIndex
)
3042 IMEINFOEX ImeInfoEx
;
3045 PIMEDPI pImeDpi
= NULL
;
3047 TRACE("(%p, %lu)\n", hKL
, fdwIndex
);
3049 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
))
3052 if (fdwIndex
== IGP_GETIMEVERSION
)
3053 return ImeInfoEx
.dwImeWinVersion
;
3055 if (ImeInfoEx
.fLoadFlag
!= 2)
3057 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3058 if (pImeDpi
== NULL
)
3061 pImeInfo
= &pImeDpi
->ImeInfo
;
3065 pImeInfo
= &ImeInfoEx
.ImeInfo
;
3070 case IGP_PROPERTY
: dwValue
= pImeInfo
->fdwProperty
; break;
3071 case IGP_CONVERSION
: dwValue
= pImeInfo
->fdwConversionCaps
; break;
3072 case IGP_SENTENCE
: dwValue
= pImeInfo
->fdwSentenceCaps
; break;
3073 case IGP_UI
: dwValue
= pImeInfo
->fdwUICaps
; break;
3074 case IGP_SETCOMPSTR
: dwValue
= pImeInfo
->fdwSCSCaps
; break;
3075 case IGP_SELECT
: dwValue
= pImeInfo
->fdwSelectCaps
; break;
3076 default: dwValue
= 0; break;
3080 ImmUnlockImeDpi(pImeDpi
);
3084 /***********************************************************************
3085 * ImmGetRegisterWordStyleA (IMM32.@)
3087 UINT WINAPI
ImmGetRegisterWordStyleA(
3088 HKL hKL
, UINT nItem
, LPSTYLEBUFA lpStyleBuf
)
3090 UINT iItem
, ret
= 0;
3093 LPSTYLEBUFW pSrcW
, pNewStylesW
= NULL
;
3097 TRACE("(%p, %u, %p)\n", hKL
, nItem
, lpStyleBuf
);
3099 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3103 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
3105 ret
= pImeDpi
->ImeGetRegisterWordStyle(nItem
, lpStyleBuf
);
3111 pNewStylesW
= Imm32HeapAlloc(0, nItem
* sizeof(STYLEBUFW
));
3116 ret
= pImeDpi
->ImeGetRegisterWordStyle(nItem
, pNewStylesW
);
3120 /* lpStyleBuf <-- pNewStylesW */
3121 for (iItem
= 0; iItem
< ret
; ++iItem
)
3123 pSrcW
= &pNewStylesW
[iItem
];
3124 pDestA
= &lpStyleBuf
[iItem
];
3125 pDestA
->dwStyle
= pSrcW
->dwStyle
;
3126 StringCchLengthW(pSrcW
->szDescription
, _countof(pSrcW
->szDescription
), &cchW
);
3127 cchA
= WideCharToMultiByte(CP_ACP
, MB_PRECOMPOSED
,
3128 pSrcW
->szDescription
, (INT
)cchW
,
3129 pDestA
->szDescription
, _countof(pDestA
->szDescription
),
3131 if (cchA
> _countof(pDestA
->szDescription
) - 1)
3132 cchA
= _countof(pDestA
->szDescription
) - 1;
3133 pDestA
->szDescription
[cchA
] = 0;
3139 HeapFree(g_hImm32Heap
, 0, pNewStylesW
);
3140 ImmUnlockImeDpi(pImeDpi
);
3144 /***********************************************************************
3145 * ImmGetRegisterWordStyleW (IMM32.@)
3147 UINT WINAPI
ImmGetRegisterWordStyleW(
3148 HKL hKL
, UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
3150 UINT iItem
, ret
= 0;
3152 LPSTYLEBUFA pSrcA
, pNewStylesA
= NULL
;
3157 TRACE("(%p, %u, %p)\n", hKL
, nItem
, lpStyleBuf
);
3159 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3163 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
3165 ret
= pImeDpi
->ImeGetRegisterWordStyle(nItem
, lpStyleBuf
);
3171 pNewStylesA
= Imm32HeapAlloc(0, nItem
* sizeof(STYLEBUFA
));
3176 ret
= pImeDpi
->ImeGetRegisterWordStyle(nItem
, pNewStylesA
);
3180 /* lpStyleBuf <-- pNewStylesA */
3181 for (iItem
= 0; iItem
< ret
; ++iItem
)
3183 pSrcA
= &pNewStylesA
[iItem
];
3184 pDestW
= &lpStyleBuf
[iItem
];
3185 pDestW
->dwStyle
= pSrcA
->dwStyle
;
3186 StringCchLengthA(pSrcA
->szDescription
, _countof(pSrcA
->szDescription
), &cchA
);
3187 cchW
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
,
3188 pSrcA
->szDescription
, (INT
)cchA
,
3189 pDestW
->szDescription
, _countof(pDestW
->szDescription
));
3190 if (cchW
> _countof(pDestW
->szDescription
) - 1)
3191 cchW
= _countof(pDestW
->szDescription
) - 1;
3192 pDestW
->szDescription
[cchW
] = 0;
3198 HeapFree(g_hImm32Heap
, 0, pNewStylesA
);
3199 ImmUnlockImeDpi(pImeDpi
);
3203 /***********************************************************************
3204 * ImmGetStatusWindowPos (IMM32.@)
3206 BOOL WINAPI
ImmGetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
3211 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
3213 pIC
= ImmLockIMC(hIMC
);
3217 ret
= !!(pIC
->fdwInit
& INIT_STATUSWNDPOS
);
3219 *lpptPos
= pIC
->ptStatusWndPos
;
3225 /***********************************************************************
3226 * ImmGetVirtualKey (IMM32.@)
3228 UINT WINAPI
ImmGetVirtualKey(HWND hWnd
)
3231 LPINPUTCONTEXTDX pIC
;
3232 UINT ret
= VK_PROCESSKEY
;
3234 TRACE("(%p)\n", hWnd
);
3236 hIMC
= ImmGetContext(hWnd
);
3237 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3248 /***********************************************************************
3249 * ImmInstallIMEA (IMM32.@)
3251 HKL WINAPI
ImmInstallIMEA(
3252 LPCSTR lpszIMEFileName
, LPCSTR lpszLayoutText
)
3255 LPWSTR pszFileNameW
= NULL
, pszLayoutTextW
= NULL
;
3257 TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName
), debugstr_a(lpszLayoutText
));
3259 pszFileNameW
= Imm32WideFromAnsi(lpszIMEFileName
);
3260 if (pszFileNameW
== NULL
)
3263 pszLayoutTextW
= Imm32WideFromAnsi(lpszLayoutText
);
3264 if (pszLayoutTextW
== NULL
)
3267 hKL
= ImmInstallIMEW(pszFileNameW
, pszLayoutTextW
);
3271 HeapFree(g_hImm32Heap
, 0, pszFileNameW
);
3273 HeapFree(g_hImm32Heap
, 0, pszLayoutTextW
);
3277 /***********************************************************************
3278 * ImmInstallIMEW (IMM32.@)
3280 HKL WINAPI
ImmInstallIMEW(
3281 LPCWSTR lpszIMEFileName
, LPCWSTR lpszLayoutText
)
3283 INT lcid
= GetUserDefaultLCID();
3288 WCHAR regKey
[ARRAY_SIZE(szImeRegFmt
)+8];
3290 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName
),
3291 debugstr_w(lpszLayoutText
));
3293 /* Start with 2. e001 will be blank and so default to the wine internal IME */
3296 while (count
< 0xfff)
3298 DWORD disposition
= 0;
3300 hkl
= (HKL
)MAKELPARAM( lcid
, 0xe000 | count
);
3301 wsprintfW( regKey
, szImeRegFmt
, (ULONG_PTR
)hkl
);
3303 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, regKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hkey
, &disposition
);
3304 if (rc
== ERROR_SUCCESS
&& disposition
== REG_CREATED_NEW_KEY
)
3306 else if (rc
== ERROR_SUCCESS
)
3314 WARN("Unable to find slot to install IME\n");
3318 if (rc
== ERROR_SUCCESS
)
3320 rc
= RegSetValueExW(hkey
, szImeFileW
, 0, REG_SZ
, (const BYTE
*)lpszIMEFileName
,
3321 (lstrlenW(lpszIMEFileName
) + 1) * sizeof(WCHAR
));
3322 if (rc
== ERROR_SUCCESS
)
3323 rc
= RegSetValueExW(hkey
, szLayoutTextW
, 0, REG_SZ
, (const BYTE
*)lpszLayoutText
,
3324 (lstrlenW(lpszLayoutText
) + 1) * sizeof(WCHAR
));
3330 WARN("Unable to set IME registry values\n");
3335 /***********************************************************************
3336 * ImmIsIME (IMM32.@)
3338 BOOL WINAPI
ImmIsIME(HKL hKL
)
3341 TRACE("(%p)\n", hKL
);
3342 return !!ImmGetImeInfoEx(&info
, ImeInfoExImeWindow
, &hKL
);
3345 /***********************************************************************
3346 * ImmIsUIMessageA (IMM32.@)
3348 BOOL WINAPI
ImmIsUIMessageA(
3349 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
3351 TRACE("(%p, %x, %ld, %ld)\n", hWndIME
, msg
, wParam
, lParam
);
3352 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
3353 (msg
== WM_IME_SETCONTEXT
) ||
3354 (msg
== WM_IME_NOTIFY
) ||
3355 (msg
== WM_IME_COMPOSITIONFULL
) ||
3356 (msg
== WM_IME_SELECT
) ||
3357 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
3360 SendMessageA(hWndIME
, msg
, wParam
, lParam
);
3367 /***********************************************************************
3368 * ImmIsUIMessageW (IMM32.@)
3370 BOOL WINAPI
ImmIsUIMessageW(
3371 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
3373 TRACE("(%p, %x, %ld, %ld)\n", hWndIME
, msg
, wParam
, lParam
);
3374 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
3375 (msg
== WM_IME_SETCONTEXT
) ||
3376 (msg
== WM_IME_NOTIFY
) ||
3377 (msg
== WM_IME_COMPOSITIONFULL
) ||
3378 (msg
== WM_IME_SELECT
) ||
3379 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
3382 SendMessageW(hWndIME
, msg
, wParam
, lParam
);
3389 /***********************************************************************
3390 * ImmNotifyIME (IMM32.@)
3392 BOOL WINAPI
ImmNotifyIME(
3393 HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
3399 TRACE("(%p, %lu, %lu, %lu)\n", hIMC
, dwAction
, dwIndex
, dwValue
);
3401 if (hIMC
&& Imm32IsCrossThreadAccess(hIMC
))
3404 hKL
= GetKeyboardLayout(0);
3405 pImeDpi
= ImmLockImeDpi(hKL
);
3406 if (pImeDpi
== NULL
)
3409 ret
= pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
3410 ImmUnlockImeDpi(pImeDpi
);
3414 /***********************************************************************
3415 * ImmRegisterWordA (IMM32.@)
3417 BOOL WINAPI
ImmRegisterWordA(
3418 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszRegister
)
3422 LPWSTR pszReadingW
= NULL
, pszRegisterW
= NULL
;
3424 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
3425 debugstr_a(lpszRegister
));
3427 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3431 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
3433 ret
= pImeDpi
->ImeRegisterWord(lpszReading
, dwStyle
, lpszRegister
);
3434 ImmUnlockImeDpi(pImeDpi
);
3440 pszReadingW
= Imm32WideFromAnsi(lpszReading
);
3441 if (pszReadingW
== NULL
)
3447 pszRegisterW
= Imm32WideFromAnsi(lpszRegister
);
3448 if (pszRegisterW
== NULL
)
3452 ret
= pImeDpi
->ImeRegisterWord(pszReadingW
, dwStyle
, pszRegisterW
);
3456 HeapFree(g_hImm32Heap
, 0, pszReadingW
);
3458 HeapFree(g_hImm32Heap
, 0, pszRegisterW
);
3459 ImmUnlockImeDpi(pImeDpi
);
3463 /***********************************************************************
3464 * ImmRegisterWordW (IMM32.@)
3466 BOOL WINAPI
ImmRegisterWordW(
3467 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszRegister
)
3471 LPSTR pszReadingA
= NULL
, pszRegisterA
= NULL
;
3473 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
3474 debugstr_w(lpszRegister
));
3476 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3480 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
3482 ret
= pImeDpi
->ImeRegisterWord(lpszReading
, dwStyle
, lpszRegister
);
3483 ImmUnlockImeDpi(pImeDpi
);
3489 pszReadingA
= Imm32AnsiFromWide(lpszReading
);
3496 pszRegisterA
= Imm32AnsiFromWide(lpszRegister
);
3501 ret
= pImeDpi
->ImeRegisterWord(pszReadingA
, dwStyle
, pszRegisterA
);
3505 HeapFree(g_hImm32Heap
, 0, pszReadingA
);
3507 HeapFree(g_hImm32Heap
, 0, pszRegisterA
);
3508 ImmUnlockImeDpi(pImeDpi
);
3512 /***********************************************************************
3513 * ImmReleaseContext (IMM32.@)
3515 BOOL WINAPI
ImmReleaseContext(HWND hWnd
, HIMC hIMC
)
3517 static BOOL shown
= FALSE
;
3520 FIXME("(%p, %p): stub\n", hWnd
, hIMC
);
3526 /***********************************************************************
3527 * ImmRequestMessageA(IMM32.@)
3529 LRESULT WINAPI
ImmRequestMessageA(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
3531 InputContextData
*data
= get_imc_data(hIMC
);
3533 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
3535 if (data
) return SendMessageA(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
3537 SetLastError(ERROR_INVALID_HANDLE
);
3541 /***********************************************************************
3542 * ImmRequestMessageW(IMM32.@)
3544 LRESULT WINAPI
ImmRequestMessageW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
3546 InputContextData
*data
= get_imc_data(hIMC
);
3548 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
3550 if (data
) return SendMessageW(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
3552 SetLastError(ERROR_INVALID_HANDLE
);
3556 /***********************************************************************
3557 * ImmSetCandidateWindow (IMM32.@)
3559 BOOL WINAPI
ImmSetCandidateWindow(
3560 HIMC hIMC
, LPCANDIDATEFORM lpCandidate
)
3562 #define MAX_CANDIDATEFORM 4
3566 TRACE("(%p, %p)\n", hIMC
, lpCandidate
);
3568 if (lpCandidate
->dwIndex
>= MAX_CANDIDATEFORM
)
3571 if (Imm32IsCrossThreadAccess(hIMC
))
3574 pIC
= ImmLockIMC(hIMC
);
3579 pIC
->cfCandForm
[lpCandidate
->dwIndex
] = *lpCandidate
;
3583 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCANDIDATEPOS
,
3584 IMN_SETCANDIDATEPOS
, (1 << lpCandidate
->dwIndex
));
3586 #undef MAX_CANDIDATEFORM
3589 static VOID APIENTRY
WideToAnsiLogFont(const LOGFONTW
*plfW
, LPLOGFONTA plfA
)
3592 size_t cchW
, cchA
= _countof(plfA
->lfFaceName
);
3593 RtlCopyMemory(plfA
, plfW
, offsetof(LOGFONTA
, lfFaceName
));
3594 StringCchLengthW(plfW
->lfFaceName
, _countof(plfW
->lfFaceName
), &cchW
);
3595 cchA
= WideCharToMultiByte(CP_ACP
, 0, plfW
->lfFaceName
, (INT
)cchW
,
3596 plfA
->lfFaceName
, (INT
)cchA
, NULL
, &bUsedDef
);
3597 if (cchA
> _countof(plfA
->lfFaceName
) - 1)
3598 cchA
= _countof(plfA
->lfFaceName
) - 1;
3599 plfA
->lfFaceName
[cchA
] = 0;
3602 static VOID APIENTRY
AnsiToWideLogFont(const LOGFONTA
*plfA
, LPLOGFONTW plfW
)
3604 size_t cchA
, cchW
= _countof(plfW
->lfFaceName
);
3605 RtlCopyMemory(plfW
, plfA
, offsetof(LOGFONTW
, lfFaceName
));
3606 StringCchLengthA(plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), &cchA
);
3607 cchW
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, plfA
->lfFaceName
, (INT
)cchA
,
3608 plfW
->lfFaceName
, cchW
);
3609 if (cchW
> _countof(plfW
->lfFaceName
) - 1)
3610 cchW
= _countof(plfW
->lfFaceName
) - 1;
3611 plfW
->lfFaceName
[cchW
] = 0;
3614 /***********************************************************************
3615 * ImmSetCompositionFontA (IMM32.@)
3617 BOOL WINAPI
ImmSetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
3620 PCLIENTIMC pClientImc
;
3622 LPINPUTCONTEXTDX pIC
;
3627 TRACE("(%p, %p)\n", hIMC
, lplf
);
3629 if (Imm32IsCrossThreadAccess(hIMC
))
3632 pClientImc
= ImmLockClientImc(hIMC
);
3633 if (pClientImc
== NULL
)
3636 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
3637 ImmUnlockClientImc(pClientImc
);
3641 AnsiToWideLogFont(lplf
, &lfW
);
3642 return ImmSetCompositionFontW(hIMC
, &lfW
);
3645 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3649 pTeb
= NtCurrentTeb();
3650 if (pTeb
->Win32ClientInfo
[2] < 0x400)
3652 lcid
= GetSystemDefaultLCID();
3653 if (PRIMARYLANGID(lcid
) == LANG_JAPANESE
&& !(pIC
->dwUIFlags
& 2) &&
3654 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
3656 PostMessageA(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
3660 pIC
->lfFont
.A
= *lplf
;
3661 pIC
->fdwInit
|= INIT_LOGFONT
;
3666 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
3667 IMN_SETCOMPOSITIONFONT
, 0);
3671 /***********************************************************************
3672 * ImmSetCompositionFontW (IMM32.@)
3674 BOOL WINAPI
ImmSetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
3677 PCLIENTIMC pClientImc
;
3680 LPINPUTCONTEXTDX pIC
;
3684 TRACE("(%p, %p)\n", hIMC
, lplf
);
3686 if (Imm32IsCrossThreadAccess(hIMC
))
3689 pClientImc
= ImmLockClientImc(hIMC
);
3690 if (pClientImc
== NULL
)
3693 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
3694 ImmUnlockClientImc(pClientImc
);
3698 WideToAnsiLogFont(lplf
, &lfA
);
3699 return ImmSetCompositionFontA(hIMC
, &lfA
);
3702 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3706 pTeb
= NtCurrentTeb();
3707 if (pTeb
->Win32ClientInfo
[2] < 0x400)
3709 lcid
= GetSystemDefaultLCID();
3710 if (PRIMARYLANGID(lcid
) == LANG_JAPANESE
&&
3711 !(pIC
->dwUIFlags
& 2) &&
3712 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
3714 PostMessageW(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
3718 pIC
->lfFont
.W
= *lplf
;
3719 pIC
->fdwInit
|= INIT_LOGFONT
;
3724 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
3725 IMN_SETCOMPOSITIONFONT
, 0);
3729 /***********************************************************************
3730 * ImmSetCompositionStringA (IMM32.@)
3732 BOOL WINAPI
ImmSetCompositionStringA(
3733 HIMC hIMC
, DWORD dwIndex
,
3734 LPCVOID lpComp
, DWORD dwCompLen
,
3735 LPCVOID lpRead
, DWORD dwReadLen
)
3739 WCHAR
*CompBuffer
= NULL
;
3740 WCHAR
*ReadBuffer
= NULL
;
3742 InputContextData
*data
= get_imc_data(hIMC
);
3744 TRACE("(%p, %d, %p, %d, %p, %d):\n",
3745 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
3750 if (!(dwIndex
== SCS_SETSTR
||
3751 dwIndex
== SCS_CHANGEATTR
||
3752 dwIndex
== SCS_CHANGECLAUSE
||
3753 dwIndex
== SCS_SETRECONVERTSTRING
||
3754 dwIndex
== SCS_QUERYRECONVERTSTRING
))
3757 if (!is_himc_ime_unicode(data
))
3758 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
3759 dwCompLen
, lpRead
, dwReadLen
);
3761 comp_len
= MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0);
3764 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
* sizeof(WCHAR
));
3765 MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
);
3768 read_len
= MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0);
3771 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
* sizeof(WCHAR
));
3772 MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
);
3775 rc
= ImmSetCompositionStringW(hIMC
, dwIndex
, CompBuffer
, comp_len
,
3776 ReadBuffer
, read_len
);
3778 HeapFree(GetProcessHeap(), 0, CompBuffer
);
3779 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
3784 /***********************************************************************
3785 * ImmSetCompositionStringW (IMM32.@)
3787 BOOL WINAPI
ImmSetCompositionStringW(
3788 HIMC hIMC
, DWORD dwIndex
,
3789 LPCVOID lpComp
, DWORD dwCompLen
,
3790 LPCVOID lpRead
, DWORD dwReadLen
)
3794 CHAR
*CompBuffer
= NULL
;
3795 CHAR
*ReadBuffer
= NULL
;
3797 InputContextData
*data
= get_imc_data(hIMC
);
3799 TRACE("(%p, %d, %p, %d, %p, %d):\n",
3800 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
3805 if (!(dwIndex
== SCS_SETSTR
||
3806 dwIndex
== SCS_CHANGEATTR
||
3807 dwIndex
== SCS_CHANGECLAUSE
||
3808 dwIndex
== SCS_SETRECONVERTSTRING
||
3809 dwIndex
== SCS_QUERYRECONVERTSTRING
))
3812 if (is_himc_ime_unicode(data
))
3813 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
3814 dwCompLen
, lpRead
, dwReadLen
);
3816 comp_len
= WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0, NULL
,
3820 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
);
3821 WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
,
3825 read_len
= WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0, NULL
,
3829 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
);
3830 WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
,
3834 rc
= ImmSetCompositionStringA(hIMC
, dwIndex
, CompBuffer
, comp_len
,
3835 ReadBuffer
, read_len
);
3837 HeapFree(GetProcessHeap(), 0, CompBuffer
);
3838 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
3843 /***********************************************************************
3844 * ImmSetCompositionWindow (IMM32.@)
3846 BOOL WINAPI
ImmSetCompositionWindow(
3847 HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
3852 if (Imm32IsCrossThreadAccess(hIMC
))
3855 pIC
= ImmLockIMC(hIMC
);
3859 pIC
->cfCompForm
= *lpCompForm
;
3860 pIC
->fdwInit
|= INIT_COMPFORM
;
3866 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
3867 IMC_SETCOMPOSITIONWINDOW
, IMN_SETCOMPOSITIONWINDOW
, 0);
3871 /***********************************************************************
3872 * ImmSetConversionStatus (IMM32.@)
3874 BOOL WINAPI
ImmSetConversionStatus(
3875 HIMC hIMC
, DWORD fdwConversion
, DWORD fdwSentence
)
3879 DWORD dwOldConversion
, dwOldSentence
;
3880 BOOL fConversionChange
= FALSE
, fSentenceChange
= FALSE
;
3883 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC
, fdwConversion
, fdwSentence
);
3885 hKL
= GetKeyboardLayout(0);
3886 if (!IS_IME_HKL(hKL
))
3888 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
3895 if (Imm32IsCrossThreadAccess(hIMC
))
3898 pIC
= ImmLockIMC(hIMC
);
3902 if (pIC
->fdwConversion
!= fdwConversion
)
3904 dwOldConversion
= pIC
->fdwConversion
;
3905 pIC
->fdwConversion
= fdwConversion
;
3906 fConversionChange
= TRUE
;
3909 if (pIC
->fdwSentence
!= fdwSentence
)
3911 dwOldSentence
= pIC
->fdwSentence
;
3912 pIC
->fdwSentence
= fdwSentence
;
3913 fSentenceChange
= TRUE
;
3919 if (fConversionChange
)
3921 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldConversion
,
3922 IMC_SETCONVERSIONMODE
, IMN_SETCONVERSIONMODE
, 0);
3923 Imm32NotifyIMEStatus(hWnd
, hIMC
, fdwConversion
);
3926 if (fSentenceChange
)
3928 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldSentence
,
3929 IMC_SETSENTENCEMODE
, IMN_SETSENTENCEMODE
, 0);
3935 /***********************************************************************
3936 * ImmLockImeDpi (IMM32.@)
3938 PIMEDPI WINAPI
ImmLockImeDpi(HKL hKL
)
3940 PIMEDPI pImeDpi
= NULL
;
3942 TRACE("(%p)\n", hKL
);
3944 RtlEnterCriticalSection(&g_csImeDpi
);
3947 for (pImeDpi
= g_pImeDpiList
; pImeDpi
; pImeDpi
= pImeDpi
->pNext
)
3949 if (pImeDpi
->hKL
== hKL
) /* found */
3951 /* lock if possible */
3952 if (pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
)
3955 ++(pImeDpi
->cLockObj
);
3960 RtlLeaveCriticalSection(&g_csImeDpi
);
3964 /***********************************************************************
3965 * ImmUnlockImeDpi (IMM32.@)
3967 VOID WINAPI
ImmUnlockImeDpi(PIMEDPI pImeDpi
)
3971 TRACE("(%p)\n", pImeDpi
);
3973 if (pImeDpi
== NULL
)
3976 RtlEnterCriticalSection(&g_csImeDpi
);
3979 --(pImeDpi
->cLockObj
);
3980 if (pImeDpi
->cLockObj
!= 0)
3982 RtlLeaveCriticalSection(&g_csImeDpi
);
3986 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
) == 0)
3988 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_LOCKED
) == 0 ||
3989 (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_END_UNLOAD
) == 0)
3991 RtlLeaveCriticalSection(&g_csImeDpi
);
3996 /* Remove from list */
3997 for (ppEntry
= &g_pImeDpiList
; *ppEntry
; ppEntry
= &((*ppEntry
)->pNext
))
3999 if (*ppEntry
== pImeDpi
) /* found */
4001 *ppEntry
= pImeDpi
->pNext
;
4006 Imm32FreeImeDpi(pImeDpi
, TRUE
);
4007 HeapFree(g_hImm32Heap
, 0, pImeDpi
);
4009 RtlLeaveCriticalSection(&g_csImeDpi
);
4012 /***********************************************************************
4013 * ImmSetOpenStatus (IMM32.@)
4015 BOOL WINAPI
ImmSetOpenStatus(HIMC hIMC
, BOOL fOpen
)
4020 BOOL bHasChange
= FALSE
;
4022 TRACE("(%p, %d)\n", hIMC
, fOpen
);
4024 if (Imm32IsCrossThreadAccess(hIMC
))
4027 pIC
= ImmLockIMC(hIMC
);
4031 if (pIC
->fOpen
!= fOpen
)
4035 dwConversion
= pIC
->fdwConversion
;
4043 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
4044 IMC_SETOPENSTATUS
, IMN_SETOPENSTATUS
, 0);
4045 Imm32NotifyIMEStatus(hWnd
, hIMC
, dwConversion
);
4051 /***********************************************************************
4052 * ImmSetStatusWindowPos (IMM32.@)
4054 BOOL WINAPI
ImmSetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
4059 TRACE("(%p, {%ld, %ld})\n", hIMC
, lpptPos
->x
, lpptPos
->y
);
4061 if (Imm32IsCrossThreadAccess(hIMC
))
4064 pIC
= ImmLockIMC(hIMC
);
4069 pIC
->ptStatusWndPos
= *lpptPos
;
4070 pIC
->fdwInit
|= INIT_STATUSWNDPOS
;
4074 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
4075 IMC_SETSTATUSWINDOWPOS
, IMN_SETSTATUSWINDOWPOS
, 0);
4079 /***********************************************************************
4080 * ImmCreateSoftKeyboard(IMM32.@)
4082 HWND WINAPI
ImmCreateSoftKeyboard(UINT uType
, UINT hOwner
, int x
, int y
)
4084 FIXME("(%d, %d, %d, %d): stub\n", uType
, hOwner
, x
, y
);
4085 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4089 /***********************************************************************
4090 * ImmDestroySoftKeyboard(IMM32.@)
4092 BOOL WINAPI
ImmDestroySoftKeyboard(HWND hSoftWnd
)
4094 TRACE("(%p)\n", hSoftWnd
);
4095 return DestroyWindow(hSoftWnd
);
4098 /***********************************************************************
4099 * ImmShowSoftKeyboard(IMM32.@)
4101 BOOL WINAPI
ImmShowSoftKeyboard(HWND hSoftWnd
, int nCmdShow
)
4103 TRACE("(%p, %d)\n", hSoftWnd
, nCmdShow
);
4105 return ShowWindow(hSoftWnd
, nCmdShow
);
4109 /***********************************************************************
4110 * ImmSimulateHotKey (IMM32.@)
4112 BOOL WINAPI
ImmSimulateHotKey(HWND hWnd
, DWORD dwHotKeyID
)
4119 TRACE("(%p, 0x%lX)\n", hWnd
, dwHotKeyID
);
4121 hIMC
= ImmGetContext(hWnd
);
4122 dwThreadId
= GetWindowThreadProcessId(hWnd
, NULL
);
4123 hKL
= GetKeyboardLayout(dwThreadId
);
4124 ret
= Imm32ProcessHotKey(hWnd
, hIMC
, hKL
, dwHotKeyID
);
4125 ImmReleaseContext(hWnd
, hIMC
);
4129 /***********************************************************************
4130 * ImmUnregisterWordA (IMM32.@)
4132 BOOL WINAPI
ImmUnregisterWordA(
4133 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszUnregister
)
4137 LPWSTR pszReadingW
= NULL
, pszUnregisterW
= NULL
;
4139 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
4140 debugstr_a(lpszUnregister
));
4142 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
4143 if (pImeDpi
== NULL
)
4146 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
4148 ret
= pImeDpi
->ImeUnregisterWord(lpszReading
, dwStyle
, lpszUnregister
);
4149 ImmUnlockImeDpi(pImeDpi
);
4155 pszReadingW
= Imm32WideFromAnsi(lpszReading
);
4156 if (pszReadingW
== NULL
)
4162 pszUnregisterW
= Imm32WideFromAnsi(lpszUnregister
);
4163 if (pszUnregisterW
== NULL
)
4167 ret
= pImeDpi
->ImeUnregisterWord(pszReadingW
, dwStyle
, pszUnregisterW
);
4171 HeapFree(g_hImm32Heap
, 0, pszReadingW
);
4173 HeapFree(g_hImm32Heap
, 0, pszUnregisterW
);
4174 ImmUnlockImeDpi(pImeDpi
);
4178 /***********************************************************************
4179 * ImmUnregisterWordW (IMM32.@)
4181 BOOL WINAPI
ImmUnregisterWordW(
4182 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszUnregister
)
4186 LPSTR pszReadingA
= NULL
, pszUnregisterA
= NULL
;
4188 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
4189 debugstr_w(lpszUnregister
));
4191 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
4195 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
4197 ret
= pImeDpi
->ImeUnregisterWord(lpszReading
, dwStyle
, lpszUnregister
);
4198 ImmUnlockImeDpi(pImeDpi
);
4204 pszReadingA
= Imm32AnsiFromWide(lpszReading
);
4211 pszUnregisterA
= Imm32AnsiFromWide(lpszUnregister
);
4212 if (!pszUnregisterA
)
4216 ret
= pImeDpi
->ImeUnregisterWord(pszReadingA
, dwStyle
, pszUnregisterA
);
4220 HeapFree(g_hImm32Heap
, 0, pszReadingA
);
4222 HeapFree(g_hImm32Heap
, 0, pszUnregisterA
);
4223 ImmUnlockImeDpi(pImeDpi
);
4227 /***********************************************************************
4228 * ImmGetImeMenuItemsA (IMM32.@)
4230 DWORD WINAPI
ImmGetImeMenuItemsA( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
4231 LPIMEMENUITEMINFOA lpImeParentMenu
, LPIMEMENUITEMINFOA lpImeMenu
,
4234 InputContextData
*data
= get_imc_data(hIMC
);
4235 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
4236 lpImeParentMenu
, lpImeMenu
, dwSize
);
4240 SetLastError(ERROR_INVALID_HANDLE
);
4244 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
4246 if (!is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
4247 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4248 (IMEMENUITEMINFOW
*)lpImeParentMenu
,
4249 (IMEMENUITEMINFOW
*)lpImeMenu
, dwSize
);
4252 IMEMENUITEMINFOW lpImeParentMenuW
;
4253 IMEMENUITEMINFOW
*lpImeMenuW
, *parent
= NULL
;
4256 if (lpImeParentMenu
)
4257 parent
= &lpImeParentMenuW
;
4260 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOA
);
4261 dwSize
= count
* sizeof(IMEMENUITEMINFOW
);
4262 lpImeMenuW
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
4267 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4268 parent
, lpImeMenuW
, dwSize
);
4270 if (lpImeParentMenu
)
4272 memcpy(lpImeParentMenu
,&lpImeParentMenuW
,sizeof(IMEMENUITEMINFOA
));
4273 lpImeParentMenu
->hbmpItem
= lpImeParentMenuW
.hbmpItem
;
4274 WideCharToMultiByte(CP_ACP
, 0, lpImeParentMenuW
.szString
,
4275 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
,
4278 if (lpImeMenu
&& rc
)
4281 for (i
= 0; i
< rc
; i
++)
4283 memcpy(&lpImeMenu
[i
],&lpImeMenuW
[1],sizeof(IMEMENUITEMINFOA
));
4284 lpImeMenu
[i
].hbmpItem
= lpImeMenuW
[i
].hbmpItem
;
4285 WideCharToMultiByte(CP_ACP
, 0, lpImeMenuW
[i
].szString
,
4286 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
,
4290 HeapFree(GetProcessHeap(),0,lpImeMenuW
);
4298 /***********************************************************************
4299 * ImmGetImeMenuItemsW (IMM32.@)
4301 DWORD WINAPI
ImmGetImeMenuItemsW( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
4302 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
4305 InputContextData
*data
= get_imc_data(hIMC
);
4306 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
4307 lpImeParentMenu
, lpImeMenu
, dwSize
);
4311 SetLastError(ERROR_INVALID_HANDLE
);
4315 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
4317 if (is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
4318 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4319 lpImeParentMenu
, lpImeMenu
, dwSize
);
4322 IMEMENUITEMINFOA lpImeParentMenuA
;
4323 IMEMENUITEMINFOA
*lpImeMenuA
, *parent
= NULL
;
4326 if (lpImeParentMenu
)
4327 parent
= &lpImeParentMenuA
;
4330 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOW
);
4331 dwSize
= count
* sizeof(IMEMENUITEMINFOA
);
4332 lpImeMenuA
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
4337 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4338 (IMEMENUITEMINFOW
*)parent
,
4339 (IMEMENUITEMINFOW
*)lpImeMenuA
, dwSize
);
4341 if (lpImeParentMenu
)
4343 memcpy(lpImeParentMenu
,&lpImeParentMenuA
,sizeof(IMEMENUITEMINFOA
));
4344 lpImeParentMenu
->hbmpItem
= lpImeParentMenuA
.hbmpItem
;
4345 MultiByteToWideChar(CP_ACP
, 0, lpImeParentMenuA
.szString
,
4346 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
);
4348 if (lpImeMenu
&& rc
)
4351 for (i
= 0; i
< rc
; i
++)
4353 memcpy(&lpImeMenu
[i
],&lpImeMenuA
[1],sizeof(IMEMENUITEMINFOA
));
4354 lpImeMenu
[i
].hbmpItem
= lpImeMenuA
[i
].hbmpItem
;
4355 MultiByteToWideChar(CP_ACP
, 0, lpImeMenuA
[i
].szString
,
4356 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
);
4359 HeapFree(GetProcessHeap(),0,lpImeMenuA
);
4367 /***********************************************************************
4368 * ImmLockIMC(IMM32.@)
4370 LPINPUTCONTEXT WINAPI
ImmLockIMC(HIMC hIMC
)
4372 InputContextData
*data
= get_imc_data(hIMC
);
4380 /***********************************************************************
4381 * ImmUnlockIMC(IMM32.@)
4383 BOOL WINAPI
ImmUnlockIMC(HIMC hIMC
)
4385 PCLIENTIMC pClientImc
;
4388 pClientImc
= ImmLockClientImc(hIMC
);
4389 if (pClientImc
== NULL
)
4392 hClientImc
= pClientImc
->hImc
;
4394 LocalUnlock(hClientImc
);
4396 InterlockedDecrement(&pClientImc
->cLockObj
);
4397 ImmUnlockClientImc(pClientImc
);
4401 /***********************************************************************
4402 * ImmGetIMCLockCount(IMM32.@)
4404 DWORD WINAPI
ImmGetIMCLockCount(HIMC hIMC
)
4408 PCLIENTIMC pClientImc
;
4410 pClientImc
= ImmLockClientImc(hIMC
);
4411 if (pClientImc
== NULL
)
4415 hClientImc
= pClientImc
->hImc
;
4417 ret
= (LocalFlags(hClientImc
) & LMEM_LOCKCOUNT
);
4419 ImmUnlockClientImc(pClientImc
);
4423 /***********************************************************************
4424 * ImmCreateIMCC(IMM32.@)
4426 HIMCC WINAPI
ImmCreateIMCC(DWORD size
)
4430 return LocalAlloc(LHND
, size
);
4433 /***********************************************************************
4434 * ImmDestroyIMCC(IMM32.@)
4436 HIMCC WINAPI
ImmDestroyIMCC(HIMCC block
)
4439 return LocalFree(block
);
4443 /***********************************************************************
4444 * ImmLockIMCC(IMM32.@)
4446 LPVOID WINAPI
ImmLockIMCC(HIMCC imcc
)
4449 return LocalLock(imcc
);
4453 /***********************************************************************
4454 * ImmUnlockIMCC(IMM32.@)
4456 BOOL WINAPI
ImmUnlockIMCC(HIMCC imcc
)
4459 return LocalUnlock(imcc
);
4463 /***********************************************************************
4464 * ImmGetIMCCLockCount(IMM32.@)
4466 DWORD WINAPI
ImmGetIMCCLockCount(HIMCC imcc
)
4468 return LocalFlags(imcc
) & LMEM_LOCKCOUNT
;
4471 /***********************************************************************
4472 * ImmReSizeIMCC(IMM32.@)
4474 HIMCC WINAPI
ImmReSizeIMCC(HIMCC imcc
, DWORD size
)
4478 return LocalReAlloc(imcc
, size
, LHND
);
4481 /***********************************************************************
4482 * ImmGetIMCCSize(IMM32.@)
4484 DWORD WINAPI
ImmGetIMCCSize(HIMCC imcc
)
4487 return LocalSize(imcc
);
4491 /***********************************************************************
4492 * ImmGenerateMessage(IMM32.@)
4494 BOOL WINAPI
ImmGenerateMessage(HIMC hIMC
)
4496 InputContextData
*data
= get_imc_data(hIMC
);
4500 SetLastError(ERROR_INVALID_HANDLE
);
4504 TRACE("%i messages queued\n",data
->IMC
.dwNumMsgBuf
);
4505 if (data
->IMC
.dwNumMsgBuf
> 0)
4507 LPTRANSMSG lpTransMsg
;
4509 DWORD i
, dwNumMsgBuf
;
4511 /* We are going to detach our hMsgBuff so that if processing messages
4512 generates new messages they go into a new buffer */
4513 hMsgBuf
= data
->IMC
.hMsgBuf
;
4514 dwNumMsgBuf
= data
->IMC
.dwNumMsgBuf
;
4516 data
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
4517 data
->IMC
.dwNumMsgBuf
= 0;
4519 lpTransMsg
= ImmLockIMCC(hMsgBuf
);
4520 for (i
= 0; i
< dwNumMsgBuf
; i
++)
4521 ImmInternalSendIMEMessage(data
, lpTransMsg
[i
].message
, lpTransMsg
[i
].wParam
, lpTransMsg
[i
].lParam
);
4523 ImmUnlockIMCC(hMsgBuf
);
4524 ImmDestroyIMCC(hMsgBuf
);
4530 /***********************************************************************
4531 * ImmTranslateMessage(IMM32.@)
4532 * ( Undocumented, call internally and from user32.dll )
4534 BOOL WINAPI
ImmTranslateMessage(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lKeyData
)
4536 InputContextData
*data
;
4537 HIMC imc
= ImmGetContext(hwnd
);
4543 static const DWORD list_count
= 10;
4545 TRACE("%p %x %x %x\n",hwnd
, msg
, (UINT
)wParam
, (UINT
)lKeyData
);
4552 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeToAsciiEx
)
4555 GetKeyboardState(state
);
4556 scancode
= lKeyData
>> 0x10 & 0xff;
4558 list
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, list_count
* sizeof(TRANSMSG
) + sizeof(DWORD
));
4559 ((DWORD
*)list
)[0] = list_count
;
4561 if (data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_KBD_CHAR_FIRST
)
4565 if (!is_himc_ime_unicode(data
))
4566 ToAscii(data
->lastVK
, scancode
, state
, &chr
, 0);
4568 ToUnicodeEx(data
->lastVK
, scancode
, state
, &chr
, 1, 0, GetKeyboardLayout(0));
4569 uVirtKey
= MAKELONG(data
->lastVK
,chr
);
4572 uVirtKey
= data
->lastVK
;
4574 msg_count
= data
->immKbd
->pImeToAsciiEx(uVirtKey
, scancode
, state
, list
, 0, imc
);
4575 TRACE("%i messages generated\n",msg_count
);
4576 if (msg_count
&& msg_count
<= list_count
)
4579 LPTRANSMSG msgs
= (LPTRANSMSG
)((LPBYTE
)list
+ sizeof(DWORD
));
4581 for (i
= 0; i
< msg_count
; i
++)
4582 ImmInternalPostIMEMessage(data
, msgs
[i
].message
, msgs
[i
].wParam
, msgs
[i
].lParam
);
4584 else if (msg_count
> list_count
)
4585 ImmGenerateMessage(imc
);
4587 HeapFree(GetProcessHeap(),0,list
);
4589 data
->lastVK
= VK_PROCESSKEY
;
4591 return (msg_count
> 0);
4594 /***********************************************************************
4595 * ImmProcessKey(IMM32.@)
4596 * ( Undocumented, called from user32.dll )
4598 BOOL WINAPI
ImmProcessKey(HWND hwnd
, HKL hKL
, UINT vKey
, LPARAM lKeyData
, DWORD unknown
)
4600 InputContextData
*data
;
4601 HIMC imc
= ImmGetContext(hwnd
);
4604 TRACE("%p %p %x %x %x\n",hwnd
, hKL
, vKey
, (UINT
)lKeyData
, unknown
);
4611 /* Make sure we are inputting to the correct keyboard */
4612 if (data
->immKbd
->hkl
!= hKL
)
4614 ImmHkl
*new_hkl
= IMM_GetImmHkl(hKL
);
4617 data
->immKbd
->pImeSelect(imc
, FALSE
);
4618 data
->immKbd
->uSelected
--;
4619 data
->immKbd
= new_hkl
;
4620 data
->immKbd
->pImeSelect(imc
, TRUE
);
4621 data
->immKbd
->uSelected
++;
4627 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeProcessKey
)
4630 GetKeyboardState(state
);
4631 if (data
->immKbd
->pImeProcessKey(imc
, vKey
, lKeyData
, state
))
4633 data
->lastVK
= vKey
;
4637 data
->lastVK
= VK_PROCESSKEY
;
4641 /***********************************************************************
4642 * ImmDisableTextFrameService(IMM32.@)
4644 BOOL WINAPI
ImmDisableTextFrameService(DWORD dwThreadId
)
4650 /***********************************************************************
4651 * ImmEnumInputContext(IMM32.@)
4653 BOOL WINAPI
ImmEnumInputContext(DWORD dwThreadId
, IMCENUMPROC lpfn
, LPARAM lParam
)
4656 DWORD dwIndex
, dwCount
;
4660 TRACE("(%lu, %p, %p)\n", dwThreadId
, lpfn
, lParam
);
4662 dwCount
= Imm32AllocAndBuildHimcList(dwThreadId
, &phList
);
4666 for (dwIndex
= 0; dwIndex
< dwCount
; ++dwIndex
)
4668 hIMC
= phList
[dwIndex
];
4669 ret
= (*lpfn
)(hIMC
, lParam
);
4674 HeapFree(g_hImm32Heap
, 0, phList
);
4678 /***********************************************************************
4679 * ImmGetHotKey(IMM32.@)
4682 ImmGetHotKey(IN DWORD dwHotKey
,
4683 OUT LPUINT lpuModifiers
,
4687 TRACE("%lx, %p, %p, %p\n", dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
4688 if (lpuModifiers
&& lpuVKey
)
4689 return NtUserGetImeHotKey(dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
4693 /***********************************************************************
4694 * ImmDisableLegacyIME(IMM32.@)
4696 BOOL WINAPI
ImmDisableLegacyIME(void)
4702 /***********************************************************************
4703 * ImmSetActiveContext(IMM32.@)
4705 BOOL WINAPI
ImmSetActiveContext(HWND hwnd
, HIMC hIMC
, BOOL fFlag
)
4707 FIXME("(%p, %p, %d): stub\n", hwnd
, hIMC
, fFlag
);
4711 /***********************************************************************
4712 * ImmSetActiveContextConsoleIME(IMM32.@)
4714 BOOL WINAPI
ImmSetActiveContextConsoleIME(HWND hwnd
, BOOL fFlag
)
4717 TRACE("(%p, %d)\n", hwnd
, fFlag
);
4719 hIMC
= ImmGetContext(hwnd
);
4721 return ImmSetActiveContext(hwnd
, hIMC
, fFlag
);
4725 /***********************************************************************
4726 * ImmRegisterClient(IMM32.@)
4727 * ( Undocumented, called from user32.dll )
4729 BOOL WINAPI
ImmRegisterClient(PSHAREDINFO ptr
, HINSTANCE hMod
)
4731 g_SharedInfo
= *ptr
;
4732 g_psi
= g_SharedInfo
.psi
;
4733 return Imm32InitInstance(hMod
);
4736 /***********************************************************************
4737 * CtfImmIsTextFrameServiceDisabled(IMM32.@)
4739 BOOL WINAPI
CtfImmIsTextFrameServiceDisabled(VOID
)
4741 PTEB pTeb
= NtCurrentTeb();
4742 if (((PW32CLIENTINFO
)pTeb
->Win32ClientInfo
)->CI_flags
& CI_TFSDISABLED
)
4747 static BOOL APIENTRY
Imm32GetImeInfoEx(PIMEINFOEX pImeInfoEx
, IMEINFOEXCLASS SearchType
)
4749 return NtUserGetImeInfoEx(pImeInfoEx
, SearchType
);
4752 /***********************************************************************
4753 * ImmGetImeInfoEx (IMM32.@)
4756 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx
,
4757 IMEINFOEXCLASS SearchType
,
4760 BOOL bDisabled
= FALSE
;
4766 case ImeInfoExKeyboardLayout
:
4769 case ImeInfoExImeWindow
:
4770 bDisabled
= CtfImmIsTextFrameServiceDisabled();
4771 SearchType
= ImeInfoExKeyboardLayout
;
4774 case ImeInfoExImeFileName
:
4775 StringCchCopyW(pImeInfoEx
->wszImeFile
, _countof(pImeInfoEx
->wszImeFile
),
4780 hKL
= *(HKL
*)pvSearchKey
;
4781 pImeInfoEx
->hkl
= hKL
;
4783 if (!IS_IME_HKL(hKL
))
4785 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
4787 pTeb
= NtCurrentTeb();
4788 if (((PW32CLIENTINFO
)pTeb
->Win32ClientInfo
)->W32ClientInfo
[0] & 2)
4797 return Imm32GetImeInfoEx(pImeInfoEx
, SearchType
);
4800 BOOL WINAPI
User32InitializeImmEntryTable(DWORD
);
4802 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpReserved
)
4808 TRACE("(%p, 0x%X, %p)\n", hinstDLL
, fdwReason
, lpReserved
);
4812 case DLL_PROCESS_ATTACH
:
4813 //Imm32GenerateRandomSeed(hinstDLL, 1, lpReserved); // Non-sense
4814 if (!Imm32InitInstance(hinstDLL
))
4816 ERR("Imm32InitInstance failed\n");
4819 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC
))
4821 ERR("User32InitializeImmEntryTable failed\n");
4826 case DLL_THREAD_ATTACH
:
4829 case DLL_THREAD_DETACH
:
4830 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
4833 pTeb
= NtCurrentTeb();
4834 if (pTeb
->Win32ThreadInfo
== NULL
)
4837 hKL
= GetKeyboardLayout(0);
4838 hWnd
= (HWND
)Imm32GetThreadState(THREADSTATE_CAPTUREWINDOW
);
4839 Imm32CleanupContext(hWnd
, hKL
, TRUE
);
4842 case DLL_PROCESS_DETACH
:
4843 RtlDeleteCriticalSection(&g_csImeDpi
);