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
26 #define WIN32_NO_STATUS
33 #include "wine/debug.h"
38 #include "wine/list.h"
41 #include <ndk/umtypes.h>
42 #include <ndk/pstypes.h>
43 #include "../../../win32ss/include/ntuser.h"
44 #include <imm32_undoc.h>
48 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
50 #define IMM_INIT_MAGIC 0x19650412
51 BOOL WINAPI
User32InitializeImmEntryTable(DWORD
);
53 typedef struct _tagImmHkl
{
58 WCHAR imeClassName
[17]; /* 16 character max */
62 /* Function Pointers */
63 BOOL (WINAPI
*pImeInquire
)(IMEINFO
*, WCHAR
*, const WCHAR
*);
64 BOOL (WINAPI
*pImeConfigure
)(HKL
, HWND
, DWORD
, void *);
65 BOOL (WINAPI
*pImeDestroy
)(UINT
);
66 LRESULT (WINAPI
*pImeEscape
)(HIMC
, UINT
, void *);
67 BOOL (WINAPI
*pImeSelect
)(HIMC
, BOOL
);
68 BOOL (WINAPI
*pImeSetActiveContext
)(HIMC
, BOOL
);
69 UINT (WINAPI
*pImeToAsciiEx
)(UINT
, UINT
, const BYTE
*, DWORD
*, UINT
, HIMC
);
70 BOOL (WINAPI
*pNotifyIME
)(HIMC
, DWORD
, DWORD
, DWORD
);
71 BOOL (WINAPI
*pImeRegisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
72 BOOL (WINAPI
*pImeUnregisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
73 UINT (WINAPI
*pImeEnumRegisterWord
)(REGISTERWORDENUMPROCW
, const WCHAR
*, DWORD
, const WCHAR
*, void *);
74 BOOL (WINAPI
*pImeSetCompositionString
)(HIMC
, DWORD
, const void *, DWORD
, const void *, DWORD
);
75 DWORD (WINAPI
*pImeConversionList
)(HIMC
, const WCHAR
*, CANDIDATELIST
*, DWORD
, UINT
);
76 BOOL (WINAPI
*pImeProcessKey
)(HIMC
, UINT
, LPARAM
, const BYTE
*);
77 UINT (WINAPI
*pImeGetRegisterWordStyle
)(UINT
, STYLEBUFW
*);
78 DWORD (WINAPI
*pImeGetImeMenuItems
)(HIMC
, DWORD
, DWORD
, IMEMENUITEMINFOW
*, IMEMENUITEMINFOW
*, DWORD
);
81 typedef struct tagInputContextData
93 #define WINE_IMC_VALID_MAGIC 0x56434D49
95 typedef struct _tagTRANSMSG
{
99 } TRANSMSG
, *LPTRANSMSG
;
101 typedef struct _tagIMMThreadData
{
110 static struct list ImmHklList
= LIST_INIT(ImmHklList
);
111 static struct list ImmThreadDataList
= LIST_INIT(ImmThreadDataList
);
113 static const WCHAR szwWineIMCProperty
[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
115 static const WCHAR szImeFileW
[] = {'I','m','e',' ','F','i','l','e',0};
116 static const WCHAR szLayoutTextW
[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
117 static const WCHAR szImeRegFmt
[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0};
119 static const WCHAR szwIME
[] = {'I','M','E',0};
120 static const WCHAR szwDefaultIME
[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
122 static CRITICAL_SECTION threaddata_cs
;
123 static CRITICAL_SECTION_DEBUG critsect_debug
=
125 0, 0, &threaddata_cs
,
126 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
127 0, 0, { (DWORD_PTR
)(__FILE__
": threaddata_cs") }
129 static CRITICAL_SECTION threaddata_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
130 static BOOL disable_ime
;
132 static inline BOOL
is_himc_ime_unicode(const InputContextData
*data
)
134 return !!(data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
137 static inline BOOL
is_kbd_ime_unicode(const ImmHkl
*hkl
)
139 return !!(hkl
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
142 static BOOL
IMM_DestroyContext(HIMC hIMC
);
143 static InputContextData
* get_imc_data(HIMC hIMC
);
145 static inline WCHAR
*strdupAtoW( const char *str
)
150 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
151 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
152 MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
157 static inline CHAR
*strdupWtoA( const WCHAR
*str
)
162 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
163 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
164 WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
169 static DWORD
convert_candidatelist_WtoA(
170 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
174 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
175 if ( lpDst
&& dwBufLen
> 0 )
178 lpDst
->dwOffset
[0] = ret
;
181 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
183 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
185 if ( lpDst
&& dwBufLen
> 0 )
187 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
189 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1,
190 (LPSTR
)dest
, dwBufLen
, NULL
, NULL
);
192 if ( i
+ 1 < lpSrc
->dwCount
)
193 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(char);
194 dwBufLen
-= len
* sizeof(char);
197 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1, NULL
, 0, NULL
, NULL
);
199 ret
+= len
* sizeof(char);
208 static DWORD
convert_candidatelist_AtoW(
209 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
213 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
214 if ( lpDst
&& dwBufLen
> 0 )
217 lpDst
->dwOffset
[0] = ret
;
220 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
222 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
224 if ( lpDst
&& dwBufLen
> 0 )
226 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
228 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1,
229 (LPWSTR
)dest
, dwBufLen
);
231 if ( i
+ 1 < lpSrc
->dwCount
)
232 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(WCHAR
);
233 dwBufLen
-= len
* sizeof(WCHAR
);
236 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1, NULL
, 0);
238 ret
+= len
* sizeof(WCHAR
);
247 static IMMThreadData
*IMM_GetThreadData(HWND hwnd
, DWORD thread
)
254 if (!(thread
= GetWindowThreadProcessId(hwnd
, &process
))) return NULL
;
255 if (process
!= GetCurrentProcessId()) return NULL
;
259 HANDLE h
= OpenThread(THREAD_QUERY_INFORMATION
, FALSE
, thread
);
261 process
= GetProcessIdOfThread(h
);
263 if (process
!= GetCurrentProcessId()) return NULL
;
266 thread
= GetCurrentThreadId();
268 EnterCriticalSection(&threaddata_cs
);
269 LIST_FOR_EACH_ENTRY(data
, &ImmThreadDataList
, IMMThreadData
, entry
)
270 if (data
->threadID
== thread
) return data
;
272 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
273 data
->threadID
= thread
;
274 list_add_head(&ImmThreadDataList
,&data
->entry
);
275 TRACE("Thread Data Created (%x)\n",thread
);
279 static BOOL
IMM_IsDefaultContext(HIMC imc
)
281 InputContextData
*data
= get_imc_data(imc
);
286 return data
->threadDefault
;
289 static void IMM_FreeThreadData(void)
293 EnterCriticalSection(&threaddata_cs
);
294 LIST_FOR_EACH_ENTRY(data
, &ImmThreadDataList
, IMMThreadData
, entry
)
296 if (data
->threadID
== GetCurrentThreadId())
298 list_remove(&data
->entry
);
299 LeaveCriticalSection(&threaddata_cs
);
300 IMM_DestroyContext(data
->defaultContext
);
301 HeapFree(GetProcessHeap(),0,data
);
302 TRACE("Thread Data Destroyed\n");
306 LeaveCriticalSection(&threaddata_cs
);
309 static HMODULE
load_graphics_driver(void)
311 static const WCHAR display_device_guid_propW
[] = {
312 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
313 'd','e','v','i','c','e','_','g','u','i','d',0 };
314 static const WCHAR key_pathW
[] = {
315 'S','y','s','t','e','m','\\',
316 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
317 'C','o','n','t','r','o','l','\\',
318 'V','i','d','e','o','\\','{',0};
319 static const WCHAR displayW
[] = {'}','\\','0','0','0','0',0};
320 static const WCHAR driverW
[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
325 WCHAR path
[MAX_PATH
];
326 WCHAR key
[ARRAY_SIZE( key_pathW
) + ARRAY_SIZE( displayW
) + 40];
327 UINT guid_atom
= HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW
));
329 if (!guid_atom
) return 0;
330 memcpy( key
, key_pathW
, sizeof(key_pathW
) );
331 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
332 lstrcatW( key
, displayW
);
333 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
335 if (!RegQueryValueExW( hkey
, driverW
, NULL
, NULL
, (BYTE
*)path
, &size
)) ret
= LoadLibraryW( path
);
337 TRACE( "%s %p\n", debugstr_w(path
), ret
);
341 /* ImmHkl loading and freeing */
342 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
343 static ImmHkl
*IMM_GetImmHkl(HKL hkl
)
346 WCHAR filename
[MAX_PATH
];
348 TRACE("Seeking ime for keyboard %p\n",hkl
);
350 LIST_FOR_EACH_ENTRY(ptr
, &ImmHklList
, ImmHkl
, entry
)
355 /* not found... create it */
357 ptr
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ImmHkl
));
360 if (ImmGetIMEFileNameW(hkl
, filename
, MAX_PATH
)) ptr
->hIME
= LoadLibraryW(filename
);
361 if (!ptr
->hIME
) ptr
->hIME
= load_graphics_driver();
364 LOAD_FUNCPTR(ImeInquire
);
365 if (!ptr
->pImeInquire
|| !ptr
->pImeInquire(&ptr
->imeInfo
, ptr
->imeClassName
, NULL
))
367 FreeLibrary(ptr
->hIME
);
372 LOAD_FUNCPTR(ImeDestroy
);
373 LOAD_FUNCPTR(ImeSelect
);
374 if (!ptr
->pImeSelect
|| !ptr
->pImeDestroy
)
376 FreeLibrary(ptr
->hIME
);
381 LOAD_FUNCPTR(ImeConfigure
);
382 LOAD_FUNCPTR(ImeEscape
);
383 LOAD_FUNCPTR(ImeSetActiveContext
);
384 LOAD_FUNCPTR(ImeToAsciiEx
);
385 LOAD_FUNCPTR(NotifyIME
);
386 LOAD_FUNCPTR(ImeRegisterWord
);
387 LOAD_FUNCPTR(ImeUnregisterWord
);
388 LOAD_FUNCPTR(ImeEnumRegisterWord
);
389 LOAD_FUNCPTR(ImeSetCompositionString
);
390 LOAD_FUNCPTR(ImeConversionList
);
391 LOAD_FUNCPTR(ImeProcessKey
);
392 LOAD_FUNCPTR(ImeGetRegisterWordStyle
);
393 LOAD_FUNCPTR(ImeGetImeMenuItems
);
394 /* make sure our classname is WCHAR */
395 if (!is_kbd_ime_unicode(ptr
))
398 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ptr
->imeClassName
,
400 lstrcpyW(ptr
->imeClassName
, bufW
);
405 list_add_head(&ImmHklList
,&ptr
->entry
);
411 HWND WINAPI
__wine_get_ui_window(HKL hkl
)
413 ImmHkl
*immHkl
= IMM_GetImmHkl(hkl
);
414 return immHkl
->UIWnd
;
417 static void IMM_FreeAllImmHkl(void)
419 ImmHkl
*ptr
,*cursor2
;
421 LIST_FOR_EACH_ENTRY_SAFE(ptr
, cursor2
, &ImmHklList
, ImmHkl
, entry
)
423 list_remove(&ptr
->entry
);
427 FreeLibrary(ptr
->hIME
);
430 DestroyWindow(ptr
->UIWnd
);
431 HeapFree(GetProcessHeap(),0,ptr
);
435 BOOL WINAPI
DllMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID lpReserved
)
437 TRACE("%p, %x, %p\n",hInstDLL
,fdwReason
,lpReserved
);
440 case DLL_PROCESS_ATTACH
:
441 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC
))
446 case DLL_THREAD_ATTACH
:
448 case DLL_THREAD_DETACH
:
449 IMM_FreeThreadData();
451 case DLL_PROCESS_DETACH
:
452 if (lpReserved
) break;
453 IMM_FreeThreadData();
460 /* for posting messages as the IME */
461 static void ImmInternalPostIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
463 HWND target
= GetFocus();
465 PostMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
467 PostMessageW(target
, msg
, wParam
, lParam
);
470 /* for sending messages as the IME */
471 static void ImmInternalSendIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
473 HWND target
= GetFocus();
475 SendMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
477 SendMessageW(target
, msg
, wParam
, lParam
);
480 static LRESULT
ImmInternalSendIMENotify(InputContextData
*data
, WPARAM notify
, LPARAM lParam
)
484 target
= data
->IMC
.hWnd
;
485 if (!target
) target
= GetFocus();
488 return SendMessageW(target
, WM_IME_NOTIFY
, notify
, lParam
);
493 static HIMCC
ImmCreateBlankCompStr(void)
496 LPCOMPOSITIONSTRING ptr
;
497 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
498 ptr
= ImmLockIMCC(rc
);
499 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
500 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
505 static InputContextData
* get_imc_data(HIMC hIMC
)
507 InputContextData
*data
= hIMC
;
512 if(IsBadReadPtr(data
, sizeof(InputContextData
)) || data
->magic
!= WINE_IMC_VALID_MAGIC
)
514 SetLastError(ERROR_INVALID_HANDLE
);
520 static HIMC
get_default_context( HWND hwnd
)
523 IMMThreadData
* thread_data
= IMM_GetThreadData( hwnd
, 0 );
525 if (!thread_data
) return 0;
527 if (thread_data
->defaultContext
)
529 ret
= thread_data
->defaultContext
;
530 LeaveCriticalSection(&threaddata_cs
);
534 /* can't create a default context in another thread */
535 if (thread_data
->threadID
!= GetCurrentThreadId())
537 LeaveCriticalSection(&threaddata_cs
);
541 LeaveCriticalSection(&threaddata_cs
);
543 ret
= ImmCreateContext();
545 ((InputContextData
*)ret
)->threadDefault
= TRUE
;
547 /* thread_data is in the current thread so we can assume it's still valid */
548 EnterCriticalSection(&threaddata_cs
);
550 if (thread_data
->defaultContext
) /* someone beat us */
552 IMM_DestroyContext( ret
);
553 ret
= thread_data
->defaultContext
;
555 else thread_data
->defaultContext
= ret
;
557 LeaveCriticalSection(&threaddata_cs
);
561 static BOOL
IMM_IsCrossThreadAccess(HWND hWnd
, HIMC hIMC
)
563 InputContextData
*data
;
567 DWORD thread
= GetWindowThreadProcessId(hWnd
, NULL
);
568 if (thread
!= GetCurrentThreadId()) return TRUE
;
570 data
= get_imc_data(hIMC
);
571 if (data
&& data
->threadID
!= GetCurrentThreadId())
577 /***********************************************************************
578 * ImmAssociateContext (IMM32.@)
580 HIMC WINAPI
ImmAssociateContext(HWND hWnd
, HIMC hIMC
)
583 InputContextData
*data
= get_imc_data(hIMC
);
585 TRACE("(%p, %p):\n", hWnd
, hIMC
);
591 * If already associated just return
593 if (hIMC
&& data
->IMC
.hWnd
== hWnd
)
596 if (hIMC
&& IMM_IsCrossThreadAccess(hWnd
, hIMC
))
601 HIMC defaultContext
= get_default_context( hWnd
);
602 old
= RemovePropW(hWnd
,szwWineIMCProperty
);
605 old
= defaultContext
;
606 else if (old
== (HIMC
)-1)
609 if (hIMC
!= defaultContext
)
611 if (hIMC
== NULL
) /* Meaning disable imm for that window*/
612 SetPropW(hWnd
,szwWineIMCProperty
,(HANDLE
)-1);
614 SetPropW(hWnd
,szwWineIMCProperty
,hIMC
);
619 InputContextData
*old_data
= old
;
620 if (old_data
->IMC
.hWnd
== hWnd
)
621 old_data
->IMC
.hWnd
= NULL
;
628 if(GetActiveWindow() == data
->IMC
.hWnd
)
630 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, FALSE
, ISC_SHOWUIALL
);
631 data
->IMC
.hWnd
= hWnd
;
632 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, TRUE
, ISC_SHOWUIALL
);
640 * Helper function for ImmAssociateContextEx
642 static BOOL CALLBACK
_ImmAssociateContextExEnumProc(HWND hwnd
, LPARAM lParam
)
644 HIMC hImc
= (HIMC
)lParam
;
645 ImmAssociateContext(hwnd
,hImc
);
649 /***********************************************************************
650 * ImmAssociateContextEx (IMM32.@)
652 BOOL WINAPI
ImmAssociateContextEx(HWND hWnd
, HIMC hIMC
, DWORD dwFlags
)
654 TRACE("(%p, %p, 0x%x):\n", hWnd
, hIMC
, dwFlags
);
662 ImmAssociateContext(hWnd
,hIMC
);
666 HIMC defaultContext
= get_default_context( hWnd
);
667 if (!defaultContext
) return FALSE
;
668 ImmAssociateContext(hWnd
,defaultContext
);
671 case IACE_IGNORENOCONTEXT
:
672 if (GetPropW(hWnd
,szwWineIMCProperty
))
673 ImmAssociateContext(hWnd
,hIMC
);
676 EnumChildWindows(hWnd
,_ImmAssociateContextExEnumProc
,(LPARAM
)hIMC
);
679 FIXME("Unknown dwFlags 0x%x\n",dwFlags
);
684 /***********************************************************************
685 * ImmConfigureIMEA (IMM32.@)
687 BOOL WINAPI
ImmConfigureIMEA(
688 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
690 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
692 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
694 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
697 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
699 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| !is_kbd_ime_unicode(immHkl
))
700 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
704 REGISTERWORDA
*rwa
= lpData
;
707 rww
.lpReading
= strdupAtoW(rwa
->lpReading
);
708 rww
.lpWord
= strdupAtoW(rwa
->lpWord
);
709 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rww
);
710 HeapFree(GetProcessHeap(),0,rww
.lpReading
);
711 HeapFree(GetProcessHeap(),0,rww
.lpWord
);
719 /***********************************************************************
720 * ImmConfigureIMEW (IMM32.@)
722 BOOL WINAPI
ImmConfigureIMEW(
723 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
725 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
727 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
729 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
732 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
734 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| is_kbd_ime_unicode(immHkl
))
735 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
738 REGISTERWORDW
*rww
= lpData
;
742 rwa
.lpReading
= strdupWtoA(rww
->lpReading
);
743 rwa
.lpWord
= strdupWtoA(rww
->lpWord
);
744 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rwa
);
745 HeapFree(GetProcessHeap(),0,rwa
.lpReading
);
746 HeapFree(GetProcessHeap(),0,rwa
.lpWord
);
754 /***********************************************************************
755 * ImmCreateContext (IMM32.@)
757 HIMC WINAPI
ImmCreateContext(void)
759 InputContextData
*new_context
;
764 new_context
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(InputContextData
));
767 new_context
->immKbd
= IMM_GetImmHkl(GetKeyboardLayout(0));
769 if (!new_context
->immKbd
->hIME
)
771 TRACE("IME dll could not be loaded\n");
772 HeapFree(GetProcessHeap(),0,new_context
);
776 /* the HIMCCs are never NULL */
777 new_context
->IMC
.hCompStr
= ImmCreateBlankCompStr();
778 new_context
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
779 new_context
->IMC
.hCandInfo
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
780 ci
= ImmLockIMCC(new_context
->IMC
.hCandInfo
);
781 memset(ci
,0,sizeof(CANDIDATEINFO
));
782 ci
->dwSize
= sizeof(CANDIDATEINFO
);
783 ImmUnlockIMCC(new_context
->IMC
.hCandInfo
);
784 new_context
->IMC
.hGuideLine
= ImmCreateIMCC(sizeof(GUIDELINE
));
785 gl
= ImmLockIMCC(new_context
->IMC
.hGuideLine
);
786 memset(gl
,0,sizeof(GUIDELINE
));
787 gl
->dwSize
= sizeof(GUIDELINE
);
788 ImmUnlockIMCC(new_context
->IMC
.hGuideLine
);
790 for (i
= 0; i
< ARRAY_SIZE(new_context
->IMC
.cfCandForm
); i
++)
791 new_context
->IMC
.cfCandForm
[i
].dwIndex
= ~0u;
793 /* Initialize the IME Private */
794 new_context
->IMC
.hPrivate
= ImmCreateIMCC(new_context
->immKbd
->imeInfo
.dwPrivateDataSize
);
796 new_context
->IMC
.fdwConversion
= new_context
->immKbd
->imeInfo
.fdwConversionCaps
;
797 new_context
->IMC
.fdwSentence
= new_context
->immKbd
->imeInfo
.fdwSentenceCaps
;
799 if (!new_context
->immKbd
->pImeSelect(new_context
, TRUE
))
801 TRACE("Selection of IME failed\n");
802 IMM_DestroyContext(new_context
);
805 new_context
->threadID
= GetCurrentThreadId();
806 SendMessageW(GetFocus(), WM_IME_SELECT
, TRUE
, (LPARAM
)new_context
->immKbd
);
808 new_context
->immKbd
->uSelected
++;
809 TRACE("Created context %p\n",new_context
);
811 new_context
->magic
= WINE_IMC_VALID_MAGIC
;
815 static BOOL
IMM_DestroyContext(HIMC hIMC
)
817 InputContextData
*data
= get_imc_data(hIMC
);
819 TRACE("Destroying %p\n",hIMC
);
824 data
->immKbd
->uSelected
--;
825 data
->immKbd
->pImeSelect(hIMC
, FALSE
);
826 SendMessageW(data
->IMC
.hWnd
, WM_IME_SELECT
, FALSE
, (LPARAM
)data
->immKbd
);
828 ImmDestroyIMCC(data
->IMC
.hCompStr
);
829 ImmDestroyIMCC(data
->IMC
.hCandInfo
);
830 ImmDestroyIMCC(data
->IMC
.hGuideLine
);
831 ImmDestroyIMCC(data
->IMC
.hPrivate
);
832 ImmDestroyIMCC(data
->IMC
.hMsgBuf
);
835 HeapFree(GetProcessHeap(),0,data
);
840 /***********************************************************************
841 * ImmDestroyContext (IMM32.@)
843 BOOL WINAPI
ImmDestroyContext(HIMC hIMC
)
845 if (!IMM_IsDefaultContext(hIMC
) && !IMM_IsCrossThreadAccess(NULL
, hIMC
))
846 return IMM_DestroyContext(hIMC
);
851 /***********************************************************************
852 * ImmDisableIME (IMM32.@)
854 BOOL WINAPI
ImmDisableIME(DWORD idThread
)
857 return NtUserDisableThreadIme(idThread
);
859 if (idThread
== (DWORD
)-1)
862 IMMThreadData
*thread_data
= IMM_GetThreadData(NULL
, idThread
);
863 if (!thread_data
) return FALSE
;
864 thread_data
->disableIME
= TRUE
;
865 LeaveCriticalSection(&threaddata_cs
);
871 /***********************************************************************
872 * ImmEnumRegisterWordA (IMM32.@)
874 UINT WINAPI
ImmEnumRegisterWordA(
875 HKL hKL
, REGISTERWORDENUMPROCA lpfnEnumProc
,
876 LPCSTR lpszReading
, DWORD dwStyle
,
877 LPCSTR lpszRegister
, LPVOID lpData
)
879 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
880 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL
, lpfnEnumProc
,
881 debugstr_a(lpszReading
), dwStyle
, debugstr_a(lpszRegister
), lpData
);
882 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
884 if (!is_kbd_ime_unicode(immHkl
))
885 return immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
886 (LPCWSTR
)lpszReading
, dwStyle
, (LPCWSTR
)lpszRegister
, lpData
);
889 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
890 LPWSTR lpszwRegister
= strdupAtoW(lpszRegister
);
893 rc
= immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
894 lpszwReading
, dwStyle
, lpszwRegister
,
897 HeapFree(GetProcessHeap(),0,lpszwReading
);
898 HeapFree(GetProcessHeap(),0,lpszwRegister
);
906 /***********************************************************************
907 * ImmEnumRegisterWordW (IMM32.@)
909 UINT WINAPI
ImmEnumRegisterWordW(
910 HKL hKL
, REGISTERWORDENUMPROCW lpfnEnumProc
,
911 LPCWSTR lpszReading
, DWORD dwStyle
,
912 LPCWSTR lpszRegister
, LPVOID lpData
)
914 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
915 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL
, lpfnEnumProc
,
916 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
), lpData
);
917 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
919 if (is_kbd_ime_unicode(immHkl
))
920 return immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, lpszReading
, dwStyle
,
921 lpszRegister
, lpData
);
924 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
925 LPSTR lpszaRegister
= strdupWtoA(lpszRegister
);
928 rc
= immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, (LPCWSTR
)lpszaReading
,
929 dwStyle
, (LPCWSTR
)lpszaRegister
, lpData
);
931 HeapFree(GetProcessHeap(),0,lpszaReading
);
932 HeapFree(GetProcessHeap(),0,lpszaRegister
);
940 static inline BOOL
EscapeRequiresWA(UINT uEscape
)
942 if (uEscape
== IME_ESC_GET_EUDC_DICTIONARY
||
943 uEscape
== IME_ESC_SET_EUDC_DICTIONARY
||
944 uEscape
== IME_ESC_IME_NAME
||
945 uEscape
== IME_ESC_GETHELPFILENAME
)
950 /***********************************************************************
951 * ImmEscapeA (IMM32.@)
953 LRESULT WINAPI
ImmEscapeA(
955 UINT uEscape
, LPVOID lpData
)
957 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
958 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
960 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
962 if (!EscapeRequiresWA(uEscape
) || !is_kbd_ime_unicode(immHkl
))
963 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
966 WCHAR buffer
[81]; /* largest required buffer should be 80 */
968 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
970 MultiByteToWideChar(CP_ACP
,0,lpData
,-1,buffer
,81);
971 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
975 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
976 WideCharToMultiByte(CP_ACP
,0,buffer
,-1,lpData
,80, NULL
, NULL
);
985 /***********************************************************************
986 * ImmEscapeW (IMM32.@)
988 LRESULT WINAPI
ImmEscapeW(
990 UINT uEscape
, LPVOID lpData
)
992 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
993 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
995 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
997 if (!EscapeRequiresWA(uEscape
) || is_kbd_ime_unicode(immHkl
))
998 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1001 CHAR buffer
[81]; /* largest required buffer should be 80 */
1003 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1005 WideCharToMultiByte(CP_ACP
,0,lpData
,-1,buffer
,81, NULL
, NULL
);
1006 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1010 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1011 MultiByteToWideChar(CP_ACP
,0,buffer
,-1,lpData
,80);
1020 /***********************************************************************
1021 * ImmGetCandidateListA (IMM32.@)
1023 DWORD WINAPI
ImmGetCandidateListA(
1024 HIMC hIMC
, DWORD dwIndex
,
1025 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1027 InputContextData
*data
= get_imc_data(hIMC
);
1028 LPCANDIDATEINFO candinfo
;
1029 LPCANDIDATELIST candlist
;
1032 TRACE("%p, %d, %p, %d\n", hIMC
, dwIndex
, lpCandList
, dwBufLen
);
1034 if (!data
|| !data
->IMC
.hCandInfo
)
1037 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1038 if (dwIndex
>= candinfo
->dwCount
|| dwIndex
>= ARRAY_SIZE(candinfo
->dwOffset
))
1041 candlist
= (LPCANDIDATELIST
)((LPBYTE
)candinfo
+ candinfo
->dwOffset
[dwIndex
]);
1042 if ( !candlist
->dwSize
|| !candlist
->dwCount
)
1045 if ( !is_himc_ime_unicode(data
) )
1047 ret
= candlist
->dwSize
;
1048 if ( lpCandList
&& dwBufLen
>= ret
)
1049 memcpy(lpCandList
, candlist
, ret
);
1052 ret
= convert_candidatelist_WtoA( candlist
, lpCandList
, dwBufLen
);
1055 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1059 /***********************************************************************
1060 * ImmGetCandidateListCountA (IMM32.@)
1062 DWORD WINAPI
ImmGetCandidateListCountA(
1063 HIMC hIMC
, LPDWORD lpdwListCount
)
1065 InputContextData
*data
= get_imc_data(hIMC
);
1066 LPCANDIDATEINFO candinfo
;
1069 TRACE("%p, %p\n", hIMC
, lpdwListCount
);
1071 if (!data
|| !lpdwListCount
|| !data
->IMC
.hCandInfo
)
1074 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1076 *lpdwListCount
= count
= candinfo
->dwCount
;
1078 if ( !is_himc_ime_unicode(data
) )
1079 ret
= candinfo
->dwSize
;
1082 ret
= sizeof(CANDIDATEINFO
);
1084 ret
+= ImmGetCandidateListA(hIMC
, count
, NULL
, 0);
1087 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1091 /***********************************************************************
1092 * ImmGetCandidateListCountW (IMM32.@)
1094 DWORD WINAPI
ImmGetCandidateListCountW(
1095 HIMC hIMC
, LPDWORD lpdwListCount
)
1097 InputContextData
*data
= get_imc_data(hIMC
);
1098 LPCANDIDATEINFO candinfo
;
1101 TRACE("%p, %p\n", hIMC
, lpdwListCount
);
1103 if (!data
|| !lpdwListCount
|| !data
->IMC
.hCandInfo
)
1106 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1108 *lpdwListCount
= count
= candinfo
->dwCount
;
1110 if ( is_himc_ime_unicode(data
) )
1111 ret
= candinfo
->dwSize
;
1114 ret
= sizeof(CANDIDATEINFO
);
1116 ret
+= ImmGetCandidateListW(hIMC
, count
, NULL
, 0);
1119 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1123 /***********************************************************************
1124 * ImmGetCandidateListW (IMM32.@)
1126 DWORD WINAPI
ImmGetCandidateListW(
1127 HIMC hIMC
, DWORD dwIndex
,
1128 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1130 InputContextData
*data
= get_imc_data(hIMC
);
1131 LPCANDIDATEINFO candinfo
;
1132 LPCANDIDATELIST candlist
;
1135 TRACE("%p, %d, %p, %d\n", hIMC
, dwIndex
, lpCandList
, dwBufLen
);
1137 if (!data
|| !data
->IMC
.hCandInfo
)
1140 candinfo
= ImmLockIMCC(data
->IMC
.hCandInfo
);
1141 if (dwIndex
>= candinfo
->dwCount
|| dwIndex
>= ARRAY_SIZE(candinfo
->dwOffset
))
1144 candlist
= (LPCANDIDATELIST
)((LPBYTE
)candinfo
+ candinfo
->dwOffset
[dwIndex
]);
1145 if ( !candlist
->dwSize
|| !candlist
->dwCount
)
1148 if ( is_himc_ime_unicode(data
) )
1150 ret
= candlist
->dwSize
;
1151 if ( lpCandList
&& dwBufLen
>= ret
)
1152 memcpy(lpCandList
, candlist
, ret
);
1155 ret
= convert_candidatelist_AtoW( candlist
, lpCandList
, dwBufLen
);
1158 ImmUnlockIMCC(data
->IMC
.hCandInfo
);
1162 /***********************************************************************
1163 * ImmGetCandidateWindow (IMM32.@)
1165 BOOL WINAPI
ImmGetCandidateWindow(
1166 HIMC hIMC
, DWORD dwIndex
, LPCANDIDATEFORM lpCandidate
)
1168 InputContextData
*data
= get_imc_data(hIMC
);
1170 TRACE("%p, %d, %p\n", hIMC
, dwIndex
, lpCandidate
);
1172 if (!data
|| !lpCandidate
)
1175 if (dwIndex
>= ARRAY_SIZE(data
->IMC
.cfCandForm
))
1178 if (data
->IMC
.cfCandForm
[dwIndex
].dwIndex
!= dwIndex
)
1181 *lpCandidate
= data
->IMC
.cfCandForm
[dwIndex
];
1186 /***********************************************************************
1187 * ImmGetCompositionFontA (IMM32.@)
1189 BOOL WINAPI
ImmGetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
1194 TRACE("(%p, %p):\n", hIMC
, lplf
);
1196 rc
= ImmGetCompositionFontW(hIMC
,&lfW
);
1200 memcpy(lplf
,&lfW
,sizeof(LOGFONTA
));
1201 WideCharToMultiByte(CP_ACP
, 0, lfW
.lfFaceName
, -1, lplf
->lfFaceName
,
1202 LF_FACESIZE
, NULL
, NULL
);
1206 /***********************************************************************
1207 * ImmGetCompositionFontW (IMM32.@)
1209 BOOL WINAPI
ImmGetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
1211 InputContextData
*data
= get_imc_data(hIMC
);
1213 TRACE("(%p, %p):\n", hIMC
, lplf
);
1218 *lplf
= data
->IMC
.lfFont
.W
;
1224 /* Helpers for the GetCompositionString functions */
1226 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
1227 length is always in bytes. */
1228 static INT
CopyCompStringIMEtoClient(const InputContextData
*data
, const void *src
, INT src_len
, void *dst
,
1229 INT dst_len
, BOOL unicode
)
1231 int char_size
= unicode
? sizeof(WCHAR
) : sizeof(char);
1234 if (is_himc_ime_unicode(data
) ^ unicode
)
1237 ret
= MultiByteToWideChar(CP_ACP
, 0, src
, src_len
, dst
, dst_len
/ sizeof(WCHAR
));
1239 ret
= WideCharToMultiByte(CP_ACP
, 0, src
, src_len
, dst
, dst_len
, NULL
, NULL
);
1246 ret
= min(src_len
* char_size
, dst_len
);
1247 memcpy(dst
, src
, ret
);
1250 ret
= src_len
* char_size
;
1256 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
1257 passed mode. String length is in characters, attributes are in byte arrays. */
1258 static INT
CopyCompAttrIMEtoClient(const InputContextData
*data
, const BYTE
*src
, INT src_len
, const void *comp_string
,
1259 INT str_len
, BYTE
*dst
, INT dst_len
, BOOL unicode
)
1269 string
.str
= comp_string
;
1271 if (is_himc_ime_unicode(data
) && !unicode
)
1273 rc
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
, str_len
, NULL
, 0, NULL
, NULL
);
1276 int i
, j
= 0, k
= 0;
1280 for (i
= 0; i
< str_len
; ++i
)
1284 len
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
+ i
, 1, NULL
, 0, NULL
, NULL
);
1285 for (; len
> 0; --len
)
1298 else if (!is_himc_ime_unicode(data
) && unicode
)
1300 rc
= MultiByteToWideChar(CP_ACP
, 0, string
.strA
, str_len
, NULL
, 0);
1307 for (i
= 0; i
< str_len
; ++i
)
1309 if (IsDBCSLeadByte(string
.strA
[i
]))
1322 memcpy(dst
, src
, min(src_len
, dst_len
));
1329 static INT
CopyCompClauseIMEtoClient(InputContextData
*data
, LPBYTE source
, INT slen
, LPBYTE ssource
,
1330 LPBYTE target
, INT tlen
, BOOL unicode
)
1334 if (is_himc_ime_unicode(data
) && !unicode
)
1342 tlen
/= sizeof (DWORD
);
1343 for (i
= 0; i
< tlen
; ++i
)
1345 ((DWORD
*)target
)[i
] = WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
,
1346 ((DWORD
*)source
)[i
],
1350 rc
= sizeof (DWORD
) * i
;
1355 else if (!is_himc_ime_unicode(data
) && unicode
)
1363 tlen
/= sizeof (DWORD
);
1364 for (i
= 0; i
< tlen
; ++i
)
1366 ((DWORD
*)target
)[i
] = MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
,
1367 ((DWORD
*)source
)[i
],
1370 rc
= sizeof (DWORD
) * i
;
1377 memcpy( target
, source
, min(slen
,tlen
));
1384 static INT
CopyCompOffsetIMEtoClient(InputContextData
*data
, DWORD offset
, LPBYTE ssource
, BOOL unicode
)
1388 if (is_himc_ime_unicode(data
) && !unicode
)
1390 rc
= WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
, offset
, NULL
, 0, NULL
, NULL
);
1392 else if (!is_himc_ime_unicode(data
) && unicode
)
1394 rc
= MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
, offset
, NULL
, 0);
1402 static LONG
ImmGetCompositionStringT( HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
,
1403 DWORD dwBufLen
, BOOL unicode
)
1406 InputContextData
*data
= get_imc_data(hIMC
);
1407 LPCOMPOSITIONSTRING compstr
;
1410 TRACE("(%p, 0x%x, %p, %d)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
1415 if (!data
->IMC
.hCompStr
)
1418 compdata
= ImmLockIMCC(data
->IMC
.hCompStr
);
1419 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1424 TRACE("GCS_RESULTSTR\n");
1425 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultStrOffset
, compstr
->dwResultStrLen
, lpBuf
, dwBufLen
, unicode
);
1428 TRACE("GCS_COMPSTR\n");
1429 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
, lpBuf
, dwBufLen
, unicode
);
1432 TRACE("GCS_COMPATTR\n");
1433 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompAttrOffset
, compstr
->dwCompAttrLen
,
1434 compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
,
1435 lpBuf
, dwBufLen
, unicode
);
1437 case GCS_COMPCLAUSE
:
1438 TRACE("GCS_COMPCLAUSE\n");
1439 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompClauseOffset
,compstr
->dwCompClauseLen
,
1440 compdata
+ compstr
->dwCompStrOffset
,
1441 lpBuf
, dwBufLen
, unicode
);
1443 case GCS_RESULTCLAUSE
:
1444 TRACE("GCS_RESULTCLAUSE\n");
1445 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultClauseOffset
,compstr
->dwResultClauseLen
,
1446 compdata
+ compstr
->dwResultStrOffset
,
1447 lpBuf
, dwBufLen
, unicode
);
1449 case GCS_RESULTREADSTR
:
1450 TRACE("GCS_RESULTREADSTR\n");
1451 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultReadStrOffset
, compstr
->dwResultReadStrLen
, lpBuf
, dwBufLen
, unicode
);
1453 case GCS_RESULTREADCLAUSE
:
1454 TRACE("GCS_RESULTREADCLAUSE\n");
1455 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultReadClauseOffset
,compstr
->dwResultReadClauseLen
,
1456 compdata
+ compstr
->dwResultStrOffset
,
1457 lpBuf
, dwBufLen
, unicode
);
1459 case GCS_COMPREADSTR
:
1460 TRACE("GCS_COMPREADSTR\n");
1461 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
, lpBuf
, dwBufLen
, unicode
);
1463 case GCS_COMPREADATTR
:
1464 TRACE("GCS_COMPREADATTR\n");
1465 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompReadAttrOffset
, compstr
->dwCompReadAttrLen
,
1466 compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
,
1467 lpBuf
, dwBufLen
, unicode
);
1469 case GCS_COMPREADCLAUSE
:
1470 TRACE("GCS_COMPREADCLAUSE\n");
1471 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompReadClauseOffset
,compstr
->dwCompReadClauseLen
,
1472 compdata
+ compstr
->dwCompStrOffset
,
1473 lpBuf
, dwBufLen
, unicode
);
1476 TRACE("GCS_CURSORPOS\n");
1477 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwCursorPos
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
1479 case GCS_DELTASTART
:
1480 TRACE("GCS_DELTASTART\n");
1481 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwDeltaStart
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
1484 FIXME("Unhandled index 0x%x\n",dwIndex
);
1488 ImmUnlockIMCC(data
->IMC
.hCompStr
);
1493 /***********************************************************************
1494 * ImmGetCompositionStringA (IMM32.@)
1496 LONG WINAPI
ImmGetCompositionStringA(
1497 HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
)
1499 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
1503 /***********************************************************************
1504 * ImmGetCompositionStringW (IMM32.@)
1506 LONG WINAPI
ImmGetCompositionStringW(
1507 HIMC hIMC
, DWORD dwIndex
,
1508 LPVOID lpBuf
, DWORD dwBufLen
)
1510 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
1513 /***********************************************************************
1514 * ImmGetCompositionWindow (IMM32.@)
1516 BOOL WINAPI
ImmGetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
1518 InputContextData
*data
= get_imc_data(hIMC
);
1520 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
1525 *lpCompForm
= data
->IMC
.cfCompForm
;
1529 /***********************************************************************
1530 * ImmGetContext (IMM32.@)
1533 HIMC WINAPI
ImmGetContext(HWND hWnd
)
1537 TRACE("%p\n", hWnd
);
1539 if (!IsWindow(hWnd
))
1541 SetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1545 rc
= GetPropW(hWnd
,szwWineIMCProperty
);
1548 else if (rc
== NULL
)
1549 rc
= get_default_context( hWnd
);
1553 InputContextData
*data
= rc
;
1554 data
->IMC
.hWnd
= hWnd
;
1557 TRACE("returning %p\n", rc
);
1562 /***********************************************************************
1563 * ImmGetConversionListA (IMM32.@)
1565 DWORD WINAPI
ImmGetConversionListA(
1567 LPCSTR pSrc
, LPCANDIDATELIST lpDst
,
1568 DWORD dwBufLen
, UINT uFlag
)
1570 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1571 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL
, hIMC
, debugstr_a(pSrc
), lpDst
,
1573 if (immHkl
->hIME
&& immHkl
->pImeConversionList
)
1575 if (!is_kbd_ime_unicode(immHkl
))
1576 return immHkl
->pImeConversionList(hIMC
,(LPCWSTR
)pSrc
,lpDst
,dwBufLen
,uFlag
);
1579 LPCANDIDATELIST lpwDst
;
1581 LPWSTR pwSrc
= strdupAtoW(pSrc
);
1583 len
= immHkl
->pImeConversionList(hIMC
, pwSrc
, NULL
, 0, uFlag
);
1584 lpwDst
= HeapAlloc(GetProcessHeap(), 0, len
);
1587 immHkl
->pImeConversionList(hIMC
, pwSrc
, lpwDst
, len
, uFlag
);
1588 ret
= convert_candidatelist_WtoA( lpwDst
, lpDst
, dwBufLen
);
1589 HeapFree(GetProcessHeap(), 0, lpwDst
);
1591 HeapFree(GetProcessHeap(), 0, pwSrc
);
1600 /***********************************************************************
1601 * ImmGetConversionListW (IMM32.@)
1603 DWORD WINAPI
ImmGetConversionListW(
1605 LPCWSTR pSrc
, LPCANDIDATELIST lpDst
,
1606 DWORD dwBufLen
, UINT uFlag
)
1608 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1609 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL
, hIMC
, debugstr_w(pSrc
), lpDst
,
1611 if (immHkl
->hIME
&& immHkl
->pImeConversionList
)
1613 if (is_kbd_ime_unicode(immHkl
))
1614 return immHkl
->pImeConversionList(hIMC
,pSrc
,lpDst
,dwBufLen
,uFlag
);
1617 LPCANDIDATELIST lpaDst
;
1619 LPSTR paSrc
= strdupWtoA(pSrc
);
1621 len
= immHkl
->pImeConversionList(hIMC
, (LPCWSTR
)paSrc
, NULL
, 0, uFlag
);
1622 lpaDst
= HeapAlloc(GetProcessHeap(), 0, len
);
1625 immHkl
->pImeConversionList(hIMC
, (LPCWSTR
)paSrc
, lpaDst
, len
, uFlag
);
1626 ret
= convert_candidatelist_AtoW( lpaDst
, lpDst
, dwBufLen
);
1627 HeapFree(GetProcessHeap(), 0, lpaDst
);
1629 HeapFree(GetProcessHeap(), 0, paSrc
);
1638 /***********************************************************************
1639 * ImmGetConversionStatus (IMM32.@)
1641 BOOL WINAPI
ImmGetConversionStatus(
1642 HIMC hIMC
, LPDWORD lpfdwConversion
, LPDWORD lpfdwSentence
)
1644 InputContextData
*data
= get_imc_data(hIMC
);
1646 TRACE("%p %p %p\n", hIMC
, lpfdwConversion
, lpfdwSentence
);
1651 if (lpfdwConversion
)
1652 *lpfdwConversion
= data
->IMC
.fdwConversion
;
1654 *lpfdwSentence
= data
->IMC
.fdwSentence
;
1659 static BOOL
needs_ime_window(HWND hwnd
)
1663 if (GetClassNameW(hwnd
, classW
, ARRAY_SIZE(classW
)) && !lstrcmpW(classW
, szwIME
))
1665 if (GetClassLongPtrW(hwnd
, GCL_STYLE
) & CS_IME
) return FALSE
;
1670 /***********************************************************************
1671 * __wine_register_window (IMM32.@)
1673 BOOL WINAPI
__wine_register_window(HWND hwnd
)
1676 IMMThreadData
*thread_data
;
1677 TRACE("(%p)\n", hwnd
);
1679 if (!needs_ime_window(hwnd
))
1682 thread_data
= IMM_GetThreadData(hwnd
, 0);
1686 if (thread_data
->disableIME
|| disable_ime
)
1688 TRACE("IME for this thread is disabled\n");
1689 LeaveCriticalSection(&threaddata_cs
);
1692 thread_data
->windowRefs
++;
1693 TRACE("windowRefs=%u, hwndDefault=%p\n",
1694 thread_data
->windowRefs
, thread_data
->hwndDefault
);
1696 /* Create default IME window */
1697 if (thread_data
->windowRefs
== 1)
1699 /* Do not create the window inside of a critical section */
1700 LeaveCriticalSection(&threaddata_cs
);
1701 new = CreateWindowExW( 0, szwIME
, szwDefaultIME
,
1702 WS_POPUP
| WS_DISABLED
| WS_CLIPSIBLINGS
,
1703 0, 0, 1, 1, 0, 0, 0, 0);
1704 /* thread_data is in the current thread so we can assume it's still valid */
1705 EnterCriticalSection(&threaddata_cs
);
1706 /* See if anyone beat us */
1707 if (thread_data
->hwndDefault
== NULL
)
1709 thread_data
->hwndDefault
= new;
1711 TRACE("Default is %p\n", thread_data
->hwndDefault
);
1715 LeaveCriticalSection(&threaddata_cs
);
1717 /* Clean up an unused new window outside of the critical section */
1723 /***********************************************************************
1724 * __wine_unregister_window (IMM32.@)
1726 void WINAPI
__wine_unregister_window(HWND hwnd
)
1728 HWND to_destroy
= 0;
1729 IMMThreadData
*thread_data
;
1730 TRACE("(%p)\n", hwnd
);
1732 thread_data
= IMM_GetThreadData(hwnd
, 0);
1733 if (!thread_data
) return;
1735 thread_data
->windowRefs
--;
1736 TRACE("windowRefs=%u, hwndDefault=%p\n",
1737 thread_data
->windowRefs
, thread_data
->hwndDefault
);
1739 /* Destroy default IME window */
1740 if (thread_data
->windowRefs
== 0 && thread_data
->hwndDefault
)
1742 to_destroy
= thread_data
->hwndDefault
;
1743 thread_data
->hwndDefault
= NULL
;
1745 LeaveCriticalSection(&threaddata_cs
);
1747 if (to_destroy
) DestroyWindow( to_destroy
);
1750 /***********************************************************************
1751 * ImmGetDefaultIMEWnd (IMM32.@)
1753 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
1756 IMMThreadData
* thread_data
= IMM_GetThreadData(hWnd
, 0);
1759 ret
= thread_data
->hwndDefault
;
1760 LeaveCriticalSection(&threaddata_cs
);
1761 TRACE("Default is %p\n",ret
);
1765 /***********************************************************************
1766 * ImmGetDescriptionA (IMM32.@)
1768 UINT WINAPI
ImmGetDescriptionA(
1769 HKL hKL
, LPSTR lpszDescription
, UINT uBufLen
)
1775 TRACE("ImmGetDescriptionA(%p,%p,%d)\n", hKL
, lpszDescription
, uBufLen
);
1777 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_KBDLAYOUT(hKL
))
1780 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
1781 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeDescription
, (INT
)cch
,
1782 lpszDescription
, uBufLen
, NULL
, NULL
);
1784 lpszDescription
[cch
] = 0;
1790 TRACE("%p %p %d\n", hKL
, lpszDescription
, uBufLen
);
1792 /* find out how many characters in the unicode buffer */
1793 len
= ImmGetDescriptionW( hKL
, NULL
, 0 );
1797 /* allocate a buffer of that size */
1798 buf
= HeapAlloc( GetProcessHeap(), 0, (len
+ 1) * sizeof (WCHAR
) );
1802 /* fetch the unicode buffer */
1803 len
= ImmGetDescriptionW( hKL
, buf
, len
+ 1 );
1805 /* convert it back to ASCII */
1806 len
= WideCharToMultiByte( CP_ACP
, 0, buf
, len
+ 1,
1807 lpszDescription
, uBufLen
, NULL
, NULL
);
1809 HeapFree( GetProcessHeap(), 0, buf
);
1818 /***********************************************************************
1819 * ImmGetDescriptionW (IMM32.@)
1821 UINT WINAPI
ImmGetDescriptionW(HKL hKL
, LPWSTR lpszDescription
, UINT uBufLen
)
1827 TRACE("ImmGetDescriptionW(%p, %p, %d)\n", hKL
, lpszDescription
, uBufLen
);
1829 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_KBDLAYOUT(hKL
))
1833 StringCchCopyW(lpszDescription
, uBufLen
, info
.wszImeDescription
);
1835 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
1838 static const WCHAR name
[] = { 'W','i','n','e',' ','X','I','M',0 };
1840 FIXME("(%p, %p, %d): semi stub\n", hKL
, lpszDescription
, uBufLen
);
1843 if (!uBufLen
) return lstrlenW( name
);
1844 lstrcpynW( lpszDescription
, name
, uBufLen
);
1845 return lstrlenW( lpszDescription
);
1849 /***********************************************************************
1850 * ImmGetGuideLineA (IMM32.@)
1852 DWORD WINAPI
ImmGetGuideLineA(
1853 HIMC hIMC
, DWORD dwIndex
, LPSTR lpBuf
, DWORD dwBufLen
)
1855 FIXME("(%p, %d, %s, %d): stub\n",
1856 hIMC
, dwIndex
, debugstr_a(lpBuf
), dwBufLen
1858 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1862 /***********************************************************************
1863 * ImmGetGuideLineW (IMM32.@)
1865 DWORD WINAPI
ImmGetGuideLineW(HIMC hIMC
, DWORD dwIndex
, LPWSTR lpBuf
, DWORD dwBufLen
)
1867 FIXME("(%p, %d, %s, %d): stub\n",
1868 hIMC
, dwIndex
, debugstr_w(lpBuf
), dwBufLen
1870 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1874 /***********************************************************************
1875 * ImmGetIMEFileNameA (IMM32.@)
1877 UINT WINAPI
ImmGetIMEFileNameA( HKL hKL
, LPSTR lpszFileName
, UINT uBufLen
)
1880 UINT wBufLen
= uBufLen
;
1883 if (uBufLen
&& lpszFileName
)
1884 bufW
= HeapAlloc(GetProcessHeap(),0,uBufLen
* sizeof(WCHAR
));
1885 else /* We need this to get the number of byte required */
1887 bufW
= HeapAlloc(GetProcessHeap(),0,MAX_PATH
* sizeof(WCHAR
));
1891 rc
= ImmGetIMEFileNameW(hKL
,bufW
,wBufLen
);
1895 if (uBufLen
&& lpszFileName
)
1896 rc
= WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, lpszFileName
,
1897 uBufLen
, NULL
, NULL
);
1898 else /* get the length */
1899 rc
= WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, NULL
, 0, NULL
,
1903 HeapFree(GetProcessHeap(),0,bufW
);
1907 /***********************************************************************
1908 * ImmGetIMEFileNameW (IMM32.@)
1910 UINT WINAPI
ImmGetIMEFileNameW(HKL hKL
, LPWSTR lpszFileName
, UINT uBufLen
)
1915 WCHAR regKey
[ARRAY_SIZE(szImeRegFmt
)+8];
1917 wsprintfW( regKey
, szImeRegFmt
, (ULONG_PTR
)hKL
);
1918 rc
= RegOpenKeyW( HKEY_LOCAL_MACHINE
, regKey
, &hkey
);
1919 if (rc
!= ERROR_SUCCESS
)
1926 rc
= RegGetValueW(hkey
, NULL
, szImeFileW
, RRF_RT_REG_SZ
, NULL
, NULL
, &length
);
1928 if (rc
!= ERROR_SUCCESS
)
1934 if (length
> uBufLen
* sizeof(WCHAR
) || !lpszFileName
)
1939 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1943 return length
/ sizeof(WCHAR
);
1946 RegGetValueW(hkey
, NULL
, szImeFileW
, RRF_RT_REG_SZ
, NULL
, lpszFileName
, &length
);
1950 return length
/ sizeof(WCHAR
);
1953 /***********************************************************************
1954 * ImmGetOpenStatus (IMM32.@)
1956 BOOL WINAPI
ImmGetOpenStatus(HIMC hIMC
)
1958 InputContextData
*data
= get_imc_data(hIMC
);
1964 TRACE("(%p): semi-stub\n", hIMC
);
1967 FIXME("(%p): semi-stub\n", hIMC
);
1969 return data
->IMC
.fOpen
;
1972 /***********************************************************************
1973 * ImmGetProperty (IMM32.@)
1975 DWORD WINAPI
ImmGetProperty(HKL hKL
, DWORD fdwIndex
)
1980 TRACE("(%p, %d)\n", hKL
, fdwIndex
);
1981 kbd
= IMM_GetImmHkl(hKL
);
1983 if (kbd
&& kbd
->hIME
)
1987 case IGP_PROPERTY
: rc
= kbd
->imeInfo
.fdwProperty
; break;
1988 case IGP_CONVERSION
: rc
= kbd
->imeInfo
.fdwConversionCaps
; break;
1989 case IGP_SENTENCE
: rc
= kbd
->imeInfo
.fdwSentenceCaps
; break;
1990 case IGP_SETCOMPSTR
: rc
= kbd
->imeInfo
.fdwSCSCaps
; break;
1991 case IGP_SELECT
: rc
= kbd
->imeInfo
.fdwSelectCaps
; break;
1992 case IGP_GETIMEVERSION
: rc
= IMEVER_0400
; break;
1993 case IGP_UI
: rc
= 0; break;
2000 /***********************************************************************
2001 * ImmGetRegisterWordStyleA (IMM32.@)
2003 UINT WINAPI
ImmGetRegisterWordStyleA(
2004 HKL hKL
, UINT nItem
, LPSTYLEBUFA lpStyleBuf
)
2006 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2007 TRACE("(%p, %d, %p):\n", hKL
, nItem
, lpStyleBuf
);
2008 if (immHkl
->hIME
&& immHkl
->pImeGetRegisterWordStyle
)
2010 if (!is_kbd_ime_unicode(immHkl
))
2011 return immHkl
->pImeGetRegisterWordStyle(nItem
,(LPSTYLEBUFW
)lpStyleBuf
);
2017 rc
= immHkl
->pImeGetRegisterWordStyle(nItem
,&sbw
);
2018 WideCharToMultiByte(CP_ACP
, 0, sbw
.szDescription
, -1,
2019 lpStyleBuf
->szDescription
, 32, NULL
, NULL
);
2020 lpStyleBuf
->dwStyle
= sbw
.dwStyle
;
2028 /***********************************************************************
2029 * ImmGetRegisterWordStyleW (IMM32.@)
2031 UINT WINAPI
ImmGetRegisterWordStyleW(
2032 HKL hKL
, UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
2034 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2035 TRACE("(%p, %d, %p):\n", hKL
, nItem
, lpStyleBuf
);
2036 if (immHkl
->hIME
&& immHkl
->pImeGetRegisterWordStyle
)
2038 if (is_kbd_ime_unicode(immHkl
))
2039 return immHkl
->pImeGetRegisterWordStyle(nItem
,lpStyleBuf
);
2045 rc
= immHkl
->pImeGetRegisterWordStyle(nItem
,(LPSTYLEBUFW
)&sba
);
2046 MultiByteToWideChar(CP_ACP
, 0, sba
.szDescription
, -1,
2047 lpStyleBuf
->szDescription
, 32);
2048 lpStyleBuf
->dwStyle
= sba
.dwStyle
;
2056 /***********************************************************************
2057 * ImmGetStatusWindowPos (IMM32.@)
2059 BOOL WINAPI
ImmGetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
2061 InputContextData
*data
= get_imc_data(hIMC
);
2063 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
2065 if (!data
|| !lpptPos
)
2068 *lpptPos
= data
->IMC
.ptStatusWndPos
;
2073 /***********************************************************************
2074 * ImmGetVirtualKey (IMM32.@)
2076 UINT WINAPI
ImmGetVirtualKey(HWND hWnd
)
2078 OSVERSIONINFOA version
;
2079 InputContextData
*data
= ImmGetContext( hWnd
);
2080 TRACE("%p\n", hWnd
);
2083 return data
->lastVK
;
2085 version
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
2086 GetVersionExA( &version
);
2087 switch(version
.dwPlatformId
)
2089 case VER_PLATFORM_WIN32_WINDOWS
:
2090 return VK_PROCESSKEY
;
2091 case VER_PLATFORM_WIN32_NT
:
2094 FIXME("%d not supported\n",version
.dwPlatformId
);
2095 return VK_PROCESSKEY
;
2099 /***********************************************************************
2100 * ImmInstallIMEA (IMM32.@)
2102 HKL WINAPI
ImmInstallIMEA(
2103 LPCSTR lpszIMEFileName
, LPCSTR lpszLayoutText
)
2105 LPWSTR lpszwIMEFileName
;
2106 LPWSTR lpszwLayoutText
;
2109 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName
),
2110 debugstr_a(lpszLayoutText
));
2112 lpszwIMEFileName
= strdupAtoW(lpszIMEFileName
);
2113 lpszwLayoutText
= strdupAtoW(lpszLayoutText
);
2115 hkl
= ImmInstallIMEW(lpszwIMEFileName
, lpszwLayoutText
);
2117 HeapFree(GetProcessHeap(),0,lpszwIMEFileName
);
2118 HeapFree(GetProcessHeap(),0,lpszwLayoutText
);
2122 /***********************************************************************
2123 * ImmInstallIMEW (IMM32.@)
2125 HKL WINAPI
ImmInstallIMEW(
2126 LPCWSTR lpszIMEFileName
, LPCWSTR lpszLayoutText
)
2128 INT lcid
= GetUserDefaultLCID();
2133 WCHAR regKey
[ARRAY_SIZE(szImeRegFmt
)+8];
2135 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName
),
2136 debugstr_w(lpszLayoutText
));
2138 /* Start with 2. e001 will be blank and so default to the wine internal IME */
2141 while (count
< 0xfff)
2143 DWORD disposition
= 0;
2145 hkl
= (HKL
)MAKELPARAM( lcid
, 0xe000 | count
);
2146 wsprintfW( regKey
, szImeRegFmt
, (ULONG_PTR
)hkl
);
2148 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, regKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hkey
, &disposition
);
2149 if (rc
== ERROR_SUCCESS
&& disposition
== REG_CREATED_NEW_KEY
)
2151 else if (rc
== ERROR_SUCCESS
)
2159 WARN("Unable to find slot to install IME\n");
2163 if (rc
== ERROR_SUCCESS
)
2165 rc
= RegSetValueExW(hkey
, szImeFileW
, 0, REG_SZ
, (const BYTE
*)lpszIMEFileName
,
2166 (lstrlenW(lpszIMEFileName
) + 1) * sizeof(WCHAR
));
2167 if (rc
== ERROR_SUCCESS
)
2168 rc
= RegSetValueExW(hkey
, szLayoutTextW
, 0, REG_SZ
, (const BYTE
*)lpszLayoutText
,
2169 (lstrlenW(lpszLayoutText
) + 1) * sizeof(WCHAR
));
2175 WARN("Unable to set IME registry values\n");
2180 /***********************************************************************
2181 * ImmIsIME (IMM32.@)
2183 BOOL WINAPI
ImmIsIME(HKL hKL
)
2186 TRACE("(%p):\n", hKL
);
2187 ptr
= IMM_GetImmHkl(hKL
);
2188 return (ptr
&& ptr
->hIME
);
2191 /***********************************************************************
2192 * ImmIsUIMessageA (IMM32.@)
2194 BOOL WINAPI
ImmIsUIMessageA(
2195 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2197 TRACE("(%p, %x, %ld, %ld)\n", hWndIME
, msg
, wParam
, lParam
);
2198 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
2199 (msg
== WM_IME_SETCONTEXT
) ||
2200 (msg
== WM_IME_NOTIFY
) ||
2201 (msg
== WM_IME_COMPOSITIONFULL
) ||
2202 (msg
== WM_IME_SELECT
) ||
2203 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
2206 SendMessageA(hWndIME
, msg
, wParam
, lParam
);
2213 /***********************************************************************
2214 * ImmIsUIMessageW (IMM32.@)
2216 BOOL WINAPI
ImmIsUIMessageW(
2217 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2219 TRACE("(%p, %x, %ld, %ld)\n", hWndIME
, msg
, wParam
, lParam
);
2220 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
2221 (msg
== WM_IME_SETCONTEXT
) ||
2222 (msg
== WM_IME_NOTIFY
) ||
2223 (msg
== WM_IME_COMPOSITIONFULL
) ||
2224 (msg
== WM_IME_SELECT
) ||
2225 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
2228 SendMessageW(hWndIME
, msg
, wParam
, lParam
);
2235 /***********************************************************************
2236 * ImmNotifyIME (IMM32.@)
2238 BOOL WINAPI
ImmNotifyIME(
2239 HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
2241 InputContextData
*data
= get_imc_data(hIMC
);
2243 TRACE("(%p, %d, %d, %d)\n",
2244 hIMC
, dwAction
, dwIndex
, dwValue
);
2248 SetLastError(ERROR_SUCCESS
);
2252 if (!data
|| ! data
->immKbd
->pNotifyIME
)
2257 return data
->immKbd
->pNotifyIME(hIMC
,dwAction
,dwIndex
,dwValue
);
2260 /***********************************************************************
2261 * ImmRegisterWordA (IMM32.@)
2263 BOOL WINAPI
ImmRegisterWordA(
2264 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszRegister
)
2266 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2267 TRACE("(%p, %s, %d, %s):\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
2268 debugstr_a(lpszRegister
));
2269 if (immHkl
->hIME
&& immHkl
->pImeRegisterWord
)
2271 if (!is_kbd_ime_unicode(immHkl
))
2272 return immHkl
->pImeRegisterWord((LPCWSTR
)lpszReading
,dwStyle
,
2273 (LPCWSTR
)lpszRegister
);
2276 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
2277 LPWSTR lpszwRegister
= strdupAtoW(lpszRegister
);
2280 rc
= immHkl
->pImeRegisterWord(lpszwReading
,dwStyle
,lpszwRegister
);
2281 HeapFree(GetProcessHeap(),0,lpszwReading
);
2282 HeapFree(GetProcessHeap(),0,lpszwRegister
);
2290 /***********************************************************************
2291 * ImmRegisterWordW (IMM32.@)
2293 BOOL WINAPI
ImmRegisterWordW(
2294 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszRegister
)
2296 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2297 TRACE("(%p, %s, %d, %s):\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
2298 debugstr_w(lpszRegister
));
2299 if (immHkl
->hIME
&& immHkl
->pImeRegisterWord
)
2301 if (is_kbd_ime_unicode(immHkl
))
2302 return immHkl
->pImeRegisterWord(lpszReading
,dwStyle
,lpszRegister
);
2305 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
2306 LPSTR lpszaRegister
= strdupWtoA(lpszRegister
);
2309 rc
= immHkl
->pImeRegisterWord((LPCWSTR
)lpszaReading
,dwStyle
,
2310 (LPCWSTR
)lpszaRegister
);
2311 HeapFree(GetProcessHeap(),0,lpszaReading
);
2312 HeapFree(GetProcessHeap(),0,lpszaRegister
);
2320 /***********************************************************************
2321 * ImmReleaseContext (IMM32.@)
2323 BOOL WINAPI
ImmReleaseContext(HWND hWnd
, HIMC hIMC
)
2325 static BOOL shown
= FALSE
;
2328 FIXME("(%p, %p): stub\n", hWnd
, hIMC
);
2334 /***********************************************************************
2335 * ImmRequestMessageA(IMM32.@)
2337 LRESULT WINAPI
ImmRequestMessageA(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
2339 InputContextData
*data
= get_imc_data(hIMC
);
2341 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
2343 if (data
) return SendMessageA(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
2345 SetLastError(ERROR_INVALID_HANDLE
);
2349 /***********************************************************************
2350 * ImmRequestMessageW(IMM32.@)
2352 LRESULT WINAPI
ImmRequestMessageW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
2354 InputContextData
*data
= get_imc_data(hIMC
);
2356 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
2358 if (data
) return SendMessageW(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
2360 SetLastError(ERROR_INVALID_HANDLE
);
2364 /***********************************************************************
2365 * ImmSetCandidateWindow (IMM32.@)
2367 BOOL WINAPI
ImmSetCandidateWindow(
2368 HIMC hIMC
, LPCANDIDATEFORM lpCandidate
)
2370 InputContextData
*data
= get_imc_data(hIMC
);
2372 TRACE("(%p, %p)\n", hIMC
, lpCandidate
);
2374 if (!data
|| !lpCandidate
)
2377 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2380 TRACE("\t%x, %x, %s, %s\n",
2381 lpCandidate
->dwIndex
, lpCandidate
->dwStyle
,
2382 wine_dbgstr_point(&lpCandidate
->ptCurrentPos
),
2383 wine_dbgstr_rect(&lpCandidate
->rcArea
));
2385 if (lpCandidate
->dwIndex
>= ARRAY_SIZE(data
->IMC
.cfCandForm
))
2388 data
->IMC
.cfCandForm
[lpCandidate
->dwIndex
] = *lpCandidate
;
2389 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCANDIDATEPOS
);
2390 ImmInternalSendIMENotify(data
, IMN_SETCANDIDATEPOS
, 1 << lpCandidate
->dwIndex
);
2395 /***********************************************************************
2396 * ImmSetCompositionFontA (IMM32.@)
2398 BOOL WINAPI
ImmSetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
2400 InputContextData
*data
= get_imc_data(hIMC
);
2401 TRACE("(%p, %p)\n", hIMC
, lplf
);
2405 SetLastError(ERROR_INVALID_HANDLE
);
2409 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2412 memcpy(&data
->IMC
.lfFont
.W
,lplf
,sizeof(LOGFONTA
));
2413 MultiByteToWideChar(CP_ACP
, 0, lplf
->lfFaceName
, -1, data
->IMC
.lfFont
.W
.lfFaceName
,
2415 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
);
2416 ImmInternalSendIMENotify(data
, IMN_SETCOMPOSITIONFONT
, 0);
2421 /***********************************************************************
2422 * ImmSetCompositionFontW (IMM32.@)
2424 BOOL WINAPI
ImmSetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
2426 InputContextData
*data
= get_imc_data(hIMC
);
2427 TRACE("(%p, %p)\n", hIMC
, lplf
);
2431 SetLastError(ERROR_INVALID_HANDLE
);
2435 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2438 data
->IMC
.lfFont
.W
= *lplf
;
2439 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
);
2440 ImmInternalSendIMENotify(data
, IMN_SETCOMPOSITIONFONT
, 0);
2445 /***********************************************************************
2446 * ImmSetCompositionStringA (IMM32.@)
2448 BOOL WINAPI
ImmSetCompositionStringA(
2449 HIMC hIMC
, DWORD dwIndex
,
2450 LPCVOID lpComp
, DWORD dwCompLen
,
2451 LPCVOID lpRead
, DWORD dwReadLen
)
2455 WCHAR
*CompBuffer
= NULL
;
2456 WCHAR
*ReadBuffer
= NULL
;
2458 InputContextData
*data
= get_imc_data(hIMC
);
2460 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2461 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2466 if (!(dwIndex
== SCS_SETSTR
||
2467 dwIndex
== SCS_CHANGEATTR
||
2468 dwIndex
== SCS_CHANGECLAUSE
||
2469 dwIndex
== SCS_SETRECONVERTSTRING
||
2470 dwIndex
== SCS_QUERYRECONVERTSTRING
))
2473 if (!is_himc_ime_unicode(data
))
2474 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
2475 dwCompLen
, lpRead
, dwReadLen
);
2477 comp_len
= MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0);
2480 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
* sizeof(WCHAR
));
2481 MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
);
2484 read_len
= MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0);
2487 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
* sizeof(WCHAR
));
2488 MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
);
2491 rc
= ImmSetCompositionStringW(hIMC
, dwIndex
, CompBuffer
, comp_len
,
2492 ReadBuffer
, read_len
);
2494 HeapFree(GetProcessHeap(), 0, CompBuffer
);
2495 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
2500 /***********************************************************************
2501 * ImmSetCompositionStringW (IMM32.@)
2503 BOOL WINAPI
ImmSetCompositionStringW(
2504 HIMC hIMC
, DWORD dwIndex
,
2505 LPCVOID lpComp
, DWORD dwCompLen
,
2506 LPCVOID lpRead
, DWORD dwReadLen
)
2510 CHAR
*CompBuffer
= NULL
;
2511 CHAR
*ReadBuffer
= NULL
;
2513 InputContextData
*data
= get_imc_data(hIMC
);
2515 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2516 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2521 if (!(dwIndex
== SCS_SETSTR
||
2522 dwIndex
== SCS_CHANGEATTR
||
2523 dwIndex
== SCS_CHANGECLAUSE
||
2524 dwIndex
== SCS_SETRECONVERTSTRING
||
2525 dwIndex
== SCS_QUERYRECONVERTSTRING
))
2528 if (is_himc_ime_unicode(data
))
2529 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
2530 dwCompLen
, lpRead
, dwReadLen
);
2532 comp_len
= WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0, NULL
,
2536 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
);
2537 WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
,
2541 read_len
= WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0, NULL
,
2545 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
);
2546 WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
,
2550 rc
= ImmSetCompositionStringA(hIMC
, dwIndex
, CompBuffer
, comp_len
,
2551 ReadBuffer
, read_len
);
2553 HeapFree(GetProcessHeap(), 0, CompBuffer
);
2554 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
2559 /***********************************************************************
2560 * ImmSetCompositionWindow (IMM32.@)
2562 BOOL WINAPI
ImmSetCompositionWindow(
2563 HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
2565 BOOL reshow
= FALSE
;
2566 InputContextData
*data
= get_imc_data(hIMC
);
2568 TRACE("(%p, %p)\n", hIMC
, lpCompForm
);
2570 TRACE("\t%x, %s, %s\n", lpCompForm
->dwStyle
,
2571 wine_dbgstr_point(&lpCompForm
->ptCurrentPos
),
2572 wine_dbgstr_rect(&lpCompForm
->rcArea
));
2576 SetLastError(ERROR_INVALID_HANDLE
);
2580 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2583 data
->IMC
.cfCompForm
= *lpCompForm
;
2585 if (IsWindowVisible(data
->immKbd
->UIWnd
))
2588 ShowWindow(data
->immKbd
->UIWnd
,SW_HIDE
);
2591 /* FIXME: this is a partial stub */
2594 ShowWindow(data
->immKbd
->UIWnd
,SW_SHOWNOACTIVATE
);
2596 ImmInternalSendIMENotify(data
, IMN_SETCOMPOSITIONWINDOW
, 0);
2600 /***********************************************************************
2601 * ImmSetConversionStatus (IMM32.@)
2603 BOOL WINAPI
ImmSetConversionStatus(
2604 HIMC hIMC
, DWORD fdwConversion
, DWORD fdwSentence
)
2606 DWORD oldConversion
, oldSentence
;
2607 InputContextData
*data
= get_imc_data(hIMC
);
2609 TRACE("%p %d %d\n", hIMC
, fdwConversion
, fdwSentence
);
2613 SetLastError(ERROR_INVALID_HANDLE
);
2617 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2620 if ( fdwConversion
!= data
->IMC
.fdwConversion
)
2622 oldConversion
= data
->IMC
.fdwConversion
;
2623 data
->IMC
.fdwConversion
= fdwConversion
;
2624 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, oldConversion
, IMC_SETCONVERSIONMODE
);
2625 ImmInternalSendIMENotify(data
, IMN_SETCONVERSIONMODE
, 0);
2627 if ( fdwSentence
!= data
->IMC
.fdwSentence
)
2629 oldSentence
= data
->IMC
.fdwSentence
;
2630 data
->IMC
.fdwSentence
= fdwSentence
;
2631 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, oldSentence
, IMC_SETSENTENCEMODE
);
2632 ImmInternalSendIMENotify(data
, IMN_SETSENTENCEMODE
, 0);
2638 /***********************************************************************
2639 * ImmSetOpenStatus (IMM32.@)
2641 BOOL WINAPI
ImmSetOpenStatus(HIMC hIMC
, BOOL fOpen
)
2643 InputContextData
*data
= get_imc_data(hIMC
);
2645 TRACE("%p %d\n", hIMC
, fOpen
);
2649 SetLastError(ERROR_INVALID_HANDLE
);
2653 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2656 if (data
->immKbd
->UIWnd
== NULL
)
2658 /* create the ime window */
2659 data
->immKbd
->UIWnd
= CreateWindowExW( WS_EX_TOOLWINDOW
,
2660 data
->immKbd
->imeClassName
, NULL
, WS_POPUP
, 0, 0, 1, 1, 0,
2661 0, data
->immKbd
->hIME
, 0);
2662 SetWindowLongPtrW(data
->immKbd
->UIWnd
, IMMGWL_IMC
, (LONG_PTR
)data
);
2665 SetWindowLongPtrW(data
->immKbd
->UIWnd
, IMMGWL_IMC
, (LONG_PTR
)data
);
2667 if (!fOpen
!= !data
->IMC
.fOpen
)
2669 data
->IMC
.fOpen
= fOpen
;
2670 ImmNotifyIME( hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETOPENSTATUS
);
2671 ImmInternalSendIMENotify(data
, IMN_SETOPENSTATUS
, 0);
2677 /***********************************************************************
2678 * ImmSetStatusWindowPos (IMM32.@)
2680 BOOL WINAPI
ImmSetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
2682 InputContextData
*data
= get_imc_data(hIMC
);
2684 TRACE("(%p, %p)\n", hIMC
, lpptPos
);
2686 if (!data
|| !lpptPos
)
2688 SetLastError(ERROR_INVALID_HANDLE
);
2692 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2695 TRACE("\t%s\n", wine_dbgstr_point(lpptPos
));
2697 data
->IMC
.ptStatusWndPos
= *lpptPos
;
2698 ImmNotifyIME( hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETSTATUSWINDOWPOS
);
2699 ImmInternalSendIMENotify(data
, IMN_SETSTATUSWINDOWPOS
, 0);
2704 /***********************************************************************
2705 * ImmCreateSoftKeyboard(IMM32.@)
2707 HWND WINAPI
ImmCreateSoftKeyboard(UINT uType
, UINT hOwner
, int x
, int y
)
2709 FIXME("(%d, %d, %d, %d): stub\n", uType
, hOwner
, x
, y
);
2710 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2714 /***********************************************************************
2715 * ImmDestroySoftKeyboard(IMM32.@)
2717 BOOL WINAPI
ImmDestroySoftKeyboard(HWND hSoftWnd
)
2720 TRACE("(%p)\n", hSoftWnd
);
2721 return DestroyWindow(hSoftWnd
);
2723 FIXME("(%p): stub\n", hSoftWnd
);
2724 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2729 /***********************************************************************
2730 * ImmShowSoftKeyboard(IMM32.@)
2732 BOOL WINAPI
ImmShowSoftKeyboard(HWND hSoftWnd
, int nCmdShow
)
2735 TRACE("(%p, %d)\n", hSoftWnd
, nCmdShow
);
2737 return ShowWindow(hSoftWnd
, nCmdShow
);
2739 FIXME("(%p, %d): stub\n", hSoftWnd
, nCmdShow
);
2740 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2745 /***********************************************************************
2746 * ImmSimulateHotKey (IMM32.@)
2748 BOOL WINAPI
ImmSimulateHotKey(HWND hWnd
, DWORD dwHotKeyID
)
2750 FIXME("(%p, %d): stub\n", hWnd
, dwHotKeyID
);
2751 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2755 /***********************************************************************
2756 * ImmUnregisterWordA (IMM32.@)
2758 BOOL WINAPI
ImmUnregisterWordA(
2759 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszUnregister
)
2761 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2762 TRACE("(%p, %s, %d, %s):\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
2763 debugstr_a(lpszUnregister
));
2764 if (immHkl
->hIME
&& immHkl
->pImeUnregisterWord
)
2766 if (!is_kbd_ime_unicode(immHkl
))
2767 return immHkl
->pImeUnregisterWord((LPCWSTR
)lpszReading
,dwStyle
,
2768 (LPCWSTR
)lpszUnregister
);
2771 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
2772 LPWSTR lpszwUnregister
= strdupAtoW(lpszUnregister
);
2775 rc
= immHkl
->pImeUnregisterWord(lpszwReading
,dwStyle
,lpszwUnregister
);
2776 HeapFree(GetProcessHeap(),0,lpszwReading
);
2777 HeapFree(GetProcessHeap(),0,lpszwUnregister
);
2785 /***********************************************************************
2786 * ImmUnregisterWordW (IMM32.@)
2788 BOOL WINAPI
ImmUnregisterWordW(
2789 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszUnregister
)
2791 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2792 TRACE("(%p, %s, %d, %s):\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
2793 debugstr_w(lpszUnregister
));
2794 if (immHkl
->hIME
&& immHkl
->pImeUnregisterWord
)
2796 if (is_kbd_ime_unicode(immHkl
))
2797 return immHkl
->pImeUnregisterWord(lpszReading
,dwStyle
,lpszUnregister
);
2800 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
2801 LPSTR lpszaUnregister
= strdupWtoA(lpszUnregister
);
2804 rc
= immHkl
->pImeUnregisterWord((LPCWSTR
)lpszaReading
,dwStyle
,
2805 (LPCWSTR
)lpszaUnregister
);
2806 HeapFree(GetProcessHeap(),0,lpszaReading
);
2807 HeapFree(GetProcessHeap(),0,lpszaUnregister
);
2815 /***********************************************************************
2816 * ImmGetImeMenuItemsA (IMM32.@)
2818 DWORD WINAPI
ImmGetImeMenuItemsA( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
2819 LPIMEMENUITEMINFOA lpImeParentMenu
, LPIMEMENUITEMINFOA lpImeMenu
,
2822 InputContextData
*data
= get_imc_data(hIMC
);
2823 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
2824 lpImeParentMenu
, lpImeMenu
, dwSize
);
2828 SetLastError(ERROR_INVALID_HANDLE
);
2832 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
2834 if (!is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
2835 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
2836 (IMEMENUITEMINFOW
*)lpImeParentMenu
,
2837 (IMEMENUITEMINFOW
*)lpImeMenu
, dwSize
);
2840 IMEMENUITEMINFOW lpImeParentMenuW
;
2841 IMEMENUITEMINFOW
*lpImeMenuW
, *parent
= NULL
;
2844 if (lpImeParentMenu
)
2845 parent
= &lpImeParentMenuW
;
2848 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOA
);
2849 dwSize
= count
* sizeof(IMEMENUITEMINFOW
);
2850 lpImeMenuW
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
2855 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
2856 parent
, lpImeMenuW
, dwSize
);
2858 if (lpImeParentMenu
)
2860 memcpy(lpImeParentMenu
,&lpImeParentMenuW
,sizeof(IMEMENUITEMINFOA
));
2861 lpImeParentMenu
->hbmpItem
= lpImeParentMenuW
.hbmpItem
;
2862 WideCharToMultiByte(CP_ACP
, 0, lpImeParentMenuW
.szString
,
2863 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
,
2866 if (lpImeMenu
&& rc
)
2869 for (i
= 0; i
< rc
; i
++)
2871 memcpy(&lpImeMenu
[i
],&lpImeMenuW
[1],sizeof(IMEMENUITEMINFOA
));
2872 lpImeMenu
[i
].hbmpItem
= lpImeMenuW
[i
].hbmpItem
;
2873 WideCharToMultiByte(CP_ACP
, 0, lpImeMenuW
[i
].szString
,
2874 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
,
2878 HeapFree(GetProcessHeap(),0,lpImeMenuW
);
2886 /***********************************************************************
2887 * ImmGetImeMenuItemsW (IMM32.@)
2889 DWORD WINAPI
ImmGetImeMenuItemsW( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
2890 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
2893 InputContextData
*data
= get_imc_data(hIMC
);
2894 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
2895 lpImeParentMenu
, lpImeMenu
, dwSize
);
2899 SetLastError(ERROR_INVALID_HANDLE
);
2903 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
2905 if (is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
2906 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
2907 lpImeParentMenu
, lpImeMenu
, dwSize
);
2910 IMEMENUITEMINFOA lpImeParentMenuA
;
2911 IMEMENUITEMINFOA
*lpImeMenuA
, *parent
= NULL
;
2914 if (lpImeParentMenu
)
2915 parent
= &lpImeParentMenuA
;
2918 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOW
);
2919 dwSize
= count
* sizeof(IMEMENUITEMINFOA
);
2920 lpImeMenuA
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
2925 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
2926 (IMEMENUITEMINFOW
*)parent
,
2927 (IMEMENUITEMINFOW
*)lpImeMenuA
, dwSize
);
2929 if (lpImeParentMenu
)
2931 memcpy(lpImeParentMenu
,&lpImeParentMenuA
,sizeof(IMEMENUITEMINFOA
));
2932 lpImeParentMenu
->hbmpItem
= lpImeParentMenuA
.hbmpItem
;
2933 MultiByteToWideChar(CP_ACP
, 0, lpImeParentMenuA
.szString
,
2934 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
);
2936 if (lpImeMenu
&& rc
)
2939 for (i
= 0; i
< rc
; i
++)
2941 memcpy(&lpImeMenu
[i
],&lpImeMenuA
[1],sizeof(IMEMENUITEMINFOA
));
2942 lpImeMenu
[i
].hbmpItem
= lpImeMenuA
[i
].hbmpItem
;
2943 MultiByteToWideChar(CP_ACP
, 0, lpImeMenuA
[i
].szString
,
2944 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
);
2947 HeapFree(GetProcessHeap(),0,lpImeMenuA
);
2955 /***********************************************************************
2956 * ImmLockIMC(IMM32.@)
2958 LPINPUTCONTEXT WINAPI
ImmLockIMC(HIMC hIMC
)
2960 InputContextData
*data
= get_imc_data(hIMC
);
2968 /***********************************************************************
2969 * ImmUnlockIMC(IMM32.@)
2971 BOOL WINAPI
ImmUnlockIMC(HIMC hIMC
)
2973 InputContextData
*data
= get_imc_data(hIMC
);
2982 /***********************************************************************
2983 * ImmGetIMCLockCount(IMM32.@)
2985 DWORD WINAPI
ImmGetIMCLockCount(HIMC hIMC
)
2987 InputContextData
*data
= get_imc_data(hIMC
);
2990 return data
->dwLock
;
2993 /***********************************************************************
2994 * ImmCreateIMCC(IMM32.@)
2996 HIMCC WINAPI
ImmCreateIMCC(DWORD size
)
2998 return GlobalAlloc(GMEM_ZEROINIT
| GMEM_MOVEABLE
, size
);
3001 /***********************************************************************
3002 * ImmDestroyIMCC(IMM32.@)
3004 HIMCC WINAPI
ImmDestroyIMCC(HIMCC block
)
3006 return GlobalFree(block
);
3009 /***********************************************************************
3010 * ImmLockIMCC(IMM32.@)
3012 LPVOID WINAPI
ImmLockIMCC(HIMCC imcc
)
3014 return GlobalLock(imcc
);
3017 /***********************************************************************
3018 * ImmUnlockIMCC(IMM32.@)
3020 BOOL WINAPI
ImmUnlockIMCC(HIMCC imcc
)
3022 return GlobalUnlock(imcc
);
3025 /***********************************************************************
3026 * ImmGetIMCCLockCount(IMM32.@)
3028 DWORD WINAPI
ImmGetIMCCLockCount(HIMCC imcc
)
3030 return GlobalFlags(imcc
) & GMEM_LOCKCOUNT
;
3033 /***********************************************************************
3034 * ImmReSizeIMCC(IMM32.@)
3036 HIMCC WINAPI
ImmReSizeIMCC(HIMCC imcc
, DWORD size
)
3038 return GlobalReAlloc(imcc
, size
, GMEM_ZEROINIT
| GMEM_MOVEABLE
);
3041 /***********************************************************************
3042 * ImmGetIMCCSize(IMM32.@)
3044 DWORD WINAPI
ImmGetIMCCSize(HIMCC imcc
)
3046 return GlobalSize(imcc
);
3049 /***********************************************************************
3050 * ImmGenerateMessage(IMM32.@)
3052 BOOL WINAPI
ImmGenerateMessage(HIMC hIMC
)
3054 InputContextData
*data
= get_imc_data(hIMC
);
3058 SetLastError(ERROR_INVALID_HANDLE
);
3062 TRACE("%i messages queued\n",data
->IMC
.dwNumMsgBuf
);
3063 if (data
->IMC
.dwNumMsgBuf
> 0)
3065 LPTRANSMSG lpTransMsg
;
3067 DWORD i
, dwNumMsgBuf
;
3069 /* We are going to detach our hMsgBuff so that if processing messages
3070 generates new messages they go into a new buffer */
3071 hMsgBuf
= data
->IMC
.hMsgBuf
;
3072 dwNumMsgBuf
= data
->IMC
.dwNumMsgBuf
;
3074 data
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
3075 data
->IMC
.dwNumMsgBuf
= 0;
3077 lpTransMsg
= ImmLockIMCC(hMsgBuf
);
3078 for (i
= 0; i
< dwNumMsgBuf
; i
++)
3079 ImmInternalSendIMEMessage(data
, lpTransMsg
[i
].message
, lpTransMsg
[i
].wParam
, lpTransMsg
[i
].lParam
);
3081 ImmUnlockIMCC(hMsgBuf
);
3082 ImmDestroyIMCC(hMsgBuf
);
3088 /***********************************************************************
3089 * ImmTranslateMessage(IMM32.@)
3090 * ( Undocumented, call internally and from user32.dll )
3092 BOOL WINAPI
ImmTranslateMessage(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lKeyData
)
3094 InputContextData
*data
;
3095 HIMC imc
= ImmGetContext(hwnd
);
3101 static const DWORD list_count
= 10;
3103 TRACE("%p %x %x %x\n",hwnd
, msg
, (UINT
)wParam
, (UINT
)lKeyData
);
3110 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeToAsciiEx
)
3113 GetKeyboardState(state
);
3114 scancode
= lKeyData
>> 0x10 & 0xff;
3116 list
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, list_count
* sizeof(TRANSMSG
) + sizeof(DWORD
));
3117 ((DWORD
*)list
)[0] = list_count
;
3119 if (data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_KBD_CHAR_FIRST
)
3123 if (!is_himc_ime_unicode(data
))
3124 ToAscii(data
->lastVK
, scancode
, state
, &chr
, 0);
3126 ToUnicodeEx(data
->lastVK
, scancode
, state
, &chr
, 1, 0, GetKeyboardLayout(0));
3127 uVirtKey
= MAKELONG(data
->lastVK
,chr
);
3130 uVirtKey
= data
->lastVK
;
3132 msg_count
= data
->immKbd
->pImeToAsciiEx(uVirtKey
, scancode
, state
, list
, 0, imc
);
3133 TRACE("%i messages generated\n",msg_count
);
3134 if (msg_count
&& msg_count
<= list_count
)
3137 LPTRANSMSG msgs
= (LPTRANSMSG
)((LPBYTE
)list
+ sizeof(DWORD
));
3139 for (i
= 0; i
< msg_count
; i
++)
3140 ImmInternalPostIMEMessage(data
, msgs
[i
].message
, msgs
[i
].wParam
, msgs
[i
].lParam
);
3142 else if (msg_count
> list_count
)
3143 ImmGenerateMessage(imc
);
3145 HeapFree(GetProcessHeap(),0,list
);
3147 data
->lastVK
= VK_PROCESSKEY
;
3149 return (msg_count
> 0);
3152 /***********************************************************************
3153 * ImmProcessKey(IMM32.@)
3154 * ( Undocumented, called from user32.dll )
3156 BOOL WINAPI
ImmProcessKey(HWND hwnd
, HKL hKL
, UINT vKey
, LPARAM lKeyData
, DWORD unknown
)
3158 InputContextData
*data
;
3159 HIMC imc
= ImmGetContext(hwnd
);
3162 TRACE("%p %p %x %x %x\n",hwnd
, hKL
, vKey
, (UINT
)lKeyData
, unknown
);
3169 /* Make sure we are inputting to the correct keyboard */
3170 if (data
->immKbd
->hkl
!= hKL
)
3172 ImmHkl
*new_hkl
= IMM_GetImmHkl(hKL
);
3175 data
->immKbd
->pImeSelect(imc
, FALSE
);
3176 data
->immKbd
->uSelected
--;
3177 data
->immKbd
= new_hkl
;
3178 data
->immKbd
->pImeSelect(imc
, TRUE
);
3179 data
->immKbd
->uSelected
++;
3185 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeProcessKey
)
3188 GetKeyboardState(state
);
3189 if (data
->immKbd
->pImeProcessKey(imc
, vKey
, lKeyData
, state
))
3191 data
->lastVK
= vKey
;
3195 data
->lastVK
= VK_PROCESSKEY
;
3199 /***********************************************************************
3200 * ImmDisableTextFrameService(IMM32.@)
3202 BOOL WINAPI
ImmDisableTextFrameService(DWORD idThread
)
3208 /***********************************************************************
3209 * ImmEnumInputContext(IMM32.@)
3212 BOOL WINAPI
ImmEnumInputContext(DWORD idThread
, IMCENUMPROC lpfn
, LPARAM lParam
)
3218 /***********************************************************************
3219 * ImmGetHotKey(IMM32.@)
3224 ImmGetHotKey(IN DWORD dwHotKey
,
3225 OUT LPUINT lpuModifiers
,
3229 TRACE("%lx, %p, %p, %p\n", dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
3230 if (lpuModifiers
&& lpuVKey
)
3231 return NtUserGetImeHotKey(dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
3235 BOOL WINAPI
ImmGetHotKey(DWORD hotkey
, UINT
*modifiers
, UINT
*key
, HKL hkl
)
3237 FIXME("%x, %p, %p, %p: stub\n", hotkey
, modifiers
, key
, hkl
);
3242 /***********************************************************************
3243 * ImmDisableLegacyIME(IMM32.@)
3245 BOOL WINAPI
ImmDisableLegacyIME(void)
3252 /***********************************************************************
3253 * ImmSetActiveContext(IMM32.@)
3255 BOOL WINAPI
ImmSetActiveContext(HWND hwnd
, HIMC hIMC
, BOOL fFlag
)
3257 FIXME("(%p, %p, %d): stub\n", hwnd
, hIMC
, fFlag
);
3261 /***********************************************************************
3262 * ImmSetActiveContextConsoleIME(IMM32.@)
3264 BOOL WINAPI
ImmSetActiveContextConsoleIME(HWND hwnd
, BOOL fFlag
)
3267 TRACE("(%p, %d)\n", hwnd
, fFlag
);
3269 hIMC
= ImmGetContext(hwnd
);
3271 return ImmSetActiveContext(hwnd
, hIMC
, fFlag
);
3275 /***********************************************************************
3276 * ImmRegisterClient(IMM32.@)
3277 * ( Undocumented, called from user32.dll )
3279 BOOL WINAPI
ImmRegisterClient(PVOID ptr
, /* FIXME: should point to SHAREDINFO structure */
3286 /***********************************************************************
3287 * ImmGetImeInfoEx (IMM32.@)
3290 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx
,
3291 IMEINFOEXCLASS SearchType
,
3296 case ImeInfoExKeyboardLayout
:
3297 pImeInfoEx
->hkl
= *(LPHKL
)pvSearchKey
;
3298 if (!IS_IME_HKL(pImeInfoEx
->hkl
))
3302 case ImeInfoExImeFileName
:
3303 lstrcpynW(pImeInfoEx
->wszImeFile
, (LPWSTR
)pvSearchKey
,
3304 ARRAY_SIZE(pImeInfoEx
->wszImeFile
));
3310 return NtUserGetImeInfoEx(pImeInfoEx
, SearchType
);