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
34 #include "wine/debug.h"
39 #include "wine/list.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
43 #define IMM_INIT_MAGIC 0x19650412
44 BOOL WINAPI
User32InitializeImmEntryTable(DWORD
);
46 typedef struct _tagImmHkl
{
51 WCHAR imeClassName
[17]; /* 16 character max */
55 /* Function Pointers */
56 BOOL (WINAPI
*pImeInquire
)(IMEINFO
*, WCHAR
*, const WCHAR
*);
57 BOOL (WINAPI
*pImeConfigure
)(HKL
, HWND
, DWORD
, void *);
58 BOOL (WINAPI
*pImeDestroy
)(UINT
);
59 LRESULT (WINAPI
*pImeEscape
)(HIMC
, UINT
, void *);
60 BOOL (WINAPI
*pImeSelect
)(HIMC
, BOOL
);
61 BOOL (WINAPI
*pImeSetActiveContext
)(HIMC
, BOOL
);
62 UINT (WINAPI
*pImeToAsciiEx
)(UINT
, UINT
, const BYTE
*, DWORD
*, UINT
, HIMC
);
63 BOOL (WINAPI
*pNotifyIME
)(HIMC
, DWORD
, DWORD
, DWORD
);
64 BOOL (WINAPI
*pImeRegisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
65 BOOL (WINAPI
*pImeUnregisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
66 UINT (WINAPI
*pImeEnumRegisterWord
)(REGISTERWORDENUMPROCW
, const WCHAR
*, DWORD
, const WCHAR
*, void *);
67 BOOL (WINAPI
*pImeSetCompositionString
)(HIMC
, DWORD
, const void *, DWORD
, const void *, DWORD
);
68 DWORD (WINAPI
*pImeConversionList
)(HIMC
, const WCHAR
*, CANDIDATELIST
*, DWORD
, UINT
);
69 BOOL (WINAPI
*pImeProcessKey
)(HIMC
, UINT
, LPARAM
, const BYTE
*);
70 UINT (WINAPI
*pImeGetRegisterWordStyle
)(UINT
, STYLEBUFW
*);
71 DWORD (WINAPI
*pImeGetImeMenuItems
)(HIMC
, DWORD
, DWORD
, IMEMENUITEMINFOW
*, IMEMENUITEMINFOW
*, DWORD
);
74 typedef struct tagInputContextData
86 #define WINE_IMC_VALID_MAGIC 0x56434D49
88 typedef struct _tagTRANSMSG
{
92 } TRANSMSG
, *LPTRANSMSG
;
94 typedef struct _tagIMMThreadData
{
101 IInitializeSpy IInitializeSpy_iface
;
102 ULARGE_INTEGER spy_cookie
;
106 IMM_APT_CREATED
= 0x2,
107 IMM_APT_CAN_FREE
= 0x4,
112 static struct list ImmHklList
= LIST_INIT(ImmHklList
);
113 static struct list ImmThreadDataList
= LIST_INIT(ImmThreadDataList
);
115 static const WCHAR szwWineIMCProperty
[] = L
"WineImmHIMCProperty";
116 static const WCHAR szImeRegFmt
[] = L
"System\\CurrentControlSet\\Control\\Keyboard Layouts\\%08lx";
118 static CRITICAL_SECTION threaddata_cs
;
119 static CRITICAL_SECTION_DEBUG critsect_debug
=
121 0, 0, &threaddata_cs
,
122 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
123 0, 0, { (DWORD_PTR
)(__FILE__
": threaddata_cs") }
125 static CRITICAL_SECTION threaddata_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
126 static BOOL disable_ime
;
128 static inline BOOL
is_himc_ime_unicode(const InputContextData
*data
)
130 return !!(data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
133 static inline BOOL
is_kbd_ime_unicode(const ImmHkl
*hkl
)
135 return !!(hkl
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
138 static BOOL
IMM_DestroyContext(HIMC hIMC
);
139 static InputContextData
* get_imc_data(HIMC hIMC
);
141 static inline WCHAR
*strdupAtoW( const char *str
)
146 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
147 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
148 MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
153 static inline CHAR
*strdupWtoA( const WCHAR
*str
)
158 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
159 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
160 WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
165 static DWORD
convert_candidatelist_WtoA(
166 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
170 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
171 if ( lpDst
&& dwBufLen
> 0 )
174 lpDst
->dwOffset
[0] = ret
;
177 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
179 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
181 if ( lpDst
&& dwBufLen
> 0 )
183 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
185 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1,
186 (LPSTR
)dest
, dwBufLen
, NULL
, NULL
);
188 if ( i
+ 1 < lpSrc
->dwCount
)
189 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(char);
190 dwBufLen
-= len
* sizeof(char);
193 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1, NULL
, 0, NULL
, NULL
);
195 ret
+= len
* sizeof(char);
204 static DWORD
convert_candidatelist_AtoW(
205 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
209 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
210 if ( lpDst
&& dwBufLen
> 0 )
213 lpDst
->dwOffset
[0] = ret
;
216 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
218 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
220 if ( lpDst
&& dwBufLen
> 0 )
222 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
224 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1,
225 (LPWSTR
)dest
, dwBufLen
);
227 if ( i
+ 1 < lpSrc
->dwCount
)
228 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(WCHAR
);
229 dwBufLen
-= len
* sizeof(WCHAR
);
232 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1, NULL
, 0);
234 ret
+= len
* sizeof(WCHAR
);
243 static void imm_coinit_thread(IMMThreadData
*thread_data
)
247 TRACE("implicit COM initialization\n");
249 if (thread_data
->threadID
!= GetCurrentThreadId())
252 if (thread_data
->apt_flags
& (IMM_APT_INIT
| IMM_APT_BROKEN
))
254 thread_data
->apt_flags
|= IMM_APT_INIT
;
256 if(!thread_data
->spy_cookie
.QuadPart
)
258 hr
= CoRegisterInitializeSpy(&thread_data
->IInitializeSpy_iface
,
259 &thread_data
->spy_cookie
);
264 hr
= CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
266 thread_data
->apt_flags
|= IMM_APT_CREATED
;
269 static void imm_couninit_thread(IMMThreadData
*thread_data
, BOOL cleanup
)
271 TRACE("implicit COM deinitialization\n");
273 if (thread_data
->apt_flags
& IMM_APT_BROKEN
)
276 if (cleanup
&& thread_data
->spy_cookie
.QuadPart
)
278 CoRevokeInitializeSpy(thread_data
->spy_cookie
);
279 thread_data
->spy_cookie
.QuadPart
= 0;
282 if (!(thread_data
->apt_flags
& IMM_APT_INIT
))
284 thread_data
->apt_flags
&= ~IMM_APT_INIT
;
286 if (thread_data
->apt_flags
& IMM_APT_CREATED
)
288 thread_data
->apt_flags
&= ~IMM_APT_CREATED
;
289 if (thread_data
->apt_flags
& IMM_APT_CAN_FREE
)
293 thread_data
->apt_flags
= 0;
296 static inline IMMThreadData
*impl_from_IInitializeSpy(IInitializeSpy
*iface
)
298 return CONTAINING_RECORD(iface
, IMMThreadData
, IInitializeSpy_iface
);
301 static HRESULT WINAPI
InitializeSpy_QueryInterface(IInitializeSpy
*iface
, REFIID riid
, void **obj
)
303 if (IsEqualIID(&IID_IInitializeSpy
, riid
) ||
304 IsEqualIID(&IID_IUnknown
, riid
))
307 IInitializeSpy_AddRef(iface
);
312 return E_NOINTERFACE
;
315 static ULONG WINAPI
InitializeSpy_AddRef(IInitializeSpy
*iface
)
320 static ULONG WINAPI
InitializeSpy_Release(IInitializeSpy
*iface
)
325 static HRESULT WINAPI
InitializeSpy_PreInitialize(IInitializeSpy
*iface
,
326 DWORD coinit
, DWORD refs
)
328 IMMThreadData
*thread_data
= impl_from_IInitializeSpy(iface
);
330 if ((thread_data
->apt_flags
& IMM_APT_CREATED
) &&
331 !(coinit
& COINIT_APARTMENTTHREADED
) && refs
== 1)
333 imm_couninit_thread(thread_data
, TRUE
);
334 thread_data
->apt_flags
|= IMM_APT_BROKEN
;
339 static HRESULT WINAPI
InitializeSpy_PostInitialize(IInitializeSpy
*iface
,
340 HRESULT hr
, DWORD coinit
, DWORD refs
)
342 IMMThreadData
*thread_data
= impl_from_IInitializeSpy(iface
);
344 if ((thread_data
->apt_flags
& IMM_APT_CREATED
) && hr
== S_FALSE
&& refs
== 2)
347 thread_data
->apt_flags
|= IMM_APT_CAN_FREE
;
351 static HRESULT WINAPI
InitializeSpy_PreUninitialize(IInitializeSpy
*iface
, DWORD refs
)
356 static HRESULT WINAPI
InitializeSpy_PostUninitialize(IInitializeSpy
*iface
, DWORD refs
)
358 IMMThreadData
*thread_data
= impl_from_IInitializeSpy(iface
);
360 if (refs
== 1 && !thread_data
->windowRefs
)
361 imm_couninit_thread(thread_data
, FALSE
);
363 thread_data
->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 IMMThreadData
*IMM_GetThreadData(HWND hwnd
, DWORD thread
)
385 if (!(thread
= GetWindowThreadProcessId(hwnd
, &process
))) return NULL
;
386 if (process
!= GetCurrentProcessId()) return NULL
;
390 HANDLE h
= OpenThread(THREAD_QUERY_INFORMATION
, FALSE
, thread
);
392 process
= GetProcessIdOfThread(h
);
394 if (process
!= GetCurrentProcessId()) return NULL
;
397 thread
= GetCurrentThreadId();
399 EnterCriticalSection(&threaddata_cs
);
400 LIST_FOR_EACH_ENTRY(data
, &ImmThreadDataList
, IMMThreadData
, entry
)
401 if (data
->threadID
== thread
) return data
;
403 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
404 data
->IInitializeSpy_iface
.lpVtbl
= &InitializeSpyVtbl
;
405 data
->threadID
= thread
;
406 list_add_head(&ImmThreadDataList
,&data
->entry
);
407 TRACE("Thread Data Created (%lx)\n",thread
);
411 static BOOL
IMM_IsDefaultContext(HIMC imc
)
413 InputContextData
*data
= get_imc_data(imc
);
418 return data
->threadDefault
;
421 static void IMM_FreeThreadData(void)
425 EnterCriticalSection(&threaddata_cs
);
426 LIST_FOR_EACH_ENTRY(data
, &ImmThreadDataList
, IMMThreadData
, entry
)
428 if (data
->threadID
== GetCurrentThreadId())
430 list_remove(&data
->entry
);
431 LeaveCriticalSection(&threaddata_cs
);
432 IMM_DestroyContext(data
->defaultContext
);
433 imm_couninit_thread(data
, TRUE
);
434 HeapFree(GetProcessHeap(),0,data
);
435 TRACE("Thread Data Destroyed\n");
439 LeaveCriticalSection(&threaddata_cs
);
442 static HMODULE
load_graphics_driver(void)
444 static const WCHAR key_pathW
[] = L
"System\\CurrentControlSet\\Control\\Video\\{";
445 static const WCHAR displayW
[] = L
"}\\0000";
450 WCHAR path
[MAX_PATH
];
451 WCHAR key
[ARRAY_SIZE( key_pathW
) + ARRAY_SIZE( displayW
) + 40];
452 UINT guid_atom
= HandleToULong( GetPropW( GetDesktopWindow(), L
"__wine_display_device_guid" ));
454 if (!guid_atom
) return 0;
455 memcpy( key
, key_pathW
, sizeof(key_pathW
) );
456 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
457 lstrcatW( key
, displayW
);
458 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
460 if (!RegQueryValueExW( hkey
, L
"GraphicsDriver", NULL
, NULL
, (BYTE
*)path
, &size
))
461 ret
= LoadLibraryW( path
);
463 TRACE( "%s %p\n", debugstr_w(path
), ret
);
467 /* ImmHkl loading and freeing */
468 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
469 static ImmHkl
*IMM_GetImmHkl(HKL hkl
)
472 WCHAR filename
[MAX_PATH
];
474 TRACE("Seeking ime for keyboard %p\n",hkl
);
476 LIST_FOR_EACH_ENTRY(ptr
, &ImmHklList
, ImmHkl
, entry
)
481 /* not found... create it */
483 ptr
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ImmHkl
));
486 if (ImmGetIMEFileNameW(hkl
, filename
, MAX_PATH
)) ptr
->hIME
= LoadLibraryW(filename
);
487 if (!ptr
->hIME
) ptr
->hIME
= load_graphics_driver();
490 LOAD_FUNCPTR(ImeInquire
);
491 if (!ptr
->pImeInquire
|| !ptr
->pImeInquire(&ptr
->imeInfo
, ptr
->imeClassName
, NULL
))
493 FreeLibrary(ptr
->hIME
);
498 LOAD_FUNCPTR(ImeDestroy
);
499 LOAD_FUNCPTR(ImeSelect
);
500 if (!ptr
->pImeSelect
|| !ptr
->pImeDestroy
)
502 FreeLibrary(ptr
->hIME
);
507 LOAD_FUNCPTR(ImeConfigure
);
508 LOAD_FUNCPTR(ImeEscape
);
509 LOAD_FUNCPTR(ImeSetActiveContext
);
510 LOAD_FUNCPTR(ImeToAsciiEx
);
511 LOAD_FUNCPTR(NotifyIME
);
512 LOAD_FUNCPTR(ImeRegisterWord
);
513 LOAD_FUNCPTR(ImeUnregisterWord
);
514 LOAD_FUNCPTR(ImeEnumRegisterWord
);
515 LOAD_FUNCPTR(ImeSetCompositionString
);
516 LOAD_FUNCPTR(ImeConversionList
);
517 LOAD_FUNCPTR(ImeProcessKey
);
518 LOAD_FUNCPTR(ImeGetRegisterWordStyle
);
519 LOAD_FUNCPTR(ImeGetImeMenuItems
);
520 /* make sure our classname is WCHAR */
521 if (!is_kbd_ime_unicode(ptr
))
524 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ptr
->imeClassName
,
526 lstrcpyW(ptr
->imeClassName
, bufW
);
531 list_add_head(&ImmHklList
,&ptr
->entry
);
537 HWND WINAPI
__wine_get_ui_window(HKL hkl
)
539 ImmHkl
*immHkl
= IMM_GetImmHkl(hkl
);
540 return immHkl
->UIWnd
;
543 static void IMM_FreeAllImmHkl(void)
545 ImmHkl
*ptr
,*cursor2
;
547 LIST_FOR_EACH_ENTRY_SAFE(ptr
, cursor2
, &ImmHklList
, ImmHkl
, entry
)
549 list_remove(&ptr
->entry
);
553 FreeLibrary(ptr
->hIME
);
556 DestroyWindow(ptr
->UIWnd
);
557 HeapFree(GetProcessHeap(),0,ptr
);
561 BOOL WINAPI
DllMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID lpReserved
)
563 TRACE("%p, %lx, %p\n",hInstDLL
,fdwReason
,lpReserved
);
566 case DLL_PROCESS_ATTACH
:
567 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC
))
572 case DLL_THREAD_ATTACH
:
574 case DLL_THREAD_DETACH
:
575 IMM_FreeThreadData();
577 case DLL_PROCESS_DETACH
:
578 if (lpReserved
) break;
579 IMM_FreeThreadData();
586 /* for posting messages as the IME */
587 static void ImmInternalPostIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
589 HWND target
= GetFocus();
591 PostMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
593 PostMessageW(target
, msg
, wParam
, lParam
);
596 /* for sending messages as the IME */
597 static void ImmInternalSendIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
599 HWND target
= GetFocus();
601 SendMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
603 SendMessageW(target
, msg
, wParam
, lParam
);
606 static LRESULT
ImmInternalSendIMENotify(InputContextData
*data
, WPARAM notify
, LPARAM lParam
)
610 target
= data
->IMC
.hWnd
;
611 if (!target
) target
= GetFocus();
614 return SendMessageW(target
, WM_IME_NOTIFY
, notify
, lParam
);
619 static HIMCC
ImmCreateBlankCompStr(void)
622 LPCOMPOSITIONSTRING ptr
;
623 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
624 ptr
= ImmLockIMCC(rc
);
625 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
626 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
631 static InputContextData
* get_imc_data(HIMC hIMC
)
633 InputContextData
*data
= hIMC
;
638 if(IsBadReadPtr(data
, sizeof(InputContextData
)) || data
->magic
!= WINE_IMC_VALID_MAGIC
)
640 SetLastError(ERROR_INVALID_HANDLE
);
646 static HIMC
get_default_context( HWND hwnd
)
649 IMMThreadData
* thread_data
= IMM_GetThreadData( hwnd
, 0 );
651 if (!thread_data
) return 0;
653 if (thread_data
->defaultContext
)
655 ret
= thread_data
->defaultContext
;
656 LeaveCriticalSection(&threaddata_cs
);
660 /* can't create a default context in another thread */
661 if (thread_data
->threadID
!= GetCurrentThreadId())
663 LeaveCriticalSection(&threaddata_cs
);
667 LeaveCriticalSection(&threaddata_cs
);
669 ret
= ImmCreateContext();
671 ((InputContextData
*)ret
)->threadDefault
= TRUE
;
673 /* thread_data is in the current thread so we can assume it's still valid */
674 EnterCriticalSection(&threaddata_cs
);
676 if (thread_data
->defaultContext
) /* someone beat us */
678 IMM_DestroyContext( ret
);
679 ret
= thread_data
->defaultContext
;
681 else thread_data
->defaultContext
= ret
;
683 LeaveCriticalSection(&threaddata_cs
);
687 static BOOL
IMM_IsCrossThreadAccess(HWND hWnd
, HIMC hIMC
)
689 InputContextData
*data
;
693 DWORD thread
= GetWindowThreadProcessId(hWnd
, NULL
);
694 if (thread
!= GetCurrentThreadId()) return TRUE
;
696 data
= get_imc_data(hIMC
);
697 if (data
&& data
->threadID
!= GetCurrentThreadId())
703 /***********************************************************************
704 * ImmSetActiveContext (IMM32.@)
706 BOOL WINAPI
ImmSetActiveContext(HWND hwnd
, HIMC himc
, BOOL activate
)
708 InputContextData
*data
= get_imc_data(himc
);
709 IMMThreadData
*thread_data
;
711 TRACE("(%p, %p, %x)\n", hwnd
, himc
, activate
);
713 if (himc
&& !data
&& activate
)
716 thread_data
= IMM_GetThreadData(hwnd
, 0);
719 imm_coinit_thread(thread_data
);
720 LeaveCriticalSection(&threaddata_cs
);
725 data
->IMC
.hWnd
= activate
? hwnd
: NULL
;
727 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeSetActiveContext
)
728 data
->immKbd
->pImeSetActiveContext(himc
, activate
);
733 SendMessageW(hwnd
, WM_IME_SETCONTEXT
, activate
, ISC_SHOWUIALL
);
734 /* TODO: send WM_IME_NOTIFY */
739 /***********************************************************************
740 * ImmAssociateContext (IMM32.@)
742 HIMC WINAPI
ImmAssociateContext(HWND hWnd
, HIMC hIMC
)
744 InputContextData
*data
= get_imc_data(hIMC
);
748 TRACE("(%p, %p):\n", hWnd
, hIMC
);
750 if (!IsWindow(hWnd
) || (hIMC
&& !data
))
753 if (hIMC
&& IMM_IsCrossThreadAccess(hWnd
, hIMC
))
756 old
= GetPropW(hWnd
, szwWineIMCProperty
);
757 defaultContext
= get_default_context( hWnd
);
759 old
= defaultContext
;
760 else if (old
== (HIMC
)-1)
763 /* If already associated just return */
767 if (!hIMC
) /* Meaning disable imm for that window*/
768 SetPropW(hWnd
, szwWineIMCProperty
, (HANDLE
)-1);
769 else if (hIMC
== defaultContext
)
770 RemovePropW(hWnd
, szwWineIMCProperty
);
772 SetPropW(hWnd
, szwWineIMCProperty
, hIMC
);
774 if (GetFocus() == hWnd
)
776 ImmSetActiveContext(hWnd
, old
, FALSE
);
777 ImmSetActiveContext(hWnd
, hIMC
, TRUE
);
784 * Helper function for ImmAssociateContextEx
786 static BOOL CALLBACK
_ImmAssociateContextExEnumProc(HWND hwnd
, LPARAM lParam
)
788 HIMC hImc
= (HIMC
)lParam
;
789 ImmAssociateContext(hwnd
,hImc
);
793 /***********************************************************************
794 * ImmAssociateContextEx (IMM32.@)
796 BOOL WINAPI
ImmAssociateContextEx(HWND hWnd
, HIMC hIMC
, DWORD dwFlags
)
798 TRACE("(%p, %p, 0x%lx):\n", hWnd
, hIMC
, dwFlags
);
806 ImmAssociateContext(hWnd
,hIMC
);
810 HIMC defaultContext
= get_default_context( hWnd
);
811 if (!defaultContext
) return FALSE
;
812 ImmAssociateContext(hWnd
,defaultContext
);
815 case IACE_IGNORENOCONTEXT
:
816 if (GetPropW(hWnd
,szwWineIMCProperty
))
817 ImmAssociateContext(hWnd
,hIMC
);
820 EnumChildWindows(hWnd
,_ImmAssociateContextExEnumProc
,(LPARAM
)hIMC
);
823 FIXME("Unknown dwFlags 0x%lx\n",dwFlags
);
828 /***********************************************************************
829 * ImmConfigureIMEA (IMM32.@)
831 BOOL WINAPI
ImmConfigureIMEA(
832 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
834 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
836 TRACE("(%p, %p, %ld, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
838 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
841 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
843 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| !is_kbd_ime_unicode(immHkl
))
844 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
848 REGISTERWORDA
*rwa
= lpData
;
851 rww
.lpReading
= strdupAtoW(rwa
->lpReading
);
852 rww
.lpWord
= strdupAtoW(rwa
->lpWord
);
853 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rww
);
854 HeapFree(GetProcessHeap(),0,rww
.lpReading
);
855 HeapFree(GetProcessHeap(),0,rww
.lpWord
);
863 /***********************************************************************
864 * ImmConfigureIMEW (IMM32.@)
866 BOOL WINAPI
ImmConfigureIMEW(
867 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
869 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
871 TRACE("(%p, %p, %ld, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
873 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
876 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
878 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| is_kbd_ime_unicode(immHkl
))
879 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
882 REGISTERWORDW
*rww
= lpData
;
886 rwa
.lpReading
= strdupWtoA(rww
->lpReading
);
887 rwa
.lpWord
= strdupWtoA(rww
->lpWord
);
888 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rwa
);
889 HeapFree(GetProcessHeap(),0,rwa
.lpReading
);
890 HeapFree(GetProcessHeap(),0,rwa
.lpWord
);
898 /***********************************************************************
899 * ImmCreateContext (IMM32.@)
901 HIMC WINAPI
ImmCreateContext(void)
903 InputContextData
*new_context
;
908 new_context
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(InputContextData
));
911 new_context
->immKbd
= IMM_GetImmHkl(GetKeyboardLayout(0));
913 if (!new_context
->immKbd
->hIME
)
915 TRACE("IME dll could not be loaded\n");
916 HeapFree(GetProcessHeap(),0,new_context
);
920 /* the HIMCCs are never NULL */
921 new_context
->IMC
.hCompStr
= ImmCreateBlankCompStr();
922 new_context
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
923 new_context
->IMC
.hCandInfo
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
924 ci
= ImmLockIMCC(new_context
->IMC
.hCandInfo
);
925 memset(ci
,0,sizeof(CANDIDATEINFO
));
926 ci
->dwSize
= sizeof(CANDIDATEINFO
);
927 ImmUnlockIMCC(new_context
->IMC
.hCandInfo
);
928 new_context
->IMC
.hGuideLine
= ImmCreateIMCC(sizeof(GUIDELINE
));
929 gl
= ImmLockIMCC(new_context
->IMC
.hGuideLine
);
930 memset(gl
,0,sizeof(GUIDELINE
));
931 gl
->dwSize
= sizeof(GUIDELINE
);
932 ImmUnlockIMCC(new_context
->IMC
.hGuideLine
);
934 for (i
= 0; i
< ARRAY_SIZE(new_context
->IMC
.cfCandForm
); i
++)
935 new_context
->IMC
.cfCandForm
[i
].dwIndex
= ~0u;
937 /* Initialize the IME Private */
938 new_context
->IMC
.hPrivate
= ImmCreateIMCC(new_context
->immKbd
->imeInfo
.dwPrivateDataSize
);
940 new_context
->IMC
.fdwConversion
= new_context
->immKbd
->imeInfo
.fdwConversionCaps
;
941 new_context
->IMC
.fdwSentence
= new_context
->immKbd
->imeInfo
.fdwSentenceCaps
;
943 if (!new_context
->immKbd
->pImeSelect(new_context
, TRUE
))
945 TRACE("Selection of IME failed\n");
946 IMM_DestroyContext(new_context
);
949 new_context
->threadID
= GetCurrentThreadId();
950 SendMessageW(GetFocus(), WM_IME_SELECT
, TRUE
, (LPARAM
)new_context
->immKbd
);
952 new_context
->immKbd
->uSelected
++;
953 TRACE("Created context %p\n",new_context
);
955 new_context
->magic
= WINE_IMC_VALID_MAGIC
;
959 static BOOL
IMM_DestroyContext(HIMC hIMC
)
961 InputContextData
*data
= get_imc_data(hIMC
);
963 TRACE("Destroying %p\n",hIMC
);
968 data
->immKbd
->uSelected
--;
969 data
->immKbd
->pImeSelect(hIMC
, FALSE
);
970 SendMessageW(data
->IMC
.hWnd
, WM_IME_SELECT
, FALSE
, (LPARAM
)data
->immKbd
);
972 ImmDestroyIMCC(data
->IMC
.hCompStr
);
973 ImmDestroyIMCC(data
->IMC
.hCandInfo
);
974 ImmDestroyIMCC(data
->IMC
.hGuideLine
);
975 ImmDestroyIMCC(data
->IMC
.hPrivate
);
976 ImmDestroyIMCC(data
->IMC
.hMsgBuf
);
979 HeapFree(GetProcessHeap(),0,data
);
984 /***********************************************************************
985 * ImmDestroyContext (IMM32.@)
987 BOOL WINAPI
ImmDestroyContext(HIMC hIMC
)
989 if (!IMM_IsDefaultContext(hIMC
) && !IMM_IsCrossThreadAccess(NULL
, hIMC
))
990 return IMM_DestroyContext(hIMC
);
995 static HWND
imm_detach_default_window(IMMThreadData
*thread_data
)
999 imm_couninit_thread(thread_data
, TRUE
);
1000 to_destroy
= thread_data
->hwndDefault
;
1001 thread_data
->hwndDefault
= NULL
;
1002 thread_data
->windowRefs
= 0;
1006 /***********************************************************************
1007 * ImmDisableIME (IMM32.@)
1009 BOOL WINAPI
ImmDisableIME(DWORD idThread
)
1011 IMMThreadData
*thread_data
;
1014 if (idThread
== (DWORD
)-1)
1021 EnterCriticalSection(&threaddata_cs
);
1022 LIST_FOR_EACH_ENTRY(thread_data
, &ImmThreadDataList
, IMMThreadData
, entry
)
1024 if (thread_data
->hwndDefault
)
1026 to_destroy
= imm_detach_default_window(thread_data
);
1030 LeaveCriticalSection(&threaddata_cs
);
1034 DestroyWindow(to_destroy
);
1039 thread_data
= IMM_GetThreadData(NULL
, idThread
);
1040 if (!thread_data
) return FALSE
;
1041 thread_data
->disableIME
= TRUE
;
1042 to_destroy
= imm_detach_default_window(thread_data
);
1043 LeaveCriticalSection(&threaddata_cs
);
1046 DestroyWindow(to_destroy
);
1051 /***********************************************************************
1052 * ImmEnumRegisterWordA (IMM32.@)
1054 UINT WINAPI
ImmEnumRegisterWordA(
1055 HKL hKL
, REGISTERWORDENUMPROCA lpfnEnumProc
,
1056 LPCSTR lpszReading
, DWORD dwStyle
,
1057 LPCSTR lpszRegister
, LPVOID lpData
)
1059 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1060 TRACE("(%p, %p, %s, %ld, %s, %p):\n", hKL
, lpfnEnumProc
,
1061 debugstr_a(lpszReading
), dwStyle
, debugstr_a(lpszRegister
), lpData
);
1062 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
1064 if (!is_kbd_ime_unicode(immHkl
))
1065 return immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
1066 (LPCWSTR
)lpszReading
, dwStyle
, (LPCWSTR
)lpszRegister
, lpData
);
1069 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
1070 LPWSTR lpszwRegister
= strdupAtoW(lpszRegister
);
1073 rc
= immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
1074 lpszwReading
, dwStyle
, lpszwRegister
,
1077 HeapFree(GetProcessHeap(),0,lpszwReading
);
1078 HeapFree(GetProcessHeap(),0,lpszwRegister
);
1086 /***********************************************************************
1087 * ImmEnumRegisterWordW (IMM32.@)
1089 UINT WINAPI
ImmEnumRegisterWordW(
1090 HKL hKL
, REGISTERWORDENUMPROCW lpfnEnumProc
,
1091 LPCWSTR lpszReading
, DWORD dwStyle
,
1092 LPCWSTR lpszRegister
, LPVOID lpData
)
1094 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1095 TRACE("(%p, %p, %s, %ld, %s, %p):\n", hKL
, lpfnEnumProc
,
1096 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
), lpData
);
1097 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
1099 if (is_kbd_ime_unicode(immHkl
))
1100 return immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, lpszReading
, dwStyle
,
1101 lpszRegister
, lpData
);
1104 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
1105 LPSTR lpszaRegister
= strdupWtoA(lpszRegister
);
1108 rc
= immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, (LPCWSTR
)lpszaReading
,
1109 dwStyle
, (LPCWSTR
)lpszaRegister
, lpData
);
1111 HeapFree(GetProcessHeap(),0,lpszaReading
);
1112 HeapFree(GetProcessHeap(),0,lpszaRegister
);
1120 static inline BOOL
EscapeRequiresWA(UINT uEscape
)
1122 if (uEscape
== IME_ESC_GET_EUDC_DICTIONARY
||
1123 uEscape
== IME_ESC_SET_EUDC_DICTIONARY
||
1124 uEscape
== IME_ESC_IME_NAME
||
1125 uEscape
== IME_ESC_GETHELPFILENAME
)
1130 /***********************************************************************
1131 * ImmEscapeA (IMM32.@)
1133 LRESULT WINAPI
ImmEscapeA(
1135 UINT uEscape
, LPVOID lpData
)
1137 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1138 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1140 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1142 if (!EscapeRequiresWA(uEscape
) || !is_kbd_ime_unicode(immHkl
))
1143 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1146 WCHAR buffer
[81]; /* largest required buffer should be 80 */
1148 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1150 MultiByteToWideChar(CP_ACP
,0,lpData
,-1,buffer
,81);
1151 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1155 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1156 WideCharToMultiByte(CP_ACP
,0,buffer
,-1,lpData
,80, NULL
, NULL
);
1165 /***********************************************************************
1166 * ImmEscapeW (IMM32.@)
1168 LRESULT WINAPI
ImmEscapeW(
1170 UINT uEscape
, LPVOID lpData
)
1172 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1173 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1175 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1177 if (!EscapeRequiresWA(uEscape
) || is_kbd_ime_unicode(immHkl
))
1178 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1181 CHAR buffer
[81]; /* largest required buffer should be 80 */
1183 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1185 WideCharToMultiByte(CP_ACP
,0,lpData
,-1,buffer
,81, NULL
, NULL
);
1186 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1190 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1191 MultiByteToWideChar(CP_ACP
,0,buffer
,-1,lpData
,80);
1200 /***********************************************************************
1201 * ImmGetCandidateListA (IMM32.@)
1203 DWORD WINAPI
ImmGetCandidateListA(
1204 HIMC hIMC
, DWORD dwIndex
,
1205 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1207 InputContextData
*data
= get_imc_data(hIMC
);
1208 LPCANDIDATEINFO candinfo
;
1209 LPCANDIDATELIST candlist
;
1212 TRACE("%p, %ld, %p, %ld\n", hIMC
, dwIndex
, lpCandList
, dwBufLen
);
1214 if (!data
|| !data
->IMC
.hCandInfo
)
1217 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1218 if (dwIndex
>= candinfo
->dwCount
|| dwIndex
>= ARRAY_SIZE(candinfo
->dwOffset
))
1221 candlist
= (LPCANDIDATELIST
)((LPBYTE
)candinfo
+ candinfo
->dwOffset
[dwIndex
]);
1222 if ( !candlist
->dwSize
|| !candlist
->dwCount
)
1225 if ( !is_himc_ime_unicode(data
) )
1227 ret
= candlist
->dwSize
;
1228 if ( lpCandList
&& dwBufLen
>= ret
)
1229 memcpy(lpCandList
, candlist
, ret
);
1232 ret
= convert_candidatelist_WtoA( candlist
, lpCandList
, dwBufLen
);
1235 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1239 /***********************************************************************
1240 * ImmGetCandidateListCountA (IMM32.@)
1242 DWORD WINAPI
ImmGetCandidateListCountA(
1243 HIMC hIMC
, LPDWORD lpdwListCount
)
1245 InputContextData
*data
= get_imc_data(hIMC
);
1246 LPCANDIDATEINFO candinfo
;
1249 TRACE("%p, %p\n", hIMC
, lpdwListCount
);
1251 if (!data
|| !lpdwListCount
|| !data
->IMC
.hCandInfo
)
1254 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1256 *lpdwListCount
= count
= candinfo
->dwCount
;
1258 if ( !is_himc_ime_unicode(data
) )
1259 ret
= candinfo
->dwSize
;
1262 ret
= sizeof(CANDIDATEINFO
);
1264 ret
+= ImmGetCandidateListA(hIMC
, count
, NULL
, 0);
1267 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1271 /***********************************************************************
1272 * ImmGetCandidateListCountW (IMM32.@)
1274 DWORD WINAPI
ImmGetCandidateListCountW(
1275 HIMC hIMC
, LPDWORD lpdwListCount
)
1277 InputContextData
*data
= get_imc_data(hIMC
);
1278 LPCANDIDATEINFO candinfo
;
1281 TRACE("%p, %p\n", hIMC
, lpdwListCount
);
1283 if (!data
|| !lpdwListCount
|| !data
->IMC
.hCandInfo
)
1286 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1288 *lpdwListCount
= count
= candinfo
->dwCount
;
1290 if ( is_himc_ime_unicode(data
) )
1291 ret
= candinfo
->dwSize
;
1294 ret
= sizeof(CANDIDATEINFO
);
1296 ret
+= ImmGetCandidateListW(hIMC
, count
, NULL
, 0);
1299 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1303 /***********************************************************************
1304 * ImmGetCandidateListW (IMM32.@)
1306 DWORD WINAPI
ImmGetCandidateListW(
1307 HIMC hIMC
, DWORD dwIndex
,
1308 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1310 InputContextData
*data
= get_imc_data(hIMC
);
1311 LPCANDIDATEINFO candinfo
;
1312 LPCANDIDATELIST candlist
;
1315 TRACE("%p, %ld, %p, %ld\n", hIMC
, dwIndex
, lpCandList
, dwBufLen
);
1317 if (!data
|| !data
->IMC
.hCandInfo
)
1320 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1321 if (dwIndex
>= candinfo
->dwCount
|| dwIndex
>= ARRAY_SIZE(candinfo
->dwOffset
))
1324 candlist
= (LPCANDIDATELIST
)((LPBYTE
)candinfo
+ candinfo
->dwOffset
[dwIndex
]);
1325 if ( !candlist
->dwSize
|| !candlist
->dwCount
)
1328 if ( is_himc_ime_unicode(data
) )
1330 ret
= candlist
->dwSize
;
1331 if ( lpCandList
&& dwBufLen
>= ret
)
1332 memcpy(lpCandList
, candlist
, ret
);
1335 ret
= convert_candidatelist_AtoW( candlist
, lpCandList
, dwBufLen
);
1338 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1342 /***********************************************************************
1343 * ImmGetCandidateWindow (IMM32.@)
1345 BOOL WINAPI
ImmGetCandidateWindow(
1346 HIMC hIMC
, DWORD dwIndex
, LPCANDIDATEFORM lpCandidate
)
1348 InputContextData
*data
= get_imc_data(hIMC
);
1350 TRACE("%p, %ld, %p\n", hIMC
, dwIndex
, lpCandidate
);
1352 if (!data
|| !lpCandidate
)
1355 if (dwIndex
>= ARRAY_SIZE(data
->IMC
.cfCandForm
))
1358 if (data
->IMC
.cfCandForm
[dwIndex
].dwIndex
!= dwIndex
)
1361 *lpCandidate
= data
->IMC
.cfCandForm
[dwIndex
];
1366 /***********************************************************************
1367 * ImmGetCompositionFontA (IMM32.@)
1369 BOOL WINAPI
ImmGetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
1374 TRACE("(%p, %p):\n", hIMC
, lplf
);
1376 rc
= ImmGetCompositionFontW(hIMC
,&lfW
);
1380 memcpy(lplf
,&lfW
,sizeof(LOGFONTA
));
1381 WideCharToMultiByte(CP_ACP
, 0, lfW
.lfFaceName
, -1, lplf
->lfFaceName
,
1382 LF_FACESIZE
, NULL
, NULL
);
1386 /***********************************************************************
1387 * ImmGetCompositionFontW (IMM32.@)
1389 BOOL WINAPI
ImmGetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
1391 InputContextData
*data
= get_imc_data(hIMC
);
1393 TRACE("(%p, %p):\n", hIMC
, lplf
);
1398 *lplf
= data
->IMC
.lfFont
.W
;
1404 /* Helpers for the GetCompositionString functions */
1406 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
1407 length is always in bytes. */
1408 static INT
CopyCompStringIMEtoClient(const InputContextData
*data
, const void *src
, INT src_len
, void *dst
,
1409 INT dst_len
, BOOL unicode
)
1411 int char_size
= unicode
? sizeof(WCHAR
) : sizeof(char);
1414 if (is_himc_ime_unicode(data
) ^ unicode
)
1417 ret
= MultiByteToWideChar(CP_ACP
, 0, src
, src_len
, dst
, dst_len
/ sizeof(WCHAR
));
1419 ret
= WideCharToMultiByte(CP_ACP
, 0, src
, src_len
, dst
, dst_len
, NULL
, NULL
);
1426 ret
= min(src_len
* char_size
, dst_len
);
1427 memcpy(dst
, src
, ret
);
1430 ret
= src_len
* char_size
;
1436 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
1437 passed mode. String length is in characters, attributes are in byte arrays. */
1438 static INT
CopyCompAttrIMEtoClient(const InputContextData
*data
, const BYTE
*src
, INT src_len
, const void *comp_string
,
1439 INT str_len
, BYTE
*dst
, INT dst_len
, BOOL unicode
)
1449 string
.str
= comp_string
;
1451 if (is_himc_ime_unicode(data
) && !unicode
)
1453 rc
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
, str_len
, NULL
, 0, NULL
, NULL
);
1456 int i
, j
= 0, k
= 0;
1460 for (i
= 0; i
< str_len
; ++i
)
1464 len
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
+ i
, 1, NULL
, 0, NULL
, NULL
);
1465 for (; len
> 0; --len
)
1478 else if (!is_himc_ime_unicode(data
) && unicode
)
1480 rc
= MultiByteToWideChar(CP_ACP
, 0, string
.strA
, str_len
, NULL
, 0);
1487 for (i
= 0; i
< str_len
; ++i
)
1489 if (IsDBCSLeadByte(string
.strA
[i
]))
1502 memcpy(dst
, src
, min(src_len
, dst_len
));
1509 static INT
CopyCompClauseIMEtoClient(InputContextData
*data
, LPBYTE source
, INT slen
, LPBYTE ssource
,
1510 LPBYTE target
, INT tlen
, BOOL unicode
)
1514 if (is_himc_ime_unicode(data
) && !unicode
)
1522 tlen
/= sizeof (DWORD
);
1523 for (i
= 0; i
< tlen
; ++i
)
1525 ((DWORD
*)target
)[i
] = WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
,
1526 ((DWORD
*)source
)[i
],
1530 rc
= sizeof (DWORD
) * i
;
1535 else if (!is_himc_ime_unicode(data
) && unicode
)
1543 tlen
/= sizeof (DWORD
);
1544 for (i
= 0; i
< tlen
; ++i
)
1546 ((DWORD
*)target
)[i
] = MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
,
1547 ((DWORD
*)source
)[i
],
1550 rc
= sizeof (DWORD
) * i
;
1557 memcpy( target
, source
, min(slen
,tlen
));
1564 static INT
CopyCompOffsetIMEtoClient(InputContextData
*data
, DWORD offset
, LPBYTE ssource
, BOOL unicode
)
1568 if (is_himc_ime_unicode(data
) && !unicode
)
1570 rc
= WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
, offset
, NULL
, 0, NULL
, NULL
);
1572 else if (!is_himc_ime_unicode(data
) && unicode
)
1574 rc
= MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
, offset
, NULL
, 0);
1582 static LONG
ImmGetCompositionStringT( HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
,
1583 DWORD dwBufLen
, BOOL unicode
)
1586 InputContextData
*data
= get_imc_data(hIMC
);
1587 LPCOMPOSITIONSTRING compstr
;
1590 TRACE("(%p, 0x%lx, %p, %ld)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
1595 if (!data
->IMC
.hCompStr
)
1598 compdata
= ImmLockIMCC(data
->IMC
.hCompStr
);
1599 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1604 TRACE("GCS_RESULTSTR\n");
1605 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultStrOffset
, compstr
->dwResultStrLen
, lpBuf
, dwBufLen
, unicode
);
1608 TRACE("GCS_COMPSTR\n");
1609 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
, lpBuf
, dwBufLen
, unicode
);
1612 TRACE("GCS_COMPATTR\n");
1613 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompAttrOffset
, compstr
->dwCompAttrLen
,
1614 compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
,
1615 lpBuf
, dwBufLen
, unicode
);
1617 case GCS_COMPCLAUSE
:
1618 TRACE("GCS_COMPCLAUSE\n");
1619 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompClauseOffset
,compstr
->dwCompClauseLen
,
1620 compdata
+ compstr
->dwCompStrOffset
,
1621 lpBuf
, dwBufLen
, unicode
);
1623 case GCS_RESULTCLAUSE
:
1624 TRACE("GCS_RESULTCLAUSE\n");
1625 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultClauseOffset
,compstr
->dwResultClauseLen
,
1626 compdata
+ compstr
->dwResultStrOffset
,
1627 lpBuf
, dwBufLen
, unicode
);
1629 case GCS_RESULTREADSTR
:
1630 TRACE("GCS_RESULTREADSTR\n");
1631 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultReadStrOffset
, compstr
->dwResultReadStrLen
, lpBuf
, dwBufLen
, unicode
);
1633 case GCS_RESULTREADCLAUSE
:
1634 TRACE("GCS_RESULTREADCLAUSE\n");
1635 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultReadClauseOffset
,compstr
->dwResultReadClauseLen
,
1636 compdata
+ compstr
->dwResultStrOffset
,
1637 lpBuf
, dwBufLen
, unicode
);
1639 case GCS_COMPREADSTR
:
1640 TRACE("GCS_COMPREADSTR\n");
1641 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
, lpBuf
, dwBufLen
, unicode
);
1643 case GCS_COMPREADATTR
:
1644 TRACE("GCS_COMPREADATTR\n");
1645 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompReadAttrOffset
, compstr
->dwCompReadAttrLen
,
1646 compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
,
1647 lpBuf
, dwBufLen
, unicode
);
1649 case GCS_COMPREADCLAUSE
:
1650 TRACE("GCS_COMPREADCLAUSE\n");
1651 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompReadClauseOffset
,compstr
->dwCompReadClauseLen
,
1652 compdata
+ compstr
->dwCompStrOffset
,
1653 lpBuf
, dwBufLen
, unicode
);
1656 TRACE("GCS_CURSORPOS\n");
1657 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwCursorPos
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
1659 case GCS_DELTASTART
:
1660 TRACE("GCS_DELTASTART\n");
1661 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwDeltaStart
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
1664 FIXME("Unhandled index 0x%lx\n",dwIndex
);
1668 ImmUnlockIMCC(data
->IMC
.hCompStr
);
1673 /***********************************************************************
1674 * ImmGetCompositionStringA (IMM32.@)
1676 LONG WINAPI
ImmGetCompositionStringA(
1677 HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
)
1679 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
1683 /***********************************************************************
1684 * ImmGetCompositionStringW (IMM32.@)
1686 LONG WINAPI
ImmGetCompositionStringW(
1687 HIMC hIMC
, DWORD dwIndex
,
1688 LPVOID lpBuf
, DWORD dwBufLen
)
1690 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
1693 /***********************************************************************
1694 * ImmGetCompositionWindow (IMM32.@)
1696 BOOL WINAPI
ImmGetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
1698 InputContextData
*data
= get_imc_data(hIMC
);
1700 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
1705 *lpCompForm
= data
->IMC
.cfCompForm
;
1709 /***********************************************************************
1710 * ImmGetContext (IMM32.@)
1713 HIMC WINAPI
ImmGetContext(HWND hWnd
)
1717 TRACE("%p\n", hWnd
);
1719 if (!IsWindow(hWnd
))
1721 SetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1725 rc
= GetPropW(hWnd
,szwWineIMCProperty
);
1728 else if (rc
== NULL
)
1729 rc
= get_default_context( hWnd
);
1733 InputContextData
*data
= rc
;
1734 data
->IMC
.hWnd
= hWnd
;
1737 TRACE("returning %p\n", rc
);
1742 /***********************************************************************
1743 * ImmGetConversionListA (IMM32.@)
1745 DWORD WINAPI
ImmGetConversionListA(
1747 LPCSTR pSrc
, LPCANDIDATELIST lpDst
,
1748 DWORD dwBufLen
, UINT uFlag
)
1750 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1751 TRACE("(%p, %p, %s, %p, %ld, %d):\n", hKL
, hIMC
, debugstr_a(pSrc
), lpDst
,
1753 if (immHkl
->hIME
&& immHkl
->pImeConversionList
)
1755 if (!is_kbd_ime_unicode(immHkl
))
1756 return immHkl
->pImeConversionList(hIMC
,(LPCWSTR
)pSrc
,lpDst
,dwBufLen
,uFlag
);
1759 LPCANDIDATELIST lpwDst
;
1761 LPWSTR pwSrc
= strdupAtoW(pSrc
);
1763 len
= immHkl
->pImeConversionList(hIMC
, pwSrc
, NULL
, 0, uFlag
);
1764 lpwDst
= HeapAlloc(GetProcessHeap(), 0, len
);
1767 immHkl
->pImeConversionList(hIMC
, pwSrc
, lpwDst
, len
, uFlag
);
1768 ret
= convert_candidatelist_WtoA( lpwDst
, lpDst
, dwBufLen
);
1769 HeapFree(GetProcessHeap(), 0, lpwDst
);
1771 HeapFree(GetProcessHeap(), 0, pwSrc
);
1780 /***********************************************************************
1781 * ImmGetConversionListW (IMM32.@)
1783 DWORD WINAPI
ImmGetConversionListW(
1785 LPCWSTR pSrc
, LPCANDIDATELIST lpDst
,
1786 DWORD dwBufLen
, UINT uFlag
)
1788 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1789 TRACE("(%p, %p, %s, %p, %ld, %d):\n", hKL
, hIMC
, debugstr_w(pSrc
), lpDst
,
1791 if (immHkl
->hIME
&& immHkl
->pImeConversionList
)
1793 if (is_kbd_ime_unicode(immHkl
))
1794 return immHkl
->pImeConversionList(hIMC
,pSrc
,lpDst
,dwBufLen
,uFlag
);
1797 LPCANDIDATELIST lpaDst
;
1799 LPSTR paSrc
= strdupWtoA(pSrc
);
1801 len
= immHkl
->pImeConversionList(hIMC
, (LPCWSTR
)paSrc
, NULL
, 0, uFlag
);
1802 lpaDst
= HeapAlloc(GetProcessHeap(), 0, len
);
1805 immHkl
->pImeConversionList(hIMC
, (LPCWSTR
)paSrc
, lpaDst
, len
, uFlag
);
1806 ret
= convert_candidatelist_AtoW( lpaDst
, lpDst
, dwBufLen
);
1807 HeapFree(GetProcessHeap(), 0, lpaDst
);
1809 HeapFree(GetProcessHeap(), 0, paSrc
);
1818 /***********************************************************************
1819 * ImmGetConversionStatus (IMM32.@)
1821 BOOL WINAPI
ImmGetConversionStatus(
1822 HIMC hIMC
, LPDWORD lpfdwConversion
, LPDWORD lpfdwSentence
)
1824 InputContextData
*data
= get_imc_data(hIMC
);
1826 TRACE("%p %p %p\n", hIMC
, lpfdwConversion
, lpfdwSentence
);
1831 if (lpfdwConversion
)
1832 *lpfdwConversion
= data
->IMC
.fdwConversion
;
1834 *lpfdwSentence
= data
->IMC
.fdwSentence
;
1839 static BOOL
needs_ime_window(HWND hwnd
)
1843 if (GetClassNameW(hwnd
, classW
, ARRAY_SIZE(classW
)) && !lstrcmpW(classW
, L
"IME"))
1845 if (GetClassLongPtrW(hwnd
, GCL_STYLE
) & CS_IME
) return FALSE
;
1850 /***********************************************************************
1851 * __wine_register_window (IMM32.@)
1853 BOOL WINAPI
__wine_register_window(HWND hwnd
)
1856 IMMThreadData
*thread_data
;
1857 TRACE("(%p)\n", hwnd
);
1859 if (!needs_ime_window(hwnd
))
1862 thread_data
= IMM_GetThreadData(hwnd
, 0);
1866 if (thread_data
->disableIME
|| disable_ime
)
1868 TRACE("IME for this thread is disabled\n");
1869 LeaveCriticalSection(&threaddata_cs
);
1872 thread_data
->windowRefs
++;
1873 TRACE("windowRefs=%lu, hwndDefault=%p\n",
1874 thread_data
->windowRefs
, thread_data
->hwndDefault
);
1876 /* Create default IME window */
1877 if (thread_data
->windowRefs
== 1)
1879 /* Do not create the window inside of a critical section */
1880 LeaveCriticalSection(&threaddata_cs
);
1881 new = CreateWindowExW( 0, L
"IME", L
"Default IME",
1882 WS_POPUP
| WS_DISABLED
| WS_CLIPSIBLINGS
,
1883 0, 0, 1, 1, 0, 0, 0, 0);
1884 /* thread_data is in the current thread so we can assume it's still valid */
1885 EnterCriticalSection(&threaddata_cs
);
1886 /* See if anyone beat us */
1887 if (thread_data
->hwndDefault
== NULL
)
1889 thread_data
->hwndDefault
= new;
1891 TRACE("Default is %p\n", thread_data
->hwndDefault
);
1895 LeaveCriticalSection(&threaddata_cs
);
1897 /* Clean up an unused new window outside of the critical section */
1903 /***********************************************************************
1904 * __wine_unregister_window (IMM32.@)
1906 void WINAPI
__wine_unregister_window(HWND hwnd
)
1908 HWND to_destroy
= 0;
1909 IMMThreadData
*thread_data
;
1910 TRACE("(%p)\n", hwnd
);
1912 thread_data
= IMM_GetThreadData(hwnd
, 0);
1913 if (!thread_data
) return;
1915 thread_data
->windowRefs
--;
1916 TRACE("windowRefs=%lu, hwndDefault=%p\n",
1917 thread_data
->windowRefs
, thread_data
->hwndDefault
);
1919 /* Destroy default IME window */
1920 if (thread_data
->windowRefs
== 0)
1921 to_destroy
= imm_detach_default_window(thread_data
);
1922 LeaveCriticalSection(&threaddata_cs
);
1924 if (to_destroy
) DestroyWindow( to_destroy
);
1927 /***********************************************************************
1928 * ImmGetDefaultIMEWnd (IMM32.@)
1930 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
1933 IMMThreadData
* thread_data
= IMM_GetThreadData(hWnd
, 0);
1936 ret
= thread_data
->hwndDefault
;
1937 LeaveCriticalSection(&threaddata_cs
);
1938 TRACE("Default is %p\n",ret
);
1942 /***********************************************************************
1943 * ImmGetDescriptionA (IMM32.@)
1945 UINT WINAPI
ImmGetDescriptionA(
1946 HKL hKL
, LPSTR lpszDescription
, UINT uBufLen
)
1951 TRACE("%p %p %d\n", hKL
, lpszDescription
, uBufLen
);
1953 /* find out how many characters in the unicode buffer */
1954 len
= ImmGetDescriptionW( hKL
, NULL
, 0 );
1958 /* allocate a buffer of that size */
1959 buf
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof (WCHAR
) );
1963 /* fetch the unicode buffer */
1964 len
= ImmGetDescriptionW( hKL
, buf
, len
+ 1 );
1966 /* convert it back to ANSI */
1967 len
= WideCharToMultiByte( CP_ACP
, 0, buf
, len
+ 1,
1968 lpszDescription
, uBufLen
, NULL
, NULL
);
1970 HeapFree( GetProcessHeap(), 0, buf
);
1978 /***********************************************************************
1979 * ImmGetDescriptionW (IMM32.@)
1981 UINT WINAPI
ImmGetDescriptionW(HKL hKL
, LPWSTR lpszDescription
, UINT uBufLen
)
1983 FIXME("(%p, %p, %d): semi stub\n", hKL
, lpszDescription
, uBufLen
);
1986 if (!uBufLen
) return lstrlenW(L
"Wine XIM" );
1987 lstrcpynW( lpszDescription
, L
"Wine XIM", uBufLen
);
1988 return lstrlenW( lpszDescription
);
1991 /***********************************************************************
1992 * ImmGetGuideLineA (IMM32.@)
1994 DWORD WINAPI
ImmGetGuideLineA(
1995 HIMC hIMC
, DWORD dwIndex
, LPSTR lpBuf
, DWORD dwBufLen
)
1997 FIXME("(%p, %ld, %s, %ld): stub\n",
1998 hIMC
, dwIndex
, debugstr_a(lpBuf
), dwBufLen
2000 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2004 /***********************************************************************
2005 * ImmGetGuideLineW (IMM32.@)
2007 DWORD WINAPI
ImmGetGuideLineW(HIMC hIMC
, DWORD dwIndex
, LPWSTR lpBuf
, DWORD dwBufLen
)
2009 FIXME("(%p, %ld, %s, %ld): stub\n",
2010 hIMC
, dwIndex
, debugstr_w(lpBuf
), dwBufLen
2012 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2016 /***********************************************************************
2017 * ImmGetIMEFileNameA (IMM32.@)
2019 UINT WINAPI
ImmGetIMEFileNameA( HKL hKL
, LPSTR lpszFileName
, UINT uBufLen
)
2022 UINT wBufLen
= uBufLen
;
2025 if (uBufLen
&& lpszFileName
)
2026 bufW
= HeapAlloc(GetProcessHeap(),0,uBufLen
* sizeof(WCHAR
));
2027 else /* We need this to get the number of byte required */
2029 bufW
= HeapAlloc(GetProcessHeap(),0,MAX_PATH
* sizeof(WCHAR
));
2033 rc
= ImmGetIMEFileNameW(hKL
,bufW
,wBufLen
);
2037 if (uBufLen
&& lpszFileName
)
2038 rc
= WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, lpszFileName
,
2039 uBufLen
, NULL
, NULL
);
2040 else /* get the length */
2041 rc
= WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, NULL
, 0, NULL
,
2045 HeapFree(GetProcessHeap(),0,bufW
);
2049 /***********************************************************************
2050 * ImmGetIMEFileNameW (IMM32.@)
2052 UINT WINAPI
ImmGetIMEFileNameW(HKL hKL
, LPWSTR lpszFileName
, UINT uBufLen
)
2057 WCHAR regKey
[ARRAY_SIZE(szImeRegFmt
)+8];
2059 wsprintfW( regKey
, szImeRegFmt
, (ULONG_PTR
)hKL
);
2060 rc
= RegOpenKeyW( HKEY_LOCAL_MACHINE
, regKey
, &hkey
);
2061 if (rc
!= ERROR_SUCCESS
)
2068 rc
= RegGetValueW(hkey
, NULL
, L
"Ime File", RRF_RT_REG_SZ
, NULL
, NULL
, &length
);
2070 if (rc
!= ERROR_SUCCESS
)
2076 if (length
> uBufLen
* sizeof(WCHAR
) || !lpszFileName
)
2081 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2085 return length
/ sizeof(WCHAR
);
2088 RegGetValueW(hkey
, NULL
, L
"Ime File", RRF_RT_REG_SZ
, NULL
, lpszFileName
, &length
);
2092 return length
/ sizeof(WCHAR
);
2095 /***********************************************************************
2096 * ImmGetOpenStatus (IMM32.@)
2098 BOOL WINAPI
ImmGetOpenStatus(HIMC hIMC
)
2100 InputContextData
*data
= get_imc_data(hIMC
);
2106 TRACE("(%p): semi-stub\n", hIMC
);
2109 FIXME("(%p): semi-stub\n", hIMC
);
2111 return data
->IMC
.fOpen
;
2114 /***********************************************************************
2115 * ImmGetProperty (IMM32.@)
2117 DWORD WINAPI
ImmGetProperty(HKL hKL
, DWORD fdwIndex
)
2122 TRACE("(%p, %ld)\n", hKL
, fdwIndex
);
2123 kbd
= IMM_GetImmHkl(hKL
);
2125 if (kbd
&& kbd
->hIME
)
2129 case IGP_PROPERTY
: rc
= kbd
->imeInfo
.fdwProperty
; break;
2130 case IGP_CONVERSION
: rc
= kbd
->imeInfo
.fdwConversionCaps
; break;
2131 case IGP_SENTENCE
: rc
= kbd
->imeInfo
.fdwSentenceCaps
; break;
2132 case IGP_SETCOMPSTR
: rc
= kbd
->imeInfo
.fdwSCSCaps
; break;
2133 case IGP_SELECT
: rc
= kbd
->imeInfo
.fdwSelectCaps
; break;
2134 case IGP_GETIMEVERSION
: rc
= IMEVER_0400
; break;
2135 case IGP_UI
: rc
= 0; break;
2142 /***********************************************************************
2143 * ImmGetRegisterWordStyleA (IMM32.@)
2145 UINT WINAPI
ImmGetRegisterWordStyleA(
2146 HKL hKL
, UINT nItem
, LPSTYLEBUFA lpStyleBuf
)
2148 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2149 TRACE("(%p, %d, %p):\n", hKL
, nItem
, lpStyleBuf
);
2150 if (immHkl
->hIME
&& immHkl
->pImeGetRegisterWordStyle
)
2152 if (!is_kbd_ime_unicode(immHkl
))
2153 return immHkl
->pImeGetRegisterWordStyle(nItem
,(LPSTYLEBUFW
)lpStyleBuf
);
2159 rc
= immHkl
->pImeGetRegisterWordStyle(nItem
,&sbw
);
2160 WideCharToMultiByte(CP_ACP
, 0, sbw
.szDescription
, -1,
2161 lpStyleBuf
->szDescription
, 32, NULL
, NULL
);
2162 lpStyleBuf
->dwStyle
= sbw
.dwStyle
;
2170 /***********************************************************************
2171 * ImmGetRegisterWordStyleW (IMM32.@)
2173 UINT WINAPI
ImmGetRegisterWordStyleW(
2174 HKL hKL
, UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
2176 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2177 TRACE("(%p, %d, %p):\n", hKL
, nItem
, lpStyleBuf
);
2178 if (immHkl
->hIME
&& immHkl
->pImeGetRegisterWordStyle
)
2180 if (is_kbd_ime_unicode(immHkl
))
2181 return immHkl
->pImeGetRegisterWordStyle(nItem
,lpStyleBuf
);
2187 rc
= immHkl
->pImeGetRegisterWordStyle(nItem
,(LPSTYLEBUFW
)&sba
);
2188 MultiByteToWideChar(CP_ACP
, 0, sba
.szDescription
, -1,
2189 lpStyleBuf
->szDescription
, 32);
2190 lpStyleBuf
->dwStyle
= sba
.dwStyle
;
2198 /***********************************************************************
2199 * ImmGetStatusWindowPos (IMM32.@)
2201 BOOL WINAPI
ImmGetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
2203 InputContextData
*data
= get_imc_data(hIMC
);
2205 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
2207 if (!data
|| !lpptPos
)
2210 *lpptPos
= data
->IMC
.ptStatusWndPos
;
2215 /***********************************************************************
2216 * ImmGetVirtualKey (IMM32.@)
2218 UINT WINAPI
ImmGetVirtualKey(HWND hWnd
)
2220 OSVERSIONINFOA version
;
2221 InputContextData
*data
= ImmGetContext( hWnd
);
2222 TRACE("%p\n", hWnd
);
2225 return data
->lastVK
;
2227 version
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
2228 GetVersionExA( &version
);
2229 switch(version
.dwPlatformId
)
2231 case VER_PLATFORM_WIN32_WINDOWS
:
2232 return VK_PROCESSKEY
;
2233 case VER_PLATFORM_WIN32_NT
:
2236 FIXME("%ld not supported\n",version
.dwPlatformId
);
2237 return VK_PROCESSKEY
;
2241 /***********************************************************************
2242 * ImmInstallIMEA (IMM32.@)
2244 HKL WINAPI
ImmInstallIMEA(
2245 LPCSTR lpszIMEFileName
, LPCSTR lpszLayoutText
)
2247 LPWSTR lpszwIMEFileName
;
2248 LPWSTR lpszwLayoutText
;
2251 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName
),
2252 debugstr_a(lpszLayoutText
));
2254 lpszwIMEFileName
= strdupAtoW(lpszIMEFileName
);
2255 lpszwLayoutText
= strdupAtoW(lpszLayoutText
);
2257 hkl
= ImmInstallIMEW(lpszwIMEFileName
, lpszwLayoutText
);
2259 HeapFree(GetProcessHeap(),0,lpszwIMEFileName
);
2260 HeapFree(GetProcessHeap(),0,lpszwLayoutText
);
2264 /***********************************************************************
2265 * ImmInstallIMEW (IMM32.@)
2267 HKL WINAPI
ImmInstallIMEW(
2268 LPCWSTR lpszIMEFileName
, LPCWSTR lpszLayoutText
)
2270 INT lcid
= GetUserDefaultLCID();
2275 WCHAR regKey
[ARRAY_SIZE(szImeRegFmt
)+8];
2277 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName
),
2278 debugstr_w(lpszLayoutText
));
2280 /* Start with 2. e001 will be blank and so default to the wine internal IME */
2283 while (count
< 0xfff)
2285 DWORD disposition
= 0;
2287 hkl
= (HKL
)MAKELPARAM( lcid
, 0xe000 | count
);
2288 wsprintfW( regKey
, szImeRegFmt
, (ULONG_PTR
)hkl
);
2290 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, regKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hkey
, &disposition
);
2291 if (rc
== ERROR_SUCCESS
&& disposition
== REG_CREATED_NEW_KEY
)
2293 else if (rc
== ERROR_SUCCESS
)
2301 WARN("Unable to find slot to install IME\n");
2305 if (rc
== ERROR_SUCCESS
)
2307 rc
= RegSetValueExW(hkey
, L
"Ime File", 0, REG_SZ
, (const BYTE
*)lpszIMEFileName
,
2308 (lstrlenW(lpszIMEFileName
) + 1) * sizeof(WCHAR
));
2309 if (rc
== ERROR_SUCCESS
)
2310 rc
= RegSetValueExW(hkey
, L
"Layout Text", 0, REG_SZ
, (const BYTE
*)lpszLayoutText
,
2311 (lstrlenW(lpszLayoutText
) + 1) * sizeof(WCHAR
));
2317 WARN("Unable to set IME registry values\n");
2322 /***********************************************************************
2323 * ImmIsIME (IMM32.@)
2325 BOOL WINAPI
ImmIsIME(HKL hKL
)
2328 TRACE("(%p):\n", hKL
);
2329 ptr
= IMM_GetImmHkl(hKL
);
2330 return (ptr
&& ptr
->hIME
);
2333 /***********************************************************************
2334 * ImmIsUIMessageA (IMM32.@)
2336 BOOL WINAPI
ImmIsUIMessageA(
2337 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2339 TRACE("(%p, %x, %Id, %Id)\n", hWndIME
, msg
, wParam
, lParam
);
2340 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
2341 (msg
== WM_IME_SETCONTEXT
) ||
2342 (msg
== WM_IME_NOTIFY
) ||
2343 (msg
== WM_IME_COMPOSITIONFULL
) ||
2344 (msg
== WM_IME_SELECT
) ||
2345 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
2348 SendMessageA(hWndIME
, msg
, wParam
, lParam
);
2355 /***********************************************************************
2356 * ImmIsUIMessageW (IMM32.@)
2358 BOOL WINAPI
ImmIsUIMessageW(
2359 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2361 TRACE("(%p, %x, %Id, %Id)\n", hWndIME
, msg
, wParam
, lParam
);
2362 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
2363 (msg
== WM_IME_SETCONTEXT
) ||
2364 (msg
== WM_IME_NOTIFY
) ||
2365 (msg
== WM_IME_COMPOSITIONFULL
) ||
2366 (msg
== WM_IME_SELECT
) ||
2367 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
2370 SendMessageW(hWndIME
, msg
, wParam
, lParam
);
2377 /***********************************************************************
2378 * ImmNotifyIME (IMM32.@)
2380 BOOL WINAPI
ImmNotifyIME(
2381 HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
2383 InputContextData
*data
= get_imc_data(hIMC
);
2385 TRACE("(%p, %ld, %ld, %ld)\n",
2386 hIMC
, dwAction
, dwIndex
, dwValue
);
2390 SetLastError(ERROR_SUCCESS
);
2394 if (!data
|| ! data
->immKbd
->pNotifyIME
)
2399 return data
->immKbd
->pNotifyIME(hIMC
,dwAction
,dwIndex
,dwValue
);
2402 /***********************************************************************
2403 * ImmRegisterWordA (IMM32.@)
2405 BOOL WINAPI
ImmRegisterWordA(
2406 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszRegister
)
2408 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2409 TRACE("(%p, %s, %ld, %s):\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
2410 debugstr_a(lpszRegister
));
2411 if (immHkl
->hIME
&& immHkl
->pImeRegisterWord
)
2413 if (!is_kbd_ime_unicode(immHkl
))
2414 return immHkl
->pImeRegisterWord((LPCWSTR
)lpszReading
,dwStyle
,
2415 (LPCWSTR
)lpszRegister
);
2418 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
2419 LPWSTR lpszwRegister
= strdupAtoW(lpszRegister
);
2422 rc
= immHkl
->pImeRegisterWord(lpszwReading
,dwStyle
,lpszwRegister
);
2423 HeapFree(GetProcessHeap(),0,lpszwReading
);
2424 HeapFree(GetProcessHeap(),0,lpszwRegister
);
2432 /***********************************************************************
2433 * ImmRegisterWordW (IMM32.@)
2435 BOOL WINAPI
ImmRegisterWordW(
2436 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszRegister
)
2438 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2439 TRACE("(%p, %s, %ld, %s):\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
2440 debugstr_w(lpszRegister
));
2441 if (immHkl
->hIME
&& immHkl
->pImeRegisterWord
)
2443 if (is_kbd_ime_unicode(immHkl
))
2444 return immHkl
->pImeRegisterWord(lpszReading
,dwStyle
,lpszRegister
);
2447 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
2448 LPSTR lpszaRegister
= strdupWtoA(lpszRegister
);
2451 rc
= immHkl
->pImeRegisterWord((LPCWSTR
)lpszaReading
,dwStyle
,
2452 (LPCWSTR
)lpszaRegister
);
2453 HeapFree(GetProcessHeap(),0,lpszaReading
);
2454 HeapFree(GetProcessHeap(),0,lpszaRegister
);
2462 /***********************************************************************
2463 * ImmReleaseContext (IMM32.@)
2465 BOOL WINAPI
ImmReleaseContext(HWND hWnd
, HIMC hIMC
)
2467 static BOOL shown
= FALSE
;
2470 FIXME("(%p, %p): stub\n", hWnd
, hIMC
);
2476 /***********************************************************************
2477 * ImmRequestMessageA(IMM32.@)
2479 LRESULT WINAPI
ImmRequestMessageA(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
2481 InputContextData
*data
= get_imc_data(hIMC
);
2483 TRACE("%p %Id %Id\n", hIMC
, wParam
, wParam
);
2485 if (data
) return SendMessageA(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
2487 SetLastError(ERROR_INVALID_HANDLE
);
2491 /***********************************************************************
2492 * ImmRequestMessageW(IMM32.@)
2494 LRESULT WINAPI
ImmRequestMessageW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
2496 InputContextData
*data
= get_imc_data(hIMC
);
2498 TRACE("%p %Id %Id\n", hIMC
, wParam
, wParam
);
2500 if (data
) return SendMessageW(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
2502 SetLastError(ERROR_INVALID_HANDLE
);
2506 /***********************************************************************
2507 * ImmSetCandidateWindow (IMM32.@)
2509 BOOL WINAPI
ImmSetCandidateWindow(
2510 HIMC hIMC
, LPCANDIDATEFORM lpCandidate
)
2512 InputContextData
*data
= get_imc_data(hIMC
);
2514 TRACE("(%p, %p)\n", hIMC
, lpCandidate
);
2516 if (!data
|| !lpCandidate
)
2519 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2522 TRACE("\t%lx, %lx, %s, %s\n",
2523 lpCandidate
->dwIndex
, lpCandidate
->dwStyle
,
2524 wine_dbgstr_point(&lpCandidate
->ptCurrentPos
),
2525 wine_dbgstr_rect(&lpCandidate
->rcArea
));
2527 if (lpCandidate
->dwIndex
>= ARRAY_SIZE(data
->IMC
.cfCandForm
))
2530 data
->IMC
.cfCandForm
[lpCandidate
->dwIndex
] = *lpCandidate
;
2531 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCANDIDATEPOS
);
2532 ImmInternalSendIMENotify(data
, IMN_SETCANDIDATEPOS
, 1 << lpCandidate
->dwIndex
);
2537 /***********************************************************************
2538 * ImmSetCompositionFontA (IMM32.@)
2540 BOOL WINAPI
ImmSetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
2542 InputContextData
*data
= get_imc_data(hIMC
);
2543 TRACE("(%p, %p)\n", hIMC
, lplf
);
2547 SetLastError(ERROR_INVALID_HANDLE
);
2551 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2554 memcpy(&data
->IMC
.lfFont
.W
,lplf
,sizeof(LOGFONTA
));
2555 MultiByteToWideChar(CP_ACP
, 0, lplf
->lfFaceName
, -1, data
->IMC
.lfFont
.W
.lfFaceName
,
2557 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
);
2558 ImmInternalSendIMENotify(data
, IMN_SETCOMPOSITIONFONT
, 0);
2563 /***********************************************************************
2564 * ImmSetCompositionFontW (IMM32.@)
2566 BOOL WINAPI
ImmSetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
2568 InputContextData
*data
= get_imc_data(hIMC
);
2569 TRACE("(%p, %p)\n", hIMC
, lplf
);
2573 SetLastError(ERROR_INVALID_HANDLE
);
2577 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2580 data
->IMC
.lfFont
.W
= *lplf
;
2581 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
);
2582 ImmInternalSendIMENotify(data
, IMN_SETCOMPOSITIONFONT
, 0);
2587 /***********************************************************************
2588 * ImmSetCompositionStringA (IMM32.@)
2590 BOOL WINAPI
ImmSetCompositionStringA(
2591 HIMC hIMC
, DWORD dwIndex
,
2592 LPCVOID lpComp
, DWORD dwCompLen
,
2593 LPCVOID lpRead
, DWORD dwReadLen
)
2597 WCHAR
*CompBuffer
= NULL
;
2598 WCHAR
*ReadBuffer
= NULL
;
2600 InputContextData
*data
= get_imc_data(hIMC
);
2602 TRACE("(%p, %ld, %p, %ld, %p, %ld):\n",
2603 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2608 if (!(dwIndex
== SCS_SETSTR
||
2609 dwIndex
== SCS_CHANGEATTR
||
2610 dwIndex
== SCS_CHANGECLAUSE
||
2611 dwIndex
== SCS_SETRECONVERTSTRING
||
2612 dwIndex
== SCS_QUERYRECONVERTSTRING
))
2615 if (!is_himc_ime_unicode(data
))
2616 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
2617 dwCompLen
, lpRead
, dwReadLen
);
2619 comp_len
= MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0);
2622 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
* sizeof(WCHAR
));
2623 MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
);
2626 read_len
= MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0);
2629 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
* sizeof(WCHAR
));
2630 MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
);
2633 rc
= ImmSetCompositionStringW(hIMC
, dwIndex
, CompBuffer
, comp_len
,
2634 ReadBuffer
, read_len
);
2636 HeapFree(GetProcessHeap(), 0, CompBuffer
);
2637 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
2642 /***********************************************************************
2643 * ImmSetCompositionStringW (IMM32.@)
2645 BOOL WINAPI
ImmSetCompositionStringW(
2646 HIMC hIMC
, DWORD dwIndex
,
2647 LPCVOID lpComp
, DWORD dwCompLen
,
2648 LPCVOID lpRead
, DWORD dwReadLen
)
2652 CHAR
*CompBuffer
= NULL
;
2653 CHAR
*ReadBuffer
= NULL
;
2655 InputContextData
*data
= get_imc_data(hIMC
);
2657 TRACE("(%p, %ld, %p, %ld, %p, %ld):\n",
2658 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2663 if (!(dwIndex
== SCS_SETSTR
||
2664 dwIndex
== SCS_CHANGEATTR
||
2665 dwIndex
== SCS_CHANGECLAUSE
||
2666 dwIndex
== SCS_SETRECONVERTSTRING
||
2667 dwIndex
== SCS_QUERYRECONVERTSTRING
))
2670 if (is_himc_ime_unicode(data
))
2671 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
2672 dwCompLen
, lpRead
, dwReadLen
);
2674 comp_len
= WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0, NULL
,
2678 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
);
2679 WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
,
2683 read_len
= WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0, NULL
,
2687 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
);
2688 WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
,
2692 rc
= ImmSetCompositionStringA(hIMC
, dwIndex
, CompBuffer
, comp_len
,
2693 ReadBuffer
, read_len
);
2695 HeapFree(GetProcessHeap(), 0, CompBuffer
);
2696 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
2701 /***********************************************************************
2702 * ImmSetCompositionWindow (IMM32.@)
2704 BOOL WINAPI
ImmSetCompositionWindow(
2705 HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
2707 BOOL reshow
= FALSE
;
2708 InputContextData
*data
= get_imc_data(hIMC
);
2710 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
2712 TRACE("\t%lx, %s, %s\n", lpCompForm
->dwStyle
,
2713 wine_dbgstr_point(&lpCompForm
->ptCurrentPos
),
2714 wine_dbgstr_rect(&lpCompForm
->rcArea
));
2718 SetLastError(ERROR_INVALID_HANDLE
);
2722 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2725 data
->IMC
.cfCompForm
= *lpCompForm
;
2727 if (IsWindowVisible(data
->immKbd
->UIWnd
))
2730 ShowWindow(data
->immKbd
->UIWnd
,SW_HIDE
);
2733 /* FIXME: this is a partial stub */
2736 ShowWindow(data
->immKbd
->UIWnd
,SW_SHOWNOACTIVATE
);
2738 ImmInternalSendIMENotify(data
, IMN_SETCOMPOSITIONWINDOW
, 0);
2742 /***********************************************************************
2743 * ImmSetConversionStatus (IMM32.@)
2745 BOOL WINAPI
ImmSetConversionStatus(
2746 HIMC hIMC
, DWORD fdwConversion
, DWORD fdwSentence
)
2748 DWORD oldConversion
, oldSentence
;
2749 InputContextData
*data
= get_imc_data(hIMC
);
2751 TRACE("%p %ld %ld\n", hIMC
, fdwConversion
, fdwSentence
);
2755 SetLastError(ERROR_INVALID_HANDLE
);
2759 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2762 if ( fdwConversion
!= data
->IMC
.fdwConversion
)
2764 oldConversion
= data
->IMC
.fdwConversion
;
2765 data
->IMC
.fdwConversion
= fdwConversion
;
2766 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, oldConversion
, IMC_SETCONVERSIONMODE
);
2767 ImmInternalSendIMENotify(data
, IMN_SETCONVERSIONMODE
, 0);
2769 if ( fdwSentence
!= data
->IMC
.fdwSentence
)
2771 oldSentence
= data
->IMC
.fdwSentence
;
2772 data
->IMC
.fdwSentence
= fdwSentence
;
2773 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, oldSentence
, IMC_SETSENTENCEMODE
);
2774 ImmInternalSendIMENotify(data
, IMN_SETSENTENCEMODE
, 0);
2780 /***********************************************************************
2781 * ImmSetOpenStatus (IMM32.@)
2783 BOOL WINAPI
ImmSetOpenStatus(HIMC hIMC
, BOOL fOpen
)
2785 InputContextData
*data
= get_imc_data(hIMC
);
2787 TRACE("%p %d\n", hIMC
, fOpen
);
2791 SetLastError(ERROR_INVALID_HANDLE
);
2795 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2798 if (data
->immKbd
->UIWnd
== NULL
)
2800 /* create the ime window */
2801 data
->immKbd
->UIWnd
= CreateWindowExW( WS_EX_TOOLWINDOW
,
2802 data
->immKbd
->imeClassName
, NULL
, WS_POPUP
, 0, 0, 1, 1, 0,
2803 0, data
->immKbd
->hIME
, 0);
2804 SetWindowLongPtrW(data
->immKbd
->UIWnd
, IMMGWL_IMC
, (LONG_PTR
)data
);
2807 SetWindowLongPtrW(data
->immKbd
->UIWnd
, IMMGWL_IMC
, (LONG_PTR
)data
);
2809 if (!fOpen
!= !data
->IMC
.fOpen
)
2811 data
->IMC
.fOpen
= fOpen
;
2812 ImmNotifyIME( hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETOPENSTATUS
);
2813 ImmInternalSendIMENotify(data
, IMN_SETOPENSTATUS
, 0);
2819 /***********************************************************************
2820 * ImmSetStatusWindowPos (IMM32.@)
2822 BOOL WINAPI
ImmSetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
2824 InputContextData
*data
= get_imc_data(hIMC
);
2826 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
2828 if (!data
|| !lpptPos
)
2830 SetLastError(ERROR_INVALID_HANDLE
);
2834 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2837 TRACE("\t%s\n", wine_dbgstr_point(lpptPos
));
2839 data
->IMC
.ptStatusWndPos
= *lpptPos
;
2840 ImmNotifyIME( hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETSTATUSWINDOWPOS
);
2841 ImmInternalSendIMENotify(data
, IMN_SETSTATUSWINDOWPOS
, 0);
2846 /***********************************************************************
2847 * ImmCreateSoftKeyboard(IMM32.@)
2849 HWND WINAPI
ImmCreateSoftKeyboard(UINT uType
, UINT hOwner
, int x
, int y
)
2851 FIXME("(%d, %d, %d, %d): stub\n", uType
, hOwner
, x
, y
);
2852 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2856 /***********************************************************************
2857 * ImmDestroySoftKeyboard(IMM32.@)
2859 BOOL WINAPI
ImmDestroySoftKeyboard(HWND hSoftWnd
)
2861 FIXME("(%p): stub\n", hSoftWnd
);
2862 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2866 /***********************************************************************
2867 * ImmShowSoftKeyboard(IMM32.@)
2869 BOOL WINAPI
ImmShowSoftKeyboard(HWND hSoftWnd
, int nCmdShow
)
2871 FIXME("(%p, %d): stub\n", hSoftWnd
, nCmdShow
);
2872 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2876 /***********************************************************************
2877 * ImmSimulateHotKey (IMM32.@)
2879 BOOL WINAPI
ImmSimulateHotKey(HWND hWnd
, DWORD dwHotKeyID
)
2881 FIXME("(%p, %ld): stub\n", hWnd
, dwHotKeyID
);
2882 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2886 /***********************************************************************
2887 * ImmUnregisterWordA (IMM32.@)
2889 BOOL WINAPI
ImmUnregisterWordA(
2890 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszUnregister
)
2892 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2893 TRACE("(%p, %s, %ld, %s):\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
2894 debugstr_a(lpszUnregister
));
2895 if (immHkl
->hIME
&& immHkl
->pImeUnregisterWord
)
2897 if (!is_kbd_ime_unicode(immHkl
))
2898 return immHkl
->pImeUnregisterWord((LPCWSTR
)lpszReading
,dwStyle
,
2899 (LPCWSTR
)lpszUnregister
);
2902 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
2903 LPWSTR lpszwUnregister
= strdupAtoW(lpszUnregister
);
2906 rc
= immHkl
->pImeUnregisterWord(lpszwReading
,dwStyle
,lpszwUnregister
);
2907 HeapFree(GetProcessHeap(),0,lpszwReading
);
2908 HeapFree(GetProcessHeap(),0,lpszwUnregister
);
2916 /***********************************************************************
2917 * ImmUnregisterWordW (IMM32.@)
2919 BOOL WINAPI
ImmUnregisterWordW(
2920 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszUnregister
)
2922 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2923 TRACE("(%p, %s, %ld, %s):\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
2924 debugstr_w(lpszUnregister
));
2925 if (immHkl
->hIME
&& immHkl
->pImeUnregisterWord
)
2927 if (is_kbd_ime_unicode(immHkl
))
2928 return immHkl
->pImeUnregisterWord(lpszReading
,dwStyle
,lpszUnregister
);
2931 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
2932 LPSTR lpszaUnregister
= strdupWtoA(lpszUnregister
);
2935 rc
= immHkl
->pImeUnregisterWord((LPCWSTR
)lpszaReading
,dwStyle
,
2936 (LPCWSTR
)lpszaUnregister
);
2937 HeapFree(GetProcessHeap(),0,lpszaReading
);
2938 HeapFree(GetProcessHeap(),0,lpszaUnregister
);
2946 /***********************************************************************
2947 * ImmGetImeMenuItemsA (IMM32.@)
2949 DWORD WINAPI
ImmGetImeMenuItemsA( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
2950 LPIMEMENUITEMINFOA lpImeParentMenu
, LPIMEMENUITEMINFOA lpImeMenu
,
2953 InputContextData
*data
= get_imc_data(hIMC
);
2954 TRACE("(%p, %li, %li, %p, %p, %li):\n", hIMC
, dwFlags
, dwType
,
2955 lpImeParentMenu
, lpImeMenu
, dwSize
);
2959 SetLastError(ERROR_INVALID_HANDLE
);
2963 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
2965 if (!is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
2966 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
2967 (IMEMENUITEMINFOW
*)lpImeParentMenu
,
2968 (IMEMENUITEMINFOW
*)lpImeMenu
, dwSize
);
2971 IMEMENUITEMINFOW lpImeParentMenuW
;
2972 IMEMENUITEMINFOW
*lpImeMenuW
, *parent
= NULL
;
2975 if (lpImeParentMenu
)
2976 parent
= &lpImeParentMenuW
;
2979 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOA
);
2980 dwSize
= count
* sizeof(IMEMENUITEMINFOW
);
2981 lpImeMenuW
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
2986 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
2987 parent
, lpImeMenuW
, dwSize
);
2989 if (lpImeParentMenu
)
2991 memcpy(lpImeParentMenu
,&lpImeParentMenuW
,sizeof(IMEMENUITEMINFOA
));
2992 lpImeParentMenu
->hbmpItem
= lpImeParentMenuW
.hbmpItem
;
2993 WideCharToMultiByte(CP_ACP
, 0, lpImeParentMenuW
.szString
,
2994 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
,
2997 if (lpImeMenu
&& rc
)
3000 for (i
= 0; i
< rc
; i
++)
3002 memcpy(&lpImeMenu
[i
],&lpImeMenuW
[1],sizeof(IMEMENUITEMINFOA
));
3003 lpImeMenu
[i
].hbmpItem
= lpImeMenuW
[i
].hbmpItem
;
3004 WideCharToMultiByte(CP_ACP
, 0, lpImeMenuW
[i
].szString
,
3005 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
,
3009 HeapFree(GetProcessHeap(),0,lpImeMenuW
);
3017 /***********************************************************************
3018 * ImmGetImeMenuItemsW (IMM32.@)
3020 DWORD WINAPI
ImmGetImeMenuItemsW( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
3021 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
3024 InputContextData
*data
= get_imc_data(hIMC
);
3025 TRACE("(%p, %li, %li, %p, %p, %li):\n", hIMC
, dwFlags
, dwType
,
3026 lpImeParentMenu
, lpImeMenu
, dwSize
);
3030 SetLastError(ERROR_INVALID_HANDLE
);
3034 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
3036 if (is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
3037 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
3038 lpImeParentMenu
, lpImeMenu
, dwSize
);
3041 IMEMENUITEMINFOA lpImeParentMenuA
;
3042 IMEMENUITEMINFOA
*lpImeMenuA
, *parent
= NULL
;
3045 if (lpImeParentMenu
)
3046 parent
= &lpImeParentMenuA
;
3049 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOW
);
3050 dwSize
= count
* sizeof(IMEMENUITEMINFOA
);
3051 lpImeMenuA
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
3056 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
3057 (IMEMENUITEMINFOW
*)parent
,
3058 (IMEMENUITEMINFOW
*)lpImeMenuA
, dwSize
);
3060 if (lpImeParentMenu
)
3062 memcpy(lpImeParentMenu
,&lpImeParentMenuA
,sizeof(IMEMENUITEMINFOA
));
3063 lpImeParentMenu
->hbmpItem
= lpImeParentMenuA
.hbmpItem
;
3064 MultiByteToWideChar(CP_ACP
, 0, lpImeParentMenuA
.szString
,
3065 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
);
3067 if (lpImeMenu
&& rc
)
3070 for (i
= 0; i
< rc
; i
++)
3072 memcpy(&lpImeMenu
[i
],&lpImeMenuA
[1],sizeof(IMEMENUITEMINFOA
));
3073 lpImeMenu
[i
].hbmpItem
= lpImeMenuA
[i
].hbmpItem
;
3074 MultiByteToWideChar(CP_ACP
, 0, lpImeMenuA
[i
].szString
,
3075 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
);
3078 HeapFree(GetProcessHeap(),0,lpImeMenuA
);
3086 /***********************************************************************
3087 * ImmLockIMC(IMM32.@)
3089 LPINPUTCONTEXT WINAPI
ImmLockIMC(HIMC hIMC
)
3091 InputContextData
*data
= get_imc_data(hIMC
);
3099 /***********************************************************************
3100 * ImmUnlockIMC(IMM32.@)
3102 BOOL WINAPI
ImmUnlockIMC(HIMC hIMC
)
3104 InputContextData
*data
= get_imc_data(hIMC
);
3113 /***********************************************************************
3114 * ImmGetIMCLockCount(IMM32.@)
3116 DWORD WINAPI
ImmGetIMCLockCount(HIMC hIMC
)
3118 InputContextData
*data
= get_imc_data(hIMC
);
3121 return data
->dwLock
;
3124 /***********************************************************************
3125 * ImmCreateIMCC(IMM32.@)
3127 HIMCC WINAPI
ImmCreateIMCC(DWORD size
)
3129 return GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
, size
);
3132 /***********************************************************************
3133 * ImmDestroyIMCC(IMM32.@)
3135 HIMCC WINAPI
ImmDestroyIMCC(HIMCC block
)
3137 return GlobalFree(block
);
3140 /***********************************************************************
3141 * ImmLockIMCC(IMM32.@)
3143 LPVOID WINAPI
ImmLockIMCC(HIMCC imcc
)
3145 return GlobalLock(imcc
);
3148 /***********************************************************************
3149 * ImmUnlockIMCC(IMM32.@)
3151 BOOL WINAPI
ImmUnlockIMCC(HIMCC imcc
)
3153 return GlobalUnlock(imcc
);
3156 /***********************************************************************
3157 * ImmGetIMCCLockCount(IMM32.@)
3159 DWORD WINAPI
ImmGetIMCCLockCount(HIMCC imcc
)
3161 return GlobalFlags(imcc
) & GMEM_LOCKCOUNT
;
3164 /***********************************************************************
3165 * ImmReSizeIMCC(IMM32.@)
3167 HIMCC WINAPI
ImmReSizeIMCC(HIMCC imcc
, DWORD size
)
3169 return GlobalReAlloc(imcc
, size
, GMEM_ZEROINIT
| GMEM_MOVEABLE
);
3172 /***********************************************************************
3173 * ImmGetIMCCSize(IMM32.@)
3175 DWORD WINAPI
ImmGetIMCCSize(HIMCC imcc
)
3177 return GlobalSize(imcc
);
3180 /***********************************************************************
3181 * ImmGenerateMessage(IMM32.@)
3183 BOOL WINAPI
ImmGenerateMessage(HIMC hIMC
)
3185 InputContextData
*data
= get_imc_data(hIMC
);
3189 SetLastError(ERROR_INVALID_HANDLE
);
3193 TRACE("%li messages queued\n",data
->IMC
.dwNumMsgBuf
);
3194 if (data
->IMC
.dwNumMsgBuf
> 0)
3196 LPTRANSMSG lpTransMsg
;
3198 DWORD i
, dwNumMsgBuf
;
3200 /* We are going to detach our hMsgBuff so that if processing messages
3201 generates new messages they go into a new buffer */
3202 hMsgBuf
= data
->IMC
.hMsgBuf
;
3203 dwNumMsgBuf
= data
->IMC
.dwNumMsgBuf
;
3205 data
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
3206 data
->IMC
.dwNumMsgBuf
= 0;
3208 lpTransMsg
= ImmLockIMCC(hMsgBuf
);
3209 for (i
= 0; i
< dwNumMsgBuf
; i
++)
3210 ImmInternalSendIMEMessage(data
, lpTransMsg
[i
].message
, lpTransMsg
[i
].wParam
, lpTransMsg
[i
].lParam
);
3212 ImmUnlockIMCC(hMsgBuf
);
3213 ImmDestroyIMCC(hMsgBuf
);
3219 /***********************************************************************
3220 * ImmTranslateMessage(IMM32.@)
3221 * ( Undocumented, call internally and from user32.dll )
3223 BOOL WINAPI
ImmTranslateMessage(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lKeyData
)
3225 InputContextData
*data
;
3226 HIMC imc
= ImmGetContext(hwnd
);
3232 static const DWORD list_count
= 10;
3234 TRACE("%p %x %x %x\n",hwnd
, msg
, (UINT
)wParam
, (UINT
)lKeyData
);
3241 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeToAsciiEx
|| data
->lastVK
== VK_PROCESSKEY
)
3244 GetKeyboardState(state
);
3245 scancode
= lKeyData
>> 0x10 & 0xff;
3247 list
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, list_count
* sizeof(TRANSMSG
) + sizeof(DWORD
));
3248 ((DWORD
*)list
)[0] = list_count
;
3250 if (data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_KBD_CHAR_FIRST
)
3254 if (!is_himc_ime_unicode(data
))
3255 ToAscii(data
->lastVK
, scancode
, state
, &chr
, 0);
3257 ToUnicodeEx(data
->lastVK
, scancode
, state
, &chr
, 1, 0, GetKeyboardLayout(0));
3258 uVirtKey
= MAKELONG(data
->lastVK
,chr
);
3261 uVirtKey
= data
->lastVK
;
3263 msg_count
= data
->immKbd
->pImeToAsciiEx(uVirtKey
, scancode
, state
, list
, 0, imc
);
3264 TRACE("%i messages generated\n",msg_count
);
3265 if (msg_count
&& msg_count
<= list_count
)
3268 LPTRANSMSG msgs
= (LPTRANSMSG
)((LPBYTE
)list
+ sizeof(DWORD
));
3270 for (i
= 0; i
< msg_count
; i
++)
3271 ImmInternalPostIMEMessage(data
, msgs
[i
].message
, msgs
[i
].wParam
, msgs
[i
].lParam
);
3273 else if (msg_count
> list_count
)
3274 ImmGenerateMessage(imc
);
3276 HeapFree(GetProcessHeap(),0,list
);
3278 data
->lastVK
= VK_PROCESSKEY
;
3280 return (msg_count
> 0);
3283 /***********************************************************************
3284 * ImmProcessKey(IMM32.@)
3285 * ( Undocumented, called from user32.dll )
3287 BOOL WINAPI
ImmProcessKey(HWND hwnd
, HKL hKL
, UINT vKey
, LPARAM lKeyData
, DWORD unknown
)
3289 InputContextData
*data
;
3290 HIMC imc
= ImmGetContext(hwnd
);
3293 TRACE("%p %p %x %x %lx\n",hwnd
, hKL
, vKey
, (UINT
)lKeyData
, unknown
);
3300 /* Make sure we are inputting to the correct keyboard */
3301 if (data
->immKbd
->hkl
!= hKL
)
3303 ImmHkl
*new_hkl
= IMM_GetImmHkl(hKL
);
3306 data
->immKbd
->pImeSelect(imc
, FALSE
);
3307 data
->immKbd
->uSelected
--;
3308 data
->immKbd
= new_hkl
;
3309 data
->immKbd
->pImeSelect(imc
, TRUE
);
3310 data
->immKbd
->uSelected
++;
3316 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeProcessKey
)
3319 GetKeyboardState(state
);
3320 if (data
->immKbd
->pImeProcessKey(imc
, vKey
, lKeyData
, state
))
3322 data
->lastVK
= vKey
;
3326 data
->lastVK
= VK_PROCESSKEY
;
3330 /***********************************************************************
3331 * ImmDisableTextFrameService(IMM32.@)
3333 BOOL WINAPI
ImmDisableTextFrameService(DWORD idThread
)
3339 /***********************************************************************
3340 * ImmEnumInputContext(IMM32.@)
3343 BOOL WINAPI
ImmEnumInputContext(DWORD idThread
, IMCENUMPROC lpfn
, LPARAM lParam
)
3349 /***********************************************************************
3350 * ImmGetHotKey(IMM32.@)
3353 BOOL WINAPI
ImmGetHotKey(DWORD hotkey
, UINT
*modifiers
, UINT
*key
, HKL hkl
)
3355 FIXME("%lx, %p, %p, %p: stub\n", hotkey
, modifiers
, key
, hkl
);
3359 /***********************************************************************
3360 * ImmDisableLegacyIME(IMM32.@)
3362 BOOL WINAPI
ImmDisableLegacyIME(void)