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 DWORD_PTR APIENTRY
Imm32QueryWindow(HWND hWnd
, DWORD Index
)
101 return NtUserQueryWindow(hWnd
, Index
);
104 static DWORD APIENTRY
105 Imm32UpdateInputContext(HIMC hIMC
, DWORD Unknown1
, PCLIENTIMC pClientImc
)
107 return NtUserUpdateInputContext(hIMC
, Unknown1
, pClientImc
);
110 static DWORD APIENTRY
Imm32QueryInputContext(HIMC hIMC
, DWORD dwUnknown2
)
112 return NtUserQueryInputContext(hIMC
, dwUnknown2
);
115 static DWORD APIENTRY
Imm32NotifyIMEStatus(HWND hwnd
, HIMC hIMC
, DWORD dwConversion
)
117 return NtUserNotifyIMEStatus(hwnd
, hIMC
, dwConversion
);
120 static HIMC APIENTRY
Imm32CreateInputContext(PCLIENTIMC pClientImc
)
122 return NtUserCreateInputContext(pClientImc
);
125 static BOOL APIENTRY
Imm32DestroyInputContext(HIMC hIMC
)
127 return NtUserDestroyInputContext(hIMC
);
130 DWORD_PTR APIENTRY
Imm32GetThreadState(DWORD Routine
)
132 return NtUserGetThreadState(Routine
);
135 static VOID APIENTRY
Imm32FreeImeDpi(PIMEDPI pImeDpi
, BOOL bDestroy
)
137 if (pImeDpi
->hInst
== NULL
)
140 pImeDpi
->ImeDestroy(0);
141 FreeLibrary(pImeDpi
->hInst
);
142 pImeDpi
->hInst
= NULL
;
146 Imm32NotifyAction(HIMC hIMC
, HWND hwnd
, DWORD dwAction
, DWORD_PTR dwIndex
, DWORD_PTR dwValue
,
147 DWORD_PTR dwCommand
, DWORD_PTR dwData
)
155 dwLayout
= Imm32QueryInputContext(hIMC
, 1);
158 /* find keyboard layout and lock it */
159 hKL
= GetKeyboardLayout(dwLayout
);
160 pImeDpi
= ImmLockImeDpi(hKL
);
164 pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
166 ImmUnlockImeDpi(pImeDpi
); /* unlock */
171 if (hwnd
&& dwCommand
)
172 SendMessageW(hwnd
, WM_IME_NOTIFY
, dwCommand
, dwData
);
177 static PIMEDPI APIENTRY
Imm32FindImeDpi(HKL hKL
)
181 RtlEnterCriticalSection(&g_csImeDpi
);
182 for (pImeDpi
= g_pImeDpiList
; pImeDpi
!= NULL
; pImeDpi
= pImeDpi
->pNext
)
184 if (pImeDpi
->hKL
== hKL
)
187 RtlLeaveCriticalSection(&g_csImeDpi
);
192 static BOOL
Imm32GetSystemLibraryPath(LPWSTR pszPath
, DWORD cchPath
, LPCWSTR pszFileName
)
194 if (!pszFileName
[0] || !GetSystemDirectoryW(pszPath
, cchPath
))
196 StringCchCatW(pszPath
, cchPath
, L
"\\");
197 StringCchCatW(pszPath
, cchPath
, pszFileName
);
201 DWORD APIENTRY
Imm32SetImeOwnerWindow(PIMEINFOEX pImeInfoEx
, BOOL fFlag
)
203 return NtUserSetImeOwnerWindow(pImeInfoEx
, fFlag
);
206 static BOOL APIENTRY
Imm32InquireIme(PIMEDPI pImeDpi
)
210 DWORD dwSysInfoFlags
= 0; // TODO: ???
211 LPIMEINFO pImeInfo
= &pImeDpi
->ImeInfo
;
213 // TODO: Imm32GetThreadState(THREADSTATE_UNKNOWN16);
215 if (!IS_IME_HKL(pImeDpi
->hKL
))
217 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
) &&
218 pImeDpi
->CtfImeInquireExW
)
225 if (!pImeDpi
->ImeInquire(pImeInfo
, szUIClass
, dwSysInfoFlags
))
228 szUIClass
[_countof(szUIClass
) - 1] = 0;
230 if (pImeInfo
->dwPrivateDataSize
== 0)
231 pImeInfo
->dwPrivateDataSize
= 4;
233 #define VALID_IME_PROP (IME_PROP_AT_CARET | \
234 IME_PROP_SPECIAL_UI | \
235 IME_PROP_CANDLIST_START_FROM_1 | \
237 IME_PROP_COMPLETE_ON_UNSELECT | \
238 IME_PROP_END_UNLOAD | \
239 IME_PROP_KBD_CHAR_FIRST | \
240 IME_PROP_IGNORE_UPKEYS | \
241 IME_PROP_NEED_ALTKEY | \
242 IME_PROP_NO_KEYS_ON_CLOSE | \
243 IME_PROP_ACCEPT_WIDE_VKEY)
244 #define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
246 IME_CMODE_KATAKANA | \
247 IME_CMODE_LANGUAGE | \
248 IME_CMODE_FULLSHAPE | \
250 IME_CMODE_CHARCODE | \
251 IME_CMODE_HANJACONVERT | \
252 IME_CMODE_SOFTKBD | \
253 IME_CMODE_NOCONVERSION | \
257 #define VALID_SMODE_CAPS (IME_SMODE_NONE | \
258 IME_SMODE_PLAURALCLAUSE | \
259 IME_SMODE_SINGLECONVERT | \
260 IME_SMODE_AUTOMATIC | \
261 IME_SMODE_PHRASEPREDICT | \
262 IME_SMODE_CONVERSATION)
263 #define VALID_UI_CAPS (UI_CAP_2700 | \
267 #define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \
269 SCS_CAP_SETRECONVERTSTRING)
270 #define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
272 if (pImeInfo
->fdwProperty
& ~VALID_IME_PROP
)
274 if (pImeInfo
->fdwConversionCaps
& ~VALID_CMODE_CAPS
)
276 if (pImeInfo
->fdwSentenceCaps
& ~VALID_SMODE_CAPS
)
278 if (pImeInfo
->fdwUICaps
& ~VALID_UI_CAPS
)
280 if (pImeInfo
->fdwSCSCaps
& ~VALID_SCS_CAPS
)
282 if (pImeInfo
->fdwSelectCaps
& ~VALID_SELECT_CAPS
)
285 #undef VALID_IME_PROP
286 #undef VALID_CMODE_CAPS
287 #undef VALID_SMODE_CAPS
289 #undef VALID_SCS_CAPS
290 #undef VALID_SELECT_CAPS
292 if (pImeInfo
->fdwProperty
& IME_PROP_UNICODE
)
294 StringCchCopyW(pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
), szUIClass
);
298 if (pImeDpi
->uCodePage
!= GetACP() && pImeDpi
->uCodePage
)
301 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, (LPSTR
)szUIClass
, -1,
302 pImeDpi
->szUIClass
, _countof(pImeDpi
->szUIClass
));
305 return GetClassInfoW(pImeDpi
->hInst
, pImeDpi
->szUIClass
, &wcW
);
308 static BOOL APIENTRY
Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx
, PIMEDPI pImeDpi
)
310 WCHAR szPath
[MAX_PATH
];
314 if (!Imm32GetSystemLibraryPath(szPath
, _countof(szPath
), pImeInfoEx
->wszImeFile
))
317 hIME
= GetModuleHandleW(szPath
);
320 hIME
= LoadLibraryW(szPath
);
323 ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath
);
327 pImeDpi
->hInst
= hIME
;
329 #define DEFINE_IME_ENTRY(type, name, params, extended) \
331 fn = GetProcAddress(hIME, #name); \
332 if (fn) pImeDpi->name = (FN_##name)fn; \
333 else if (!extended) goto Failed; \
335 #include "../../../win32ss/include/imetable.h"
336 #undef DEFINE_IME_ENTRY
338 if (!Imm32InquireIme(pImeDpi
))
340 ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
344 if (pImeInfoEx
->fLoadFlag
)
347 Imm32SetImeOwnerWindow(pImeInfoEx
, TRUE
);
351 FreeLibrary(pImeDpi
->hInst
);
352 pImeDpi
->hInst
= NULL
;
356 static PIMEDPI APIENTRY
Ime32LoadImeDpi(HKL hKL
, BOOL bLock
)
360 PIMEDPI pImeDpiNew
, pImeDpiFound
;
364 if (!ImmGetImeInfoEx(&ImeInfoEx
, ImeInfoExKeyboardLayout
, &hKL
) ||
365 ImeInfoEx
.fLoadFlag
== 1)
370 pImeDpiNew
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(IMEDPI
));
371 if (pImeDpiNew
== NULL
)
374 pImeDpiNew
->hKL
= hKL
;
377 if (TranslateCharsetInfo((LPDWORD
)(DWORD_PTR
)lcid
, &ci
, TCI_SRCLOCALE
))
378 uCodePage
= ci
.ciACP
;
381 pImeDpiNew
->uCodePage
= uCodePage
;
383 if (!Imm32LoadImeInfo(&ImeInfoEx
, pImeDpiNew
))
385 HeapFree(g_hImm32Heap
, 0, pImeDpiNew
);
389 RtlEnterCriticalSection(&g_csImeDpi
);
391 pImeDpiFound
= Imm32FindImeDpi(hKL
);
395 pImeDpiFound
->dwFlags
&= ~IMEDPI_FLAG_LOCKED
;
397 RtlLeaveCriticalSection(&g_csImeDpi
);
399 Imm32FreeImeDpi(pImeDpiNew
, FALSE
);
400 HeapFree(g_hImm32Heap
, 0, pImeDpiNew
);
407 pImeDpiNew
->dwFlags
|= IMEDPI_FLAG_LOCKED
;
408 pImeDpiNew
->cLockObj
= 1;
411 pImeDpiNew
->pNext
= g_pImeDpiList
;
412 g_pImeDpiList
= pImeDpiNew
;
414 RtlLeaveCriticalSection(&g_csImeDpi
);
419 BOOL WINAPI
ImmLoadIME(HKL hKL
)
421 PW32CLIENTINFO pInfo
;
424 if (!IS_IME_HKL(hKL
))
426 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
429 pInfo
= (PW32CLIENTINFO
)(NtCurrentTeb()->Win32ClientInfo
);
430 if ((pInfo
->W32ClientInfo
[0] & 2))
434 pImeDpi
= Imm32FindImeDpi(hKL
);
436 pImeDpi
= Ime32LoadImeDpi(hKL
, FALSE
);
437 return (pImeDpi
!= NULL
);
440 PIMEDPI APIENTRY
ImmLockOrLoadImeDpi(HKL hKL
)
442 PW32CLIENTINFO pInfo
;
445 if (!IS_IME_HKL(hKL
))
447 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
450 pInfo
= (PW32CLIENTINFO
)(NtCurrentTeb()->Win32ClientInfo
);
451 if ((pInfo
->W32ClientInfo
[0] & 2))
455 pImeDpi
= ImmLockImeDpi(hKL
);
457 pImeDpi
= Ime32LoadImeDpi(hKL
, TRUE
);
461 HKL WINAPI
ImmLoadLayout(HKL hKL
, PIMEINFOEX pImeInfoEx
)
464 UNICODE_STRING UnicodeString
;
465 HKEY hLayoutKey
= NULL
, hLayoutsKey
= NULL
;
468 WCHAR szLayout
[MAX_PATH
];
470 TRACE("(%p, %p)\n", hKL
, pImeInfoEx
);
472 if (IS_IME_HKL(hKL
) ||
473 !g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
) ||
474 ((PW32CLIENTINFO
)NtCurrentTeb()->Win32ClientInfo
)->W32ClientInfo
[0] & 2)
476 UnicodeString
.Buffer
= szLayout
;
477 UnicodeString
.MaximumLength
= sizeof(szLayout
);
478 Status
= RtlIntegerToUnicodeString((DWORD_PTR
)hKL
, 16, &UnicodeString
);
479 if (!NT_SUCCESS(Status
))
482 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_KEYBOARD_LAYOUTS
, &hLayoutsKey
);
486 error
= RegOpenKeyW(hLayoutsKey
, szLayout
, &hLayoutKey
);
490 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_IMM
, &hLayoutKey
);
495 ERR("RegOpenKeyW error: 0x%08lX\n", error
);
500 cbData
= sizeof(pImeInfoEx
->wszImeFile
);
501 error
= RegQueryValueExW(hLayoutKey
, L
"Ime File", 0, 0,
502 (LPBYTE
)pImeInfoEx
->wszImeFile
, &cbData
);
507 RegCloseKey(hLayoutKey
);
509 RegCloseKey(hLayoutsKey
);
513 typedef struct _tagImmHkl
{
518 WCHAR imeClassName
[17]; /* 16 character max */
522 /* Function Pointers */
523 BOOL (WINAPI
*pImeInquire
)(IMEINFO
*, WCHAR
*, const WCHAR
*);
524 BOOL (WINAPI
*pImeConfigure
)(HKL
, HWND
, DWORD
, void *);
525 BOOL (WINAPI
*pImeDestroy
)(UINT
);
526 LRESULT (WINAPI
*pImeEscape
)(HIMC
, UINT
, void *);
527 BOOL (WINAPI
*pImeSelect
)(HIMC
, BOOL
);
528 BOOL (WINAPI
*pImeSetActiveContext
)(HIMC
, BOOL
);
529 UINT (WINAPI
*pImeToAsciiEx
)(UINT
, UINT
, const BYTE
*, DWORD
*, UINT
, HIMC
);
530 BOOL (WINAPI
*pNotifyIME
)(HIMC
, DWORD
, DWORD
, DWORD
);
531 BOOL (WINAPI
*pImeRegisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
532 BOOL (WINAPI
*pImeUnregisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
533 UINT (WINAPI
*pImeEnumRegisterWord
)(REGISTERWORDENUMPROCW
, const WCHAR
*, DWORD
, const WCHAR
*, void *);
534 BOOL (WINAPI
*pImeSetCompositionString
)(HIMC
, DWORD
, const void *, DWORD
, const void *, DWORD
);
535 DWORD (WINAPI
*pImeConversionList
)(HIMC
, const WCHAR
*, CANDIDATELIST
*, DWORD
, UINT
);
536 BOOL (WINAPI
*pImeProcessKey
)(HIMC
, UINT
, LPARAM
, const BYTE
*);
537 UINT (WINAPI
*pImeGetRegisterWordStyle
)(UINT
, STYLEBUFW
*);
538 DWORD (WINAPI
*pImeGetImeMenuItems
)(HIMC
, DWORD
, DWORD
, IMEMENUITEMINFOW
*, IMEMENUITEMINFOW
*, DWORD
);
541 typedef struct tagInputContextData
553 #define WINE_IMC_VALID_MAGIC 0x56434D49
555 typedef struct _tagTRANSMSG
{
559 } TRANSMSG
, *LPTRANSMSG
;
561 typedef struct _tagIMMThreadData
{
570 static struct list ImmHklList
= LIST_INIT(ImmHklList
);
571 static struct list ImmThreadDataList
= LIST_INIT(ImmThreadDataList
);
573 static const WCHAR szwWineIMCProperty
[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
575 static const WCHAR szImeFileW
[] = {'I','m','e',' ','F','i','l','e',0};
576 static const WCHAR szLayoutTextW
[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
577 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};
579 static const WCHAR szwIME
[] = {'I','M','E',0};
580 static const WCHAR szwDefaultIME
[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
582 static CRITICAL_SECTION threaddata_cs
;
583 static CRITICAL_SECTION_DEBUG critsect_debug
=
585 0, 0, &threaddata_cs
,
586 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
587 0, 0, { (DWORD_PTR
)(__FILE__
": threaddata_cs") }
589 static CRITICAL_SECTION threaddata_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
590 static BOOL disable_ime
;
592 static inline BOOL
is_himc_ime_unicode(const InputContextData
*data
)
594 return !!(data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
597 static inline BOOL
is_kbd_ime_unicode(const ImmHkl
*hkl
)
599 return !!(hkl
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
602 static InputContextData
* get_imc_data(HIMC hIMC
);
604 static inline WCHAR
*strdupAtoW( const char *str
)
609 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
610 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
611 MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
616 static inline CHAR
*strdupWtoA( const WCHAR
*str
)
621 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
622 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
623 WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
628 static DWORD
convert_candidatelist_WtoA(
629 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
633 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
634 if ( lpDst
&& dwBufLen
> 0 )
637 lpDst
->dwOffset
[0] = ret
;
640 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
642 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
644 if ( lpDst
&& dwBufLen
> 0 )
646 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
648 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1,
649 (LPSTR
)dest
, dwBufLen
, NULL
, NULL
);
651 if ( i
+ 1 < lpSrc
->dwCount
)
652 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(char);
653 dwBufLen
-= len
* sizeof(char);
656 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1, NULL
, 0, NULL
, NULL
);
658 ret
+= len
* sizeof(char);
667 static DWORD
convert_candidatelist_AtoW(
668 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
672 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
673 if ( lpDst
&& dwBufLen
> 0 )
676 lpDst
->dwOffset
[0] = ret
;
679 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
681 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
683 if ( lpDst
&& dwBufLen
> 0 )
685 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
687 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1,
688 (LPWSTR
)dest
, dwBufLen
);
690 if ( i
+ 1 < lpSrc
->dwCount
)
691 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(WCHAR
);
692 dwBufLen
-= len
* sizeof(WCHAR
);
695 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1, NULL
, 0);
697 ret
+= len
* sizeof(WCHAR
);
706 static IMMThreadData
*IMM_GetThreadData(HWND hwnd
, DWORD thread
)
713 if (!(thread
= GetWindowThreadProcessId(hwnd
, &process
))) return NULL
;
714 if (process
!= GetCurrentProcessId()) return NULL
;
718 HANDLE h
= OpenThread(THREAD_QUERY_INFORMATION
, FALSE
, thread
);
720 process
= GetProcessIdOfThread(h
);
722 if (process
!= GetCurrentProcessId()) return NULL
;
725 thread
= GetCurrentThreadId();
727 EnterCriticalSection(&threaddata_cs
);
728 LIST_FOR_EACH_ENTRY(data
, &ImmThreadDataList
, IMMThreadData
, entry
)
729 if (data
->threadID
== thread
) return data
;
731 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
732 data
->threadID
= thread
;
733 list_add_head(&ImmThreadDataList
,&data
->entry
);
734 TRACE("Thread Data Created (%x)\n",thread
);
738 static HMODULE
load_graphics_driver(void)
740 static const WCHAR display_device_guid_propW
[] = {
741 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
742 'd','e','v','i','c','e','_','g','u','i','d',0 };
743 static const WCHAR key_pathW
[] = {
744 'S','y','s','t','e','m','\\',
745 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
746 'C','o','n','t','r','o','l','\\',
747 'V','i','d','e','o','\\','{',0};
748 static const WCHAR displayW
[] = {'}','\\','0','0','0','0',0};
749 static const WCHAR driverW
[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
754 WCHAR path
[MAX_PATH
];
755 WCHAR key
[ARRAY_SIZE( key_pathW
) + ARRAY_SIZE( displayW
) + 40];
756 UINT guid_atom
= HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW
));
758 if (!guid_atom
) return 0;
759 memcpy( key
, key_pathW
, sizeof(key_pathW
) );
760 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
761 lstrcatW( key
, displayW
);
762 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
764 if (!RegQueryValueExW( hkey
, driverW
, NULL
, NULL
, (BYTE
*)path
, &size
)) ret
= LoadLibraryW( path
);
766 TRACE( "%s %p\n", debugstr_w(path
), ret
);
770 /* ImmHkl loading and freeing */
771 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
772 static ImmHkl
*IMM_GetImmHkl(HKL hkl
)
775 WCHAR filename
[MAX_PATH
];
777 TRACE("Seeking ime for keyboard %p\n",hkl
);
779 LIST_FOR_EACH_ENTRY(ptr
, &ImmHklList
, ImmHkl
, entry
)
784 /* not found... create it */
786 ptr
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ImmHkl
));
789 if (ImmGetIMEFileNameW(hkl
, filename
, MAX_PATH
)) ptr
->hIME
= LoadLibraryW(filename
);
790 if (!ptr
->hIME
) ptr
->hIME
= load_graphics_driver();
793 LOAD_FUNCPTR(ImeInquire
);
794 if (!ptr
->pImeInquire
|| !ptr
->pImeInquire(&ptr
->imeInfo
, ptr
->imeClassName
, NULL
))
796 FreeLibrary(ptr
->hIME
);
801 LOAD_FUNCPTR(ImeDestroy
);
802 LOAD_FUNCPTR(ImeSelect
);
803 if (!ptr
->pImeSelect
|| !ptr
->pImeDestroy
)
805 FreeLibrary(ptr
->hIME
);
810 LOAD_FUNCPTR(ImeConfigure
);
811 LOAD_FUNCPTR(ImeEscape
);
812 LOAD_FUNCPTR(ImeSetActiveContext
);
813 LOAD_FUNCPTR(ImeToAsciiEx
);
814 LOAD_FUNCPTR(NotifyIME
);
815 LOAD_FUNCPTR(ImeRegisterWord
);
816 LOAD_FUNCPTR(ImeUnregisterWord
);
817 LOAD_FUNCPTR(ImeEnumRegisterWord
);
818 LOAD_FUNCPTR(ImeSetCompositionString
);
819 LOAD_FUNCPTR(ImeConversionList
);
820 LOAD_FUNCPTR(ImeProcessKey
);
821 LOAD_FUNCPTR(ImeGetRegisterWordStyle
);
822 LOAD_FUNCPTR(ImeGetImeMenuItems
);
823 /* make sure our classname is WCHAR */
824 if (!is_kbd_ime_unicode(ptr
))
827 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ptr
->imeClassName
,
829 lstrcpyW(ptr
->imeClassName
, bufW
);
834 list_add_head(&ImmHklList
,&ptr
->entry
);
840 HWND WINAPI
__wine_get_ui_window(HKL hkl
)
842 ImmHkl
*immHkl
= IMM_GetImmHkl(hkl
);
843 return immHkl
->UIWnd
;
846 /* for posting messages as the IME */
847 static void ImmInternalPostIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
849 HWND target
= GetFocus();
851 PostMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
853 PostMessageW(target
, msg
, wParam
, lParam
);
856 /* for sending messages as the IME */
857 static void ImmInternalSendIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
859 HWND target
= GetFocus();
861 SendMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
863 SendMessageW(target
, msg
, wParam
, lParam
);
866 static InputContextData
* get_imc_data(HIMC hIMC
)
868 InputContextData
*data
= hIMC
;
873 if(IsBadReadPtr(data
, sizeof(InputContextData
)) || data
->magic
!= WINE_IMC_VALID_MAGIC
)
875 SetLastError(ERROR_INVALID_HANDLE
);
881 static HIMC
get_default_context( HWND hwnd
)
883 FIXME("Don't use this function\n");
887 static BOOL
IMM_IsCrossThreadAccess(HWND hWnd
, HIMC hIMC
)
889 InputContextData
*data
;
893 DWORD thread
= GetWindowThreadProcessId(hWnd
, NULL
);
894 if (thread
!= GetCurrentThreadId()) return TRUE
;
896 data
= get_imc_data(hIMC
);
897 if (data
&& data
->threadID
!= GetCurrentThreadId())
903 /***********************************************************************
904 * ImmAssociateContext (IMM32.@)
906 HIMC WINAPI
ImmAssociateContext(HWND hWnd
, HIMC hIMC
)
909 InputContextData
*data
= get_imc_data(hIMC
);
911 TRACE("(%p, %p):\n", hWnd
, hIMC
);
917 * If already associated just return
919 if (hIMC
&& data
->IMC
.hWnd
== hWnd
)
922 if (hIMC
&& IMM_IsCrossThreadAccess(hWnd
, hIMC
))
927 HIMC defaultContext
= get_default_context( hWnd
);
928 old
= RemovePropW(hWnd
,szwWineIMCProperty
);
931 old
= defaultContext
;
932 else if (old
== (HIMC
)-1)
935 if (hIMC
!= defaultContext
)
937 if (hIMC
== NULL
) /* Meaning disable imm for that window*/
938 SetPropW(hWnd
,szwWineIMCProperty
,(HANDLE
)-1);
940 SetPropW(hWnd
,szwWineIMCProperty
,hIMC
);
945 InputContextData
*old_data
= old
;
946 if (old_data
->IMC
.hWnd
== hWnd
)
947 old_data
->IMC
.hWnd
= NULL
;
954 if(GetActiveWindow() == data
->IMC
.hWnd
)
956 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, FALSE
, ISC_SHOWUIALL
);
957 data
->IMC
.hWnd
= hWnd
;
958 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, TRUE
, ISC_SHOWUIALL
);
966 * Helper function for ImmAssociateContextEx
968 static BOOL CALLBACK
_ImmAssociateContextExEnumProc(HWND hwnd
, LPARAM lParam
)
970 HIMC hImc
= (HIMC
)lParam
;
971 ImmAssociateContext(hwnd
,hImc
);
975 /***********************************************************************
976 * ImmAssociateContextEx (IMM32.@)
978 BOOL WINAPI
ImmAssociateContextEx(HWND hWnd
, HIMC hIMC
, DWORD dwFlags
)
980 TRACE("(%p, %p, 0x%x):\n", hWnd
, hIMC
, dwFlags
);
988 ImmAssociateContext(hWnd
,hIMC
);
992 HIMC defaultContext
= get_default_context( hWnd
);
993 if (!defaultContext
) return FALSE
;
994 ImmAssociateContext(hWnd
,defaultContext
);
997 case IACE_IGNORENOCONTEXT
:
998 if (GetPropW(hWnd
,szwWineIMCProperty
))
999 ImmAssociateContext(hWnd
,hIMC
);
1002 EnumChildWindows(hWnd
,_ImmAssociateContextExEnumProc
,(LPARAM
)hIMC
);
1005 FIXME("Unknown dwFlags 0x%x\n",dwFlags
);
1010 /***********************************************************************
1011 * ImmConfigureIMEA (IMM32.@)
1013 BOOL WINAPI
ImmConfigureIMEA(
1014 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
1016 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1018 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
1020 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
1023 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
1025 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| !is_kbd_ime_unicode(immHkl
))
1026 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
1030 REGISTERWORDA
*rwa
= lpData
;
1033 rww
.lpReading
= strdupAtoW(rwa
->lpReading
);
1034 rww
.lpWord
= strdupAtoW(rwa
->lpWord
);
1035 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rww
);
1036 HeapFree(GetProcessHeap(),0,rww
.lpReading
);
1037 HeapFree(GetProcessHeap(),0,rww
.lpWord
);
1045 /***********************************************************************
1046 * ImmConfigureIMEW (IMM32.@)
1048 BOOL WINAPI
ImmConfigureIMEW(
1049 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
1051 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1053 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
1055 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
1058 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
1060 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| is_kbd_ime_unicode(immHkl
))
1061 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
1064 REGISTERWORDW
*rww
= lpData
;
1068 rwa
.lpReading
= strdupWtoA(rww
->lpReading
);
1069 rwa
.lpWord
= strdupWtoA(rww
->lpWord
);
1070 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rwa
);
1071 HeapFree(GetProcessHeap(),0,rwa
.lpReading
);
1072 HeapFree(GetProcessHeap(),0,rwa
.lpWord
);
1080 /***********************************************************************
1081 * ImmCreateContext (IMM32.@)
1083 HIMC WINAPI
ImmCreateContext(void)
1085 PCLIENTIMC pClientImc
;
1090 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
1093 pClientImc
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
1094 if (pClientImc
== NULL
)
1097 hIMC
= Imm32CreateInputContext(pClientImc
);
1100 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1104 RtlInitializeCriticalSection(&pClientImc
->cs
);
1105 pClientImc
->unknown
= Imm32GetThreadState(THREADSTATE_UNKNOWN13
);
1109 static VOID APIENTRY
Imm32CleanupContextExtra(LPINPUTCONTEXT pIC
)
1111 FIXME("We have to do something do here");
1114 static PCLIENTIMC APIENTRY
Imm32FindClientImc(HIMC hIMC
)
1120 BOOL APIENTRY
Imm32CleanupContext(HIMC hIMC
, HKL hKL
, BOOL bKeep
)
1124 PCLIENTIMC pClientImc
;
1126 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
) || hIMC
== NULL
)
1129 FIXME("We have do something to do here\n");
1130 pClientImc
= Imm32FindClientImc(hIMC
);
1134 if (pClientImc
->hImc
== NULL
)
1136 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN1
;
1137 ImmUnlockClientImc(pClientImc
);
1139 return Imm32DestroyInputContext(hIMC
);
1143 pIC
= ImmLockIMC(hIMC
);
1146 ImmUnlockClientImc(pClientImc
);
1150 FIXME("We have do something to do here\n");
1152 if (pClientImc
->hKL
== hKL
)
1154 pImeDpi
= ImmLockImeDpi(hKL
);
1155 if (pImeDpi
!= NULL
)
1157 if (IS_IME_HKL(hKL
))
1159 pImeDpi
->ImeSelect(hIMC
, FALSE
);
1161 else if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
1163 FIXME("We have do something to do here\n");
1165 ImmUnlockImeDpi(pImeDpi
);
1167 pClientImc
->hKL
= NULL
;
1170 ImmDestroyIMCC(pIC
->hPrivate
);
1171 ImmDestroyIMCC(pIC
->hMsgBuf
);
1172 ImmDestroyIMCC(pIC
->hGuideLine
);
1173 ImmDestroyIMCC(pIC
->hCandInfo
);
1174 ImmDestroyIMCC(pIC
->hCompStr
);
1176 Imm32CleanupContextExtra(pIC
);
1180 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN1
;
1181 ImmUnlockClientImc(pClientImc
);
1184 return Imm32DestroyInputContext(hIMC
);
1189 /***********************************************************************
1190 * ImmDestroyContext (IMM32.@)
1192 BOOL WINAPI
ImmDestroyContext(HIMC hIMC
)
1194 DWORD dwImeThreadId
, dwThreadId
;
1197 TRACE("(%p)\n", hIMC
);
1199 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
1202 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
1203 dwThreadId
= GetCurrentThreadId();
1204 if (dwImeThreadId
!= dwThreadId
)
1207 hKL
= GetKeyboardLayout(0);
1208 return Imm32CleanupContext(hIMC
, hKL
, FALSE
);
1211 /***********************************************************************
1212 * ImmDisableIME (IMM32.@)
1214 BOOL WINAPI
ImmDisableIME(DWORD dwThreadId
)
1216 return NtUserDisableThreadIme(dwThreadId
);
1219 /***********************************************************************
1220 * ImmEnumRegisterWordA (IMM32.@)
1222 UINT WINAPI
ImmEnumRegisterWordA(
1223 HKL hKL
, REGISTERWORDENUMPROCA lpfnEnumProc
,
1224 LPCSTR lpszReading
, DWORD dwStyle
,
1225 LPCSTR lpszRegister
, LPVOID lpData
)
1227 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1228 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL
, lpfnEnumProc
,
1229 debugstr_a(lpszReading
), dwStyle
, debugstr_a(lpszRegister
), lpData
);
1230 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
1232 if (!is_kbd_ime_unicode(immHkl
))
1233 return immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
1234 (LPCWSTR
)lpszReading
, dwStyle
, (LPCWSTR
)lpszRegister
, lpData
);
1237 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
1238 LPWSTR lpszwRegister
= strdupAtoW(lpszRegister
);
1241 rc
= immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
1242 lpszwReading
, dwStyle
, lpszwRegister
,
1245 HeapFree(GetProcessHeap(),0,lpszwReading
);
1246 HeapFree(GetProcessHeap(),0,lpszwRegister
);
1254 /***********************************************************************
1255 * ImmEnumRegisterWordW (IMM32.@)
1257 UINT WINAPI
ImmEnumRegisterWordW(
1258 HKL hKL
, REGISTERWORDENUMPROCW lpfnEnumProc
,
1259 LPCWSTR lpszReading
, DWORD dwStyle
,
1260 LPCWSTR lpszRegister
, LPVOID lpData
)
1262 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1263 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL
, lpfnEnumProc
,
1264 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
), lpData
);
1265 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
1267 if (is_kbd_ime_unicode(immHkl
))
1268 return immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, lpszReading
, dwStyle
,
1269 lpszRegister
, lpData
);
1272 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
1273 LPSTR lpszaRegister
= strdupWtoA(lpszRegister
);
1276 rc
= immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, (LPCWSTR
)lpszaReading
,
1277 dwStyle
, (LPCWSTR
)lpszaRegister
, lpData
);
1279 HeapFree(GetProcessHeap(),0,lpszaReading
);
1280 HeapFree(GetProcessHeap(),0,lpszaRegister
);
1288 static inline BOOL
EscapeRequiresWA(UINT uEscape
)
1290 if (uEscape
== IME_ESC_GET_EUDC_DICTIONARY
||
1291 uEscape
== IME_ESC_SET_EUDC_DICTIONARY
||
1292 uEscape
== IME_ESC_IME_NAME
||
1293 uEscape
== IME_ESC_GETHELPFILENAME
)
1298 /***********************************************************************
1299 * ImmEscapeA (IMM32.@)
1301 LRESULT WINAPI
ImmEscapeA(
1303 UINT uEscape
, LPVOID lpData
)
1305 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1306 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1308 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1310 if (!EscapeRequiresWA(uEscape
) || !is_kbd_ime_unicode(immHkl
))
1311 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1314 WCHAR buffer
[81]; /* largest required buffer should be 80 */
1316 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1318 MultiByteToWideChar(CP_ACP
,0,lpData
,-1,buffer
,81);
1319 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1323 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1324 WideCharToMultiByte(CP_ACP
,0,buffer
,-1,lpData
,80, NULL
, NULL
);
1333 /***********************************************************************
1334 * ImmEscapeW (IMM32.@)
1336 LRESULT WINAPI
ImmEscapeW(
1338 UINT uEscape
, LPVOID lpData
)
1340 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1341 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1343 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1345 if (!EscapeRequiresWA(uEscape
) || is_kbd_ime_unicode(immHkl
))
1346 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1349 CHAR buffer
[81]; /* largest required buffer should be 80 */
1351 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1353 WideCharToMultiByte(CP_ACP
,0,lpData
,-1,buffer
,81, NULL
, NULL
);
1354 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1358 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1359 MultiByteToWideChar(CP_ACP
,0,buffer
,-1,lpData
,80);
1368 static PCLIENTIMC APIENTRY
Imm32GetClientImcCache(void)
1370 // FIXME: Do something properly here
1374 static NTSTATUS APIENTRY
1375 Imm32BuildHimcList(DWORD dwThreadId
, DWORD dwCount
, HIMC
*phList
, LPDWORD pdwCount
)
1377 return NtUserBuildHimcList(dwThreadId
, dwCount
, phList
, pdwCount
);
1380 static DWORD APIENTRY
Imm32AllocAndBuildHimcList(DWORD dwThreadId
, HIMC
**pphList
)
1382 #define INITIAL_COUNT 0x40
1383 #define MAX_RETRY 10
1385 DWORD dwCount
= INITIAL_COUNT
, cRetry
= 0;
1388 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
1389 if (phNewList
== NULL
)
1392 Status
= Imm32BuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
1393 while (Status
== STATUS_BUFFER_TOO_SMALL
)
1395 HeapFree(g_hImm32Heap
, 0, phNewList
);
1396 if (cRetry
++ >= MAX_RETRY
)
1399 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
1400 if (phNewList
== NULL
)
1403 Status
= Imm32BuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
1406 if (NT_ERROR(Status
) || !dwCount
)
1408 HeapFree(g_hImm32Heap
, 0, phNewList
);
1412 *pphList
= phNewList
;
1414 #undef INITIAL_COUNT
1418 static BOOL APIENTRY
Imm32ImeNonImeToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
, LANGID LangID
)
1426 if (!IS_IME_HKL(hKL
) || LOWORD(hKL
) != LangID
)
1428 FIXME("We have to do something here\n");
1432 pIC
= ImmLockIMC(hIMC
);
1441 ImmSetOpenStatus(hIMC
, TRUE
);
1445 FIXME("We have to do something here\n");
1449 static BOOL APIENTRY
Imm32CShapeToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1453 DWORD dwConversion
, dwSentence
;
1455 if (hWnd
== NULL
|| !IS_IME_HKL(hKL
))
1458 pIC
= ImmLockIMC(hIMC
);
1465 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_FULLSHAPE
);
1466 dwSentence
= pIC
->fdwSentence
;
1472 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1474 ImmSetOpenStatus(hIMC
, TRUE
);
1479 static BOOL APIENTRY
Imm32CSymbolToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1483 DWORD dwConversion
, dwSentence
;
1485 if (hWnd
== NULL
|| !IS_IME_HKL(hKL
))
1488 pIC
= ImmLockIMC(hIMC
);
1495 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_SYMBOL
);
1496 dwSentence
= pIC
->fdwSentence
;
1502 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1504 ImmSetOpenStatus(hIMC
, TRUE
);
1509 static BOOL APIENTRY
Imm32JCloseOpen(HIMC hIMC
, HKL hKL
, HWND hWnd
)
1513 if (ImmIsIME(hKL
) && LOWORD(hKL
) == LANGID_JAPANESE
)
1515 fOpen
= ImmGetOpenStatus(hIMC
);
1516 ImmSetOpenStatus(hIMC
, !fOpen
);
1520 FIXME("We have to do something here\n");
1524 static BOOL APIENTRY
Imm32KShapeToggle(HIMC hIMC
)
1527 DWORD dwConversion
, dwSentence
;
1529 pIC
= ImmLockIMC(hIMC
);
1533 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_FULLSHAPE
);
1534 dwSentence
= pIC
->fdwSentence
;
1535 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1537 if (pIC
->fdwConversion
& (IME_CMODE_FULLSHAPE
| IME_CMODE_NATIVE
))
1538 ImmSetOpenStatus(hIMC
, TRUE
);
1540 ImmSetOpenStatus(hIMC
, FALSE
);
1546 static BOOL APIENTRY
Imm32KHanjaConvert(HIMC hIMC
)
1549 DWORD dwConversion
, dwSentence
;
1551 pIC
= ImmLockIMC(hIMC
);
1555 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_HANJACONVERT
);
1556 dwSentence
= pIC
->fdwSentence
;
1559 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1563 static BOOL APIENTRY
Imm32KEnglish(HIMC hIMC
)
1566 DWORD dwConversion
, dwSentence
;
1569 pIC
= ImmLockIMC(hIMC
);
1573 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_NATIVE
);
1574 dwSentence
= pIC
->fdwSentence
;
1575 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
1577 fOpen
= ((pIC
->fdwConversion
& (IME_CMODE_FULLSHAPE
| IME_CMODE_NATIVE
)) != 0);
1578 ImmSetOpenStatus(hIMC
, fOpen
);
1584 static BOOL APIENTRY
Imm32ProcessHotKey(HWND hWnd
, HIMC hIMC
, HKL hKL
, DWORD dwHotKeyID
)
1586 DWORD dwImeThreadId
, dwThreadId
;
1592 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
1593 dwThreadId
= GetCurrentThreadId();
1594 if (dwImeThreadId
!= dwThreadId
)
1600 case IME_CHOTKEY_IME_NONIME_TOGGLE
:
1601 return Imm32ImeNonImeToggle(hIMC
, hKL
, hWnd
, LANGID_CHINESE_SIMPLIFIED
);
1603 case IME_CHOTKEY_SHAPE_TOGGLE
:
1604 return Imm32CShapeToggle(hIMC
, hKL
, hWnd
);
1606 case IME_CHOTKEY_SYMBOL_TOGGLE
:
1607 return Imm32CSymbolToggle(hIMC
, hKL
, hWnd
);
1609 case IME_JHOTKEY_CLOSE_OPEN
:
1610 return Imm32JCloseOpen(hIMC
, hKL
, hWnd
);
1612 case IME_KHOTKEY_SHAPE_TOGGLE
:
1613 return Imm32KShapeToggle(hIMC
);
1615 case IME_KHOTKEY_HANJACONVERT
:
1616 return Imm32KHanjaConvert(hIMC
);
1618 case IME_KHOTKEY_ENGLISH
:
1619 return Imm32KEnglish(hIMC
);
1621 case IME_THOTKEY_IME_NONIME_TOGGLE
:
1622 return Imm32ImeNonImeToggle(hIMC
, hKL
, hWnd
, LANGID_CHINESE_TRADITIONAL
);
1624 case IME_THOTKEY_SHAPE_TOGGLE
:
1625 return Imm32CShapeToggle(hIMC
, hKL
, hWnd
);
1627 case IME_THOTKEY_SYMBOL_TOGGLE
:
1628 return Imm32CSymbolToggle(hIMC
, hKL
, hWnd
);
1634 if (dwHotKeyID
< IME_HOTKEY_PRIVATE_FIRST
|| IME_HOTKEY_PRIVATE_LAST
< dwHotKeyID
)
1637 pImeDpi
= ImmLockImeDpi(hKL
);
1638 if (pImeDpi
== NULL
)
1641 ret
= (BOOL
)pImeDpi
->ImeEscape(hIMC
, IME_ESC_PRIVATE_HOTKEY
, &dwHotKeyID
);
1642 ImmUnlockImeDpi(pImeDpi
);
1646 PCLIENTIMC WINAPI
ImmLockClientImc(HIMC hImc
)
1648 PCLIENTIMC pClientImc
;
1650 TRACE("(%p)\n", hImc
);
1655 pClientImc
= Imm32GetClientImcCache();
1658 pClientImc
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
1662 RtlInitializeCriticalSection(&pClientImc
->cs
);
1663 pClientImc
->unknown
= Imm32GetThreadState(THREADSTATE_UNKNOWN13
);
1665 if (!Imm32UpdateInputContext(hImc
, 0, pClientImc
))
1667 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1671 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN2
;
1675 if (pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN1
)
1679 InterlockedIncrement(&pClientImc
->cLockObj
);
1683 VOID WINAPI
ImmUnlockClientImc(PCLIENTIMC pClientImc
)
1688 TRACE("(%p)\n", pClientImc
);
1690 cLocks
= InterlockedDecrement(&pClientImc
->cLockObj
);
1691 if (cLocks
!= 0 || !(pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN1
))
1694 hImc
= pClientImc
->hImc
;
1698 RtlDeleteCriticalSection(&pClientImc
->cs
);
1699 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1702 static DWORD APIENTRY
1703 CandidateListWideToAnsi(const CANDIDATELIST
*pWideCL
, LPCANDIDATELIST pAnsiCL
, DWORD dwBufLen
,
1707 DWORD dwSize
, dwIndex
, cbGot
, cbLeft
;
1712 /* calculate total ansi size */
1713 if (pWideCL
->dwCount
> 0)
1715 dwSize
= sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1716 for (dwIndex
= 0; dwIndex
< pWideCL
->dwCount
; ++dwIndex
)
1718 pbWide
= (const BYTE
*)pWideCL
+ pWideCL
->dwOffset
[dwIndex
];
1719 cbGot
= WideCharToMultiByte(uCodePage
, 0, (LPCWSTR
)pbWide
, -1, NULL
, 0,
1720 NULL
, &bUsedDefault
);
1726 dwSize
= sizeof(CANDIDATELIST
);
1729 dwSize
= ROUNDUP4(dwSize
);
1732 if (dwBufLen
< dwSize
)
1736 pAnsiCL
->dwSize
= dwBufLen
;
1737 pAnsiCL
->dwStyle
= pWideCL
->dwStyle
;
1738 pAnsiCL
->dwCount
= pWideCL
->dwCount
;
1739 pAnsiCL
->dwSelection
= pWideCL
->dwSelection
;
1740 pAnsiCL
->dwPageStart
= pWideCL
->dwPageStart
;
1741 pAnsiCL
->dwPageSize
= pWideCL
->dwPageSize
;
1743 pibOffsets
= pAnsiCL
->dwOffset
;
1744 if (pWideCL
->dwCount
> 0)
1746 pibOffsets
[0] = sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1747 cbLeft
= dwBufLen
- pibOffsets
[0];
1749 for (dwIndex
= 0; dwIndex
< pWideCL
->dwCount
; ++dwIndex
)
1751 pbWide
= (const BYTE
*)pWideCL
+ pWideCL
->dwOffset
[dwIndex
];
1752 pbAnsi
= (LPBYTE
)pAnsiCL
+ pibOffsets
[dwIndex
];
1754 /* convert to ansi */
1755 cbGot
= WideCharToMultiByte(uCodePage
, 0, (LPCWSTR
)pbWide
, -1,
1756 (LPSTR
)pbAnsi
, cbLeft
, NULL
, &bUsedDefault
);
1759 if (dwIndex
< pWideCL
->dwCount
- 1)
1760 pibOffsets
[dwIndex
+ 1] = pibOffsets
[dwIndex
] + cbGot
;
1765 pibOffsets
[0] = sizeof(CANDIDATELIST
);
1771 static DWORD APIENTRY
1772 CandidateListAnsiToWide(const CANDIDATELIST
*pAnsiCL
, LPCANDIDATELIST pWideCL
, DWORD dwBufLen
,
1775 DWORD dwSize
, dwIndex
, cchGot
, cbGot
, cbLeft
;
1780 /* calculate total wide size */
1781 if (pAnsiCL
->dwCount
> 0)
1783 dwSize
= sizeof(CANDIDATELIST
) + ((pAnsiCL
->dwCount
- 1) * sizeof(DWORD
));
1784 for (dwIndex
= 0; dwIndex
< pAnsiCL
->dwCount
; ++dwIndex
)
1786 pbAnsi
= (const BYTE
*)pAnsiCL
+ pAnsiCL
->dwOffset
[dwIndex
];
1787 cchGot
= MultiByteToWideChar(uCodePage
, MB_PRECOMPOSED
, (LPCSTR
)pbAnsi
, -1, NULL
, 0);
1788 dwSize
+= cchGot
* sizeof(WCHAR
);
1793 dwSize
= sizeof(CANDIDATELIST
);
1796 dwSize
= ROUNDUP4(dwSize
);
1799 if (dwBufLen
< dwSize
)
1803 pWideCL
->dwSize
= dwBufLen
;
1804 pWideCL
->dwStyle
= pAnsiCL
->dwStyle
;
1805 pWideCL
->dwCount
= pAnsiCL
->dwCount
;
1806 pWideCL
->dwSelection
= pAnsiCL
->dwSelection
;
1807 pWideCL
->dwPageStart
= pAnsiCL
->dwPageStart
;
1808 pWideCL
->dwPageSize
= pAnsiCL
->dwPageSize
;
1810 pibOffsets
= pWideCL
->dwOffset
;
1811 if (pAnsiCL
->dwCount
> 0)
1813 pibOffsets
[0] = sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1814 cbLeft
= dwBufLen
- pibOffsets
[0];
1816 for (dwIndex
= 0; dwIndex
< pAnsiCL
->dwCount
; ++dwIndex
)
1818 pbAnsi
= (const BYTE
*)pAnsiCL
+ pAnsiCL
->dwOffset
[dwIndex
];
1819 pbWide
= (LPBYTE
)pWideCL
+ pibOffsets
[dwIndex
];
1821 /* convert to wide */
1822 cchGot
= MultiByteToWideChar(uCodePage
, MB_PRECOMPOSED
, (LPCSTR
)pbAnsi
, -1,
1823 (LPWSTR
)pbWide
, cbLeft
/ sizeof(WCHAR
));
1824 cbGot
= cchGot
* sizeof(WCHAR
);
1827 if (dwIndex
+ 1 < pAnsiCL
->dwCount
)
1828 pibOffsets
[dwIndex
+ 1] = pibOffsets
[dwIndex
] + cbGot
;
1833 pibOffsets
[0] = sizeof(CANDIDATELIST
);
1839 static DWORD APIENTRY
1840 ImmGetCandidateListAW(HIMC hIMC
, DWORD dwIndex
, LPCANDIDATELIST lpCandList
, DWORD dwBufLen
,
1845 PCLIENTIMC pClientImc
;
1846 LPCANDIDATEINFO pCI
;
1847 LPCANDIDATELIST pCL
;
1850 pClientImc
= ImmLockClientImc(hIMC
);
1854 pIC
= ImmLockIMC(hIMC
);
1857 ImmUnlockClientImc(pClientImc
);
1861 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
1865 ImmUnlockClientImc(pClientImc
);
1869 if (pCI
->dwSize
< sizeof(CANDIDATEINFO
) || pCI
->dwCount
<= dwIndex
)
1872 /* get required size */
1873 pCL
= (LPCANDIDATELIST
)((LPBYTE
)pCI
+ pCI
->dwOffset
[dwIndex
]);
1876 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1877 dwSize
= CandidateListAnsiToWide(pCL
, NULL
, 0, CP_ACP
);
1879 dwSize
= pCL
->dwSize
;
1883 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1884 dwSize
= pCL
->dwSize
;
1886 dwSize
= CandidateListWideToAnsi(pCL
, NULL
, 0, CP_ACP
);
1889 if (dwBufLen
!= 0 && dwSize
!= 0)
1891 if (lpCandList
== NULL
|| dwBufLen
< dwSize
)
1897 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1898 CandidateListAnsiToWide(pCL
, lpCandList
, dwSize
, CP_ACP
);
1900 RtlCopyMemory(lpCandList
, pCL
, dwSize
);
1904 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1905 RtlCopyMemory(lpCandList
, pCL
, dwSize
);
1907 CandidateListWideToAnsi(pCL
, lpCandList
, dwSize
, CP_ACP
);
1914 ImmUnlockIMCC(pIC
->hCandInfo
);
1916 ImmUnlockClientImc(pClientImc
);
1920 DWORD APIENTRY
ImmGetCandidateListCountAW(HIMC hIMC
, LPDWORD lpdwListCount
, BOOL bAnsi
)
1922 DWORD ret
= 0, cbGot
, dwIndex
;
1923 PCLIENTIMC pClientImc
;
1925 const CANDIDATEINFO
*pCI
;
1927 const CANDIDATELIST
*pCL
;
1928 const DWORD
*pdwOffsets
;
1930 if (lpdwListCount
== NULL
)
1935 pClientImc
= ImmLockClientImc(hIMC
);
1936 if (pClientImc
== NULL
)
1939 pIC
= ImmLockIMC(hIMC
);
1942 ImmUnlockClientImc(pClientImc
);
1946 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
1950 ImmUnlockClientImc(pClientImc
);
1954 if (pCI
->dwSize
< sizeof(CANDIDATEINFO
))
1957 *lpdwListCount
= pCI
->dwCount
; /* the number of candidate lists */
1959 /* calculate total size of candidate lists */
1962 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1964 ret
= ROUNDUP4(pCI
->dwPrivateSize
);
1965 pdwOffsets
= pCI
->dwOffset
;
1966 for (dwIndex
= 0; dwIndex
< pCI
->dwCount
; ++dwIndex
)
1968 pb
= (const BYTE
*)pCI
+ pdwOffsets
[dwIndex
];
1969 pCL
= (const CANDIDATELIST
*)pb
;
1970 cbGot
= CandidateListWideToAnsi(pCL
, NULL
, 0, CP_ACP
);
1981 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1987 ret
= ROUNDUP4(pCI
->dwPrivateSize
);
1988 pdwOffsets
= pCI
->dwOffset
;
1989 for (dwIndex
= 0; dwIndex
< pCI
->dwCount
; ++dwIndex
)
1991 pb
= (const BYTE
*)pCI
+ pdwOffsets
[dwIndex
];
1992 pCL
= (const CANDIDATELIST
*)pb
;
1993 cbGot
= CandidateListAnsiToWide(pCL
, NULL
, 0, CP_ACP
);
2000 ImmUnlockIMCC(pIC
->hCandInfo
);
2002 ImmUnlockClientImc(pClientImc
);
2006 /***********************************************************************
2007 * ImmGetCandidateListA (IMM32.@)
2009 DWORD WINAPI
ImmGetCandidateListA(
2010 HIMC hIMC
, DWORD dwIndex
,
2011 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
2013 return ImmGetCandidateListAW(hIMC
, dwIndex
, lpCandList
, dwBufLen
, TRUE
);
2016 /***********************************************************************
2017 * ImmGetCandidateListCountA (IMM32.@)
2019 DWORD WINAPI
ImmGetCandidateListCountA(
2020 HIMC hIMC
, LPDWORD lpdwListCount
)
2022 return ImmGetCandidateListCountAW(hIMC
, lpdwListCount
, TRUE
);
2025 /***********************************************************************
2026 * ImmGetCandidateListCountW (IMM32.@)
2028 DWORD WINAPI
ImmGetCandidateListCountW(
2029 HIMC hIMC
, LPDWORD lpdwListCount
)
2031 return ImmGetCandidateListCountAW(hIMC
, lpdwListCount
, FALSE
);
2034 /***********************************************************************
2035 * ImmGetCandidateListW (IMM32.@)
2037 DWORD WINAPI
ImmGetCandidateListW(
2038 HIMC hIMC
, DWORD dwIndex
,
2039 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
2041 return ImmGetCandidateListAW(hIMC
, dwIndex
, lpCandList
, dwBufLen
, FALSE
);
2044 /***********************************************************************
2045 * ImmGetCandidateWindow (IMM32.@)
2047 BOOL WINAPI
ImmGetCandidateWindow(
2048 HIMC hIMC
, DWORD dwIndex
, LPCANDIDATEFORM lpCandidate
)
2052 LPCANDIDATEFORM pCF
;
2054 TRACE("(%p, %lu, %p)\n", hIMC
, dwIndex
, lpCandidate
);
2056 pIC
= ImmLockIMC(hIMC
);
2060 pCF
= &pIC
->cfCandForm
[dwIndex
];
2061 if (pCF
->dwIndex
!= IMM_INVALID_CANDFORM
)
2063 *lpCandidate
= *pCF
;
2071 static VOID APIENTRY
LogFontAnsiToWide(const LOGFONTA
*plfA
, LPLOGFONTW plfW
)
2074 RtlCopyMemory(plfW
, plfA
, offsetof(LOGFONTA
, lfFaceName
));
2075 StringCchLengthA(plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), &cch
);
2076 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, plfA
->lfFaceName
, (INT
)cch
,
2077 plfW
->lfFaceName
, _countof(plfW
->lfFaceName
));
2078 if (cch
> _countof(plfW
->lfFaceName
) - 1)
2079 cch
= _countof(plfW
->lfFaceName
) - 1;
2080 plfW
->lfFaceName
[cch
] = 0;
2083 static VOID APIENTRY
LogFontWideToAnsi(const LOGFONTW
*plfW
, LPLOGFONTA plfA
)
2086 RtlCopyMemory(plfA
, plfW
, offsetof(LOGFONTW
, lfFaceName
));
2087 StringCchLengthW(plfW
->lfFaceName
, _countof(plfW
->lfFaceName
), &cch
);
2088 cch
= WideCharToMultiByte(CP_ACP
, 0, plfW
->lfFaceName
, (INT
)cch
,
2089 plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), NULL
, NULL
);
2090 if (cch
> _countof(plfA
->lfFaceName
) - 1)
2091 cch
= _countof(plfA
->lfFaceName
) - 1;
2092 plfA
->lfFaceName
[cch
] = 0;
2095 /***********************************************************************
2096 * ImmGetCompositionFontA (IMM32.@)
2098 BOOL WINAPI
ImmGetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
2100 PCLIENTIMC pClientImc
;
2101 BOOL ret
= FALSE
, bWide
;
2104 TRACE("(%p, %p)\n", hIMC
, lplf
);
2106 pClientImc
= ImmLockClientImc(hIMC
);
2107 if (pClientImc
== NULL
)
2110 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
2111 ImmUnlockClientImc(pClientImc
);
2113 pIC
= ImmLockIMC(hIMC
);
2117 if (pIC
->fdwInit
& INIT_LOGFONT
)
2120 LogFontWideToAnsi(&pIC
->lfFont
.W
, lplf
);
2122 *lplf
= pIC
->lfFont
.A
;
2131 /***********************************************************************
2132 * ImmGetCompositionFontW (IMM32.@)
2134 BOOL WINAPI
ImmGetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
2136 PCLIENTIMC pClientImc
;
2141 TRACE("(%p, %p)\n", hIMC
, lplf
);
2143 pClientImc
= ImmLockClientImc(hIMC
);
2144 if (pClientImc
== NULL
)
2147 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
2148 ImmUnlockClientImc(pClientImc
);
2150 pIC
= ImmLockIMC(hIMC
);
2154 if (pIC
->fdwInit
& INIT_LOGFONT
)
2157 *lplf
= pIC
->lfFont
.W
;
2159 LogFontAnsiToWide(&pIC
->lfFont
.A
, lplf
);
2169 /* Helpers for the GetCompositionString functions */
2171 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
2172 length is always in bytes. */
2173 static INT
CopyCompStringIMEtoClient(const InputContextData
*data
, const void *src
, INT src_len
, void *dst
,
2174 INT dst_len
, BOOL unicode
)
2176 int char_size
= unicode
? sizeof(WCHAR
) : sizeof(char);
2179 if (is_himc_ime_unicode(data
) ^ unicode
)
2182 ret
= MultiByteToWideChar(CP_ACP
, 0, src
, src_len
, dst
, dst_len
/ sizeof(WCHAR
));
2184 ret
= WideCharToMultiByte(CP_ACP
, 0, src
, src_len
, dst
, dst_len
, NULL
, NULL
);
2191 ret
= min(src_len
* char_size
, dst_len
);
2192 memcpy(dst
, src
, ret
);
2195 ret
= src_len
* char_size
;
2201 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
2202 passed mode. String length is in characters, attributes are in byte arrays. */
2203 static INT
CopyCompAttrIMEtoClient(const InputContextData
*data
, const BYTE
*src
, INT src_len
, const void *comp_string
,
2204 INT str_len
, BYTE
*dst
, INT dst_len
, BOOL unicode
)
2214 string
.str
= comp_string
;
2216 if (is_himc_ime_unicode(data
) && !unicode
)
2218 rc
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
, str_len
, NULL
, 0, NULL
, NULL
);
2221 int i
, j
= 0, k
= 0;
2225 for (i
= 0; i
< str_len
; ++i
)
2229 len
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
+ i
, 1, NULL
, 0, NULL
, NULL
);
2230 for (; len
> 0; --len
)
2243 else if (!is_himc_ime_unicode(data
) && unicode
)
2245 rc
= MultiByteToWideChar(CP_ACP
, 0, string
.strA
, str_len
, NULL
, 0);
2252 for (i
= 0; i
< str_len
; ++i
)
2254 if (IsDBCSLeadByte(string
.strA
[i
]))
2267 memcpy(dst
, src
, min(src_len
, dst_len
));
2274 static INT
CopyCompClauseIMEtoClient(InputContextData
*data
, LPBYTE source
, INT slen
, LPBYTE ssource
,
2275 LPBYTE target
, INT tlen
, BOOL unicode
)
2279 if (is_himc_ime_unicode(data
) && !unicode
)
2287 tlen
/= sizeof (DWORD
);
2288 for (i
= 0; i
< tlen
; ++i
)
2290 ((DWORD
*)target
)[i
] = WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
,
2291 ((DWORD
*)source
)[i
],
2295 rc
= sizeof (DWORD
) * i
;
2300 else if (!is_himc_ime_unicode(data
) && unicode
)
2308 tlen
/= sizeof (DWORD
);
2309 for (i
= 0; i
< tlen
; ++i
)
2311 ((DWORD
*)target
)[i
] = MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
,
2312 ((DWORD
*)source
)[i
],
2315 rc
= sizeof (DWORD
) * i
;
2322 memcpy( target
, source
, min(slen
,tlen
));
2329 static INT
CopyCompOffsetIMEtoClient(InputContextData
*data
, DWORD offset
, LPBYTE ssource
, BOOL unicode
)
2333 if (is_himc_ime_unicode(data
) && !unicode
)
2335 rc
= WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
, offset
, NULL
, 0, NULL
, NULL
);
2337 else if (!is_himc_ime_unicode(data
) && unicode
)
2339 rc
= MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
, offset
, NULL
, 0);
2347 static LONG
ImmGetCompositionStringT( HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
,
2348 DWORD dwBufLen
, BOOL unicode
)
2351 InputContextData
*data
= get_imc_data(hIMC
);
2352 LPCOMPOSITIONSTRING compstr
;
2355 TRACE("(%p, 0x%x, %p, %d)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2360 if (!data
->IMC
.hCompStr
)
2363 compdata
= ImmLockIMCC(data
->IMC
.hCompStr
);
2364 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
2369 TRACE("GCS_RESULTSTR\n");
2370 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultStrOffset
, compstr
->dwResultStrLen
, lpBuf
, dwBufLen
, unicode
);
2373 TRACE("GCS_COMPSTR\n");
2374 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
, lpBuf
, dwBufLen
, unicode
);
2377 TRACE("GCS_COMPATTR\n");
2378 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompAttrOffset
, compstr
->dwCompAttrLen
,
2379 compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
,
2380 lpBuf
, dwBufLen
, unicode
);
2382 case GCS_COMPCLAUSE
:
2383 TRACE("GCS_COMPCLAUSE\n");
2384 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompClauseOffset
,compstr
->dwCompClauseLen
,
2385 compdata
+ compstr
->dwCompStrOffset
,
2386 lpBuf
, dwBufLen
, unicode
);
2388 case GCS_RESULTCLAUSE
:
2389 TRACE("GCS_RESULTCLAUSE\n");
2390 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultClauseOffset
,compstr
->dwResultClauseLen
,
2391 compdata
+ compstr
->dwResultStrOffset
,
2392 lpBuf
, dwBufLen
, unicode
);
2394 case GCS_RESULTREADSTR
:
2395 TRACE("GCS_RESULTREADSTR\n");
2396 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultReadStrOffset
, compstr
->dwResultReadStrLen
, lpBuf
, dwBufLen
, unicode
);
2398 case GCS_RESULTREADCLAUSE
:
2399 TRACE("GCS_RESULTREADCLAUSE\n");
2400 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultReadClauseOffset
,compstr
->dwResultReadClauseLen
,
2401 compdata
+ compstr
->dwResultStrOffset
,
2402 lpBuf
, dwBufLen
, unicode
);
2404 case GCS_COMPREADSTR
:
2405 TRACE("GCS_COMPREADSTR\n");
2406 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
, lpBuf
, dwBufLen
, unicode
);
2408 case GCS_COMPREADATTR
:
2409 TRACE("GCS_COMPREADATTR\n");
2410 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompReadAttrOffset
, compstr
->dwCompReadAttrLen
,
2411 compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
,
2412 lpBuf
, dwBufLen
, unicode
);
2414 case GCS_COMPREADCLAUSE
:
2415 TRACE("GCS_COMPREADCLAUSE\n");
2416 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompReadClauseOffset
,compstr
->dwCompReadClauseLen
,
2417 compdata
+ compstr
->dwCompStrOffset
,
2418 lpBuf
, dwBufLen
, unicode
);
2421 TRACE("GCS_CURSORPOS\n");
2422 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwCursorPos
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
2424 case GCS_DELTASTART
:
2425 TRACE("GCS_DELTASTART\n");
2426 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwDeltaStart
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
2429 FIXME("Unhandled index 0x%x\n",dwIndex
);
2433 ImmUnlockIMCC(data
->IMC
.hCompStr
);
2438 /***********************************************************************
2439 * ImmGetCompositionStringA (IMM32.@)
2441 LONG WINAPI
ImmGetCompositionStringA(
2442 HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
)
2444 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
2448 /***********************************************************************
2449 * ImmGetCompositionStringW (IMM32.@)
2451 LONG WINAPI
ImmGetCompositionStringW(
2452 HIMC hIMC
, DWORD dwIndex
,
2453 LPVOID lpBuf
, DWORD dwBufLen
)
2455 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
2458 /***********************************************************************
2459 * ImmGetCompositionWindow (IMM32.@)
2461 BOOL WINAPI
ImmGetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
2466 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
2468 pIC
= ImmLockIMC(hIMC
);
2472 if (pIC
->fdwInit
& INIT_COMPFORM
)
2474 *lpCompForm
= pIC
->cfCompForm
;
2482 /***********************************************************************
2483 * ImmGetContext (IMM32.@)
2486 HIMC WINAPI
ImmGetContext(HWND hWnd
)
2490 TRACE("%p\n", hWnd
);
2492 if (!IsWindow(hWnd
))
2494 SetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2498 rc
= GetPropW(hWnd
,szwWineIMCProperty
);
2501 else if (rc
== NULL
)
2502 rc
= get_default_context( hWnd
);
2506 InputContextData
*data
= rc
;
2507 data
->IMC
.hWnd
= hWnd
;
2510 TRACE("returning %p\n", rc
);
2515 /***********************************************************************
2516 * ImmGetConversionListA (IMM32.@)
2518 DWORD WINAPI
ImmGetConversionListA(
2520 LPCSTR pSrc
, LPCANDIDATELIST lpDst
,
2521 DWORD dwBufLen
, UINT uFlag
)
2523 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2524 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL
, hIMC
, debugstr_a(pSrc
), lpDst
,
2526 if (immHkl
->hIME
&& immHkl
->pImeConversionList
)
2528 if (!is_kbd_ime_unicode(immHkl
))
2529 return immHkl
->pImeConversionList(hIMC
,(LPCWSTR
)pSrc
,lpDst
,dwBufLen
,uFlag
);
2532 LPCANDIDATELIST lpwDst
;
2534 LPWSTR pwSrc
= strdupAtoW(pSrc
);
2536 len
= immHkl
->pImeConversionList(hIMC
, pwSrc
, NULL
, 0, uFlag
);
2537 lpwDst
= HeapAlloc(GetProcessHeap(), 0, len
);
2540 immHkl
->pImeConversionList(hIMC
, pwSrc
, lpwDst
, len
, uFlag
);
2541 ret
= convert_candidatelist_WtoA( lpwDst
, lpDst
, dwBufLen
);
2542 HeapFree(GetProcessHeap(), 0, lpwDst
);
2544 HeapFree(GetProcessHeap(), 0, pwSrc
);
2553 /***********************************************************************
2554 * ImmGetConversionListW (IMM32.@)
2556 DWORD WINAPI
ImmGetConversionListW(
2558 LPCWSTR pSrc
, LPCANDIDATELIST lpDst
,
2559 DWORD dwBufLen
, UINT uFlag
)
2561 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2562 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL
, hIMC
, debugstr_w(pSrc
), lpDst
,
2564 if (immHkl
->hIME
&& immHkl
->pImeConversionList
)
2566 if (is_kbd_ime_unicode(immHkl
))
2567 return immHkl
->pImeConversionList(hIMC
,pSrc
,lpDst
,dwBufLen
,uFlag
);
2570 LPCANDIDATELIST lpaDst
;
2572 LPSTR paSrc
= strdupWtoA(pSrc
);
2574 len
= immHkl
->pImeConversionList(hIMC
, (LPCWSTR
)paSrc
, NULL
, 0, uFlag
);
2575 lpaDst
= HeapAlloc(GetProcessHeap(), 0, len
);
2578 immHkl
->pImeConversionList(hIMC
, (LPCWSTR
)paSrc
, lpaDst
, len
, uFlag
);
2579 ret
= convert_candidatelist_AtoW( lpaDst
, lpDst
, dwBufLen
);
2580 HeapFree(GetProcessHeap(), 0, lpaDst
);
2582 HeapFree(GetProcessHeap(), 0, paSrc
);
2591 /***********************************************************************
2592 * ImmGetConversionStatus (IMM32.@)
2594 BOOL WINAPI
ImmGetConversionStatus(
2595 HIMC hIMC
, LPDWORD lpfdwConversion
, LPDWORD lpfdwSentence
)
2599 TRACE("(%p %p %p)\n", hIMC
, lpfdwConversion
, lpfdwSentence
);
2601 pIC
= ImmLockIMC(hIMC
);
2605 if (lpfdwConversion
)
2606 *lpfdwConversion
= pIC
->fdwConversion
;
2608 *lpfdwSentence
= pIC
->fdwSentence
;
2614 static BOOL
needs_ime_window(HWND hwnd
)
2618 if (GetClassNameW(hwnd
, classW
, ARRAY_SIZE(classW
)) && !lstrcmpW(classW
, szwIME
))
2620 if (GetClassLongPtrW(hwnd
, GCL_STYLE
) & CS_IME
) return FALSE
;
2625 /***********************************************************************
2626 * __wine_register_window (IMM32.@)
2628 BOOL WINAPI
__wine_register_window(HWND hwnd
)
2631 IMMThreadData
*thread_data
;
2632 TRACE("(%p)\n", hwnd
);
2634 if (!needs_ime_window(hwnd
))
2637 thread_data
= IMM_GetThreadData(hwnd
, 0);
2641 if (thread_data
->disableIME
|| disable_ime
)
2643 TRACE("IME for this thread is disabled\n");
2644 LeaveCriticalSection(&threaddata_cs
);
2647 thread_data
->windowRefs
++;
2648 TRACE("windowRefs=%u, hwndDefault=%p\n",
2649 thread_data
->windowRefs
, thread_data
->hwndDefault
);
2651 /* Create default IME window */
2652 if (thread_data
->windowRefs
== 1)
2654 /* Do not create the window inside of a critical section */
2655 LeaveCriticalSection(&threaddata_cs
);
2656 new = CreateWindowExW( 0, szwIME
, szwDefaultIME
,
2657 WS_POPUP
| WS_DISABLED
| WS_CLIPSIBLINGS
,
2658 0, 0, 1, 1, 0, 0, 0, 0);
2659 /* thread_data is in the current thread so we can assume it's still valid */
2660 EnterCriticalSection(&threaddata_cs
);
2661 /* See if anyone beat us */
2662 if (thread_data
->hwndDefault
== NULL
)
2664 thread_data
->hwndDefault
= new;
2666 TRACE("Default is %p\n", thread_data
->hwndDefault
);
2670 LeaveCriticalSection(&threaddata_cs
);
2672 /* Clean up an unused new window outside of the critical section */
2678 /***********************************************************************
2679 * __wine_unregister_window (IMM32.@)
2681 void WINAPI
__wine_unregister_window(HWND hwnd
)
2683 HWND to_destroy
= 0;
2684 IMMThreadData
*thread_data
;
2685 TRACE("(%p)\n", hwnd
);
2687 thread_data
= IMM_GetThreadData(hwnd
, 0);
2688 if (!thread_data
) return;
2690 thread_data
->windowRefs
--;
2691 TRACE("windowRefs=%u, hwndDefault=%p\n",
2692 thread_data
->windowRefs
, thread_data
->hwndDefault
);
2694 /* Destroy default IME window */
2695 if (thread_data
->windowRefs
== 0 && thread_data
->hwndDefault
)
2697 to_destroy
= thread_data
->hwndDefault
;
2698 thread_data
->hwndDefault
= NULL
;
2700 LeaveCriticalSection(&threaddata_cs
);
2702 if (to_destroy
) DestroyWindow( to_destroy
);
2705 /***********************************************************************
2706 * ImmGetDefaultIMEWnd (IMM32.@)
2708 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
2710 if (!g_psi
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
2714 return (HWND
)Imm32GetThreadState(THREADSTATE_ACTIVEWINDOW
);
2716 return (HWND
)Imm32QueryWindow(hWnd
, QUERY_WINDOW_DEFAULT_IME
);
2719 /***********************************************************************
2720 * CtfImmIsCiceroEnabled (IMM32.@)
2722 BOOL WINAPI
CtfImmIsCiceroEnabled(VOID
)
2724 return (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
));
2727 /***********************************************************************
2728 * ImmGetDescriptionA (IMM32.@)
2730 UINT WINAPI
ImmGetDescriptionA(
2731 HKL hKL
, LPSTR lpszDescription
, UINT uBufLen
)
2736 TRACE("(%p,%p,%d)\n", hKL
, lpszDescription
, uBufLen
);
2738 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2741 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
2742 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeDescription
, (INT
)cch
,
2743 lpszDescription
, uBufLen
, NULL
, NULL
);
2745 lpszDescription
[cch
] = 0;
2749 /***********************************************************************
2750 * ImmGetDescriptionW (IMM32.@)
2752 UINT WINAPI
ImmGetDescriptionW(HKL hKL
, LPWSTR lpszDescription
, UINT uBufLen
)
2757 TRACE("(%p, %p, %d)\n", hKL
, lpszDescription
, uBufLen
);
2759 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2763 StringCchCopyW(lpszDescription
, uBufLen
, info
.wszImeDescription
);
2765 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
2769 static DWORD APIENTRY
2770 ImmGetGuideLineAW(HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
, BOOL bAnsi
)
2772 PCLIENTIMC pClientImc
;
2774 LPGUIDELINE pGuideLine
;
2776 LPVOID pvStr
, pvPrivate
;
2779 pClientImc
= ImmLockClientImc(hIMC
);
2783 pIC
= ImmLockIMC(hIMC
);
2786 ImmUnlockClientImc(pClientImc
);
2790 pGuideLine
= ImmLockIMCC(pIC
->hGuideLine
);
2794 ImmUnlockClientImc(pClientImc
);
2798 if (dwIndex
== GGL_LEVEL
)
2800 ret
= pGuideLine
->dwLevel
;
2804 if (dwIndex
== GGL_INDEX
)
2806 ret
= pGuideLine
->dwIndex
;
2810 if (dwIndex
== GGL_STRING
)
2812 pvStr
= (LPBYTE
)pGuideLine
+ pGuideLine
->dwStrOffset
;
2817 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2819 cb
= WideCharToMultiByte(CP_ACP
, 0, pvStr
, pGuideLine
->dwStrLen
,
2820 NULL
, 0, NULL
, &bUsedDefault
);
2824 cb
= pGuideLine
->dwStrLen
* sizeof(CHAR
);
2829 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2831 cb
= pGuideLine
->dwStrLen
* sizeof(WCHAR
);
2835 cb
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, pvStr
, pGuideLine
->dwStrLen
,
2836 NULL
, 0) * sizeof(WCHAR
);
2840 if (dwBufLen
== 0 || cb
== 0 || lpBuf
== NULL
|| dwBufLen
< cb
)
2846 /* store to buffer */
2849 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
2851 ret
= WideCharToMultiByte(CP_ACP
, 0, pvStr
, pGuideLine
->dwStrLen
,
2852 lpBuf
, dwBufLen
, NULL
, &bUsedDefault
);
2858 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
))
2860 ret
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, pvStr
, pGuideLine
->dwStrLen
,
2861 lpBuf
, dwBufLen
) * sizeof(WCHAR
);
2866 RtlCopyMemory(lpBuf
, pvStr
, cb
);
2871 if (dwIndex
== GGL_PRIVATE
)
2873 pvPrivate
= (LPBYTE
)pGuideLine
+ pGuideLine
->dwPrivateOffset
;
2878 if ((pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2879 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2881 cb
= CandidateListWideToAnsi(pvPrivate
, NULL
, 0, CP_ACP
);
2885 cb
= pGuideLine
->dwPrivateSize
;
2890 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2891 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2893 cb
= CandidateListAnsiToWide(pvPrivate
, NULL
, 0, CP_ACP
);
2897 cb
= pGuideLine
->dwPrivateSize
;
2901 if (dwBufLen
== 0 || cb
== 0 || lpBuf
== NULL
|| dwBufLen
< cb
)
2907 /* store to buffer */
2910 if ((pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2911 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2913 ret
= CandidateListWideToAnsi(pvPrivate
, lpBuf
, cb
, CP_ACP
);
2919 if (!(pClientImc
->dwFlags
& CLIENTIMC_WIDE
) &&
2920 pGuideLine
->dwIndex
== GL_ID_REVERSECONVERSION
)
2922 ret
= CandidateListAnsiToWide(pvPrivate
, lpBuf
, cb
, CP_ACP
);
2927 RtlCopyMemory(lpBuf
, pvPrivate
, cb
);
2933 ImmUnlockIMCC(pIC
->hGuideLine
);
2935 ImmUnlockClientImc(pClientImc
);
2939 /***********************************************************************
2940 * ImmGetGuideLineA (IMM32.@)
2942 DWORD WINAPI
ImmGetGuideLineA(
2943 HIMC hIMC
, DWORD dwIndex
, LPSTR lpBuf
, DWORD dwBufLen
)
2945 TRACE("(%p, %lu, %p, %lu)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2946 return ImmGetGuideLineAW(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
2949 /***********************************************************************
2950 * ImmGetGuideLineW (IMM32.@)
2952 DWORD WINAPI
ImmGetGuideLineW(HIMC hIMC
, DWORD dwIndex
, LPWSTR lpBuf
, DWORD dwBufLen
)
2954 TRACE("(%p, %lu, %p, %lu)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
2955 return ImmGetGuideLineAW(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
2958 /***********************************************************************
2959 * ImmGetIMEFileNameA (IMM32.@)
2961 UINT WINAPI
ImmGetIMEFileNameA( HKL hKL
, LPSTR lpszFileName
, UINT uBufLen
)
2967 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
2969 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2972 lpszFileName
[0] = 0;
2976 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
2978 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeFile
, (INT
)cch
,
2979 lpszFileName
, uBufLen
, NULL
, &bDefUsed
);
2983 if (cch
> uBufLen
- 1)
2986 lpszFileName
[cch
] = 0;
2990 /***********************************************************************
2991 * ImmGetIMEFileNameW (IMM32.@)
2993 UINT WINAPI
ImmGetIMEFileNameW(HKL hKL
, LPWSTR lpszFileName
, UINT uBufLen
)
2998 TRACE("(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
3000 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
3003 lpszFileName
[0] = 0;
3007 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
3011 StringCchCopyNW(lpszFileName
, uBufLen
, info
.wszImeFile
, cch
);
3013 if (cch
> uBufLen
- 1)
3016 lpszFileName
[cch
] = 0;
3020 /***********************************************************************
3021 * ImmGetOpenStatus (IMM32.@)
3023 BOOL WINAPI
ImmGetOpenStatus(HIMC hIMC
)
3028 TRACE("(%p)\n", hIMC
);
3033 pIC
= ImmLockIMC(hIMC
);
3043 /***********************************************************************
3044 * ImmGetProperty (IMM32.@)
3046 DWORD WINAPI
ImmGetProperty(HKL hKL
, DWORD fdwIndex
)
3051 TRACE("(%p, %d)\n", hKL
, fdwIndex
);
3052 kbd
= IMM_GetImmHkl(hKL
);
3054 if (kbd
&& kbd
->hIME
)
3058 case IGP_PROPERTY
: rc
= kbd
->imeInfo
.fdwProperty
; break;
3059 case IGP_CONVERSION
: rc
= kbd
->imeInfo
.fdwConversionCaps
; break;
3060 case IGP_SENTENCE
: rc
= kbd
->imeInfo
.fdwSentenceCaps
; break;
3061 case IGP_SETCOMPSTR
: rc
= kbd
->imeInfo
.fdwSCSCaps
; break;
3062 case IGP_SELECT
: rc
= kbd
->imeInfo
.fdwSelectCaps
; break;
3063 case IGP_GETIMEVERSION
: rc
= IMEVER_0400
; break;
3064 case IGP_UI
: rc
= 0; break;
3071 /***********************************************************************
3072 * ImmGetRegisterWordStyleA (IMM32.@)
3074 UINT WINAPI
ImmGetRegisterWordStyleA(
3075 HKL hKL
, UINT nItem
, LPSTYLEBUFA lpStyleBuf
)
3077 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
3078 TRACE("(%p, %d, %p):\n", hKL
, nItem
, lpStyleBuf
);
3079 if (immHkl
->hIME
&& immHkl
->pImeGetRegisterWordStyle
)
3081 if (!is_kbd_ime_unicode(immHkl
))
3082 return immHkl
->pImeGetRegisterWordStyle(nItem
,(LPSTYLEBUFW
)lpStyleBuf
);
3088 rc
= immHkl
->pImeGetRegisterWordStyle(nItem
,&sbw
);
3089 WideCharToMultiByte(CP_ACP
, 0, sbw
.szDescription
, -1,
3090 lpStyleBuf
->szDescription
, 32, NULL
, NULL
);
3091 lpStyleBuf
->dwStyle
= sbw
.dwStyle
;
3099 /***********************************************************************
3100 * ImmGetRegisterWordStyleW (IMM32.@)
3102 UINT WINAPI
ImmGetRegisterWordStyleW(
3103 HKL hKL
, UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
3105 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
3106 TRACE("(%p, %d, %p):\n", hKL
, nItem
, lpStyleBuf
);
3107 if (immHkl
->hIME
&& immHkl
->pImeGetRegisterWordStyle
)
3109 if (is_kbd_ime_unicode(immHkl
))
3110 return immHkl
->pImeGetRegisterWordStyle(nItem
,lpStyleBuf
);
3116 rc
= immHkl
->pImeGetRegisterWordStyle(nItem
,(LPSTYLEBUFW
)&sba
);
3117 MultiByteToWideChar(CP_ACP
, 0, sba
.szDescription
, -1,
3118 lpStyleBuf
->szDescription
, 32);
3119 lpStyleBuf
->dwStyle
= sba
.dwStyle
;
3127 /***********************************************************************
3128 * ImmGetStatusWindowPos (IMM32.@)
3130 BOOL WINAPI
ImmGetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
3135 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
3137 pIC
= ImmLockIMC(hIMC
);
3141 ret
= !!(pIC
->fdwInit
& INIT_STATUSWNDPOS
);
3143 *lpptPos
= pIC
->ptStatusWndPos
;
3149 /***********************************************************************
3150 * ImmGetVirtualKey (IMM32.@)
3152 UINT WINAPI
ImmGetVirtualKey(HWND hWnd
)
3155 LPINPUTCONTEXTDX pIC
;
3156 UINT ret
= VK_PROCESSKEY
;
3158 TRACE("(%p)\n", hWnd
);
3160 hIMC
= ImmGetContext(hWnd
);
3161 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3172 /***********************************************************************
3173 * ImmInstallIMEA (IMM32.@)
3175 HKL WINAPI
ImmInstallIMEA(
3176 LPCSTR lpszIMEFileName
, LPCSTR lpszLayoutText
)
3178 INT cchFileName
, cchLayoutText
;
3179 LPWSTR pszFileNameW
, pszLayoutTextW
;
3182 TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName
), debugstr_a(lpszLayoutText
));
3184 cchFileName
= lstrlenA(lpszIMEFileName
) + 1;
3185 cchLayoutText
= lstrlenA(lpszLayoutText
) + 1;
3187 pszFileNameW
= Imm32HeapAlloc(0, cchFileName
* sizeof(WCHAR
));
3188 if (pszFileNameW
== NULL
)
3191 pszLayoutTextW
= Imm32HeapAlloc(0, cchLayoutText
* sizeof(WCHAR
));
3192 if (pszLayoutTextW
== NULL
)
3194 HeapFree(g_hImm32Heap
, 0, pszFileNameW
);
3198 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, lpszIMEFileName
, -1, pszFileNameW
, cchFileName
);
3199 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, lpszLayoutText
, -1, pszLayoutTextW
, cchLayoutText
);
3201 hKL
= ImmInstallIMEW(pszFileNameW
, pszLayoutTextW
);
3202 HeapFree(g_hImm32Heap
, 0, pszFileNameW
);
3203 HeapFree(g_hImm32Heap
, 0, pszLayoutTextW
);
3207 /***********************************************************************
3208 * ImmInstallIMEW (IMM32.@)
3210 HKL WINAPI
ImmInstallIMEW(
3211 LPCWSTR lpszIMEFileName
, LPCWSTR lpszLayoutText
)
3213 INT lcid
= GetUserDefaultLCID();
3218 WCHAR regKey
[ARRAY_SIZE(szImeRegFmt
)+8];
3220 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName
),
3221 debugstr_w(lpszLayoutText
));
3223 /* Start with 2. e001 will be blank and so default to the wine internal IME */
3226 while (count
< 0xfff)
3228 DWORD disposition
= 0;
3230 hkl
= (HKL
)MAKELPARAM( lcid
, 0xe000 | count
);
3231 wsprintfW( regKey
, szImeRegFmt
, (ULONG_PTR
)hkl
);
3233 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, regKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hkey
, &disposition
);
3234 if (rc
== ERROR_SUCCESS
&& disposition
== REG_CREATED_NEW_KEY
)
3236 else if (rc
== ERROR_SUCCESS
)
3244 WARN("Unable to find slot to install IME\n");
3248 if (rc
== ERROR_SUCCESS
)
3250 rc
= RegSetValueExW(hkey
, szImeFileW
, 0, REG_SZ
, (const BYTE
*)lpszIMEFileName
,
3251 (lstrlenW(lpszIMEFileName
) + 1) * sizeof(WCHAR
));
3252 if (rc
== ERROR_SUCCESS
)
3253 rc
= RegSetValueExW(hkey
, szLayoutTextW
, 0, REG_SZ
, (const BYTE
*)lpszLayoutText
,
3254 (lstrlenW(lpszLayoutText
) + 1) * sizeof(WCHAR
));
3260 WARN("Unable to set IME registry values\n");
3265 /***********************************************************************
3266 * ImmIsIME (IMM32.@)
3268 BOOL WINAPI
ImmIsIME(HKL hKL
)
3271 TRACE("(%p)\n", hKL
);
3272 return !!ImmGetImeInfoEx(&info
, ImeInfoExImeWindow
, &hKL
);
3275 /***********************************************************************
3276 * ImmIsUIMessageA (IMM32.@)
3278 BOOL WINAPI
ImmIsUIMessageA(
3279 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
3281 TRACE("(%p, %x, %ld, %ld)\n", hWndIME
, msg
, wParam
, lParam
);
3282 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
3283 (msg
== WM_IME_SETCONTEXT
) ||
3284 (msg
== WM_IME_NOTIFY
) ||
3285 (msg
== WM_IME_COMPOSITIONFULL
) ||
3286 (msg
== WM_IME_SELECT
) ||
3287 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
3290 SendMessageA(hWndIME
, msg
, wParam
, lParam
);
3297 /***********************************************************************
3298 * ImmIsUIMessageW (IMM32.@)
3300 BOOL WINAPI
ImmIsUIMessageW(
3301 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
3303 TRACE("(%p, %x, %ld, %ld)\n", hWndIME
, msg
, wParam
, lParam
);
3304 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
3305 (msg
== WM_IME_SETCONTEXT
) ||
3306 (msg
== WM_IME_NOTIFY
) ||
3307 (msg
== WM_IME_COMPOSITIONFULL
) ||
3308 (msg
== WM_IME_SELECT
) ||
3309 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
3312 SendMessageW(hWndIME
, msg
, wParam
, lParam
);
3319 /***********************************************************************
3320 * ImmNotifyIME (IMM32.@)
3322 BOOL WINAPI
ImmNotifyIME(
3323 HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
3325 DWORD dwImeThreadId
, dwThreadId
;
3330 TRACE("(%p, %lu, %lu, %lu)\n", hIMC
, dwAction
, dwIndex
, dwValue
);
3334 dwImeThreadId
= Imm32QueryWindow(hIMC
, QUERY_WINDOW_UNIQUE_THREAD_ID
);
3335 dwThreadId
= GetCurrentThreadId();
3336 if (dwImeThreadId
!= dwThreadId
)
3340 hKL
= GetKeyboardLayout(0);
3341 pImeDpi
= ImmLockImeDpi(hKL
);
3342 if (pImeDpi
== NULL
)
3345 ret
= pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
3346 ImmUnlockImeDpi(pImeDpi
);
3350 /***********************************************************************
3351 * ImmRegisterWordA (IMM32.@)
3353 BOOL WINAPI
ImmRegisterWordA(
3354 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszRegister
)
3358 LPWSTR pszReadingW
= NULL
, pszRegisterW
= NULL
;
3361 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
3362 debugstr_a(lpszRegister
));
3364 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3368 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
3370 ret
= pImeDpi
->ImeRegisterWord(lpszReading
, dwStyle
, lpszRegister
);
3371 ImmUnlockImeDpi(pImeDpi
);
3377 cch
= lstrlenA(lpszReading
);
3378 pszReadingW
= Imm32HeapAlloc(0, (cch
+ 1) * sizeof(WCHAR
));
3379 if (pszReadingW
== NULL
)
3381 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, lpszReading
, cch
,
3382 pszReadingW
, cch
+ 1);
3383 pszReadingW
[cch
] = 0;
3388 cch
= lstrlenA(lpszRegister
);
3389 pszRegisterW
= Imm32HeapAlloc(0, (cch
+ 1) * sizeof(WCHAR
));
3390 if (pszRegisterW
== NULL
)
3392 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, lpszRegister
, cch
,
3393 pszRegisterW
, cch
+ 1);
3394 pszRegisterW
[cch
] = 0;
3397 ret
= pImeDpi
->ImeRegisterWord(pszReadingW
, dwStyle
, pszRegisterW
);
3401 HeapFree(g_hImm32Heap
, 0, pszReadingW
);
3403 HeapFree(g_hImm32Heap
, 0, pszRegisterW
);
3404 ImmUnlockImeDpi(pImeDpi
);
3408 /***********************************************************************
3409 * ImmRegisterWordW (IMM32.@)
3411 BOOL WINAPI
ImmRegisterWordW(
3412 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszRegister
)
3416 LPSTR pszReadingA
= NULL
, pszRegisterA
= NULL
;
3419 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
3420 debugstr_w(lpszRegister
));
3422 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
3426 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
3428 ret
= pImeDpi
->ImeRegisterWord(lpszReading
, dwStyle
, lpszRegister
);
3429 ImmUnlockImeDpi(pImeDpi
);
3435 cchW
= lstrlenW(lpszReading
);
3436 cchA
= (cchW
+ 1) * sizeof(WCHAR
);
3437 pszReadingA
= Imm32HeapAlloc(0, cchA
);
3440 cchA
= WideCharToMultiByte(CP_ACP
, 0, lpszReading
, cchW
, pszReadingA
, cchA
, NULL
, NULL
);
3441 pszReadingA
[cchA
] = 0;
3446 cchW
= lstrlenW(lpszRegister
);
3447 cchA
= (cchW
+ 1) * sizeof(WCHAR
);
3448 pszRegisterA
= Imm32HeapAlloc(0, cchA
);
3451 cchA
= WideCharToMultiByte(CP_ACP
, 0, lpszRegister
, cchW
, pszRegisterA
, cchA
, NULL
, NULL
);
3452 pszRegisterA
[cchA
] = 0;
3455 ret
= pImeDpi
->ImeRegisterWord(pszReadingA
, dwStyle
, pszRegisterA
);
3459 HeapFree(g_hImm32Heap
, 0, pszReadingA
);
3461 HeapFree(g_hImm32Heap
, 0, pszRegisterA
);
3462 ImmUnlockImeDpi(pImeDpi
);
3466 /***********************************************************************
3467 * ImmReleaseContext (IMM32.@)
3469 BOOL WINAPI
ImmReleaseContext(HWND hWnd
, HIMC hIMC
)
3471 static BOOL shown
= FALSE
;
3474 FIXME("(%p, %p): stub\n", hWnd
, hIMC
);
3480 /***********************************************************************
3481 * ImmRequestMessageA(IMM32.@)
3483 LRESULT WINAPI
ImmRequestMessageA(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
3485 InputContextData
*data
= get_imc_data(hIMC
);
3487 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
3489 if (data
) return SendMessageA(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
3491 SetLastError(ERROR_INVALID_HANDLE
);
3495 /***********************************************************************
3496 * ImmRequestMessageW(IMM32.@)
3498 LRESULT WINAPI
ImmRequestMessageW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
3500 InputContextData
*data
= get_imc_data(hIMC
);
3502 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
3504 if (data
) return SendMessageW(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
3506 SetLastError(ERROR_INVALID_HANDLE
);
3510 /***********************************************************************
3511 * ImmSetCandidateWindow (IMM32.@)
3513 BOOL WINAPI
ImmSetCandidateWindow(
3514 HIMC hIMC
, LPCANDIDATEFORM lpCandidate
)
3516 #define MAX_CANDIDATEFORM 4
3517 DWORD dwImeThreadId
, dwThreadId
;
3521 TRACE("(%p, %p)\n", hIMC
, lpCandidate
);
3523 if (lpCandidate
->dwIndex
>= MAX_CANDIDATEFORM
)
3526 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
3527 dwThreadId
= GetCurrentThreadId();
3528 if (dwImeThreadId
!= dwThreadId
)
3531 pIC
= ImmLockIMC(hIMC
);
3536 pIC
->cfCandForm
[lpCandidate
->dwIndex
] = *lpCandidate
;
3540 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCANDIDATEPOS
,
3541 IMN_SETCANDIDATEPOS
, (1 << lpCandidate
->dwIndex
));
3543 #undef MAX_CANDIDATEFORM
3546 static VOID APIENTRY
WideToAnsiLogFont(const LOGFONTW
*plfW
, LPLOGFONTA plfA
)
3549 size_t cchW
, cchA
= _countof(plfA
->lfFaceName
);
3550 RtlCopyMemory(plfA
, plfW
, offsetof(LOGFONTA
, lfFaceName
));
3551 StringCchLengthW(plfW
->lfFaceName
, _countof(plfW
->lfFaceName
), &cchW
);
3552 cchA
= WideCharToMultiByte(CP_ACP
, 0, plfW
->lfFaceName
, (INT
)cchW
,
3553 plfA
->lfFaceName
, (INT
)cchA
, NULL
, &bUsedDef
);
3554 if (cchA
> _countof(plfA
->lfFaceName
) - 1)
3555 cchA
= _countof(plfA
->lfFaceName
) - 1;
3556 plfA
->lfFaceName
[cchA
] = 0;
3559 static VOID APIENTRY
AnsiToWideLogFont(const LOGFONTA
*plfA
, LPLOGFONTW plfW
)
3561 size_t cchA
, cchW
= _countof(plfW
->lfFaceName
);
3562 RtlCopyMemory(plfW
, plfA
, offsetof(LOGFONTW
, lfFaceName
));
3563 StringCchLengthA(plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), &cchA
);
3564 cchW
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, plfA
->lfFaceName
, (INT
)cchA
,
3565 plfW
->lfFaceName
, cchW
);
3566 if (cchW
> _countof(plfW
->lfFaceName
) - 1)
3567 cchW
= _countof(plfW
->lfFaceName
) - 1;
3568 plfW
->lfFaceName
[cchW
] = 0;
3571 /***********************************************************************
3572 * ImmSetCompositionFontA (IMM32.@)
3574 BOOL WINAPI
ImmSetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
3577 DWORD dwImeThreadId
, dwThreadId
;
3578 PCLIENTIMC pClientImc
;
3580 LPINPUTCONTEXTDX pIC
;
3585 TRACE("(%p, %p)\n", hIMC
, lplf
);
3587 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
3588 dwThreadId
= GetCurrentThreadId();
3589 if (dwImeThreadId
!= dwThreadId
)
3592 pClientImc
= ImmLockClientImc(hIMC
);
3593 if (pClientImc
== NULL
)
3596 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
3597 ImmUnlockClientImc(pClientImc
);
3601 AnsiToWideLogFont(lplf
, &lfW
);
3602 return ImmSetCompositionFontW(hIMC
, &lfW
);
3605 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3609 pTeb
= NtCurrentTeb();
3610 if (pTeb
->Win32ClientInfo
[2] < 0x400)
3612 lcid
= GetSystemDefaultLCID();
3613 if (PRIMARYLANGID(lcid
) == LANG_JAPANESE
&& !(pIC
->dwUIFlags
& 2) &&
3614 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
3616 PostMessageA(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
3620 pIC
->lfFont
.A
= *lplf
;
3621 pIC
->fdwInit
|= INIT_LOGFONT
;
3626 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
3627 IMN_SETCOMPOSITIONFONT
, 0);
3631 /***********************************************************************
3632 * ImmSetCompositionFontW (IMM32.@)
3634 BOOL WINAPI
ImmSetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
3637 DWORD dwImeThreadId
, dwThreadId
;
3638 PCLIENTIMC pClientImc
;
3641 LPINPUTCONTEXTDX pIC
;
3645 TRACE("(%p, %p)\n", hIMC
, lplf
);
3647 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
3648 dwThreadId
= GetCurrentThreadId();
3649 if (dwImeThreadId
!= dwThreadId
)
3652 pClientImc
= ImmLockClientImc(hIMC
);
3653 if (pClientImc
== NULL
)
3656 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
3657 ImmUnlockClientImc(pClientImc
);
3661 WideToAnsiLogFont(lplf
, &lfA
);
3662 return ImmSetCompositionFontA(hIMC
, &lfA
);
3665 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
3669 pTeb
= NtCurrentTeb();
3670 if (pTeb
->Win32ClientInfo
[2] < 0x400)
3672 lcid
= GetSystemDefaultLCID();
3673 if (PRIMARYLANGID(lcid
) == LANG_JAPANESE
&&
3674 !(pIC
->dwUIFlags
& 2) &&
3675 pIC
->cfCompForm
.dwStyle
!= CFS_DEFAULT
)
3677 PostMessageW(pIC
->hWnd
, WM_IME_REPORT
, IR_CHANGECONVERT
, 0);
3681 pIC
->lfFont
.W
= *lplf
;
3682 pIC
->fdwInit
|= INIT_LOGFONT
;
3687 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
,
3688 IMN_SETCOMPOSITIONFONT
, 0);
3692 /***********************************************************************
3693 * ImmSetCompositionStringA (IMM32.@)
3695 BOOL WINAPI
ImmSetCompositionStringA(
3696 HIMC hIMC
, DWORD dwIndex
,
3697 LPCVOID lpComp
, DWORD dwCompLen
,
3698 LPCVOID lpRead
, DWORD dwReadLen
)
3702 WCHAR
*CompBuffer
= NULL
;
3703 WCHAR
*ReadBuffer
= NULL
;
3705 InputContextData
*data
= get_imc_data(hIMC
);
3707 TRACE("(%p, %d, %p, %d, %p, %d):\n",
3708 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
3713 if (!(dwIndex
== SCS_SETSTR
||
3714 dwIndex
== SCS_CHANGEATTR
||
3715 dwIndex
== SCS_CHANGECLAUSE
||
3716 dwIndex
== SCS_SETRECONVERTSTRING
||
3717 dwIndex
== SCS_QUERYRECONVERTSTRING
))
3720 if (!is_himc_ime_unicode(data
))
3721 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
3722 dwCompLen
, lpRead
, dwReadLen
);
3724 comp_len
= MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0);
3727 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
* sizeof(WCHAR
));
3728 MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
);
3731 read_len
= MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0);
3734 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
* sizeof(WCHAR
));
3735 MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
);
3738 rc
= ImmSetCompositionStringW(hIMC
, dwIndex
, CompBuffer
, comp_len
,
3739 ReadBuffer
, read_len
);
3741 HeapFree(GetProcessHeap(), 0, CompBuffer
);
3742 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
3747 /***********************************************************************
3748 * ImmSetCompositionStringW (IMM32.@)
3750 BOOL WINAPI
ImmSetCompositionStringW(
3751 HIMC hIMC
, DWORD dwIndex
,
3752 LPCVOID lpComp
, DWORD dwCompLen
,
3753 LPCVOID lpRead
, DWORD dwReadLen
)
3757 CHAR
*CompBuffer
= NULL
;
3758 CHAR
*ReadBuffer
= NULL
;
3760 InputContextData
*data
= get_imc_data(hIMC
);
3762 TRACE("(%p, %d, %p, %d, %p, %d):\n",
3763 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
3768 if (!(dwIndex
== SCS_SETSTR
||
3769 dwIndex
== SCS_CHANGEATTR
||
3770 dwIndex
== SCS_CHANGECLAUSE
||
3771 dwIndex
== SCS_SETRECONVERTSTRING
||
3772 dwIndex
== SCS_QUERYRECONVERTSTRING
))
3775 if (is_himc_ime_unicode(data
))
3776 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
3777 dwCompLen
, lpRead
, dwReadLen
);
3779 comp_len
= WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0, NULL
,
3783 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
);
3784 WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
,
3788 read_len
= WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0, NULL
,
3792 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
);
3793 WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
,
3797 rc
= ImmSetCompositionStringA(hIMC
, dwIndex
, CompBuffer
, comp_len
,
3798 ReadBuffer
, read_len
);
3800 HeapFree(GetProcessHeap(), 0, CompBuffer
);
3801 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
3806 /***********************************************************************
3807 * ImmSetCompositionWindow (IMM32.@)
3809 BOOL WINAPI
ImmSetCompositionWindow(
3810 HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
3812 DWORD dwImeThreadId
, dwThreadId
;
3816 dwImeThreadId
= NtUserQueryInputContext(hIMC
, 1);
3817 dwThreadId
= GetCurrentThreadId();
3818 if (dwImeThreadId
!= dwThreadId
)
3821 pIC
= ImmLockIMC(hIMC
);
3825 pIC
->cfCompForm
= *lpCompForm
;
3826 pIC
->fdwInit
|= INIT_COMPFORM
;
3832 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
3833 IMC_SETCOMPOSITIONWINDOW
, IMN_SETCOMPOSITIONWINDOW
, 0);
3837 /***********************************************************************
3838 * ImmSetConversionStatus (IMM32.@)
3840 BOOL WINAPI
ImmSetConversionStatus(
3841 HIMC hIMC
, DWORD fdwConversion
, DWORD fdwSentence
)
3845 DWORD dwImeThreadId
, dwThreadId
, dwOldConversion
, dwOldSentence
;
3846 BOOL fConversionChange
= FALSE
, fSentenceChange
= FALSE
;
3849 TRACE("(%p, 0x%lX, 0x%lX)\n", hIMC
, fdwConversion
, fdwSentence
);
3851 hKL
= GetKeyboardLayout(0);
3852 if (!IS_IME_HKL(hKL
))
3854 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
3861 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
3862 dwThreadId
= GetCurrentThreadId();
3863 if (dwImeThreadId
!= dwThreadId
)
3866 pIC
= ImmLockIMC(hIMC
);
3870 if (pIC
->fdwConversion
!= fdwConversion
)
3872 dwOldConversion
= pIC
->fdwConversion
;
3873 pIC
->fdwConversion
= fdwConversion
;
3874 fConversionChange
= TRUE
;
3877 if (pIC
->fdwSentence
!= fdwSentence
)
3879 dwOldSentence
= pIC
->fdwSentence
;
3880 pIC
->fdwSentence
= fdwSentence
;
3881 fSentenceChange
= TRUE
;
3887 if (fConversionChange
)
3889 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldConversion
,
3890 IMC_SETCONVERSIONMODE
, IMN_SETCONVERSIONMODE
, 0);
3891 Imm32NotifyIMEStatus(hWnd
, hIMC
, fdwConversion
);
3894 if (fSentenceChange
)
3896 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, dwOldSentence
,
3897 IMC_SETSENTENCEMODE
, IMN_SETSENTENCEMODE
, 0);
3903 /***********************************************************************
3904 * ImmLockImeDpi (IMM32.@)
3906 PIMEDPI WINAPI
ImmLockImeDpi(HKL hKL
)
3908 PIMEDPI pImeDpi
= NULL
;
3910 TRACE("(%p)\n", hKL
);
3912 RtlEnterCriticalSection(&g_csImeDpi
);
3915 for (pImeDpi
= g_pImeDpiList
; pImeDpi
; pImeDpi
= pImeDpi
->pNext
)
3917 if (pImeDpi
->hKL
== hKL
) /* found */
3919 /* lock if possible */
3920 if (pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
)
3923 ++(pImeDpi
->cLockObj
);
3928 RtlLeaveCriticalSection(&g_csImeDpi
);
3932 /***********************************************************************
3933 * ImmUnlockImeDpi (IMM32.@)
3935 VOID WINAPI
ImmUnlockImeDpi(PIMEDPI pImeDpi
)
3939 TRACE("(%p)\n", pImeDpi
);
3941 if (pImeDpi
== NULL
)
3944 RtlEnterCriticalSection(&g_csImeDpi
);
3947 --(pImeDpi
->cLockObj
);
3948 if (pImeDpi
->cLockObj
!= 0)
3950 RtlLeaveCriticalSection(&g_csImeDpi
);
3954 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
) == 0)
3956 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_LOCKED
) == 0 ||
3957 (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_END_UNLOAD
) == 0)
3959 RtlLeaveCriticalSection(&g_csImeDpi
);
3964 /* Remove from list */
3965 for (ppEntry
= &g_pImeDpiList
; *ppEntry
; ppEntry
= &((*ppEntry
)->pNext
))
3967 if (*ppEntry
== pImeDpi
) /* found */
3969 *ppEntry
= pImeDpi
->pNext
;
3974 Imm32FreeImeDpi(pImeDpi
, TRUE
);
3975 HeapFree(g_hImm32Heap
, 0, pImeDpi
);
3977 RtlLeaveCriticalSection(&g_csImeDpi
);
3980 /***********************************************************************
3981 * ImmSetOpenStatus (IMM32.@)
3983 BOOL WINAPI
ImmSetOpenStatus(HIMC hIMC
, BOOL fOpen
)
3985 DWORD dwImeThreadId
, dwThreadId
, dwConversion
;
3988 BOOL bHasChange
= FALSE
;
3990 TRACE("(%p, %d)\n", hIMC
, fOpen
);
3992 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
3993 dwThreadId
= GetCurrentThreadId();
3994 if (dwImeThreadId
!= dwThreadId
)
3997 pIC
= ImmLockIMC(hIMC
);
4001 if (pIC
->fOpen
!= fOpen
)
4005 dwConversion
= pIC
->fdwConversion
;
4013 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
4014 IMC_SETOPENSTATUS
, IMN_SETOPENSTATUS
, 0);
4015 Imm32NotifyIMEStatus(hWnd
, hIMC
, dwConversion
);
4021 /***********************************************************************
4022 * ImmSetStatusWindowPos (IMM32.@)
4024 BOOL WINAPI
ImmSetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
4028 DWORD dwImeThreadId
, dwThreadId
;
4030 TRACE("(%p, {%ld, %ld})\n", hIMC
, lpptPos
->x
, lpptPos
->y
);
4032 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
4033 dwThreadId
= GetCurrentThreadId();
4034 if (dwImeThreadId
!= dwThreadId
)
4037 pIC
= ImmLockIMC(hIMC
);
4042 pIC
->ptStatusWndPos
= *lpptPos
;
4043 pIC
->fdwInit
|= INIT_STATUSWNDPOS
;
4047 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
4048 IMC_SETSTATUSWINDOWPOS
, IMN_SETSTATUSWINDOWPOS
, 0);
4052 /***********************************************************************
4053 * ImmCreateSoftKeyboard(IMM32.@)
4055 HWND WINAPI
ImmCreateSoftKeyboard(UINT uType
, UINT hOwner
, int x
, int y
)
4057 FIXME("(%d, %d, %d, %d): stub\n", uType
, hOwner
, x
, y
);
4058 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
4062 /***********************************************************************
4063 * ImmDestroySoftKeyboard(IMM32.@)
4065 BOOL WINAPI
ImmDestroySoftKeyboard(HWND hSoftWnd
)
4067 TRACE("(%p)\n", hSoftWnd
);
4068 return DestroyWindow(hSoftWnd
);
4071 /***********************************************************************
4072 * ImmShowSoftKeyboard(IMM32.@)
4074 BOOL WINAPI
ImmShowSoftKeyboard(HWND hSoftWnd
, int nCmdShow
)
4076 TRACE("(%p, %d)\n", hSoftWnd
, nCmdShow
);
4078 return ShowWindow(hSoftWnd
, nCmdShow
);
4082 /***********************************************************************
4083 * ImmSimulateHotKey (IMM32.@)
4085 BOOL WINAPI
ImmSimulateHotKey(HWND hWnd
, DWORD dwHotKeyID
)
4092 TRACE("(%p, 0x%lX)\n", hWnd
, dwHotKeyID
);
4094 hIMC
= ImmGetContext(hWnd
);
4095 dwThreadId
= GetWindowThreadProcessId(hWnd
, NULL
);
4096 hKL
= GetKeyboardLayout(dwThreadId
);
4097 ret
= Imm32ProcessHotKey(hWnd
, hIMC
, hKL
, dwHotKeyID
);
4098 ImmReleaseContext(hWnd
, hIMC
);
4102 /***********************************************************************
4103 * ImmUnregisterWordA (IMM32.@)
4105 BOOL WINAPI
ImmUnregisterWordA(
4106 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszUnregister
)
4110 LPWSTR pszReadingW
= NULL
, pszUnregisterW
= NULL
;
4113 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
4114 debugstr_a(lpszUnregister
));
4116 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
4117 if (pImeDpi
== NULL
)
4120 if (!(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
))
4122 ret
= pImeDpi
->ImeUnregisterWord(lpszReading
, dwStyle
, lpszUnregister
);
4123 ImmUnlockImeDpi(pImeDpi
);
4129 cch
= lstrlenA(lpszReading
);
4130 pszReadingW
= Imm32HeapAlloc(0, (cch
+ 1) * sizeof(WCHAR
));
4131 if (pszReadingW
== NULL
)
4133 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, lpszReading
, cch
,
4134 pszReadingW
, cch
+ 1);
4135 pszReadingW
[cch
] = 0;
4140 cch
= lstrlenA(lpszUnregister
);
4141 pszUnregisterW
= Imm32HeapAlloc(0, (cch
+ 1) * sizeof(WCHAR
));
4142 if (pszUnregisterW
== NULL
)
4144 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, lpszUnregister
, cch
,
4145 pszUnregisterW
, cch
+ 1);
4146 pszUnregisterW
[cch
] = 0;
4149 ret
= pImeDpi
->ImeUnregisterWord(pszReadingW
, dwStyle
, pszUnregisterW
);
4153 HeapFree(g_hImm32Heap
, 0, pszReadingW
);
4155 HeapFree(g_hImm32Heap
, 0, pszUnregisterW
);
4156 ImmUnlockImeDpi(pImeDpi
);
4160 /***********************************************************************
4161 * ImmUnregisterWordW (IMM32.@)
4163 BOOL WINAPI
ImmUnregisterWordW(
4164 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszUnregister
)
4168 LPSTR pszReadingA
= NULL
, pszUnregisterA
= NULL
;
4171 TRACE("(%p, %s, 0x%lX, %s)\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
4172 debugstr_w(lpszUnregister
));
4174 pImeDpi
= ImmLockOrLoadImeDpi(hKL
);
4178 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_UNICODE
)
4180 ret
= pImeDpi
->ImeUnregisterWord(lpszReading
, dwStyle
, lpszUnregister
);
4181 ImmUnlockImeDpi(pImeDpi
);
4187 cchW
= lstrlenW(lpszReading
);
4188 cchA
= (cchW
+ 1) * sizeof(WCHAR
);
4189 pszReadingA
= Imm32HeapAlloc(0, cchA
);
4192 cchA
= WideCharToMultiByte(CP_ACP
, 0, lpszReading
, cchW
, pszReadingA
, cchA
, NULL
, NULL
);
4193 pszReadingA
[cchA
] = 0;
4198 cchW
= lstrlenW(lpszUnregister
);
4199 cchA
= (cchW
+ 1) * sizeof(WCHAR
);
4200 pszUnregisterA
= Imm32HeapAlloc(0, cchA
);
4201 if (!pszUnregisterA
)
4203 cchA
= WideCharToMultiByte(CP_ACP
, 0, lpszUnregister
, cchW
, pszUnregisterA
, cchA
, NULL
, NULL
);
4204 pszUnregisterA
[cchA
] = 0;
4207 ret
= pImeDpi
->ImeUnregisterWord(pszReadingA
, dwStyle
, pszUnregisterA
);
4211 HeapFree(g_hImm32Heap
, 0, pszReadingA
);
4213 HeapFree(g_hImm32Heap
, 0, pszUnregisterA
);
4214 ImmUnlockImeDpi(pImeDpi
);
4218 /***********************************************************************
4219 * ImmGetImeMenuItemsA (IMM32.@)
4221 DWORD WINAPI
ImmGetImeMenuItemsA( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
4222 LPIMEMENUITEMINFOA lpImeParentMenu
, LPIMEMENUITEMINFOA lpImeMenu
,
4225 InputContextData
*data
= get_imc_data(hIMC
);
4226 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
4227 lpImeParentMenu
, lpImeMenu
, dwSize
);
4231 SetLastError(ERROR_INVALID_HANDLE
);
4235 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
4237 if (!is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
4238 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4239 (IMEMENUITEMINFOW
*)lpImeParentMenu
,
4240 (IMEMENUITEMINFOW
*)lpImeMenu
, dwSize
);
4243 IMEMENUITEMINFOW lpImeParentMenuW
;
4244 IMEMENUITEMINFOW
*lpImeMenuW
, *parent
= NULL
;
4247 if (lpImeParentMenu
)
4248 parent
= &lpImeParentMenuW
;
4251 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOA
);
4252 dwSize
= count
* sizeof(IMEMENUITEMINFOW
);
4253 lpImeMenuW
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
4258 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4259 parent
, lpImeMenuW
, dwSize
);
4261 if (lpImeParentMenu
)
4263 memcpy(lpImeParentMenu
,&lpImeParentMenuW
,sizeof(IMEMENUITEMINFOA
));
4264 lpImeParentMenu
->hbmpItem
= lpImeParentMenuW
.hbmpItem
;
4265 WideCharToMultiByte(CP_ACP
, 0, lpImeParentMenuW
.szString
,
4266 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
,
4269 if (lpImeMenu
&& rc
)
4272 for (i
= 0; i
< rc
; i
++)
4274 memcpy(&lpImeMenu
[i
],&lpImeMenuW
[1],sizeof(IMEMENUITEMINFOA
));
4275 lpImeMenu
[i
].hbmpItem
= lpImeMenuW
[i
].hbmpItem
;
4276 WideCharToMultiByte(CP_ACP
, 0, lpImeMenuW
[i
].szString
,
4277 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
,
4281 HeapFree(GetProcessHeap(),0,lpImeMenuW
);
4289 /***********************************************************************
4290 * ImmGetImeMenuItemsW (IMM32.@)
4292 DWORD WINAPI
ImmGetImeMenuItemsW( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
4293 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
4296 InputContextData
*data
= get_imc_data(hIMC
);
4297 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
4298 lpImeParentMenu
, lpImeMenu
, dwSize
);
4302 SetLastError(ERROR_INVALID_HANDLE
);
4306 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
4308 if (is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
4309 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4310 lpImeParentMenu
, lpImeMenu
, dwSize
);
4313 IMEMENUITEMINFOA lpImeParentMenuA
;
4314 IMEMENUITEMINFOA
*lpImeMenuA
, *parent
= NULL
;
4317 if (lpImeParentMenu
)
4318 parent
= &lpImeParentMenuA
;
4321 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOW
);
4322 dwSize
= count
* sizeof(IMEMENUITEMINFOA
);
4323 lpImeMenuA
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
4328 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
4329 (IMEMENUITEMINFOW
*)parent
,
4330 (IMEMENUITEMINFOW
*)lpImeMenuA
, dwSize
);
4332 if (lpImeParentMenu
)
4334 memcpy(lpImeParentMenu
,&lpImeParentMenuA
,sizeof(IMEMENUITEMINFOA
));
4335 lpImeParentMenu
->hbmpItem
= lpImeParentMenuA
.hbmpItem
;
4336 MultiByteToWideChar(CP_ACP
, 0, lpImeParentMenuA
.szString
,
4337 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
);
4339 if (lpImeMenu
&& rc
)
4342 for (i
= 0; i
< rc
; i
++)
4344 memcpy(&lpImeMenu
[i
],&lpImeMenuA
[1],sizeof(IMEMENUITEMINFOA
));
4345 lpImeMenu
[i
].hbmpItem
= lpImeMenuA
[i
].hbmpItem
;
4346 MultiByteToWideChar(CP_ACP
, 0, lpImeMenuA
[i
].szString
,
4347 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
);
4350 HeapFree(GetProcessHeap(),0,lpImeMenuA
);
4358 /***********************************************************************
4359 * ImmLockIMC(IMM32.@)
4361 LPINPUTCONTEXT WINAPI
ImmLockIMC(HIMC hIMC
)
4363 InputContextData
*data
= get_imc_data(hIMC
);
4371 /***********************************************************************
4372 * ImmUnlockIMC(IMM32.@)
4374 BOOL WINAPI
ImmUnlockIMC(HIMC hIMC
)
4376 PCLIENTIMC pClientImc
;
4379 pClientImc
= ImmLockClientImc(hIMC
);
4380 if (pClientImc
== NULL
)
4383 hClientImc
= pClientImc
->hImc
;
4385 LocalUnlock(hClientImc
);
4387 InterlockedDecrement(&pClientImc
->cLockObj
);
4388 ImmUnlockClientImc(pClientImc
);
4392 /***********************************************************************
4393 * ImmGetIMCLockCount(IMM32.@)
4395 DWORD WINAPI
ImmGetIMCLockCount(HIMC hIMC
)
4399 PCLIENTIMC pClientImc
;
4401 pClientImc
= ImmLockClientImc(hIMC
);
4402 if (pClientImc
== NULL
)
4406 hClientImc
= pClientImc
->hImc
;
4408 ret
= (LocalFlags(hClientImc
) & LMEM_LOCKCOUNT
);
4410 ImmUnlockClientImc(pClientImc
);
4414 /***********************************************************************
4415 * ImmCreateIMCC(IMM32.@)
4417 HIMCC WINAPI
ImmCreateIMCC(DWORD size
)
4421 return LocalAlloc(LHND
, size
);
4424 /***********************************************************************
4425 * ImmDestroyIMCC(IMM32.@)
4427 HIMCC WINAPI
ImmDestroyIMCC(HIMCC block
)
4430 return LocalFree(block
);
4434 /***********************************************************************
4435 * ImmLockIMCC(IMM32.@)
4437 LPVOID WINAPI
ImmLockIMCC(HIMCC imcc
)
4440 return LocalLock(imcc
);
4444 /***********************************************************************
4445 * ImmUnlockIMCC(IMM32.@)
4447 BOOL WINAPI
ImmUnlockIMCC(HIMCC imcc
)
4450 return LocalUnlock(imcc
);
4454 /***********************************************************************
4455 * ImmGetIMCCLockCount(IMM32.@)
4457 DWORD WINAPI
ImmGetIMCCLockCount(HIMCC imcc
)
4459 return LocalFlags(imcc
) & LMEM_LOCKCOUNT
;
4462 /***********************************************************************
4463 * ImmReSizeIMCC(IMM32.@)
4465 HIMCC WINAPI
ImmReSizeIMCC(HIMCC imcc
, DWORD size
)
4469 return LocalReAlloc(imcc
, size
, LHND
);
4472 /***********************************************************************
4473 * ImmGetIMCCSize(IMM32.@)
4475 DWORD WINAPI
ImmGetIMCCSize(HIMCC imcc
)
4478 return LocalSize(imcc
);
4482 /***********************************************************************
4483 * ImmGenerateMessage(IMM32.@)
4485 BOOL WINAPI
ImmGenerateMessage(HIMC hIMC
)
4487 InputContextData
*data
= get_imc_data(hIMC
);
4491 SetLastError(ERROR_INVALID_HANDLE
);
4495 TRACE("%i messages queued\n",data
->IMC
.dwNumMsgBuf
);
4496 if (data
->IMC
.dwNumMsgBuf
> 0)
4498 LPTRANSMSG lpTransMsg
;
4500 DWORD i
, dwNumMsgBuf
;
4502 /* We are going to detach our hMsgBuff so that if processing messages
4503 generates new messages they go into a new buffer */
4504 hMsgBuf
= data
->IMC
.hMsgBuf
;
4505 dwNumMsgBuf
= data
->IMC
.dwNumMsgBuf
;
4507 data
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
4508 data
->IMC
.dwNumMsgBuf
= 0;
4510 lpTransMsg
= ImmLockIMCC(hMsgBuf
);
4511 for (i
= 0; i
< dwNumMsgBuf
; i
++)
4512 ImmInternalSendIMEMessage(data
, lpTransMsg
[i
].message
, lpTransMsg
[i
].wParam
, lpTransMsg
[i
].lParam
);
4514 ImmUnlockIMCC(hMsgBuf
);
4515 ImmDestroyIMCC(hMsgBuf
);
4521 /***********************************************************************
4522 * ImmTranslateMessage(IMM32.@)
4523 * ( Undocumented, call internally and from user32.dll )
4525 BOOL WINAPI
ImmTranslateMessage(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lKeyData
)
4527 InputContextData
*data
;
4528 HIMC imc
= ImmGetContext(hwnd
);
4534 static const DWORD list_count
= 10;
4536 TRACE("%p %x %x %x\n",hwnd
, msg
, (UINT
)wParam
, (UINT
)lKeyData
);
4543 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeToAsciiEx
)
4546 GetKeyboardState(state
);
4547 scancode
= lKeyData
>> 0x10 & 0xff;
4549 list
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, list_count
* sizeof(TRANSMSG
) + sizeof(DWORD
));
4550 ((DWORD
*)list
)[0] = list_count
;
4552 if (data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_KBD_CHAR_FIRST
)
4556 if (!is_himc_ime_unicode(data
))
4557 ToAscii(data
->lastVK
, scancode
, state
, &chr
, 0);
4559 ToUnicodeEx(data
->lastVK
, scancode
, state
, &chr
, 1, 0, GetKeyboardLayout(0));
4560 uVirtKey
= MAKELONG(data
->lastVK
,chr
);
4563 uVirtKey
= data
->lastVK
;
4565 msg_count
= data
->immKbd
->pImeToAsciiEx(uVirtKey
, scancode
, state
, list
, 0, imc
);
4566 TRACE("%i messages generated\n",msg_count
);
4567 if (msg_count
&& msg_count
<= list_count
)
4570 LPTRANSMSG msgs
= (LPTRANSMSG
)((LPBYTE
)list
+ sizeof(DWORD
));
4572 for (i
= 0; i
< msg_count
; i
++)
4573 ImmInternalPostIMEMessage(data
, msgs
[i
].message
, msgs
[i
].wParam
, msgs
[i
].lParam
);
4575 else if (msg_count
> list_count
)
4576 ImmGenerateMessage(imc
);
4578 HeapFree(GetProcessHeap(),0,list
);
4580 data
->lastVK
= VK_PROCESSKEY
;
4582 return (msg_count
> 0);
4585 /***********************************************************************
4586 * ImmProcessKey(IMM32.@)
4587 * ( Undocumented, called from user32.dll )
4589 BOOL WINAPI
ImmProcessKey(HWND hwnd
, HKL hKL
, UINT vKey
, LPARAM lKeyData
, DWORD unknown
)
4591 InputContextData
*data
;
4592 HIMC imc
= ImmGetContext(hwnd
);
4595 TRACE("%p %p %x %x %x\n",hwnd
, hKL
, vKey
, (UINT
)lKeyData
, unknown
);
4602 /* Make sure we are inputting to the correct keyboard */
4603 if (data
->immKbd
->hkl
!= hKL
)
4605 ImmHkl
*new_hkl
= IMM_GetImmHkl(hKL
);
4608 data
->immKbd
->pImeSelect(imc
, FALSE
);
4609 data
->immKbd
->uSelected
--;
4610 data
->immKbd
= new_hkl
;
4611 data
->immKbd
->pImeSelect(imc
, TRUE
);
4612 data
->immKbd
->uSelected
++;
4618 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeProcessKey
)
4621 GetKeyboardState(state
);
4622 if (data
->immKbd
->pImeProcessKey(imc
, vKey
, lKeyData
, state
))
4624 data
->lastVK
= vKey
;
4628 data
->lastVK
= VK_PROCESSKEY
;
4632 /***********************************************************************
4633 * ImmDisableTextFrameService(IMM32.@)
4635 BOOL WINAPI
ImmDisableTextFrameService(DWORD dwThreadId
)
4641 /***********************************************************************
4642 * ImmEnumInputContext(IMM32.@)
4644 BOOL WINAPI
ImmEnumInputContext(DWORD dwThreadId
, IMCENUMPROC lpfn
, LPARAM lParam
)
4647 DWORD dwIndex
, dwCount
;
4651 TRACE("(%lu, %p, %p)\n", dwThreadId
, lpfn
, lParam
);
4653 dwCount
= Imm32AllocAndBuildHimcList(dwThreadId
, &phList
);
4657 for (dwIndex
= 0; dwIndex
< dwCount
; ++dwIndex
)
4659 hIMC
= phList
[dwIndex
];
4660 ret
= (*lpfn
)(hIMC
, lParam
);
4665 HeapFree(g_hImm32Heap
, 0, phList
);
4669 /***********************************************************************
4670 * ImmGetHotKey(IMM32.@)
4674 ImmGetHotKey(IN DWORD dwHotKey
,
4675 OUT LPUINT lpuModifiers
,
4679 TRACE("%lx, %p, %p, %p\n", dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
4680 if (lpuModifiers
&& lpuVKey
)
4681 return NtUserGetImeHotKey(dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
4685 /***********************************************************************
4686 * ImmDisableLegacyIME(IMM32.@)
4688 BOOL WINAPI
ImmDisableLegacyIME(void)
4694 /***********************************************************************
4695 * ImmSetActiveContext(IMM32.@)
4697 BOOL WINAPI
ImmSetActiveContext(HWND hwnd
, HIMC hIMC
, BOOL fFlag
)
4699 FIXME("(%p, %p, %d): stub\n", hwnd
, hIMC
, fFlag
);
4703 /***********************************************************************
4704 * ImmSetActiveContextConsoleIME(IMM32.@)
4706 BOOL WINAPI
ImmSetActiveContextConsoleIME(HWND hwnd
, BOOL fFlag
)
4709 TRACE("(%p, %d)\n", hwnd
, fFlag
);
4711 hIMC
= ImmGetContext(hwnd
);
4713 return ImmSetActiveContext(hwnd
, hIMC
, fFlag
);
4717 /***********************************************************************
4718 * ImmRegisterClient(IMM32.@)
4719 * ( Undocumented, called from user32.dll )
4721 BOOL WINAPI
ImmRegisterClient(PSHAREDINFO ptr
, HINSTANCE hMod
)
4723 g_SharedInfo
= *ptr
;
4724 g_psi
= g_SharedInfo
.psi
;
4725 return Imm32InitInstance(hMod
);
4728 /***********************************************************************
4729 * CtfImmIsTextFrameServiceDisabled(IMM32.@)
4731 BOOL WINAPI
CtfImmIsTextFrameServiceDisabled(VOID
)
4733 PTEB pTeb
= NtCurrentTeb();
4734 if (((PW32CLIENTINFO
)pTeb
->Win32ClientInfo
)->CI_flags
& CI_TFSDISABLED
)
4739 /***********************************************************************
4740 * ImmGetImeInfoEx (IMM32.@)
4743 static BOOL APIENTRY
Imm32GetImeInfoEx(PIMEINFOEX pImeInfoEx
, IMEINFOEXCLASS SearchType
)
4745 return NtUserGetImeInfoEx(pImeInfoEx
, SearchType
);
4749 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx
,
4750 IMEINFOEXCLASS SearchType
,
4753 BOOL bDisabled
= FALSE
;
4759 case ImeInfoExKeyboardLayout
:
4762 case ImeInfoExImeWindow
:
4763 bDisabled
= CtfImmIsTextFrameServiceDisabled();
4764 SearchType
= ImeInfoExKeyboardLayout
;
4767 case ImeInfoExImeFileName
:
4768 StringCchCopyW(pImeInfoEx
->wszImeFile
, _countof(pImeInfoEx
->wszImeFile
),
4773 hKL
= *(HKL
*)pvSearchKey
;
4774 pImeInfoEx
->hkl
= hKL
;
4776 if (!IS_IME_HKL(hKL
))
4778 if (g_psi
&& (g_psi
->dwSRVIFlags
& SRVINFO_CICERO_ENABLED
))
4780 pTeb
= NtCurrentTeb();
4781 if (((PW32CLIENTINFO
)pTeb
->Win32ClientInfo
)->W32ClientInfo
[0] & 2)
4790 return Imm32GetImeInfoEx(pImeInfoEx
, SearchType
);
4793 BOOL WINAPI
User32InitializeImmEntryTable(DWORD
);
4795 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpReserved
)
4801 TRACE("(%p, 0x%X, %p)\n", hinstDLL
, fdwReason
, lpReserved
);
4805 case DLL_PROCESS_ATTACH
:
4806 //Imm32GenerateRandomSeed(hinstDLL, 1, lpReserved); // Non-sense
4807 if (!Imm32InitInstance(hinstDLL
))
4809 ERR("Imm32InitInstance failed\n");
4812 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC
))
4814 ERR("User32InitializeImmEntryTable failed\n");
4819 case DLL_THREAD_ATTACH
:
4822 case DLL_THREAD_DETACH
:
4823 if (g_psi
== NULL
|| !(g_psi
->dwSRVIFlags
& SRVINFO_IMM32
))
4826 pTeb
= NtCurrentTeb();
4827 if (pTeb
->Win32ThreadInfo
== NULL
)
4830 hKL
= GetKeyboardLayout(0);
4831 hWnd
= (HWND
)Imm32GetThreadState(THREADSTATE_CAPTUREWINDOW
);
4832 Imm32CleanupContext(hWnd
, hKL
, TRUE
);
4835 case DLL_PROCESS_DETACH
:
4836 RtlDeleteCriticalSection(&g_csImeDpi
);