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
24 #include "imm_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
28 #define IMM_INIT_MAGIC 0x19650412
29 BOOL WINAPI
User32InitializeImmEntryTable(DWORD
);
34 UINT WM_MSIME_SERVICE
;
35 UINT WM_MSIME_RECONVERTOPTIONS
;
37 UINT WM_MSIME_RECONVERTREQUEST
;
38 UINT WM_MSIME_RECONVERT
;
39 UINT WM_MSIME_QUERYPOSITION
;
40 UINT WM_MSIME_DOCUMENTFEED
;
51 LONG refcount
; /* guarded by ime_cs */
59 struct list input_contexts
;
61 BOOL (WINAPI
*pImeInquire
)(IMEINFO
*, void *, DWORD
);
62 BOOL (WINAPI
*pImeConfigure
)(HKL
, HWND
, DWORD
, void *);
63 BOOL (WINAPI
*pImeDestroy
)(UINT
);
64 LRESULT (WINAPI
*pImeEscape
)(HIMC
, UINT
, void *);
65 BOOL (WINAPI
*pImeSelect
)(HIMC
, BOOL
);
66 BOOL (WINAPI
*pImeSetActiveContext
)(HIMC
, BOOL
);
67 UINT (WINAPI
*pImeToAsciiEx
)(UINT
, UINT
, const BYTE
*, TRANSMSGLIST
*, UINT
, HIMC
);
68 BOOL (WINAPI
*pNotifyIME
)(HIMC
, DWORD
, DWORD
, DWORD
);
69 BOOL (WINAPI
*pImeRegisterWord
)(const void/*TCHAR*/*, DWORD
, const void/*TCHAR*/*);
70 BOOL (WINAPI
*pImeUnregisterWord
)(const void/*TCHAR*/*, DWORD
, const void/*TCHAR*/*);
71 UINT (WINAPI
*pImeEnumRegisterWord
)(void */
*REGISTERWORDENUMPROCW*/
, const void/*TCHAR*/*, DWORD
, const void/*TCHAR*/*, void *);
72 BOOL (WINAPI
*pImeSetCompositionString
)(HIMC
, DWORD
, const void/*TCHAR*/*, DWORD
, const void/*TCHAR*/*, DWORD
);
73 DWORD (WINAPI
*pImeConversionList
)(HIMC
, const void/*TCHAR*/*, CANDIDATELIST
*, DWORD
, UINT
);
74 UINT (WINAPI
*pImeGetRegisterWordStyle
)(UINT
, void/*STYLEBUFW*/*);
75 BOOL (WINAPI
*pImeProcessKey
)(HIMC
, UINT
, LPARAM
, const BYTE
*);
76 DWORD (WINAPI
*pImeGetImeMenuItems
)(HIMC
, DWORD
, DWORD
, void/*IMEMENUITEMINFOW*/*, void/*IMEMENUITEMINFOW*/*, DWORD
);
79 static HRESULT (WINAPI
*pCoRevokeInitializeSpy
)(ULARGE_INTEGER cookie
);
80 static void (WINAPI
*pCoUninitialize
)(void);
91 HWND ui_hwnd
; /* IME UI window, on the default input context */
94 #define WINE_IMC_VALID_MAGIC 0x56434D49
98 IInitializeSpy IInitializeSpy_iface
;
100 ULARGE_INTEGER cookie
;
104 IMM_APT_CREATED
= 0x2,
105 IMM_APT_CAN_FREE
= 0x4,
110 static CRITICAL_SECTION ime_cs
;
111 static CRITICAL_SECTION_DEBUG ime_cs_debug
=
114 { &ime_cs_debug
.ProcessLocksList
, &ime_cs_debug
.ProcessLocksList
},
115 0, 0, { (DWORD_PTR
)(__FILE__
": ime_cs") }
117 static CRITICAL_SECTION ime_cs
= { &ime_cs_debug
, -1, 0, 0, 0, 0 };
118 static struct list ime_list
= LIST_INIT( ime_list
);
120 static const WCHAR layouts_formatW
[] = L
"System\\CurrentControlSet\\Control\\Keyboard Layouts\\%08lx";
122 static const char *debugstr_composition( const COMPOSITIONFORM
*composition
)
124 if (!composition
) return "(null)";
125 return wine_dbg_sprintf( "style %#lx, pos %s, area %s", composition
->dwStyle
,
126 wine_dbgstr_point( &composition
->ptCurrentPos
),
127 wine_dbgstr_rect( &composition
->rcArea
) );
130 static const char *debugstr_candidate( const CANDIDATEFORM
*candidate
)
132 if (!candidate
) return "(null)";
133 return wine_dbg_sprintf( "idx %#lx, style %#lx, pos %s, area %s", candidate
->dwIndex
,
134 candidate
->dwStyle
, wine_dbgstr_point( &candidate
->ptCurrentPos
),
135 wine_dbgstr_rect( &candidate
->rcArea
) );
138 static BOOL
ime_is_unicode( const struct ime
*ime
)
140 return !!(ime
->info
.fdwProperty
& IME_PROP_UNICODE
);
143 static BOOL
input_context_is_unicode( INPUTCONTEXT
*ctx
)
145 struct imc
*imc
= CONTAINING_RECORD( ctx
, struct imc
, IMC
);
146 return !imc
->ime
|| ime_is_unicode( imc
->ime
);
149 static BOOL
IMM_DestroyContext(HIMC hIMC
);
150 static struct imc
*get_imc_data( HIMC hIMC
);
152 static inline WCHAR
*strdupAtoW( const char *str
)
157 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
158 if ((ret
= malloc( len
* sizeof(WCHAR
) ))) MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
163 static inline CHAR
*strdupWtoA( const WCHAR
*str
)
168 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
169 if ((ret
= malloc( len
))) WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
174 static DWORD
convert_candidatelist_WtoA(
175 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
179 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
180 if ( lpDst
&& dwBufLen
> 0 )
183 lpDst
->dwOffset
[0] = ret
;
186 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
188 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
190 if ( lpDst
&& dwBufLen
> 0 )
192 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
194 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1,
195 (LPSTR
)dest
, dwBufLen
, NULL
, NULL
);
197 if ( i
+ 1 < lpSrc
->dwCount
)
198 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(char);
199 dwBufLen
-= len
* sizeof(char);
202 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1, NULL
, 0, NULL
, NULL
);
204 ret
+= len
* sizeof(char);
213 static DWORD
convert_candidatelist_AtoW(
214 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
218 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
219 if ( lpDst
&& dwBufLen
> 0 )
222 lpDst
->dwOffset
[0] = ret
;
225 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
227 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
229 if ( lpDst
&& dwBufLen
> 0 )
231 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
233 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1,
234 (LPWSTR
)dest
, dwBufLen
);
236 if ( i
+ 1 < lpSrc
->dwCount
)
237 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(WCHAR
);
238 dwBufLen
-= len
* sizeof(WCHAR
);
241 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1, NULL
, 0);
243 ret
+= len
* sizeof(WCHAR
);
252 static struct coinit_spy
*get_thread_coinit_spy(void)
254 return (struct coinit_spy
*)(UINT_PTR
)NtUserGetThreadInfo()->client_imm
;
257 static void imm_couninit_thread(BOOL cleanup
)
259 struct coinit_spy
*spy
;
261 TRACE("implicit COM deinitialization\n");
263 if (!(spy
= get_thread_coinit_spy()) || (spy
->apt_flags
& IMM_APT_BROKEN
))
266 if (cleanup
&& spy
->cookie
.QuadPart
)
268 pCoRevokeInitializeSpy(spy
->cookie
);
269 spy
->cookie
.QuadPart
= 0;
272 if (!(spy
->apt_flags
& IMM_APT_INIT
))
274 spy
->apt_flags
&= ~IMM_APT_INIT
;
276 if (spy
->apt_flags
& IMM_APT_CREATED
)
278 spy
->apt_flags
&= ~IMM_APT_CREATED
;
279 if (spy
->apt_flags
& IMM_APT_CAN_FREE
)
286 static inline struct coinit_spy
*impl_from_IInitializeSpy(IInitializeSpy
*iface
)
288 return CONTAINING_RECORD(iface
, struct coinit_spy
, IInitializeSpy_iface
);
291 static HRESULT WINAPI
InitializeSpy_QueryInterface(IInitializeSpy
*iface
, REFIID riid
, void **obj
)
293 if (IsEqualIID(&IID_IInitializeSpy
, riid
) ||
294 IsEqualIID(&IID_IUnknown
, riid
))
297 IInitializeSpy_AddRef(iface
);
302 return E_NOINTERFACE
;
305 static ULONG WINAPI
InitializeSpy_AddRef(IInitializeSpy
*iface
)
307 struct coinit_spy
*spy
= impl_from_IInitializeSpy(iface
);
308 return InterlockedIncrement(&spy
->ref
);
311 static ULONG WINAPI
InitializeSpy_Release(IInitializeSpy
*iface
)
313 struct coinit_spy
*spy
= impl_from_IInitializeSpy(iface
);
314 LONG ref
= InterlockedDecrement(&spy
->ref
);
318 NtUserGetThreadInfo()->client_imm
= 0;
323 static HRESULT WINAPI
InitializeSpy_PreInitialize(IInitializeSpy
*iface
,
324 DWORD coinit
, DWORD refs
)
326 struct coinit_spy
*spy
= impl_from_IInitializeSpy(iface
);
328 if ((spy
->apt_flags
& IMM_APT_CREATED
) &&
329 !(coinit
& COINIT_APARTMENTTHREADED
) && refs
== 1)
331 imm_couninit_thread(TRUE
);
332 spy
->apt_flags
|= IMM_APT_BROKEN
;
337 static HRESULT WINAPI
InitializeSpy_PostInitialize(IInitializeSpy
*iface
,
338 HRESULT hr
, DWORD coinit
, DWORD refs
)
340 struct coinit_spy
*spy
= impl_from_IInitializeSpy(iface
);
342 if ((spy
->apt_flags
& IMM_APT_CREATED
) && hr
== S_FALSE
&& refs
== 2)
345 spy
->apt_flags
|= IMM_APT_CAN_FREE
;
349 static HRESULT WINAPI
InitializeSpy_PreUninitialize(IInitializeSpy
*iface
, DWORD refs
)
354 static HRESULT WINAPI
InitializeSpy_PostUninitialize(IInitializeSpy
*iface
, DWORD refs
)
356 struct coinit_spy
*spy
= impl_from_IInitializeSpy(iface
);
358 TRACE("%lu %p\n", refs
, ImmGetDefaultIMEWnd(0));
360 if (refs
== 1 && !ImmGetDefaultIMEWnd(0))
361 imm_couninit_thread(FALSE
);
363 spy
->apt_flags
&= ~IMM_APT_CAN_FREE
;
367 static const IInitializeSpyVtbl InitializeSpyVtbl
=
369 InitializeSpy_QueryInterface
,
370 InitializeSpy_AddRef
,
371 InitializeSpy_Release
,
372 InitializeSpy_PreInitialize
,
373 InitializeSpy_PostInitialize
,
374 InitializeSpy_PreUninitialize
,
375 InitializeSpy_PostUninitialize
,
378 static BOOL WINAPI
init_ole32_funcs( INIT_ONCE
*once
, void *param
, void **context
)
380 HMODULE module_ole32
= GetModuleHandleA("ole32");
381 pCoRevokeInitializeSpy
= (void*)GetProcAddress(module_ole32
, "CoRevokeInitializeSpy");
382 pCoUninitialize
= (void*)GetProcAddress(module_ole32
, "CoUninitialize");
386 static void imm_coinit_thread(void)
388 struct coinit_spy
*spy
;
390 static INIT_ONCE init_ole32_once
= INIT_ONCE_STATIC_INIT
;
392 TRACE("implicit COM initialization\n");
394 if (!(spy
= get_thread_coinit_spy()))
396 if (!(spy
= malloc( sizeof(*spy
) ))) return;
397 spy
->IInitializeSpy_iface
.lpVtbl
= &InitializeSpyVtbl
;
399 spy
->cookie
.QuadPart
= 0;
401 NtUserGetThreadInfo()->client_imm
= (UINT_PTR
)spy
;
405 if (spy
->apt_flags
& (IMM_APT_INIT
| IMM_APT_BROKEN
))
407 spy
->apt_flags
|= IMM_APT_INIT
;
409 if(!spy
->cookie
.QuadPart
)
411 hr
= CoRegisterInitializeSpy(&spy
->IInitializeSpy_iface
, &spy
->cookie
);
416 hr
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
418 spy
->apt_flags
|= IMM_APT_CREATED
;
420 InitOnceExecuteOnce(&init_ole32_once
, init_ole32_funcs
, NULL
, NULL
);
423 static struct imc
*query_imc_data( HIMC handle
)
427 if (!handle
) return NULL
;
428 ret
= (void *)NtUserQueryInputContext(handle
, NtUserInputContextClientPtr
);
429 return ret
&& ret
->handle
== handle
? ret
: NULL
;
432 static HMODULE
load_graphics_driver(void)
434 static const WCHAR key_pathW
[] = L
"System\\CurrentControlSet\\Control\\Video\\{";
435 static const WCHAR displayW
[] = L
"}\\0000";
440 WCHAR path
[MAX_PATH
];
441 WCHAR key
[ARRAY_SIZE( key_pathW
) + ARRAY_SIZE( displayW
) + 40];
442 UINT guid_atom
= HandleToULong( GetPropW( GetDesktopWindow(), L
"__wine_display_device_guid" ));
444 if (!guid_atom
) return 0;
445 memcpy( key
, key_pathW
, sizeof(key_pathW
) );
446 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
447 lstrcatW( key
, displayW
);
448 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
450 if (!RegQueryValueExW( hkey
, L
"GraphicsDriver", NULL
, NULL
, (BYTE
*)path
, &size
))
451 ret
= LoadLibraryW( path
);
453 TRACE( "%s %p\n", debugstr_w(path
), ret
);
457 /* lookup an IME from a HKL, must hold ime_cs */
458 static struct ime
*find_ime_from_hkl( HKL hkl
)
460 struct ime
*ime
= NULL
;
461 LIST_FOR_EACH_ENTRY( ime
, &ime_list
, struct ime
, entry
)
462 if (ime
->hkl
== hkl
) return ime
;
466 BOOL WINAPI
ImmFreeLayout( HKL hkl
)
468 struct imc_entry
*imc_entry
, *imc_next
;
471 TRACE( "hkl %p\n", hkl
);
473 EnterCriticalSection( &ime_cs
);
474 if ((ime
= find_ime_from_hkl( hkl
)))
476 list_remove( &ime
->entry
);
477 if (!ime
->pImeDestroy( 0 )) WARN( "ImeDestroy failed\n" );
478 LIST_FOR_EACH_ENTRY_SAFE( imc_entry
, imc_next
, &ime
->input_contexts
, struct imc_entry
, entry
)
480 ImmDestroyIMCC( imc_entry
->context
.hPrivate
);
484 LeaveCriticalSection( &ime_cs
);
485 if (!ime
) return TRUE
;
487 FreeLibrary( ime
->module
);
492 BOOL WINAPI
ImmLoadIME( HKL hkl
)
494 WCHAR buffer
[MAX_PATH
] = {0};
495 BOOL use_default_ime
;
498 TRACE( "hkl %p\n", hkl
);
500 EnterCriticalSection( &ime_cs
);
501 if ((ime
= find_ime_from_hkl( hkl
)) || !(ime
= calloc( 1, sizeof(*ime
) )))
503 LeaveCriticalSection( &ime_cs
);
507 if (!ImmGetIMEFileNameW( hkl
, buffer
, MAX_PATH
)) use_default_ime
= TRUE
;
508 else if (!(ime
->module
= LoadLibraryW( buffer
))) use_default_ime
= TRUE
;
509 else use_default_ime
= FALSE
;
513 if (*buffer
) WARN( "Failed to load %s, falling back to default.\n", debugstr_w(buffer
) );
514 if (!(ime
->module
= load_graphics_driver())) ime
->module
= LoadLibraryW( L
"imm32" );
517 #define LOAD_FUNCPTR( f ) \
518 if (!(ime->p##f = (void *)GetProcAddress( ime->module, #f )) && \
519 !(ime->p##f = use_default_ime ? (void *)f : NULL)) \
521 LeaveCriticalSection( &ime_cs ); \
522 WARN( "Can't find function %s in HKL %p IME\n", #f, hkl ); \
525 LOAD_FUNCPTR( ImeInquire
);
526 LOAD_FUNCPTR( ImeDestroy
);
527 LOAD_FUNCPTR( ImeSelect
);
528 LOAD_FUNCPTR( ImeConfigure
);
529 LOAD_FUNCPTR( ImeEscape
);
530 LOAD_FUNCPTR( ImeSetActiveContext
);
531 LOAD_FUNCPTR( ImeToAsciiEx
);
532 LOAD_FUNCPTR( NotifyIME
);
533 LOAD_FUNCPTR( ImeRegisterWord
);
534 LOAD_FUNCPTR( ImeUnregisterWord
);
535 LOAD_FUNCPTR( ImeEnumRegisterWord
);
536 LOAD_FUNCPTR( ImeSetCompositionString
);
537 LOAD_FUNCPTR( ImeConversionList
);
538 LOAD_FUNCPTR( ImeProcessKey
);
539 LOAD_FUNCPTR( ImeGetRegisterWordStyle
);
540 LOAD_FUNCPTR( ImeGetImeMenuItems
);
544 if (!ime
->pImeInquire( &ime
->info
, buffer
, 0 ))
546 LeaveCriticalSection( &ime_cs
);
550 if (ime_is_unicode( ime
)) lstrcpynW( ime
->ui_class
, buffer
, ARRAY_SIZE(ime
->ui_class
) );
551 else MultiByteToWideChar( CP_ACP
, 0, (char *)buffer
, -1, ime
->ui_class
, ARRAY_SIZE(ime
->ui_class
) );
552 list_init( &ime
->input_contexts
);
554 list_add_tail( &ime_list
, &ime
->entry
);
555 LeaveCriticalSection( &ime_cs
);
557 TRACE( "Created IME %p for HKL %p\n", ime
, hkl
);
561 if (ime
->module
) FreeLibrary( ime
->module
);
566 static struct ime
*ime_acquire( HKL hkl
)
570 EnterCriticalSection( &ime_cs
);
572 if (!ImmLoadIME( hkl
)) ime
= NULL
;
573 else ime
= find_ime_from_hkl( hkl
);
577 ULONG ref
= ++ime
->refcount
;
578 TRACE( "ime %p increasing refcount to %lu.\n", ime
, ref
);
581 LeaveCriticalSection( &ime_cs
);
586 static void ime_release( struct ime
*ime
)
590 EnterCriticalSection( &ime_cs
);
592 ref
= --ime
->refcount
;
593 TRACE( "ime %p decreasing refcount to %lu.\n", ime
, ref
);
595 if (!ref
&& (ime
->info
.fdwProperty
& IME_PROP_END_UNLOAD
))
596 ImmFreeLayout( ime
->hkl
);
598 LeaveCriticalSection( &ime_cs
);
601 static void ime_save_input_context( struct ime
*ime
, HIMC himc
, INPUTCONTEXT
*ctx
)
603 static INPUTCONTEXT default_input_context
=
605 .cfCandForm
= {{.dwIndex
= -1}, {.dwIndex
= -1}, {.dwIndex
= -1}, {.dwIndex
= -1}}
607 const INPUTCONTEXT old
= *ctx
;
608 struct imc_entry
*entry
;
610 *ctx
= default_input_context
;
611 ctx
->hWnd
= old
.hWnd
;
612 ctx
->hMsgBuf
= old
.hMsgBuf
;
613 ctx
->hCompStr
= old
.hCompStr
;
614 ctx
->hCandInfo
= old
.hCandInfo
;
615 ctx
->hGuideLine
= old
.hGuideLine
;
616 if (!(ctx
->hPrivate
= ImmCreateIMCC( ime
->info
.dwPrivateDataSize
)))
617 WARN( "Failed to allocate IME private data\n" );
619 if (!(entry
= malloc( sizeof(*entry
) ))) return;
621 entry
->context
= *ctx
;
623 EnterCriticalSection( &ime_cs
);
625 /* reference the IME the first time the input context cache is used
626 * in the same way Windows does it, so it doesn't get destroyed and
627 * INPUTCONTEXT cache lost when keyboard layout is changed
629 if (list_empty( &ime
->input_contexts
)) ime
->refcount
++;
631 list_add_tail( &ime
->input_contexts
, &entry
->entry
);
632 LeaveCriticalSection( &ime_cs
);
635 static INPUTCONTEXT
*ime_find_input_context( struct ime
*ime
, HIMC himc
)
637 struct imc_entry
*entry
;
639 EnterCriticalSection( &ime_cs
);
640 LIST_FOR_EACH_ENTRY( entry
, &ime
->input_contexts
, struct imc_entry
, entry
)
641 if (entry
->himc
== himc
) break;
642 LeaveCriticalSection( &ime_cs
);
644 if (&entry
->entry
== &ime
->input_contexts
) return NULL
;
645 return &entry
->context
;
648 static void imc_release_ime( struct imc
*imc
, struct ime
*ime
)
652 if (imc
->ui_hwnd
) DestroyWindow( imc
->ui_hwnd
);
654 ime
->pImeSelect( imc
->handle
, FALSE
);
656 if ((ctx
= ime_find_input_context( ime
, imc
->handle
))) *ctx
= imc
->IMC
;
660 static struct ime
*imc_select_ime( struct imc
*imc
)
662 HKL hkl
= GetKeyboardLayout( 0 );
665 if ((ime
= imc
->ime
))
667 if (ime
->hkl
== hkl
) return ime
;
669 imc_release_ime( imc
, ime
);
672 if (!(imc
->ime
= ime_acquire( hkl
)))
673 WARN( "Failed to acquire IME for HKL %p\n", hkl
);
678 if ((ctx
= ime_find_input_context( imc
->ime
, imc
->handle
))) imc
->IMC
= *ctx
;
679 else ime_save_input_context( imc
->ime
, imc
->handle
, &imc
->IMC
);
681 imc
->ime
->pImeSelect( imc
->handle
, TRUE
);
687 static BOOL CALLBACK
enum_activate_layout( HIMC himc
, LPARAM lparam
)
689 if (ImmLockIMC( himc
)) ImmUnlockIMC( himc
);
693 BOOL WINAPI
ImmActivateLayout( HKL hkl
)
695 TRACE( "hkl %p\n", hkl
);
697 if (hkl
== GetKeyboardLayout( 0 )) return TRUE
;
698 if (!ActivateKeyboardLayout( hkl
, 0 )) return FALSE
;
700 ImmEnumInputContext( 0, enum_activate_layout
, 0 );
705 static BOOL
free_input_context_data( HIMC hIMC
)
707 struct imc
*data
= query_imc_data( hIMC
);
710 if (!data
) return FALSE
;
712 TRACE( "Destroying %p\n", hIMC
);
714 if ((ime
= imc_select_ime( data
))) imc_release_ime( data
, ime
);
716 ImmDestroyIMCC( data
->IMC
.hCompStr
);
717 ImmDestroyIMCC( data
->IMC
.hCandInfo
);
718 ImmDestroyIMCC( data
->IMC
.hGuideLine
);
719 ImmDestroyIMCC( data
->IMC
.hMsgBuf
);
726 static void input_context_init( INPUTCONTEXT
*ctx
)
728 COMPOSITIONSTRING
*str
;
733 if (!(ctx
->hMsgBuf
= ImmCreateIMCC( 0 )))
734 WARN( "Failed to allocate %p message buffer\n", ctx
);
736 if (!(ctx
->hCompStr
= ImmCreateIMCC( sizeof(COMPOSITIONSTRING
) )))
737 WARN( "Failed to allocate %p COMPOSITIONSTRING\n", ctx
);
738 else if (!(str
= ImmLockIMCC( ctx
->hCompStr
)))
739 WARN( "Failed to lock IMCC for COMPOSITIONSTRING\n" );
742 str
->dwSize
= sizeof(COMPOSITIONSTRING
);
743 ImmUnlockIMCC( ctx
->hCompStr
);
746 if (!(ctx
->hCandInfo
= ImmCreateIMCC( sizeof(CANDIDATEINFO
) )))
747 WARN( "Failed to allocate %p CANDIDATEINFO\n", ctx
);
748 else if (!(info
= ImmLockIMCC( ctx
->hCandInfo
)))
749 WARN( "Failed to lock IMCC for CANDIDATEINFO\n" );
752 info
->dwSize
= sizeof(CANDIDATEINFO
);
753 ImmUnlockIMCC( ctx
->hCandInfo
);
756 if (!(ctx
->hGuideLine
= ImmCreateIMCC( sizeof(GUIDELINE
) )))
757 WARN( "Failed to allocate %p GUIDELINE\n", ctx
);
758 else if (!(line
= ImmLockIMCC( ctx
->hGuideLine
)))
759 WARN( "Failed to lock IMCC for GUIDELINE\n" );
762 line
->dwSize
= sizeof(GUIDELINE
);
763 ImmUnlockIMCC( ctx
->hGuideLine
);
766 for (i
= 0; i
< ARRAY_SIZE(ctx
->cfCandForm
); i
++)
767 ctx
->cfCandForm
[i
].dwIndex
= ~0u;
770 static void IMM_FreeThreadData(void)
772 struct coinit_spy
*spy
;
774 free_input_context_data( UlongToHandle( NtUserGetThreadInfo()->default_imc
) );
775 if ((spy
= get_thread_coinit_spy())) IInitializeSpy_Release( &spy
->IInitializeSpy_iface
);
778 static void IMM_FreeAllImmHkl(void)
780 struct ime
*ime
, *ime_next
;
782 LIST_FOR_EACH_ENTRY_SAFE( ime
, ime_next
, &ime_list
, struct ime
, entry
)
784 struct imc_entry
*imc_entry
, *imc_next
;
785 list_remove( &ime
->entry
);
787 ime
->pImeDestroy( 1 );
788 FreeLibrary( ime
->module
);
789 LIST_FOR_EACH_ENTRY_SAFE( imc_entry
, imc_next
, &ime
->input_contexts
, struct imc_entry
, entry
)
791 ImmDestroyIMCC( imc_entry
->context
.hPrivate
);
799 BOOL WINAPI
DllMain( HINSTANCE instance
, DWORD reason
, void *reserved
)
801 TRACE( "instance %p, reason %lx, reserved %p\n", instance
, reason
, reserved
);
805 case DLL_PROCESS_ATTACH
:
806 if (!User32InitializeImmEntryTable( IMM_INIT_MAGIC
)) return FALSE
;
807 imm32_module
= instance
;
809 case DLL_THREAD_ATTACH
:
811 case DLL_THREAD_DETACH
:
812 IMM_FreeThreadData();
814 case DLL_PROCESS_DETACH
:
816 IMM_FreeThreadData();
824 static void imc_post_message( struct imc
*imc
, TRANSMSG
*message
)
827 if (!(target
= GetFocus()) && !(target
= imc
->IMC
.hWnd
)) return;
828 PostMessageW( target
, message
->message
, message
->wParam
, message
->lParam
);
831 static void imc_send_message( struct imc
*imc
, TRANSMSG
*message
)
834 if (!(target
= GetFocus()) && !(target
= imc
->IMC
.hWnd
)) return;
835 SendMessageW( target
, message
->message
, message
->wParam
, message
->lParam
);
838 /***********************************************************************
839 * ImmSetActiveContext (IMM32.@)
841 BOOL WINAPI
ImmSetActiveContext(HWND hwnd
, HIMC himc
, BOOL activate
)
843 struct imc
*data
= get_imc_data( himc
);
846 TRACE("(%p, %p, %x)\n", hwnd
, himc
, activate
);
848 if (himc
&& !data
&& activate
)
855 if (activate
) data
->IMC
.hWnd
= hwnd
;
856 if ((ime
= imc_select_ime( data
))) ime
->pImeSetActiveContext( himc
, activate
);
861 SendMessageW(hwnd
, WM_IME_SETCONTEXT
, activate
, ISC_SHOWUIALL
);
862 /* TODO: send WM_IME_NOTIFY */
868 /***********************************************************************
869 * ImmConfigureIMEA (IMM32.@)
871 BOOL WINAPI
ImmConfigureIMEA( HKL hkl
, HWND hwnd
, DWORD mode
, void *data
)
876 TRACE( "hkl %p, hwnd %p, mode %lu, data %p.\n", hkl
, hwnd
, mode
, data
);
878 if (mode
== IME_CONFIG_REGISTERWORD
&& !data
) return FALSE
;
879 if (!(ime
= ime_acquire( hkl
))) return FALSE
;
881 if (mode
!= IME_CONFIG_REGISTERWORD
|| !ime_is_unicode( ime
))
882 ret
= ime
->pImeConfigure( hkl
, hwnd
, mode
, data
);
885 REGISTERWORDA
*wordA
= data
;
887 wordW
.lpWord
= strdupAtoW( wordA
->lpWord
);
888 wordW
.lpReading
= strdupAtoW( wordA
->lpReading
);
889 ret
= ime
->pImeConfigure( hkl
, hwnd
, mode
, &wordW
);
890 free( wordW
.lpReading
);
891 free( wordW
.lpWord
);
898 /***********************************************************************
899 * ImmConfigureIMEW (IMM32.@)
901 BOOL WINAPI
ImmConfigureIMEW( HKL hkl
, HWND hwnd
, DWORD mode
, void *data
)
906 TRACE( "hkl %p, hwnd %p, mode %lu, data %p.\n", hkl
, hwnd
, mode
, data
);
908 if (mode
== IME_CONFIG_REGISTERWORD
&& !data
) return FALSE
;
909 if (!(ime
= ime_acquire( hkl
))) return FALSE
;
911 if (mode
!= IME_CONFIG_REGISTERWORD
|| ime_is_unicode( ime
))
912 ret
= ime
->pImeConfigure( hkl
, hwnd
, mode
, data
);
915 REGISTERWORDW
*wordW
= data
;
917 wordA
.lpWord
= strdupWtoA( wordW
->lpWord
);
918 wordA
.lpReading
= strdupWtoA( wordW
->lpReading
);
919 ret
= ime
->pImeConfigure( hkl
, hwnd
, mode
, &wordA
);
920 free( wordA
.lpReading
);
921 free( wordA
.lpWord
);
928 static struct imc
*create_input_context( HIMC default_imc
)
930 struct imc
*new_context
;
932 if (!(new_context
= calloc( 1, sizeof(*new_context
) ))) return NULL
;
933 input_context_init( &new_context
->IMC
);
936 new_context
->handle
= NtUserCreateInputContext((UINT_PTR
)new_context
);
937 else if (NtUserUpdateInputContext(default_imc
, NtUserInputContextClientPtr
, (UINT_PTR
)new_context
))
938 new_context
->handle
= default_imc
;
939 if (!new_context
->handle
)
941 free_input_context_data(new_context
);
945 TRACE("Created context %p\n", new_context
);
949 static struct imc
*get_imc_data( HIMC handle
)
953 if ((ret
= query_imc_data(handle
)) || !handle
) return ret
;
954 return create_input_context(handle
);
957 static struct imc
*default_input_context(void)
959 UINT
*himc
= &NtUserGetThreadInfo()->default_imc
;
960 if (!*himc
) *himc
= (UINT_PTR
)NtUserCreateInputContext( 0 );
961 return get_imc_data( (HIMC
)(UINT_PTR
)*himc
);
964 static HWND
get_ime_ui_window(void)
966 struct imc
*imc
= default_input_context();
969 if (!(ime
= imc_select_ime( imc
))) return 0;
973 imc
->ui_hwnd
= CreateWindowExW( WS_EX_TOOLWINDOW
, ime
->ui_class
, NULL
, WS_POPUP
, 0, 0, 1, 1,
974 ImmGetDefaultIMEWnd( 0 ), 0, ime
->module
, 0 );
975 SetWindowLongPtrW( imc
->ui_hwnd
, IMMGWL_IMC
, (LONG_PTR
)imc
->handle
);
980 /***********************************************************************
981 * ImmCreateContext (IMM32.@)
983 HIMC WINAPI
ImmCreateContext(void)
985 struct imc
*new_context
;
987 if (!(new_context
= create_input_context(0))) return 0;
988 return new_context
->handle
;
991 static BOOL
IMM_DestroyContext(HIMC hIMC
)
993 if (!free_input_context_data(hIMC
)) return FALSE
;
994 NtUserDestroyInputContext(hIMC
);
998 /***********************************************************************
999 * ImmDestroyContext (IMM32.@)
1001 BOOL WINAPI
ImmDestroyContext(HIMC hIMC
)
1003 if ((UINT_PTR
)hIMC
== NtUserGetThreadInfo()->default_imc
) return FALSE
;
1004 if (NtUserQueryInputContext( hIMC
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
1005 return IMM_DestroyContext(hIMC
);
1008 /***********************************************************************
1009 * ImmAssociateContext (IMM32.@)
1011 HIMC WINAPI
ImmAssociateContext( HWND hwnd
, HIMC new_himc
)
1016 TRACE( "hwnd %p, new_himc %p\n", hwnd
, new_himc
);
1018 old_himc
= NtUserGetWindowInputContext( hwnd
);
1019 ret
= NtUserAssociateInputContext( hwnd
, new_himc
, 0 );
1020 if (ret
== AICR_FOCUS_CHANGED
)
1022 ImmSetActiveContext( hwnd
, old_himc
, FALSE
);
1023 ImmSetActiveContext( hwnd
, new_himc
, TRUE
);
1026 return ret
== AICR_FAILED
? 0 : old_himc
;
1029 static BOOL CALLBACK
enum_associate_context( HWND hwnd
, LPARAM lparam
)
1031 ImmAssociateContext( hwnd
, (HIMC
)lparam
);
1035 /***********************************************************************
1036 * ImmAssociateContextEx (IMM32.@)
1038 BOOL WINAPI
ImmAssociateContextEx( HWND hwnd
, HIMC new_himc
, DWORD flags
)
1043 TRACE( "hwnd %p, new_himc %p, flags %#lx\n", hwnd
, new_himc
, flags
);
1045 if (!hwnd
) return FALSE
;
1047 if (flags
== IACE_CHILDREN
)
1049 EnumChildWindows( hwnd
, enum_associate_context
, (LPARAM
)new_himc
);
1053 old_himc
= NtUserGetWindowInputContext( hwnd
);
1054 ret
= NtUserAssociateInputContext( hwnd
, new_himc
, flags
);
1055 if (ret
== AICR_FOCUS_CHANGED
)
1057 ImmSetActiveContext( hwnd
, old_himc
, FALSE
);
1058 ImmSetActiveContext( hwnd
, new_himc
, TRUE
);
1061 return ret
!= AICR_FAILED
;
1064 struct enum_register_word_params_WtoA
1066 REGISTERWORDENUMPROCA proc
;
1070 static int CALLBACK
enum_register_word_WtoA( const WCHAR
*readingW
, DWORD style
,
1071 const WCHAR
*stringW
, void *user
)
1073 char *readingA
= strdupWtoA( readingW
), *stringA
= strdupWtoA( stringW
);
1074 struct enum_register_word_params_WtoA
*params
= user
;
1075 int ret
= params
->proc( readingA
, style
, stringA
, params
->user
);
1081 /***********************************************************************
1082 * ImmEnumRegisterWordA (IMM32.@)
1084 UINT WINAPI
ImmEnumRegisterWordA( HKL hkl
, REGISTERWORDENUMPROCA procA
, const char *readingA
,
1085 DWORD style
, const char *stringA
, void *user
)
1090 TRACE( "hkl %p, procA %p, readingA %s, style %lu, stringA %s, user %p.\n", hkl
, procA
,
1091 debugstr_a(readingA
), style
, debugstr_a(stringA
), user
);
1093 if (!(ime
= ime_acquire( hkl
))) return 0;
1095 if (!ime_is_unicode( ime
))
1096 ret
= ime
->pImeEnumRegisterWord( procA
, readingA
, style
, stringA
, user
);
1099 struct enum_register_word_params_WtoA params
= {.proc
= procA
, .user
= user
};
1100 WCHAR
*readingW
= strdupAtoW( readingA
), *stringW
= strdupAtoW( stringA
);
1101 ret
= ime
->pImeEnumRegisterWord( enum_register_word_WtoA
, readingW
, style
, stringW
, ¶ms
);
1110 struct enum_register_word_params_AtoW
1112 REGISTERWORDENUMPROCW proc
;
1116 static int CALLBACK
enum_register_word_AtoW( const char *readingA
, DWORD style
,
1117 const char *stringA
, void *user
)
1119 WCHAR
*readingW
= strdupAtoW( readingA
), *stringW
= strdupAtoW( stringA
);
1120 struct enum_register_word_params_AtoW
*params
= user
;
1121 int ret
= params
->proc( readingW
, style
, stringW
, params
->user
);
1127 /***********************************************************************
1128 * ImmEnumRegisterWordW (IMM32.@)
1130 UINT WINAPI
ImmEnumRegisterWordW( HKL hkl
, REGISTERWORDENUMPROCW procW
, const WCHAR
*readingW
,
1131 DWORD style
, const WCHAR
*stringW
, void *user
)
1136 TRACE( "hkl %p, procW %p, readingW %s, style %lu, stringW %s, user %p.\n", hkl
, procW
,
1137 debugstr_w(readingW
), style
, debugstr_w(stringW
), user
);
1139 if (!(ime
= ime_acquire( hkl
))) return 0;
1141 if (ime_is_unicode( ime
))
1142 ret
= ime
->pImeEnumRegisterWord( procW
, readingW
, style
, stringW
, user
);
1145 struct enum_register_word_params_AtoW params
= {.proc
= procW
, .user
= user
};
1146 char *readingA
= strdupWtoA( readingW
), *stringA
= strdupWtoA( stringW
);
1147 ret
= ime
->pImeEnumRegisterWord( enum_register_word_AtoW
, readingA
, style
, stringA
, ¶ms
);
1156 static inline BOOL
EscapeRequiresWA(UINT uEscape
)
1158 if (uEscape
== IME_ESC_GET_EUDC_DICTIONARY
||
1159 uEscape
== IME_ESC_SET_EUDC_DICTIONARY
||
1160 uEscape
== IME_ESC_IME_NAME
||
1161 uEscape
== IME_ESC_GETHELPFILENAME
)
1166 /***********************************************************************
1167 * ImmEscapeA (IMM32.@)
1169 LRESULT WINAPI
ImmEscapeA( HKL hkl
, HIMC himc
, UINT code
, void *data
)
1174 TRACE( "hkl %p, himc %p, code %u, data %p.\n", hkl
, himc
, code
, data
);
1176 if (!(ime
= ime_acquire( hkl
))) return 0;
1178 if (!EscapeRequiresWA( code
) || !ime_is_unicode( ime
) || !data
)
1179 ret
= ime
->pImeEscape( himc
, code
, data
);
1182 WCHAR buffer
[81]; /* largest required buffer should be 80 */
1183 if (code
== IME_ESC_SET_EUDC_DICTIONARY
)
1185 MultiByteToWideChar( CP_ACP
, 0, data
, -1, buffer
, 81 );
1186 ret
= ime
->pImeEscape( himc
, code
, buffer
);
1190 ret
= ime
->pImeEscape( himc
, code
, buffer
);
1191 WideCharToMultiByte( CP_ACP
, 0, buffer
, -1, data
, 80, NULL
, NULL
);
1199 /***********************************************************************
1200 * ImmEscapeW (IMM32.@)
1202 LRESULT WINAPI
ImmEscapeW( HKL hkl
, HIMC himc
, UINT code
, void *data
)
1207 TRACE( "hkl %p, himc %p, code %u, data %p.\n", hkl
, himc
, code
, data
);
1209 if (!(ime
= ime_acquire( hkl
))) return 0;
1211 if (!EscapeRequiresWA( code
) || ime_is_unicode( ime
) || !data
)
1212 ret
= ime
->pImeEscape( himc
, code
, data
);
1215 char buffer
[81]; /* largest required buffer should be 80 */
1216 if (code
== IME_ESC_SET_EUDC_DICTIONARY
)
1218 WideCharToMultiByte( CP_ACP
, 0, data
, -1, buffer
, 81, NULL
, NULL
);
1219 ret
= ime
->pImeEscape( himc
, code
, buffer
);
1223 ret
= ime
->pImeEscape( himc
, code
, buffer
);
1224 MultiByteToWideChar( CP_ACP
, 0, buffer
, -1, data
, 80 );
1232 /***********************************************************************
1233 * ImmGetCandidateListA (IMM32.@)
1235 DWORD WINAPI
ImmGetCandidateListA(
1236 HIMC hIMC
, DWORD dwIndex
,
1237 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1239 struct imc
*data
= get_imc_data( hIMC
);
1240 LPCANDIDATEINFO candinfo
;
1241 LPCANDIDATELIST candlist
;
1245 TRACE("%p, %ld, %p, %ld\n", hIMC
, dwIndex
, lpCandList
, dwBufLen
);
1247 if (!data
|| !data
->IMC
.hCandInfo
)
1250 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1251 if (dwIndex
>= candinfo
->dwCount
|| dwIndex
>= ARRAY_SIZE(candinfo
->dwOffset
))
1254 candlist
= (LPCANDIDATELIST
)((LPBYTE
)candinfo
+ candinfo
->dwOffset
[dwIndex
]);
1255 if ( !candlist
->dwSize
|| !candlist
->dwCount
)
1258 if (!(ime
= imc_select_ime( data
)))
1260 else if (!ime_is_unicode( ime
))
1262 ret
= candlist
->dwSize
;
1263 if ( lpCandList
&& dwBufLen
>= ret
)
1264 memcpy(lpCandList
, candlist
, ret
);
1267 ret
= convert_candidatelist_WtoA( candlist
, lpCandList
, dwBufLen
);
1270 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1274 /***********************************************************************
1275 * ImmGetCandidateListCountA (IMM32.@)
1277 DWORD WINAPI
ImmGetCandidateListCountA(
1278 HIMC hIMC
, LPDWORD lpdwListCount
)
1280 struct imc
*data
= get_imc_data( hIMC
);
1281 LPCANDIDATEINFO candinfo
;
1285 TRACE("%p, %p\n", hIMC
, lpdwListCount
);
1287 if (!data
|| !lpdwListCount
|| !data
->IMC
.hCandInfo
)
1290 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1292 *lpdwListCount
= count
= candinfo
->dwCount
;
1294 if (!(ime
= imc_select_ime( data
)))
1296 else if (!ime_is_unicode( ime
))
1297 ret
= candinfo
->dwSize
;
1300 ret
= sizeof(CANDIDATEINFO
);
1302 ret
+= ImmGetCandidateListA(hIMC
, count
, NULL
, 0);
1305 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1309 /***********************************************************************
1310 * ImmGetCandidateListCountW (IMM32.@)
1312 DWORD WINAPI
ImmGetCandidateListCountW(
1313 HIMC hIMC
, LPDWORD lpdwListCount
)
1315 struct imc
*data
= get_imc_data( hIMC
);
1316 LPCANDIDATEINFO candinfo
;
1320 TRACE("%p, %p\n", hIMC
, lpdwListCount
);
1322 if (!data
|| !lpdwListCount
|| !data
->IMC
.hCandInfo
)
1325 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1327 *lpdwListCount
= count
= candinfo
->dwCount
;
1329 if (!(ime
= imc_select_ime( data
)))
1331 else if (ime_is_unicode( ime
))
1332 ret
= candinfo
->dwSize
;
1335 ret
= sizeof(CANDIDATEINFO
);
1337 ret
+= ImmGetCandidateListW(hIMC
, count
, NULL
, 0);
1340 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1344 /***********************************************************************
1345 * ImmGetCandidateListW (IMM32.@)
1347 DWORD WINAPI
ImmGetCandidateListW(
1348 HIMC hIMC
, DWORD dwIndex
,
1349 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1351 struct imc
*data
= get_imc_data( hIMC
);
1352 LPCANDIDATEINFO candinfo
;
1353 LPCANDIDATELIST candlist
;
1357 TRACE("%p, %ld, %p, %ld\n", hIMC
, dwIndex
, lpCandList
, dwBufLen
);
1359 if (!data
|| !data
->IMC
.hCandInfo
)
1362 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1363 if (dwIndex
>= candinfo
->dwCount
|| dwIndex
>= ARRAY_SIZE(candinfo
->dwOffset
))
1366 candlist
= (LPCANDIDATELIST
)((LPBYTE
)candinfo
+ candinfo
->dwOffset
[dwIndex
]);
1367 if ( !candlist
->dwSize
|| !candlist
->dwCount
)
1370 if (!(ime
= imc_select_ime( data
)))
1372 else if (ime_is_unicode( ime
))
1374 ret
= candlist
->dwSize
;
1375 if ( lpCandList
&& dwBufLen
>= ret
)
1376 memcpy(lpCandList
, candlist
, ret
);
1379 ret
= convert_candidatelist_AtoW( candlist
, lpCandList
, dwBufLen
);
1382 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1386 /***********************************************************************
1387 * ImmGetCandidateWindow (IMM32.@)
1389 BOOL WINAPI
ImmGetCandidateWindow( HIMC himc
, DWORD index
, CANDIDATEFORM
*candidate
)
1394 TRACE( "himc %p, index %lu, candidate %p\n", himc
, index
, candidate
);
1396 if (!candidate
) return FALSE
;
1398 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
1399 if (ctx
->cfCandForm
[index
].dwIndex
== -1) ret
= FALSE
;
1400 else *candidate
= ctx
->cfCandForm
[index
];
1401 ImmUnlockIMC( himc
);
1406 /***********************************************************************
1407 * ImmGetCompositionFontA (IMM32.@)
1409 BOOL WINAPI
ImmGetCompositionFontA( HIMC himc
, LOGFONTA
*fontA
)
1415 TRACE( "himc %p, fontA %p\n", himc
, fontA
);
1417 if (!fontA
) return FALSE
;
1419 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
1420 if (!(ctx
->fdwInit
& INIT_LOGFONT
)) ret
= FALSE
;
1421 else if (!input_context_is_unicode( ctx
)) *fontA
= ctx
->lfFont
.A
;
1422 else if ((ret
= ImmGetCompositionFontW( himc
, &fontW
)))
1424 memcpy( fontA
, &fontW
, offsetof(LOGFONTA
, lfFaceName
) );
1425 WideCharToMultiByte( CP_ACP
, 0, fontW
.lfFaceName
, -1, fontA
->lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
1427 ImmUnlockIMC( himc
);
1432 /***********************************************************************
1433 * ImmGetCompositionFontW (IMM32.@)
1435 BOOL WINAPI
ImmGetCompositionFontW( HIMC himc
, LOGFONTW
*fontW
)
1441 TRACE( "himc %p, fontW %p\n", himc
, fontW
);
1443 if (!fontW
) return FALSE
;
1445 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
1446 if (!(ctx
->fdwInit
& INIT_LOGFONT
)) ret
= FALSE
;
1447 else if (input_context_is_unicode( ctx
)) *fontW
= ctx
->lfFont
.W
;
1448 else if ((ret
= ImmGetCompositionFontA( himc
, &fontA
)))
1450 memcpy( fontW
, &fontA
, offsetof(LOGFONTW
, lfFaceName
) );
1451 MultiByteToWideChar( CP_ACP
, 0, fontA
.lfFaceName
, -1, fontW
->lfFaceName
, LF_FACESIZE
);
1453 ImmUnlockIMC( himc
);
1459 /* Helpers for the GetCompositionString functions */
1461 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
1462 length is always in bytes. */
1463 static INT
CopyCompStringIMEtoClient( BOOL src_unicode
, const void *src
, INT src_len
,
1464 void *dst
, INT dst_len
, BOOL dst_unicode
)
1466 int char_size
= dst_unicode
? sizeof(WCHAR
) : sizeof(char);
1469 if (src_unicode
^ dst_unicode
)
1472 ret
= MultiByteToWideChar(CP_ACP
, 0, src
, src_len
, dst
, dst_len
/ sizeof(WCHAR
));
1474 ret
= WideCharToMultiByte(CP_ACP
, 0, src
, src_len
, dst
, dst_len
, NULL
, NULL
);
1481 ret
= min(src_len
* char_size
, dst_len
);
1482 memcpy(dst
, src
, ret
);
1485 ret
= src_len
* char_size
;
1491 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
1492 passed mode. String length is in characters, attributes are in byte arrays. */
1493 static INT
CopyCompAttrIMEtoClient( BOOL src_unicode
, const BYTE
*src
, INT src_len
, const void *comp_string
, INT str_len
,
1494 BYTE
*dst
, INT dst_len
, BOOL unicode
)
1504 string
.str
= comp_string
;
1506 if (src_unicode
&& !unicode
)
1508 rc
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
, str_len
, NULL
, 0, NULL
, NULL
);
1511 int i
, j
= 0, k
= 0;
1515 for (i
= 0; i
< str_len
; ++i
)
1519 len
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
+ i
, 1, NULL
, 0, NULL
, NULL
);
1520 for (; len
> 0; --len
)
1533 else if (!src_unicode
&& unicode
)
1535 rc
= MultiByteToWideChar(CP_ACP
, 0, string
.strA
, str_len
, NULL
, 0);
1542 for (i
= 0; i
< str_len
; ++i
)
1544 if (IsDBCSLeadByte(string
.strA
[i
]))
1557 memcpy(dst
, src
, min(src_len
, dst_len
));
1564 static INT
CopyCompClauseIMEtoClient( BOOL src_unicode
, LPBYTE source
, INT slen
, LPBYTE ssource
,
1565 LPBYTE target
, INT tlen
, BOOL unicode
)
1569 if (src_unicode
&& !unicode
)
1577 tlen
/= sizeof (DWORD
);
1578 for (i
= 0; i
< tlen
; ++i
)
1580 ((DWORD
*)target
)[i
] = WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
,
1581 ((DWORD
*)source
)[i
],
1585 rc
= sizeof (DWORD
) * i
;
1590 else if (!src_unicode
&& unicode
)
1598 tlen
/= sizeof (DWORD
);
1599 for (i
= 0; i
< tlen
; ++i
)
1601 ((DWORD
*)target
)[i
] = MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
,
1602 ((DWORD
*)source
)[i
],
1605 rc
= sizeof (DWORD
) * i
;
1612 memcpy( target
, source
, min(slen
,tlen
));
1619 static INT
CopyCompOffsetIMEtoClient( BOOL src_unicode
, DWORD offset
, LPBYTE ssource
, BOOL unicode
)
1623 if (src_unicode
&& !unicode
)
1625 rc
= WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
, offset
, NULL
, 0, NULL
, NULL
);
1627 else if (!src_unicode
&& unicode
)
1629 rc
= MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
, offset
, NULL
, 0);
1637 static LONG
ImmGetCompositionStringT( HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
,
1638 DWORD dwBufLen
, BOOL unicode
)
1641 struct imc
*data
= get_imc_data( hIMC
);
1642 LPCOMPOSITIONSTRING compstr
;
1647 TRACE("(%p, 0x%lx, %p, %ld)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
1652 if (!data
->IMC
.hCompStr
)
1655 if (!(ime
= imc_select_ime( data
)))
1657 src_unicode
= ime_is_unicode( ime
);
1659 compdata
= ImmLockIMCC(data
->IMC
.hCompStr
);
1660 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1665 TRACE("GCS_RESULTSTR\n");
1666 rc
= CopyCompStringIMEtoClient(src_unicode
, compdata
+ compstr
->dwResultStrOffset
, compstr
->dwResultStrLen
, lpBuf
, dwBufLen
, unicode
);
1669 TRACE("GCS_COMPSTR\n");
1670 rc
= CopyCompStringIMEtoClient(src_unicode
, compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
, lpBuf
, dwBufLen
, unicode
);
1673 TRACE("GCS_COMPATTR\n");
1674 rc
= CopyCompAttrIMEtoClient(src_unicode
, compdata
+ compstr
->dwCompAttrOffset
, compstr
->dwCompAttrLen
,
1675 compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
,
1676 lpBuf
, dwBufLen
, unicode
);
1678 case GCS_COMPCLAUSE
:
1679 TRACE("GCS_COMPCLAUSE\n");
1680 rc
= CopyCompClauseIMEtoClient(src_unicode
, compdata
+ compstr
->dwCompClauseOffset
,compstr
->dwCompClauseLen
,
1681 compdata
+ compstr
->dwCompStrOffset
,
1682 lpBuf
, dwBufLen
, unicode
);
1684 case GCS_RESULTCLAUSE
:
1685 TRACE("GCS_RESULTCLAUSE\n");
1686 rc
= CopyCompClauseIMEtoClient(src_unicode
, compdata
+ compstr
->dwResultClauseOffset
,compstr
->dwResultClauseLen
,
1687 compdata
+ compstr
->dwResultStrOffset
,
1688 lpBuf
, dwBufLen
, unicode
);
1690 case GCS_RESULTREADSTR
:
1691 TRACE("GCS_RESULTREADSTR\n");
1692 rc
= CopyCompStringIMEtoClient(src_unicode
, compdata
+ compstr
->dwResultReadStrOffset
, compstr
->dwResultReadStrLen
, lpBuf
, dwBufLen
, unicode
);
1694 case GCS_RESULTREADCLAUSE
:
1695 TRACE("GCS_RESULTREADCLAUSE\n");
1696 rc
= CopyCompClauseIMEtoClient(src_unicode
, compdata
+ compstr
->dwResultReadClauseOffset
,compstr
->dwResultReadClauseLen
,
1697 compdata
+ compstr
->dwResultStrOffset
,
1698 lpBuf
, dwBufLen
, unicode
);
1700 case GCS_COMPREADSTR
:
1701 TRACE("GCS_COMPREADSTR\n");
1702 rc
= CopyCompStringIMEtoClient(src_unicode
, compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
, lpBuf
, dwBufLen
, unicode
);
1704 case GCS_COMPREADATTR
:
1705 TRACE("GCS_COMPREADATTR\n");
1706 rc
= CopyCompAttrIMEtoClient(src_unicode
, compdata
+ compstr
->dwCompReadAttrOffset
, compstr
->dwCompReadAttrLen
,
1707 compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
,
1708 lpBuf
, dwBufLen
, unicode
);
1710 case GCS_COMPREADCLAUSE
:
1711 TRACE("GCS_COMPREADCLAUSE\n");
1712 rc
= CopyCompClauseIMEtoClient(src_unicode
, compdata
+ compstr
->dwCompReadClauseOffset
,compstr
->dwCompReadClauseLen
,
1713 compdata
+ compstr
->dwCompStrOffset
,
1714 lpBuf
, dwBufLen
, unicode
);
1717 TRACE("GCS_CURSORPOS\n");
1718 rc
= CopyCompOffsetIMEtoClient(src_unicode
, compstr
->dwCursorPos
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
1720 case GCS_DELTASTART
:
1721 TRACE("GCS_DELTASTART\n");
1722 rc
= CopyCompOffsetIMEtoClient(src_unicode
, compstr
->dwDeltaStart
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
1725 FIXME("Unhandled index 0x%lx\n",dwIndex
);
1729 ImmUnlockIMCC(data
->IMC
.hCompStr
);
1734 /***********************************************************************
1735 * ImmGetCompositionStringA (IMM32.@)
1737 LONG WINAPI
ImmGetCompositionStringA(
1738 HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
)
1740 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
1744 /***********************************************************************
1745 * ImmGetCompositionStringW (IMM32.@)
1747 LONG WINAPI
ImmGetCompositionStringW(
1748 HIMC hIMC
, DWORD dwIndex
,
1749 LPVOID lpBuf
, DWORD dwBufLen
)
1751 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
1754 /***********************************************************************
1755 * ImmGetCompositionWindow (IMM32.@)
1757 BOOL WINAPI
ImmGetCompositionWindow( HIMC himc
, COMPOSITIONFORM
*composition
)
1762 TRACE( "himc %p, composition %p\n", himc
, composition
);
1764 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
1765 if ((ret
= !!(ctx
->fdwInit
& INIT_COMPFORM
))) *composition
= ctx
->cfCompForm
;
1766 ImmUnlockIMC( himc
);
1771 /***********************************************************************
1772 * ImmGetContext (IMM32.@)
1775 HIMC WINAPI
ImmGetContext( HWND hwnd
)
1777 TRACE( "hwnd %p\n", hwnd
);
1778 return NtUserGetWindowInputContext( hwnd
);
1781 /***********************************************************************
1782 * ImmGetConversionListA (IMM32.@)
1784 DWORD WINAPI
ImmGetConversionListA( HKL hkl
, HIMC himc
, const char *srcA
, CANDIDATELIST
*listA
,
1785 DWORD lengthA
, UINT flags
)
1790 TRACE( "hkl %p, himc %p, srcA %s, listA %p, lengthA %lu, flags %#x.\n", hkl
, himc
,
1791 debugstr_a(srcA
), listA
, lengthA
, flags
);
1793 if (!(ime
= ime_acquire( hkl
))) return 0;
1795 if (!ime_is_unicode( ime
))
1796 ret
= ime
->pImeConversionList( himc
, srcA
, listA
, lengthA
, flags
);
1799 CANDIDATELIST
*listW
;
1800 WCHAR
*srcW
= strdupAtoW( srcA
);
1801 DWORD lengthW
= ime
->pImeConversionList( himc
, srcW
, NULL
, 0, flags
);
1803 if (!(listW
= malloc( lengthW
))) ret
= 0;
1806 ime
->pImeConversionList( himc
, srcW
, listW
, lengthW
, flags
);
1807 ret
= convert_candidatelist_WtoA( listW
, listA
, lengthA
);
1817 /***********************************************************************
1818 * ImmGetConversionListW (IMM32.@)
1820 DWORD WINAPI
ImmGetConversionListW( HKL hkl
, HIMC himc
, const WCHAR
*srcW
, CANDIDATELIST
*listW
,
1821 DWORD lengthW
, UINT flags
)
1826 TRACE( "hkl %p, himc %p, srcW %s, listW %p, lengthW %lu, flags %#x.\n", hkl
, himc
,
1827 debugstr_w(srcW
), listW
, lengthW
, flags
);
1829 if (!(ime
= ime_acquire( hkl
))) return 0;
1831 if (ime_is_unicode( ime
))
1832 ret
= ime
->pImeConversionList( himc
, srcW
, listW
, lengthW
, flags
);
1835 CANDIDATELIST
*listA
;
1836 char *srcA
= strdupWtoA( srcW
);
1837 DWORD lengthA
= ime
->pImeConversionList( himc
, srcA
, NULL
, 0, flags
);
1839 if (!(listA
= malloc( lengthA
))) ret
= 0;
1842 ime
->pImeConversionList( himc
, srcA
, listA
, lengthA
, flags
);
1843 ret
= convert_candidatelist_AtoW( listA
, listW
, lengthW
);
1853 /***********************************************************************
1854 * ImmGetConversionStatus (IMM32.@)
1856 BOOL WINAPI
ImmGetConversionStatus( HIMC himc
, DWORD
*conversion
, DWORD
*sentence
)
1860 TRACE( "himc %p, conversion %p, sentence %p\n", himc
, conversion
, sentence
);
1862 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
1863 if (conversion
) *conversion
= ctx
->fdwConversion
;
1864 if (sentence
) *sentence
= ctx
->fdwSentence
;
1865 ImmUnlockIMC( himc
);
1870 /***********************************************************************
1871 * ImmGetDefaultIMEWnd (IMM32.@)
1873 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
1875 return NtUserGetDefaultImeWindow(hWnd
);
1878 /***********************************************************************
1879 * ImmGetDescriptionA (IMM32.@)
1881 UINT WINAPI
ImmGetDescriptionA( HKL hkl
, LPSTR bufferA
, UINT lengthA
)
1886 TRACE( "hkl %p, bufferA %p, lengthA %d\n", hkl
, bufferA
, lengthA
);
1888 if (!(lengthW
= ImmGetDescriptionW( hkl
, NULL
, 0 ))) return 0;
1889 if (!(bufferW
= malloc( (lengthW
+ 1) * sizeof(WCHAR
) ))) return 0;
1890 lengthW
= ImmGetDescriptionW( hkl
, bufferW
, lengthW
+ 1 );
1891 lengthA
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, lengthW
, bufferA
,
1892 bufferA
? lengthA
: 0, NULL
, NULL
);
1893 if (bufferA
) bufferA
[lengthA
] = 0;
1899 /***********************************************************************
1900 * ImmGetDescriptionW (IMM32.@)
1902 UINT WINAPI
ImmGetDescriptionW( HKL hkl
, WCHAR
*buffer
, UINT length
)
1904 WCHAR path
[MAX_PATH
];
1908 TRACE( "hkl %p, buffer %p, length %u\n", hkl
, buffer
, length
);
1910 swprintf( path
, ARRAY_SIZE(path
), layouts_formatW
, (ULONG
)(ULONG_PTR
)hkl
);
1911 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, path
, &hkey
)) return 0;
1913 size
= ARRAY_SIZE(path
) * sizeof(WCHAR
);
1914 if (RegGetValueW( hkey
, NULL
, L
"Layout Text", RRF_RT_REG_SZ
, NULL
, path
, &size
)) *path
= 0;
1915 RegCloseKey( hkey
);
1917 size
= wcslen( path
);
1918 if (!buffer
) return size
;
1920 lstrcpynW( buffer
, path
, length
);
1921 return wcslen( buffer
);
1924 /***********************************************************************
1925 * ImmGetGuideLineA (IMM32.@)
1927 DWORD WINAPI
ImmGetGuideLineA(
1928 HIMC hIMC
, DWORD dwIndex
, LPSTR lpBuf
, DWORD dwBufLen
)
1930 FIXME("(%p, %ld, %s, %ld): stub\n",
1931 hIMC
, dwIndex
, debugstr_a(lpBuf
), dwBufLen
1933 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1937 /***********************************************************************
1938 * ImmGetGuideLineW (IMM32.@)
1940 DWORD WINAPI
ImmGetGuideLineW(HIMC hIMC
, DWORD dwIndex
, LPWSTR lpBuf
, DWORD dwBufLen
)
1942 FIXME("(%p, %ld, %s, %ld): stub\n",
1943 hIMC
, dwIndex
, debugstr_w(lpBuf
), dwBufLen
1945 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1949 /***********************************************************************
1950 * ImmGetIMEFileNameA (IMM32.@)
1952 UINT WINAPI
ImmGetIMEFileNameA( HKL hkl
, char *bufferA
, UINT lengthA
)
1957 TRACE( "hkl %p, bufferA %p, lengthA %d\n", hkl
, bufferA
, lengthA
);
1959 if (!(lengthW
= ImmGetIMEFileNameW( hkl
, NULL
, 0 ))) return 0;
1960 if (!(bufferW
= malloc( (lengthW
+ 1) * sizeof(WCHAR
) ))) return 0;
1961 lengthW
= ImmGetIMEFileNameW( hkl
, bufferW
, lengthW
+ 1 );
1962 lengthA
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, lengthW
, bufferA
,
1963 bufferA
? lengthA
: 0, NULL
, NULL
);
1964 if (bufferA
) bufferA
[lengthA
] = 0;
1970 /***********************************************************************
1971 * ImmGetIMEFileNameW (IMM32.@)
1973 UINT WINAPI
ImmGetIMEFileNameW( HKL hkl
, WCHAR
*buffer
, UINT length
)
1975 WCHAR path
[MAX_PATH
];
1979 TRACE( "hkl %p, buffer %p, length %u\n", hkl
, buffer
, length
);
1981 swprintf( path
, ARRAY_SIZE(path
), layouts_formatW
, (ULONG
)(ULONG_PTR
)hkl
);
1982 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, path
, &hkey
)) return 0;
1984 size
= ARRAY_SIZE(path
) * sizeof(WCHAR
);
1985 if (RegGetValueW( hkey
, NULL
, L
"Ime File", RRF_RT_REG_SZ
, NULL
, path
, &size
)) *path
= 0;
1986 RegCloseKey( hkey
);
1988 size
= wcslen( path
);
1989 if (!buffer
) return size
;
1991 lstrcpynW( buffer
, path
, length
);
1992 return wcslen( buffer
);
1995 /***********************************************************************
1996 * ImmGetOpenStatus (IMM32.@)
1998 BOOL WINAPI
ImmGetOpenStatus( HIMC himc
)
2003 TRACE( "himc %p\n", himc
);
2005 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2006 status
= ctx
->fOpen
;
2007 ImmUnlockIMC( himc
);
2012 /***********************************************************************
2013 * ImmGetProperty (IMM32.@)
2015 DWORD WINAPI
ImmGetProperty( HKL hkl
, DWORD index
)
2020 TRACE( "hkl %p, index %lu.\n", hkl
, index
);
2022 if (!(ime
= ime_acquire( hkl
))) return 0;
2026 case IGP_PROPERTY
: ret
= ime
->info
.fdwProperty
; break;
2027 case IGP_CONVERSION
: ret
= ime
->info
.fdwConversionCaps
; break;
2028 case IGP_SENTENCE
: ret
= ime
->info
.fdwSentenceCaps
; break;
2029 case IGP_SETCOMPSTR
: ret
= ime
->info
.fdwSCSCaps
; break;
2030 case IGP_SELECT
: ret
= ime
->info
.fdwSelectCaps
; break;
2031 case IGP_GETIMEVERSION
: ret
= IMEVER_0400
; break;
2032 case IGP_UI
: ret
= 0; break;
2033 default: ret
= 0; break;
2040 /***********************************************************************
2041 * ImmGetRegisterWordStyleA (IMM32.@)
2043 UINT WINAPI
ImmGetRegisterWordStyleA( HKL hkl
, UINT count
, STYLEBUFA
*styleA
)
2048 TRACE( "hkl %p, count %u, styleA %p.\n", hkl
, count
, styleA
);
2050 if (!(ime
= ime_acquire( hkl
))) return 0;
2052 if (!ime_is_unicode( ime
))
2053 ret
= ime
->pImeGetRegisterWordStyle( count
, styleA
);
2057 ret
= ime
->pImeGetRegisterWordStyle( count
, &styleW
);
2058 WideCharToMultiByte( CP_ACP
, 0, styleW
.szDescription
, -1, styleA
->szDescription
, 32, NULL
, NULL
);
2059 styleA
->dwStyle
= styleW
.dwStyle
;
2066 /***********************************************************************
2067 * ImmGetRegisterWordStyleW (IMM32.@)
2069 UINT WINAPI
ImmGetRegisterWordStyleW( HKL hkl
, UINT count
, STYLEBUFW
*styleW
)
2074 TRACE( "hkl %p, count %u, styleW %p.\n", hkl
, count
, styleW
);
2076 if (!(ime
= ime_acquire( hkl
))) return 0;
2078 if (ime_is_unicode( ime
))
2079 ret
= ime
->pImeGetRegisterWordStyle( count
, styleW
);
2083 ret
= ime
->pImeGetRegisterWordStyle( count
, &styleA
);
2084 MultiByteToWideChar( CP_ACP
, 0, styleA
.szDescription
, -1, styleW
->szDescription
, 32 );
2085 styleW
->dwStyle
= styleA
.dwStyle
;
2092 /***********************************************************************
2093 * ImmGetStatusWindowPos (IMM32.@)
2095 BOOL WINAPI
ImmGetStatusWindowPos( HIMC himc
, POINT
*pos
)
2100 TRACE( "himc %p, pos %p\n", himc
, pos
);
2102 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2103 if ((ret
= !!(ctx
->fdwInit
& INIT_STATUSWNDPOS
))) *pos
= ctx
->ptStatusWndPos
;
2104 ImmUnlockIMC( himc
);
2109 /***********************************************************************
2110 * ImmGetVirtualKey (IMM32.@)
2112 UINT WINAPI
ImmGetVirtualKey(HWND hWnd
)
2114 OSVERSIONINFOA version
;
2115 struct imc
*data
= get_imc_data( ImmGetContext( hWnd
) );
2116 TRACE("%p\n", hWnd
);
2119 return data
->lastVK
;
2121 version
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
2122 GetVersionExA( &version
);
2123 switch(version
.dwPlatformId
)
2125 case VER_PLATFORM_WIN32_WINDOWS
:
2126 return VK_PROCESSKEY
;
2127 case VER_PLATFORM_WIN32_NT
:
2130 FIXME("%ld not supported\n",version
.dwPlatformId
);
2131 return VK_PROCESSKEY
;
2135 /***********************************************************************
2136 * ImmInstallIMEA (IMM32.@)
2138 HKL WINAPI
ImmInstallIMEA( const char *filenameA
, const char *descriptionA
)
2140 WCHAR
*filenameW
= strdupAtoW( filenameA
), *descriptionW
= strdupAtoW( descriptionA
);
2143 TRACE( "filenameA %s, descriptionA %s\n", debugstr_a(filenameA
), debugstr_a(descriptionA
) );
2145 hkl
= ImmInstallIMEW( filenameW
, descriptionW
);
2146 free( descriptionW
);
2152 static LCID
get_ime_file_lang( const WCHAR
*filename
)
2159 if (!(len
= GetFileVersionInfoSizeW( filename
, NULL
))) return 0;
2160 if (!(info
= malloc( len
))) goto done
;
2161 if (!GetFileVersionInfoW( filename
, 0, len
, info
)) goto done
;
2162 if (!VerQueryValueW( info
, L
"\\VarFileInfo\\Translation", (void **)&languages
, &len
) || !len
) goto done
;
2163 lcid
= languages
[0];
2170 /***********************************************************************
2171 * ImmInstallIMEW (IMM32.@)
2173 HKL WINAPI
ImmInstallIMEW( const WCHAR
*filename
, const WCHAR
*description
)
2175 WCHAR path
[ARRAY_SIZE(layouts_formatW
)+8], buffer
[MAX_PATH
];
2183 TRACE( "filename %s, description %s\n", debugstr_w(filename
), debugstr_w(description
) );
2185 if (!filename
|| !description
|| !(lcid
= get_ime_file_lang( filename
)))
2187 SetLastError( ERROR_INVALID_PARAMETER
);
2191 while (count
< 0xfff)
2193 DWORD disposition
= 0;
2195 hkl
= (HKL
)(UINT_PTR
)MAKELONG( lcid
, 0xe000 | count
);
2196 swprintf( path
, ARRAY_SIZE(path
), layouts_formatW
, (ULONG
)(ULONG_PTR
)hkl
);
2197 if (!RegCreateKeyExW( HKEY_LOCAL_MACHINE
, path
, 0, NULL
, 0,
2198 KEY_WRITE
, NULL
, &hkey
, &disposition
))
2200 if (disposition
== REG_CREATED_NEW_KEY
) break;
2201 RegCloseKey( hkey
);
2209 WARN("Unable to find slot to install IME\n");
2213 if ((tmp
= wcsrchr( filename
, '\\' ))) tmp
++;
2214 else tmp
= filename
;
2216 length
= LCMapStringW( LOCALE_USER_DEFAULT
, LCMAP_UPPERCASE
, tmp
, -1, buffer
, ARRAY_SIZE(buffer
) );
2218 if (RegSetValueExW( hkey
, L
"Ime File", 0, REG_SZ
, (const BYTE
*)buffer
, length
* sizeof(WCHAR
) ) ||
2219 RegSetValueExW( hkey
, L
"Layout Text", 0, REG_SZ
, (const BYTE
*)description
,
2220 (wcslen(description
) + 1) * sizeof(WCHAR
) ))
2222 WARN( "Unable to write registry to install IME\n");
2225 RegCloseKey( hkey
);
2227 if (!hkl
) RegDeleteKeyW( HKEY_LOCAL_MACHINE
, path
);
2231 /***********************************************************************
2232 * ImmIsIME (IMM32.@)
2234 BOOL WINAPI
ImmIsIME( HKL hkl
)
2236 TRACE( "hkl %p\n", hkl
);
2237 if (!hkl
) return FALSE
;
2241 /***********************************************************************
2242 * ImmIsUIMessageA (IMM32.@)
2244 BOOL WINAPI
ImmIsUIMessageA(
2245 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2247 TRACE("(%p, %x, %Id, %Id)\n", hWndIME
, msg
, wParam
, lParam
);
2248 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
2249 (msg
== WM_IME_SETCONTEXT
) ||
2250 (msg
== WM_IME_NOTIFY
) ||
2251 (msg
== WM_IME_COMPOSITIONFULL
) ||
2252 (msg
== WM_IME_SELECT
) ||
2253 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
2256 SendMessageA(hWndIME
, msg
, wParam
, lParam
);
2263 /***********************************************************************
2264 * ImmIsUIMessageW (IMM32.@)
2266 BOOL WINAPI
ImmIsUIMessageW(
2267 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2269 TRACE("(%p, %x, %Id, %Id)\n", hWndIME
, msg
, wParam
, lParam
);
2270 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
2271 (msg
== WM_IME_SETCONTEXT
) ||
2272 (msg
== WM_IME_NOTIFY
) ||
2273 (msg
== WM_IME_COMPOSITIONFULL
) ||
2274 (msg
== WM_IME_SELECT
) ||
2275 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
2278 SendMessageW(hWndIME
, msg
, wParam
, lParam
);
2285 /***********************************************************************
2286 * ImmNotifyIME (IMM32.@)
2288 BOOL WINAPI
ImmNotifyIME(
2289 HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
2291 struct imc
*data
= get_imc_data( hIMC
);
2294 TRACE("(%p, %ld, %ld, %ld)\n",
2295 hIMC
, dwAction
, dwIndex
, dwValue
);
2299 SetLastError(ERROR_SUCCESS
);
2308 if (!(ime
= imc_select_ime( data
))) return FALSE
;
2309 return ime
->pNotifyIME( hIMC
, dwAction
, dwIndex
, dwValue
);
2312 /***********************************************************************
2313 * ImmRegisterWordA (IMM32.@)
2315 BOOL WINAPI
ImmRegisterWordA( HKL hkl
, const char *readingA
, DWORD style
, const char *stringA
)
2320 TRACE( "hkl %p, readingA %s, style %lu, stringA %s.\n", hkl
, debugstr_a(readingA
), style
, debugstr_a(stringA
) );
2322 if (!(ime
= ime_acquire( hkl
))) return FALSE
;
2324 if (!ime_is_unicode( ime
))
2325 ret
= ime
->pImeRegisterWord( readingA
, style
, stringA
);
2328 WCHAR
*readingW
= strdupAtoW( readingA
), *stringW
= strdupAtoW( stringA
);
2329 ret
= ime
->pImeRegisterWord( readingW
, style
, stringW
);
2338 /***********************************************************************
2339 * ImmRegisterWordW (IMM32.@)
2341 BOOL WINAPI
ImmRegisterWordW( HKL hkl
, const WCHAR
*readingW
, DWORD style
, const WCHAR
*stringW
)
2346 TRACE( "hkl %p, readingW %s, style %lu, stringW %s.\n", hkl
, debugstr_w(readingW
), style
, debugstr_w(stringW
) );
2348 if (!(ime
= ime_acquire( hkl
))) return FALSE
;
2350 if (ime_is_unicode( ime
))
2351 ret
= ime
->pImeRegisterWord( readingW
, style
, stringW
);
2354 char *readingA
= strdupWtoA( readingW
), *stringA
= strdupWtoA( stringW
);
2355 ret
= ime
->pImeRegisterWord( readingA
, style
, stringA
);
2364 /***********************************************************************
2365 * ImmReleaseContext (IMM32.@)
2367 BOOL WINAPI
ImmReleaseContext(HWND hWnd
, HIMC hIMC
)
2369 static BOOL shown
= FALSE
;
2372 FIXME("(%p, %p): stub\n", hWnd
, hIMC
);
2378 /***********************************************************************
2379 * ImmRequestMessageA(IMM32.@)
2381 LRESULT WINAPI
ImmRequestMessageA(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
2383 struct imc
*data
= get_imc_data( hIMC
);
2385 TRACE("%p %Id %Id\n", hIMC
, wParam
, wParam
);
2387 if (data
) return SendMessageA(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
2389 SetLastError(ERROR_INVALID_HANDLE
);
2393 /***********************************************************************
2394 * ImmRequestMessageW(IMM32.@)
2396 LRESULT WINAPI
ImmRequestMessageW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
2398 struct imc
*data
= get_imc_data( hIMC
);
2400 TRACE("%p %Id %Id\n", hIMC
, wParam
, wParam
);
2402 if (data
) return SendMessageW(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
2404 SetLastError(ERROR_INVALID_HANDLE
);
2408 /***********************************************************************
2409 * ImmSetCandidateWindow (IMM32.@)
2411 BOOL WINAPI
ImmSetCandidateWindow( HIMC himc
, CANDIDATEFORM
*candidate
)
2415 TRACE( "hwnd %p, candidate %s\n", himc
, debugstr_candidate( candidate
) );
2417 if (!candidate
) return FALSE
;
2418 if (candidate
->dwIndex
>= ARRAY_SIZE(ctx
->cfCandForm
)) return FALSE
;
2420 if (NtUserQueryInputContext( himc
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2421 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2423 ctx
->cfCandForm
[candidate
->dwIndex
] = *candidate
;
2425 ImmNotifyIME( himc
, NI_CONTEXTUPDATED
, 0, IMC_SETCANDIDATEPOS
);
2426 SendMessageW( ctx
->hWnd
, WM_IME_NOTIFY
, IMN_SETCANDIDATEPOS
, 1 << candidate
->dwIndex
);
2428 ImmUnlockIMC( himc
);
2433 /***********************************************************************
2434 * ImmSetCompositionFontA (IMM32.@)
2436 BOOL WINAPI
ImmSetCompositionFontA( HIMC himc
, LOGFONTA
*fontA
)
2441 TRACE( "hwnd %p, fontA %p\n", himc
, fontA
);
2443 if (!fontA
) return FALSE
;
2445 if (NtUserQueryInputContext( himc
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2446 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2448 if (input_context_is_unicode( ctx
))
2451 memcpy( &fontW
, fontA
, offsetof(LOGFONTW
, lfFaceName
) );
2452 MultiByteToWideChar( CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
.lfFaceName
, LF_FACESIZE
);
2453 ret
= ImmSetCompositionFontW( himc
, &fontW
);
2457 ctx
->lfFont
.A
= *fontA
;
2458 ctx
->fdwInit
|= INIT_LOGFONT
;
2460 ImmNotifyIME( himc
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
);
2461 SendMessageW( ctx
->hWnd
, WM_IME_NOTIFY
, IMN_SETCOMPOSITIONFONT
, 0 );
2464 ImmUnlockIMC( himc
);
2469 /***********************************************************************
2470 * ImmSetCompositionFontW (IMM32.@)
2472 BOOL WINAPI
ImmSetCompositionFontW( HIMC himc
, LOGFONTW
*fontW
)
2477 TRACE( "hwnd %p, fontW %p\n", himc
, fontW
);
2479 if (!fontW
) return FALSE
;
2481 if (NtUserQueryInputContext( himc
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2482 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2484 if (!input_context_is_unicode( ctx
))
2487 memcpy( &fontA
, fontW
, offsetof(LOGFONTA
, lfFaceName
) );
2488 WideCharToMultiByte( CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
.lfFaceName
, LF_FACESIZE
, NULL
, NULL
);
2489 ret
= ImmSetCompositionFontA( himc
, &fontA
);
2493 ctx
->lfFont
.W
= *fontW
;
2494 ctx
->fdwInit
|= INIT_LOGFONT
;
2496 ImmNotifyIME( himc
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
);
2497 SendMessageW( ctx
->hWnd
, WM_IME_NOTIFY
, IMN_SETCOMPOSITIONFONT
, 0 );
2500 ImmUnlockIMC( himc
);
2505 /***********************************************************************
2506 * ImmSetCompositionStringA (IMM32.@)
2508 BOOL WINAPI
ImmSetCompositionStringA(
2509 HIMC hIMC
, DWORD dwIndex
,
2510 LPCVOID lpComp
, DWORD dwCompLen
,
2511 LPCVOID lpRead
, DWORD dwReadLen
)
2515 WCHAR
*CompBuffer
= NULL
;
2516 WCHAR
*ReadBuffer
= NULL
;
2518 struct imc
*data
= get_imc_data( hIMC
);
2521 TRACE("(%p, %ld, %p, %ld, %p, %ld):\n",
2522 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2527 if (NtUserQueryInputContext( hIMC
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2529 if (!(dwIndex
== SCS_SETSTR
||
2530 dwIndex
== SCS_CHANGEATTR
||
2531 dwIndex
== SCS_CHANGECLAUSE
||
2532 dwIndex
== SCS_SETRECONVERTSTRING
||
2533 dwIndex
== SCS_QUERYRECONVERTSTRING
))
2536 if (!(ime
= imc_select_ime( data
))) return FALSE
;
2537 if (!ime_is_unicode( ime
)) return ime
->pImeSetCompositionString( hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2539 comp_len
= MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0);
2542 CompBuffer
= malloc( comp_len
* sizeof(WCHAR
) );
2543 MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
);
2546 read_len
= MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0);
2549 ReadBuffer
= malloc( read_len
* sizeof(WCHAR
) );
2550 MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
);
2553 rc
= ImmSetCompositionStringW(hIMC
, dwIndex
, CompBuffer
, comp_len
,
2554 ReadBuffer
, read_len
);
2562 /***********************************************************************
2563 * ImmSetCompositionStringW (IMM32.@)
2565 BOOL WINAPI
ImmSetCompositionStringW(
2566 HIMC hIMC
, DWORD dwIndex
,
2567 LPCVOID lpComp
, DWORD dwCompLen
,
2568 LPCVOID lpRead
, DWORD dwReadLen
)
2572 CHAR
*CompBuffer
= NULL
;
2573 CHAR
*ReadBuffer
= NULL
;
2575 struct imc
*data
= get_imc_data( hIMC
);
2578 TRACE("(%p, %ld, %p, %ld, %p, %ld):\n",
2579 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2584 if (NtUserQueryInputContext( hIMC
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2586 if (!(dwIndex
== SCS_SETSTR
||
2587 dwIndex
== SCS_CHANGEATTR
||
2588 dwIndex
== SCS_CHANGECLAUSE
||
2589 dwIndex
== SCS_SETRECONVERTSTRING
||
2590 dwIndex
== SCS_QUERYRECONVERTSTRING
))
2593 if (!(ime
= imc_select_ime( data
))) return FALSE
;
2594 if (ime_is_unicode( ime
)) return ime
->pImeSetCompositionString( hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2596 comp_len
= WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0, NULL
,
2600 CompBuffer
= malloc( comp_len
);
2601 WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
,
2605 read_len
= WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0, NULL
,
2609 ReadBuffer
= malloc( read_len
);
2610 WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
,
2614 rc
= ImmSetCompositionStringA(hIMC
, dwIndex
, CompBuffer
, comp_len
,
2615 ReadBuffer
, read_len
);
2623 /***********************************************************************
2624 * ImmSetCompositionWindow (IMM32.@)
2626 BOOL WINAPI
ImmSetCompositionWindow( HIMC himc
, COMPOSITIONFORM
*composition
)
2630 TRACE( "himc %p, composition %s\n", himc
, debugstr_composition( composition
) );
2632 if (NtUserQueryInputContext( himc
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2633 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2635 ctx
->cfCompForm
= *composition
;
2636 ctx
->fdwInit
|= INIT_COMPFORM
;
2638 ImmNotifyIME( himc
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONWINDOW
);
2639 SendMessageW( ctx
->hWnd
, WM_IME_NOTIFY
, IMN_SETCOMPOSITIONWINDOW
, 0 );
2641 ImmUnlockIMC( himc
);
2646 /***********************************************************************
2647 * ImmSetConversionStatus (IMM32.@)
2649 BOOL WINAPI
ImmSetConversionStatus( HIMC himc
, DWORD conversion
, DWORD sentence
)
2651 DWORD old_conversion
, old_sentence
;
2654 TRACE( "himc %p, conversion %#lx, sentence %#lx\n", himc
, conversion
, sentence
);
2656 if (NtUserQueryInputContext( himc
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2657 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2659 if (conversion
!= ctx
->fdwConversion
)
2661 old_conversion
= ctx
->fdwConversion
;
2662 ctx
->fdwConversion
= conversion
;
2663 ImmNotifyIME( himc
, NI_CONTEXTUPDATED
, old_conversion
, IMC_SETCONVERSIONMODE
);
2664 SendMessageW( ctx
->hWnd
, WM_IME_NOTIFY
, IMN_SETCONVERSIONMODE
, 0 );
2667 if (sentence
!= ctx
->fdwSentence
)
2669 old_sentence
= ctx
->fdwSentence
;
2670 ctx
->fdwSentence
= sentence
;
2671 ImmNotifyIME( himc
, NI_CONTEXTUPDATED
, old_sentence
, IMC_SETSENTENCEMODE
);
2672 SendMessageW( ctx
->hWnd
, WM_IME_NOTIFY
, IMN_SETSENTENCEMODE
, 0 );
2675 ImmUnlockIMC( himc
);
2680 /***********************************************************************
2681 * ImmSetOpenStatus (IMM32.@)
2683 BOOL WINAPI
ImmSetOpenStatus( HIMC himc
, BOOL status
)
2688 TRACE( "himc %p, status %u\n", himc
, status
);
2690 if (NtUserQueryInputContext( himc
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2691 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2693 if ((ui_hwnd
= get_ime_ui_window())) SetWindowLongPtrW( ui_hwnd
, IMMGWL_IMC
, (LONG_PTR
)himc
);
2695 if (status
!= ctx
->fOpen
)
2697 ctx
->fOpen
= status
;
2698 ImmNotifyIME( himc
, NI_CONTEXTUPDATED
, 0, IMC_SETOPENSTATUS
);
2699 SendMessageW( ctx
->hWnd
, WM_IME_NOTIFY
, IMN_SETOPENSTATUS
, 0 );
2702 ImmUnlockIMC( himc
);
2707 /***********************************************************************
2708 * ImmSetStatusWindowPos (IMM32.@)
2710 BOOL WINAPI
ImmSetStatusWindowPos( HIMC himc
, POINT
*pos
)
2714 TRACE( "himc %p, pos %s\n", himc
, wine_dbgstr_point( pos
) );
2718 SetLastError( ERROR_INVALID_HANDLE
);
2722 if (NtUserQueryInputContext( himc
, NtUserInputContextThreadId
) != GetCurrentThreadId()) return FALSE
;
2723 if (!(ctx
= ImmLockIMC( himc
))) return FALSE
;
2725 ctx
->ptStatusWndPos
= *pos
;
2726 ctx
->fdwInit
|= INIT_STATUSWNDPOS
;
2728 ImmNotifyIME( himc
, NI_CONTEXTUPDATED
, 0, IMC_SETSTATUSWINDOWPOS
);
2729 SendMessageW( ctx
->hWnd
, WM_IME_NOTIFY
, IMN_SETSTATUSWINDOWPOS
, 0 );
2731 ImmUnlockIMC( himc
);
2736 /***********************************************************************
2737 * ImmCreateSoftKeyboard(IMM32.@)
2739 HWND WINAPI
ImmCreateSoftKeyboard(UINT uType
, UINT hOwner
, int x
, int y
)
2741 FIXME("(%d, %d, %d, %d): stub\n", uType
, hOwner
, x
, y
);
2742 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2746 /***********************************************************************
2747 * ImmDestroySoftKeyboard(IMM32.@)
2749 BOOL WINAPI
ImmDestroySoftKeyboard(HWND hSoftWnd
)
2751 FIXME("(%p): stub\n", hSoftWnd
);
2752 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2756 /***********************************************************************
2757 * ImmShowSoftKeyboard(IMM32.@)
2759 BOOL WINAPI
ImmShowSoftKeyboard(HWND hSoftWnd
, int nCmdShow
)
2761 FIXME("(%p, %d): stub\n", hSoftWnd
, nCmdShow
);
2762 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2766 /***********************************************************************
2767 * ImmSimulateHotKey (IMM32.@)
2769 BOOL WINAPI
ImmSimulateHotKey(HWND hWnd
, DWORD dwHotKeyID
)
2771 FIXME("(%p, %ld): stub\n", hWnd
, dwHotKeyID
);
2772 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2776 /***********************************************************************
2777 * ImmUnregisterWordA (IMM32.@)
2779 BOOL WINAPI
ImmUnregisterWordA( HKL hkl
, const char *readingA
, DWORD style
, const char *stringA
)
2784 TRACE( "hkl %p, readingA %s, style %lu, stringA %s.\n", hkl
, debugstr_a(readingA
), style
, debugstr_a(stringA
) );
2786 if (!(ime
= ime_acquire( hkl
))) return FALSE
;
2788 if (!ime_is_unicode( ime
))
2789 ret
= ime
->pImeUnregisterWord( readingA
, style
, stringA
);
2792 WCHAR
*readingW
= strdupAtoW( readingA
), *stringW
= strdupAtoW( stringA
);
2793 ret
= ime
->pImeUnregisterWord( readingW
, style
, stringW
);
2802 /***********************************************************************
2803 * ImmUnregisterWordW (IMM32.@)
2805 BOOL WINAPI
ImmUnregisterWordW( HKL hkl
, const WCHAR
*readingW
, DWORD style
, const WCHAR
*stringW
)
2810 TRACE( "hkl %p, readingW %s, style %lu, stringW %s.\n", hkl
, debugstr_w(readingW
), style
, debugstr_w(stringW
) );
2812 if (!(ime
= ime_acquire( hkl
))) return FALSE
;
2814 if (ime_is_unicode( ime
))
2815 ret
= ime
->pImeUnregisterWord( readingW
, style
, stringW
);
2818 char *readingA
= strdupWtoA( readingW
), *stringA
= strdupWtoA( stringW
);
2819 ret
= ime
->pImeUnregisterWord( readingA
, style
, stringA
);
2828 /***********************************************************************
2829 * ImmGetImeMenuItemsA (IMM32.@)
2831 DWORD WINAPI
ImmGetImeMenuItemsA( HIMC himc
, DWORD flags
, DWORD type
, IMEMENUITEMINFOA
*parentA
,
2832 IMEMENUITEMINFOA
*menuA
, DWORD size
)
2834 struct imc
*data
= get_imc_data( himc
);
2838 TRACE( "himc %p, flags %#lx, type %lu, parentA %p, menuA %p, size %lu.\n",
2839 himc
, flags
, type
, parentA
, menuA
, size
);
2843 SetLastError( ERROR_INVALID_HANDLE
);
2847 if (!(ime
= imc_select_ime( data
))) return 0;
2848 if (!ime_is_unicode( ime
) || (!parentA
&& !menuA
))
2849 ret
= ime
->pImeGetImeMenuItems( himc
, flags
, type
, parentA
, menuA
, size
);
2852 IMEMENUITEMINFOW tmpW
, *menuW
, *parentW
= parentA
? &tmpW
: NULL
;
2854 if (!menuA
) menuW
= NULL
;
2857 int count
= size
/ sizeof(LPIMEMENUITEMINFOA
);
2858 size
= count
* sizeof(IMEMENUITEMINFOW
);
2859 menuW
= malloc( size
);
2862 ret
= ime
->pImeGetImeMenuItems( himc
, flags
, type
, parentW
, menuW
, size
);
2866 memcpy( parentA
, parentW
, sizeof(IMEMENUITEMINFOA
) );
2867 parentA
->hbmpItem
= parentW
->hbmpItem
;
2868 WideCharToMultiByte( CP_ACP
, 0, parentW
->szString
, -1, parentA
->szString
,
2869 IMEMENUITEM_STRING_SIZE
, NULL
, NULL
);
2874 for (i
= 0; i
< ret
; i
++)
2876 memcpy( &menuA
[i
], &menuW
[1], sizeof(IMEMENUITEMINFOA
) );
2877 menuA
[i
].hbmpItem
= menuW
[i
].hbmpItem
;
2878 WideCharToMultiByte( CP_ACP
, 0, menuW
[i
].szString
, -1, menuA
[i
].szString
,
2879 IMEMENUITEM_STRING_SIZE
, NULL
, NULL
);
2888 /***********************************************************************
2889 * ImmGetImeMenuItemsW (IMM32.@)
2891 DWORD WINAPI
ImmGetImeMenuItemsW( HIMC himc
, DWORD flags
, DWORD type
, IMEMENUITEMINFOW
*parentW
,
2892 IMEMENUITEMINFOW
*menuW
, DWORD size
)
2894 struct imc
*data
= get_imc_data( himc
);
2898 TRACE( "himc %p, flags %#lx, type %lu, parentW %p, menuW %p, size %lu.\n",
2899 himc
, flags
, type
, parentW
, menuW
, size
);
2903 SetLastError( ERROR_INVALID_HANDLE
);
2907 if (!(ime
= imc_select_ime( data
))) return 0;
2908 if (ime_is_unicode( ime
) || (!parentW
&& !menuW
))
2909 ret
= ime
->pImeGetImeMenuItems( himc
, flags
, type
, parentW
, menuW
, size
);
2912 IMEMENUITEMINFOA tmpA
, *menuA
, *parentA
= parentW
? &tmpA
: NULL
;
2914 if (!menuW
) menuA
= NULL
;
2917 int count
= size
/ sizeof(LPIMEMENUITEMINFOW
);
2918 size
= count
* sizeof(IMEMENUITEMINFOA
);
2919 menuA
= malloc( size
);
2922 ret
= ime
->pImeGetImeMenuItems( himc
, flags
, type
, parentA
, menuA
, size
);
2926 memcpy( parentW
, parentA
, sizeof(IMEMENUITEMINFOA
) );
2927 parentW
->hbmpItem
= parentA
->hbmpItem
;
2928 MultiByteToWideChar( CP_ACP
, 0, parentA
->szString
, -1, parentW
->szString
, IMEMENUITEM_STRING_SIZE
);
2933 for (i
= 0; i
< ret
; i
++)
2935 memcpy( &menuW
[i
], &menuA
[1], sizeof(IMEMENUITEMINFOA
) );
2936 menuW
[i
].hbmpItem
= menuA
[i
].hbmpItem
;
2937 MultiByteToWideChar( CP_ACP
, 0, menuA
[i
].szString
, -1, menuW
[i
].szString
, IMEMENUITEM_STRING_SIZE
);
2946 /***********************************************************************
2947 * ImmLockIMC(IMM32.@)
2949 INPUTCONTEXT
*WINAPI
ImmLockIMC( HIMC himc
)
2951 struct imc
*imc
= get_imc_data( himc
);
2953 TRACE( "himc %p\n", himc
);
2955 if (!imc
) return NULL
;
2958 imc_select_ime( imc
);
2962 /***********************************************************************
2963 * ImmUnlockIMC(IMM32.@)
2965 BOOL WINAPI
ImmUnlockIMC(HIMC hIMC
)
2967 struct imc
*data
= get_imc_data( hIMC
);
2976 /***********************************************************************
2977 * ImmGetIMCLockCount(IMM32.@)
2979 DWORD WINAPI
ImmGetIMCLockCount(HIMC hIMC
)
2981 struct imc
*data
= get_imc_data( hIMC
);
2984 return data
->dwLock
;
2987 /***********************************************************************
2988 * ImmCreateIMCC(IMM32.@)
2990 HIMCC WINAPI
ImmCreateIMCC(DWORD size
)
2992 return GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
, size
);
2995 /***********************************************************************
2996 * ImmDestroyIMCC(IMM32.@)
2998 HIMCC WINAPI
ImmDestroyIMCC(HIMCC block
)
3000 return GlobalFree(block
);
3003 /***********************************************************************
3004 * ImmLockIMCC(IMM32.@)
3006 LPVOID WINAPI
ImmLockIMCC(HIMCC imcc
)
3008 return GlobalLock(imcc
);
3011 /***********************************************************************
3012 * ImmUnlockIMCC(IMM32.@)
3014 BOOL WINAPI
ImmUnlockIMCC(HIMCC imcc
)
3016 return GlobalUnlock(imcc
);
3019 /***********************************************************************
3020 * ImmGetIMCCLockCount(IMM32.@)
3022 DWORD WINAPI
ImmGetIMCCLockCount(HIMCC imcc
)
3024 return GlobalFlags(imcc
) & GMEM_LOCKCOUNT
;
3027 /***********************************************************************
3028 * ImmReSizeIMCC(IMM32.@)
3030 HIMCC WINAPI
ImmReSizeIMCC(HIMCC imcc
, DWORD size
)
3032 return GlobalReAlloc(imcc
, size
, GMEM_ZEROINIT
| GMEM_MOVEABLE
);
3035 /***********************************************************************
3036 * ImmGetIMCCSize(IMM32.@)
3038 DWORD WINAPI
ImmGetIMCCSize(HIMCC imcc
)
3040 return GlobalSize(imcc
);
3043 /***********************************************************************
3044 * ImmGenerateMessage(IMM32.@)
3046 BOOL WINAPI
ImmGenerateMessage(HIMC hIMC
)
3048 struct imc
*data
= get_imc_data( hIMC
);
3052 SetLastError(ERROR_INVALID_HANDLE
);
3056 TRACE("%li messages queued\n",data
->IMC
.dwNumMsgBuf
);
3057 if (data
->IMC
.dwNumMsgBuf
> 0)
3059 LPTRANSMSG lpTransMsg
;
3061 DWORD i
, dwNumMsgBuf
;
3063 /* We are going to detach our hMsgBuff so that if processing messages
3064 generates new messages they go into a new buffer */
3065 hMsgBuf
= data
->IMC
.hMsgBuf
;
3066 dwNumMsgBuf
= data
->IMC
.dwNumMsgBuf
;
3068 data
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
3069 data
->IMC
.dwNumMsgBuf
= 0;
3071 lpTransMsg
= ImmLockIMCC(hMsgBuf
);
3072 for (i
= 0; i
< dwNumMsgBuf
; i
++) imc_send_message( data
, lpTransMsg
+ i
);
3073 ImmUnlockIMCC(hMsgBuf
);
3074 ImmDestroyIMCC(hMsgBuf
);
3080 /***********************************************************************
3081 * ImmTranslateMessage(IMM32.@)
3082 * ( Undocumented, call internally and from user32.dll )
3084 BOOL WINAPI
ImmTranslateMessage( HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
3091 TRANSMSG TransMsg
[10];
3094 } buffer
= {.uMsgCount
= ARRAY_SIZE(buffer
.TransMsg
)};
3095 UINT scan
, vkey
, count
, i
;
3101 TRACE( "hwnd %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd
, msg
, wparam
, lparam
);
3103 if (!(data
= get_imc_data( ImmGetContext( hwnd
) ))) return FALSE
;
3104 if (!(ime
= imc_select_ime( data
))) return FALSE
;
3105 if (data
->lastVK
== VK_PROCESSKEY
) return FALSE
;
3107 GetKeyboardState( state
);
3108 scan
= lparam
>> 0x10 & 0xff;
3109 vkey
= data
->lastVK
;
3111 if (ime
->info
.fdwProperty
& IME_PROP_KBD_CHAR_FIRST
)
3113 if (!ime_is_unicode( ime
)) ToAscii( data
->lastVK
, scan
, state
, &chr
, 0 );
3114 else ToUnicodeEx( data
->lastVK
, scan
, state
, &chr
, 1, 0, GetKeyboardLayout( 0 ) );
3115 vkey
= MAKELONG( data
->lastVK
, chr
);
3118 count
= ime
->pImeToAsciiEx( vkey
, scan
, state
, &buffer
.list
, 0, data
->handle
);
3119 TRACE( "%u messages generated\n", count
);
3121 if (count
> ARRAY_SIZE(buffer
.TransMsg
)) ImmGenerateMessage( data
->handle
);
3122 else for (i
= 0; i
< count
; i
++) imc_post_message( data
, buffer
.TransMsg
+ i
);
3124 data
->lastVK
= VK_PROCESSKEY
;
3129 /***********************************************************************
3130 * ImmProcessKey(IMM32.@)
3131 * ( Undocumented, called from user32.dll )
3133 BOOL WINAPI
ImmProcessKey( HWND hwnd
, HKL hkl
, UINT vkey
, LPARAM lparam
, DWORD unknown
)
3140 TRACE( "hwnd %p, hkl %p, vkey %#x, lparam %#Ix, unknown %#lx\n", hwnd
, hkl
, vkey
, lparam
, unknown
);
3142 if (hkl
!= GetKeyboardLayout( 0 )) return FALSE
;
3143 if (!(imc
= get_imc_data( ImmGetContext( hwnd
) ))) return FALSE
;
3144 if (!(ime
= imc_select_ime( imc
))) return FALSE
;
3146 GetKeyboardState( state
);
3148 ret
= ime
->pImeProcessKey( imc
->handle
, vkey
, lparam
, state
);
3149 imc
->lastVK
= ret
? vkey
: VK_PROCESSKEY
;
3154 /***********************************************************************
3155 * ImmDisableTextFrameService(IMM32.@)
3157 BOOL WINAPI
ImmDisableTextFrameService(DWORD idThread
)
3163 /***********************************************************************
3164 * ImmEnumInputContext(IMM32.@)
3167 BOOL WINAPI
ImmEnumInputContext( DWORD thread
, IMCENUMPROC callback
, LPARAM lparam
)
3173 TRACE( "thread %lu, callback %p, lparam %#Ix\n", thread
, callback
, lparam
);
3175 if ((status
= NtUserBuildHimcList( thread
, ARRAY_SIZE(buffer
), buffer
, &size
)))
3177 RtlSetLastWin32Error( RtlNtStatusToDosError( status
) );
3178 WARN( "NtUserBuildHimcList returned %#lx\n", status
);
3182 if (size
== ARRAY_SIZE(buffer
)) FIXME( "NtUserBuildHimcList returned %u handles\n", size
);
3183 for (i
= 0; i
< size
; i
++) if (!callback( buffer
[i
], lparam
)) return FALSE
;
3188 /***********************************************************************
3189 * ImmGetHotKey(IMM32.@)
3192 BOOL WINAPI
ImmGetHotKey(DWORD hotkey
, UINT
*modifiers
, UINT
*key
, HKL
*hkl
)
3194 FIXME("%lx, %p, %p, %p: stub\n", hotkey
, modifiers
, key
, hkl
);
3198 /***********************************************************************
3199 * ImmDisableLegacyIME(IMM32.@)
3201 BOOL WINAPI
ImmDisableLegacyIME(void)
3207 static BOOL
is_ime_ui_msg(UINT msg
)
3211 case WM_IME_STARTCOMPOSITION
:
3212 case WM_IME_ENDCOMPOSITION
:
3213 case WM_IME_COMPOSITION
:
3214 case WM_IME_SETCONTEXT
:
3216 case WM_IME_CONTROL
:
3217 case WM_IME_COMPOSITIONFULL
:
3220 case WM_IME_REQUEST
:
3221 case WM_IME_KEYDOWN
:
3225 return msg
== WM_MSIME_RECONVERTOPTIONS
||
3226 msg
== WM_MSIME_SERVICE
||
3227 msg
== WM_MSIME_MOUSE
||
3228 msg
== WM_MSIME_RECONVERTREQUEST
||
3229 msg
== WM_MSIME_RECONVERT
||
3230 msg
== WM_MSIME_QUERYPOSITION
||
3231 msg
== WM_MSIME_DOCUMENTFEED
;
3235 static LRESULT
ime_internal_msg( WPARAM wparam
, LPARAM lparam
)
3242 case IME_INTERNAL_ACTIVATE
:
3243 case IME_INTERNAL_DEACTIVATE
:
3244 hwnd
= (HWND
)lparam
;
3245 himc
= ImmGetContext(hwnd
);
3246 ImmSetActiveContext(hwnd
, himc
, wparam
== IME_INTERNAL_ACTIVATE
);
3247 ImmReleaseContext(hwnd
, himc
);
3249 case IME_INTERNAL_HKL_ACTIVATE
:
3250 ImmEnumInputContext( 0, enum_activate_layout
, 0 );
3251 if (!(hwnd
= get_ime_ui_window())) break;
3252 SendMessageW( hwnd
, WM_IME_SELECT
, TRUE
, lparam
);
3254 case IME_INTERNAL_HKL_DEACTIVATE
:
3255 if (!(hwnd
= get_ime_ui_window())) break;
3256 SendMessageW( hwnd
, WM_IME_SELECT
, FALSE
, lparam
);
3259 FIXME("wparam = %Ix\n", wparam
);
3266 static void init_messages(void)
3268 static BOOL initialized
;
3270 if (initialized
) return;
3272 WM_MSIME_SERVICE
= RegisterWindowMessageW(L
"MSIMEService");
3273 WM_MSIME_RECONVERTOPTIONS
= RegisterWindowMessageW(L
"MSIMEReconvertOptions");
3274 WM_MSIME_MOUSE
= RegisterWindowMessageW(L
"MSIMEMouseOperation");
3275 WM_MSIME_RECONVERTREQUEST
= RegisterWindowMessageW(L
"MSIMEReconvertRequest");
3276 WM_MSIME_RECONVERT
= RegisterWindowMessageW(L
"MSIMEReconvert");
3277 WM_MSIME_QUERYPOSITION
= RegisterWindowMessageW(L
"MSIMEQueryPosition");
3278 WM_MSIME_DOCUMENTFEED
= RegisterWindowMessageW(L
"MSIMEDocumentFeed");
3282 LRESULT WINAPI
__wine_ime_wnd_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
, BOOL ansi
)
3286 TRACE( "hwnd %p, msg %s, wparam %#Ix, lparam %#Ix, ansi %u\n",
3287 hwnd
, debugstr_wm_ime(msg
), wparam
, lparam
, ansi
);
3297 HWND default_hwnd
= ImmGetDefaultIMEWnd(0);
3298 if (!default_hwnd
|| hwnd
== default_hwnd
)
3299 imm_couninit_thread(TRUE
);
3303 case WM_IME_INTERNAL
:
3304 return ime_internal_msg(wparam
, lparam
);
3307 if (is_ime_ui_msg(msg
))
3309 if ((ui_hwnd
= get_ime_ui_window()))
3312 return SendMessageA(ui_hwnd
, msg
, wparam
, lparam
);
3314 return SendMessageW(ui_hwnd
, msg
, wparam
, lparam
);
3320 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
3322 return DefWindowProcW(hwnd
, msg
, wparam
, lparam
);