4 * Copyright 1998 Patrik Stridvall
5 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WIN32_NO_STATUS
31 #include <wine/debug.h>
36 #include <wine/list.h>
38 #include <ndk/umtypes.h>
39 #include <ndk/pstypes.h>
40 #include <ndk/rtlfuncs.h>
41 #include "../../../win32ss/include/ntuser.h"
42 #include "../../../win32ss/include/ntwin32.h"
43 #include <imm32_undoc.h>
46 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
48 #define IMM_INIT_MAGIC 0x19650412
49 #define IMM_INVALID_CANDFORM ULONG_MAX
51 #define REGKEY_KEYBOARD_LAYOUTS \
52 L"System\\CurrentControlSet\\Control\\Keyboard Layouts"
54 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM"
56 RTL_CRITICAL_SECTION g_csImeDpi
;
57 PIMEDPI g_pImeDpiList
= NULL
;
58 PSERVERINFO g_psi
= NULL
;
60 BOOL WINAPI
User32InitializeImmEntryTable(DWORD
);
62 static DWORD APIENTRY
Imm32QueryInputContext(HIMC hIMC
, DWORD dwUnknown2
)
64 return NtUserQueryInputContext(hIMC
, dwUnknown2
);
67 static DWORD APIENTRY
Imm32NotifyIMEStatus(HWND hwnd
, HIMC hIMC
, DWORD dwConversion
)
69 return NtUserNotifyIMEStatus(hwnd
, hIMC
, dwConversion
);
72 static VOID APIENTRY
Imm32FreeImeDpi(PIMEDPI pImeDpi
, BOOL bDestroy
)
74 if (pImeDpi
->hInst
== NULL
)
77 pImeDpi
->ImeDestroy(0);
78 FreeLibrary(pImeDpi
->hInst
);
79 pImeDpi
->hInst
= NULL
;
83 Imm32NotifyAction(HIMC hIMC
, HWND hwnd
, DWORD dwAction
, DWORD_PTR dwIndex
, DWORD_PTR dwValue
,
84 DWORD_PTR dwCommand
, DWORD_PTR dwData
)
92 dwLayout
= Imm32QueryInputContext(hIMC
, 1);
95 /* find keyboard layout and lock it */
96 hKL
= GetKeyboardLayout(dwLayout
);
97 pImeDpi
= ImmLockImeDpi(hKL
);
101 pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
103 ImmUnlockImeDpi(pImeDpi
); /* unlock */
108 if (hwnd
&& dwCommand
)
109 SendMessageW(hwnd
, WM_IME_NOTIFY
, dwCommand
, dwData
);
114 HKL WINAPI
ImmLoadLayout(HKL hKL
, PIMEINFOEX pImeInfoEx
)
117 UNICODE_STRING UnicodeString
;
118 HKEY hLayoutKey
= NULL
, hLayoutsKey
= NULL
;
121 WCHAR szLayout
[MAX_PATH
];
123 TRACE("ImmLoadLayout(%p, %p)\n", hKL
, pImeInfoEx
);
125 if (IS_IME_HKL(hKL
) ||
126 !g_psi
|| (g_psi
->dwSRVIFlags
& SRVINFO_METRICS
) == 0 ||
127 ((PW32CLIENTINFO
)NtCurrentTeb()->Win32ClientInfo
)->W32ClientInfo
[0] & 2)
129 UnicodeString
.Buffer
= szLayout
;
130 UnicodeString
.MaximumLength
= sizeof(szLayout
);
131 Status
= RtlIntegerToUnicodeString((DWORD_PTR
)hKL
, 16, &UnicodeString
);
132 if (!NT_SUCCESS(Status
))
135 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_KEYBOARD_LAYOUTS
, &hLayoutsKey
);
139 error
= RegOpenKeyW(hLayoutsKey
, szLayout
, &hLayoutKey
);
143 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_IMM
, &hLayoutKey
);
148 ERR("RegOpenKeyW error: 0x%08lX\n", error
);
153 cbData
= sizeof(pImeInfoEx
->wszImeFile
);
154 error
= RegQueryValueExW(hLayoutKey
, L
"Ime File", 0, 0,
155 (LPBYTE
)pImeInfoEx
->wszImeFile
, &cbData
);
160 RegCloseKey(hLayoutKey
);
162 RegCloseKey(hLayoutsKey
);
166 typedef struct _tagImmHkl
{
171 WCHAR imeClassName
[17]; /* 16 character max */
175 /* Function Pointers */
176 BOOL (WINAPI
*pImeInquire
)(IMEINFO
*, WCHAR
*, const WCHAR
*);
177 BOOL (WINAPI
*pImeConfigure
)(HKL
, HWND
, DWORD
, void *);
178 BOOL (WINAPI
*pImeDestroy
)(UINT
);
179 LRESULT (WINAPI
*pImeEscape
)(HIMC
, UINT
, void *);
180 BOOL (WINAPI
*pImeSelect
)(HIMC
, BOOL
);
181 BOOL (WINAPI
*pImeSetActiveContext
)(HIMC
, BOOL
);
182 UINT (WINAPI
*pImeToAsciiEx
)(UINT
, UINT
, const BYTE
*, DWORD
*, UINT
, HIMC
);
183 BOOL (WINAPI
*pNotifyIME
)(HIMC
, DWORD
, DWORD
, DWORD
);
184 BOOL (WINAPI
*pImeRegisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
185 BOOL (WINAPI
*pImeUnregisterWord
)(const WCHAR
*, DWORD
, const WCHAR
*);
186 UINT (WINAPI
*pImeEnumRegisterWord
)(REGISTERWORDENUMPROCW
, const WCHAR
*, DWORD
, const WCHAR
*, void *);
187 BOOL (WINAPI
*pImeSetCompositionString
)(HIMC
, DWORD
, const void *, DWORD
, const void *, DWORD
);
188 DWORD (WINAPI
*pImeConversionList
)(HIMC
, const WCHAR
*, CANDIDATELIST
*, DWORD
, UINT
);
189 BOOL (WINAPI
*pImeProcessKey
)(HIMC
, UINT
, LPARAM
, const BYTE
*);
190 UINT (WINAPI
*pImeGetRegisterWordStyle
)(UINT
, STYLEBUFW
*);
191 DWORD (WINAPI
*pImeGetImeMenuItems
)(HIMC
, DWORD
, DWORD
, IMEMENUITEMINFOW
*, IMEMENUITEMINFOW
*, DWORD
);
194 typedef struct tagInputContextData
206 #define WINE_IMC_VALID_MAGIC 0x56434D49
208 typedef struct _tagTRANSMSG
{
212 } TRANSMSG
, *LPTRANSMSG
;
214 typedef struct _tagIMMThreadData
{
223 static struct list ImmHklList
= LIST_INIT(ImmHklList
);
224 static struct list ImmThreadDataList
= LIST_INIT(ImmThreadDataList
);
226 static const WCHAR szwWineIMCProperty
[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
228 static const WCHAR szImeFileW
[] = {'I','m','e',' ','F','i','l','e',0};
229 static const WCHAR szLayoutTextW
[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
230 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};
232 static const WCHAR szwIME
[] = {'I','M','E',0};
233 static const WCHAR szwDefaultIME
[] = {'D','e','f','a','u','l','t',' ','I','M','E',0};
235 static CRITICAL_SECTION threaddata_cs
;
236 static CRITICAL_SECTION_DEBUG critsect_debug
=
238 0, 0, &threaddata_cs
,
239 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
240 0, 0, { (DWORD_PTR
)(__FILE__
": threaddata_cs") }
242 static CRITICAL_SECTION threaddata_cs
= { &critsect_debug
, -1, 0, 0, 0, 0 };
243 static BOOL disable_ime
;
245 static inline BOOL
is_himc_ime_unicode(const InputContextData
*data
)
247 return !!(data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
250 static inline BOOL
is_kbd_ime_unicode(const ImmHkl
*hkl
)
252 return !!(hkl
->imeInfo
.fdwProperty
& IME_PROP_UNICODE
);
255 static BOOL
IMM_DestroyContext(HIMC hIMC
);
256 static InputContextData
* get_imc_data(HIMC hIMC
);
258 static inline WCHAR
*strdupAtoW( const char *str
)
263 DWORD len
= MultiByteToWideChar( CP_ACP
, 0, str
, -1, NULL
, 0 );
264 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) )))
265 MultiByteToWideChar( CP_ACP
, 0, str
, -1, ret
, len
);
270 static inline CHAR
*strdupWtoA( const WCHAR
*str
)
275 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, str
, -1, NULL
, 0, NULL
, NULL
);
276 if ((ret
= HeapAlloc( GetProcessHeap(), 0, len
)))
277 WideCharToMultiByte( CP_ACP
, 0, str
, -1, ret
, len
, NULL
, NULL
);
282 static DWORD
convert_candidatelist_WtoA(
283 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
287 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
288 if ( lpDst
&& dwBufLen
> 0 )
291 lpDst
->dwOffset
[0] = ret
;
294 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
296 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
298 if ( lpDst
&& dwBufLen
> 0 )
300 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
302 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1,
303 (LPSTR
)dest
, dwBufLen
, NULL
, NULL
);
305 if ( i
+ 1 < lpSrc
->dwCount
)
306 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(char);
307 dwBufLen
-= len
* sizeof(char);
310 len
= WideCharToMultiByte(CP_ACP
, 0, (LPCWSTR
)src
, -1, NULL
, 0, NULL
, NULL
);
312 ret
+= len
* sizeof(char);
321 static DWORD
convert_candidatelist_AtoW(
322 LPCANDIDATELIST lpSrc
, LPCANDIDATELIST lpDst
, DWORD dwBufLen
)
326 ret
= FIELD_OFFSET( CANDIDATELIST
, dwOffset
[lpSrc
->dwCount
] );
327 if ( lpDst
&& dwBufLen
> 0 )
330 lpDst
->dwOffset
[0] = ret
;
333 for ( i
= 0; i
< lpSrc
->dwCount
; i
++)
335 LPBYTE src
= (LPBYTE
)lpSrc
+ lpSrc
->dwOffset
[i
];
337 if ( lpDst
&& dwBufLen
> 0 )
339 LPBYTE dest
= (LPBYTE
)lpDst
+ lpDst
->dwOffset
[i
];
341 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1,
342 (LPWSTR
)dest
, dwBufLen
);
344 if ( i
+ 1 < lpSrc
->dwCount
)
345 lpDst
->dwOffset
[i
+1] = lpDst
->dwOffset
[i
] + len
* sizeof(WCHAR
);
346 dwBufLen
-= len
* sizeof(WCHAR
);
349 len
= MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)src
, -1, NULL
, 0);
351 ret
+= len
* sizeof(WCHAR
);
360 static IMMThreadData
*IMM_GetThreadData(HWND hwnd
, DWORD thread
)
367 if (!(thread
= GetWindowThreadProcessId(hwnd
, &process
))) return NULL
;
368 if (process
!= GetCurrentProcessId()) return NULL
;
372 HANDLE h
= OpenThread(THREAD_QUERY_INFORMATION
, FALSE
, thread
);
374 process
= GetProcessIdOfThread(h
);
376 if (process
!= GetCurrentProcessId()) return NULL
;
379 thread
= GetCurrentThreadId();
381 EnterCriticalSection(&threaddata_cs
);
382 LIST_FOR_EACH_ENTRY(data
, &ImmThreadDataList
, IMMThreadData
, entry
)
383 if (data
->threadID
== thread
) return data
;
385 data
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*data
));
386 data
->threadID
= thread
;
387 list_add_head(&ImmThreadDataList
,&data
->entry
);
388 TRACE("Thread Data Created (%x)\n",thread
);
392 static BOOL
IMM_IsDefaultContext(HIMC imc
)
394 InputContextData
*data
= get_imc_data(imc
);
399 return data
->threadDefault
;
402 static void IMM_FreeThreadData(void)
406 EnterCriticalSection(&threaddata_cs
);
407 LIST_FOR_EACH_ENTRY(data
, &ImmThreadDataList
, IMMThreadData
, entry
)
409 if (data
->threadID
== GetCurrentThreadId())
411 list_remove(&data
->entry
);
412 LeaveCriticalSection(&threaddata_cs
);
413 IMM_DestroyContext(data
->defaultContext
);
414 HeapFree(GetProcessHeap(),0,data
);
415 TRACE("Thread Data Destroyed\n");
419 LeaveCriticalSection(&threaddata_cs
);
422 static HMODULE
load_graphics_driver(void)
424 static const WCHAR display_device_guid_propW
[] = {
425 '_','_','w','i','n','e','_','d','i','s','p','l','a','y','_',
426 'd','e','v','i','c','e','_','g','u','i','d',0 };
427 static const WCHAR key_pathW
[] = {
428 'S','y','s','t','e','m','\\',
429 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
430 'C','o','n','t','r','o','l','\\',
431 'V','i','d','e','o','\\','{',0};
432 static const WCHAR displayW
[] = {'}','\\','0','0','0','0',0};
433 static const WCHAR driverW
[] = {'G','r','a','p','h','i','c','s','D','r','i','v','e','r',0};
438 WCHAR path
[MAX_PATH
];
439 WCHAR key
[ARRAY_SIZE( key_pathW
) + ARRAY_SIZE( displayW
) + 40];
440 UINT guid_atom
= HandleToULong( GetPropW( GetDesktopWindow(), display_device_guid_propW
));
442 if (!guid_atom
) return 0;
443 memcpy( key
, key_pathW
, sizeof(key_pathW
) );
444 if (!GlobalGetAtomNameW( guid_atom
, key
+ lstrlenW(key
), 40 )) return 0;
445 lstrcatW( key
, displayW
);
446 if (RegOpenKeyW( HKEY_LOCAL_MACHINE
, key
, &hkey
)) return 0;
448 if (!RegQueryValueExW( hkey
, driverW
, NULL
, NULL
, (BYTE
*)path
, &size
)) ret
= LoadLibraryW( path
);
450 TRACE( "%s %p\n", debugstr_w(path
), ret
);
454 /* ImmHkl loading and freeing */
455 #define LOAD_FUNCPTR(f) if((ptr->p##f = (LPVOID)GetProcAddress(ptr->hIME, #f)) == NULL){WARN("Can't find function %s in ime\n", #f);}
456 static ImmHkl
*IMM_GetImmHkl(HKL hkl
)
459 WCHAR filename
[MAX_PATH
];
461 TRACE("Seeking ime for keyboard %p\n",hkl
);
463 LIST_FOR_EACH_ENTRY(ptr
, &ImmHklList
, ImmHkl
, entry
)
468 /* not found... create it */
470 ptr
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ImmHkl
));
473 if (ImmGetIMEFileNameW(hkl
, filename
, MAX_PATH
)) ptr
->hIME
= LoadLibraryW(filename
);
474 if (!ptr
->hIME
) ptr
->hIME
= load_graphics_driver();
477 LOAD_FUNCPTR(ImeInquire
);
478 if (!ptr
->pImeInquire
|| !ptr
->pImeInquire(&ptr
->imeInfo
, ptr
->imeClassName
, NULL
))
480 FreeLibrary(ptr
->hIME
);
485 LOAD_FUNCPTR(ImeDestroy
);
486 LOAD_FUNCPTR(ImeSelect
);
487 if (!ptr
->pImeSelect
|| !ptr
->pImeDestroy
)
489 FreeLibrary(ptr
->hIME
);
494 LOAD_FUNCPTR(ImeConfigure
);
495 LOAD_FUNCPTR(ImeEscape
);
496 LOAD_FUNCPTR(ImeSetActiveContext
);
497 LOAD_FUNCPTR(ImeToAsciiEx
);
498 LOAD_FUNCPTR(NotifyIME
);
499 LOAD_FUNCPTR(ImeRegisterWord
);
500 LOAD_FUNCPTR(ImeUnregisterWord
);
501 LOAD_FUNCPTR(ImeEnumRegisterWord
);
502 LOAD_FUNCPTR(ImeSetCompositionString
);
503 LOAD_FUNCPTR(ImeConversionList
);
504 LOAD_FUNCPTR(ImeProcessKey
);
505 LOAD_FUNCPTR(ImeGetRegisterWordStyle
);
506 LOAD_FUNCPTR(ImeGetImeMenuItems
);
507 /* make sure our classname is WCHAR */
508 if (!is_kbd_ime_unicode(ptr
))
511 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ptr
->imeClassName
,
513 lstrcpyW(ptr
->imeClassName
, bufW
);
518 list_add_head(&ImmHklList
,&ptr
->entry
);
524 HWND WINAPI
__wine_get_ui_window(HKL hkl
)
526 ImmHkl
*immHkl
= IMM_GetImmHkl(hkl
);
527 return immHkl
->UIWnd
;
530 static void IMM_FreeAllImmHkl(void)
532 ImmHkl
*ptr
,*cursor2
;
534 LIST_FOR_EACH_ENTRY_SAFE(ptr
, cursor2
, &ImmHklList
, ImmHkl
, entry
)
536 list_remove(&ptr
->entry
);
540 FreeLibrary(ptr
->hIME
);
543 DestroyWindow(ptr
->UIWnd
);
544 HeapFree(GetProcessHeap(),0,ptr
);
548 BOOL WINAPI
DllMain(HINSTANCE hInstDLL
, DWORD fdwReason
, LPVOID lpReserved
)
550 TRACE("%p, %x, %p\n",hInstDLL
,fdwReason
,lpReserved
);
553 case DLL_PROCESS_ATTACH
:
554 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC
))
559 case DLL_THREAD_ATTACH
:
561 case DLL_THREAD_DETACH
:
562 IMM_FreeThreadData();
564 case DLL_PROCESS_DETACH
:
565 if (lpReserved
) break;
566 IMM_FreeThreadData();
573 /* for posting messages as the IME */
574 static void ImmInternalPostIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
576 HWND target
= GetFocus();
578 PostMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
580 PostMessageW(target
, msg
, wParam
, lParam
);
583 /* for sending messages as the IME */
584 static void ImmInternalSendIMEMessage(InputContextData
*data
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
586 HWND target
= GetFocus();
588 SendMessageW(data
->IMC
.hWnd
,msg
,wParam
,lParam
);
590 SendMessageW(target
, msg
, wParam
, lParam
);
593 static LRESULT
ImmInternalSendIMENotify(InputContextData
*data
, WPARAM notify
, LPARAM lParam
)
597 target
= data
->IMC
.hWnd
;
598 if (!target
) target
= GetFocus();
601 return SendMessageW(target
, WM_IME_NOTIFY
, notify
, lParam
);
606 static HIMCC
ImmCreateBlankCompStr(void)
609 LPCOMPOSITIONSTRING ptr
;
610 rc
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
611 ptr
= ImmLockIMCC(rc
);
612 memset(ptr
,0,sizeof(COMPOSITIONSTRING
));
613 ptr
->dwSize
= sizeof(COMPOSITIONSTRING
);
618 static InputContextData
* get_imc_data(HIMC hIMC
)
620 InputContextData
*data
= hIMC
;
625 if(IsBadReadPtr(data
, sizeof(InputContextData
)) || data
->magic
!= WINE_IMC_VALID_MAGIC
)
627 SetLastError(ERROR_INVALID_HANDLE
);
633 static HIMC
get_default_context( HWND hwnd
)
636 IMMThreadData
* thread_data
= IMM_GetThreadData( hwnd
, 0 );
638 if (!thread_data
) return 0;
640 if (thread_data
->defaultContext
)
642 ret
= thread_data
->defaultContext
;
643 LeaveCriticalSection(&threaddata_cs
);
647 /* can't create a default context in another thread */
648 if (thread_data
->threadID
!= GetCurrentThreadId())
650 LeaveCriticalSection(&threaddata_cs
);
654 LeaveCriticalSection(&threaddata_cs
);
656 ret
= ImmCreateContext();
658 ((InputContextData
*)ret
)->threadDefault
= TRUE
;
660 /* thread_data is in the current thread so we can assume it's still valid */
661 EnterCriticalSection(&threaddata_cs
);
663 if (thread_data
->defaultContext
) /* someone beat us */
665 IMM_DestroyContext( ret
);
666 ret
= thread_data
->defaultContext
;
668 else thread_data
->defaultContext
= ret
;
670 LeaveCriticalSection(&threaddata_cs
);
674 static BOOL
IMM_IsCrossThreadAccess(HWND hWnd
, HIMC hIMC
)
676 InputContextData
*data
;
680 DWORD thread
= GetWindowThreadProcessId(hWnd
, NULL
);
681 if (thread
!= GetCurrentThreadId()) return TRUE
;
683 data
= get_imc_data(hIMC
);
684 if (data
&& data
->threadID
!= GetCurrentThreadId())
690 /***********************************************************************
691 * ImmAssociateContext (IMM32.@)
693 HIMC WINAPI
ImmAssociateContext(HWND hWnd
, HIMC hIMC
)
696 InputContextData
*data
= get_imc_data(hIMC
);
698 TRACE("(%p, %p):\n", hWnd
, hIMC
);
704 * If already associated just return
706 if (hIMC
&& data
->IMC
.hWnd
== hWnd
)
709 if (hIMC
&& IMM_IsCrossThreadAccess(hWnd
, hIMC
))
714 HIMC defaultContext
= get_default_context( hWnd
);
715 old
= RemovePropW(hWnd
,szwWineIMCProperty
);
718 old
= defaultContext
;
719 else if (old
== (HIMC
)-1)
722 if (hIMC
!= defaultContext
)
724 if (hIMC
== NULL
) /* Meaning disable imm for that window*/
725 SetPropW(hWnd
,szwWineIMCProperty
,(HANDLE
)-1);
727 SetPropW(hWnd
,szwWineIMCProperty
,hIMC
);
732 InputContextData
*old_data
= old
;
733 if (old_data
->IMC
.hWnd
== hWnd
)
734 old_data
->IMC
.hWnd
= NULL
;
741 if(GetActiveWindow() == data
->IMC
.hWnd
)
743 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, FALSE
, ISC_SHOWUIALL
);
744 data
->IMC
.hWnd
= hWnd
;
745 SendMessageW(data
->IMC
.hWnd
, WM_IME_SETCONTEXT
, TRUE
, ISC_SHOWUIALL
);
753 * Helper function for ImmAssociateContextEx
755 static BOOL CALLBACK
_ImmAssociateContextExEnumProc(HWND hwnd
, LPARAM lParam
)
757 HIMC hImc
= (HIMC
)lParam
;
758 ImmAssociateContext(hwnd
,hImc
);
762 /***********************************************************************
763 * ImmAssociateContextEx (IMM32.@)
765 BOOL WINAPI
ImmAssociateContextEx(HWND hWnd
, HIMC hIMC
, DWORD dwFlags
)
767 TRACE("(%p, %p, 0x%x):\n", hWnd
, hIMC
, dwFlags
);
775 ImmAssociateContext(hWnd
,hIMC
);
779 HIMC defaultContext
= get_default_context( hWnd
);
780 if (!defaultContext
) return FALSE
;
781 ImmAssociateContext(hWnd
,defaultContext
);
784 case IACE_IGNORENOCONTEXT
:
785 if (GetPropW(hWnd
,szwWineIMCProperty
))
786 ImmAssociateContext(hWnd
,hIMC
);
789 EnumChildWindows(hWnd
,_ImmAssociateContextExEnumProc
,(LPARAM
)hIMC
);
792 FIXME("Unknown dwFlags 0x%x\n",dwFlags
);
797 /***********************************************************************
798 * ImmConfigureIMEA (IMM32.@)
800 BOOL WINAPI
ImmConfigureIMEA(
801 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
803 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
805 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
807 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
810 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
812 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| !is_kbd_ime_unicode(immHkl
))
813 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
817 REGISTERWORDA
*rwa
= lpData
;
820 rww
.lpReading
= strdupAtoW(rwa
->lpReading
);
821 rww
.lpWord
= strdupAtoW(rwa
->lpWord
);
822 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rww
);
823 HeapFree(GetProcessHeap(),0,rww
.lpReading
);
824 HeapFree(GetProcessHeap(),0,rww
.lpWord
);
832 /***********************************************************************
833 * ImmConfigureIMEW (IMM32.@)
835 BOOL WINAPI
ImmConfigureIMEW(
836 HKL hKL
, HWND hWnd
, DWORD dwMode
, LPVOID lpData
)
838 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
840 TRACE("(%p, %p, %d, %p):\n", hKL
, hWnd
, dwMode
, lpData
);
842 if (dwMode
== IME_CONFIG_REGISTERWORD
&& !lpData
)
845 if (immHkl
->hIME
&& immHkl
->pImeConfigure
)
847 if (dwMode
!= IME_CONFIG_REGISTERWORD
|| is_kbd_ime_unicode(immHkl
))
848 return immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,lpData
);
851 REGISTERWORDW
*rww
= lpData
;
855 rwa
.lpReading
= strdupWtoA(rww
->lpReading
);
856 rwa
.lpWord
= strdupWtoA(rww
->lpWord
);
857 rc
= immHkl
->pImeConfigure(hKL
,hWnd
,dwMode
,&rwa
);
858 HeapFree(GetProcessHeap(),0,rwa
.lpReading
);
859 HeapFree(GetProcessHeap(),0,rwa
.lpWord
);
867 /***********************************************************************
868 * ImmCreateContext (IMM32.@)
870 HIMC WINAPI
ImmCreateContext(void)
872 InputContextData
*new_context
;
877 new_context
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(InputContextData
));
880 new_context
->immKbd
= IMM_GetImmHkl(GetKeyboardLayout(0));
882 if (!new_context
->immKbd
->hIME
)
884 TRACE("IME dll could not be loaded\n");
885 HeapFree(GetProcessHeap(),0,new_context
);
889 /* the HIMCCs are never NULL */
890 new_context
->IMC
.hCompStr
= ImmCreateBlankCompStr();
891 new_context
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
892 new_context
->IMC
.hCandInfo
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
893 ci
= ImmLockIMCC(new_context
->IMC
.hCandInfo
);
894 memset(ci
,0,sizeof(CANDIDATEINFO
));
895 ci
->dwSize
= sizeof(CANDIDATEINFO
);
896 ImmUnlockIMCC(new_context
->IMC
.hCandInfo
);
897 new_context
->IMC
.hGuideLine
= ImmCreateIMCC(sizeof(GUIDELINE
));
898 gl
= ImmLockIMCC(new_context
->IMC
.hGuideLine
);
899 memset(gl
,0,sizeof(GUIDELINE
));
900 gl
->dwSize
= sizeof(GUIDELINE
);
901 ImmUnlockIMCC(new_context
->IMC
.hGuideLine
);
903 for (i
= 0; i
< ARRAY_SIZE(new_context
->IMC
.cfCandForm
); i
++)
904 new_context
->IMC
.cfCandForm
[i
].dwIndex
= ~0u;
906 /* Initialize the IME Private */
907 new_context
->IMC
.hPrivate
= ImmCreateIMCC(new_context
->immKbd
->imeInfo
.dwPrivateDataSize
);
909 new_context
->IMC
.fdwConversion
= new_context
->immKbd
->imeInfo
.fdwConversionCaps
;
910 new_context
->IMC
.fdwSentence
= new_context
->immKbd
->imeInfo
.fdwSentenceCaps
;
912 if (!new_context
->immKbd
->pImeSelect(new_context
, TRUE
))
914 TRACE("Selection of IME failed\n");
915 IMM_DestroyContext(new_context
);
918 new_context
->threadID
= GetCurrentThreadId();
919 SendMessageW(GetFocus(), WM_IME_SELECT
, TRUE
, (LPARAM
)new_context
->immKbd
);
921 new_context
->immKbd
->uSelected
++;
922 TRACE("Created context %p\n",new_context
);
924 new_context
->magic
= WINE_IMC_VALID_MAGIC
;
928 static BOOL
IMM_DestroyContext(HIMC hIMC
)
930 InputContextData
*data
= get_imc_data(hIMC
);
932 TRACE("Destroying %p\n",hIMC
);
937 data
->immKbd
->uSelected
--;
938 data
->immKbd
->pImeSelect(hIMC
, FALSE
);
939 SendMessageW(data
->IMC
.hWnd
, WM_IME_SELECT
, FALSE
, (LPARAM
)data
->immKbd
);
941 ImmDestroyIMCC(data
->IMC
.hCompStr
);
942 ImmDestroyIMCC(data
->IMC
.hCandInfo
);
943 ImmDestroyIMCC(data
->IMC
.hGuideLine
);
944 ImmDestroyIMCC(data
->IMC
.hPrivate
);
945 ImmDestroyIMCC(data
->IMC
.hMsgBuf
);
948 HeapFree(GetProcessHeap(),0,data
);
953 /***********************************************************************
954 * ImmDestroyContext (IMM32.@)
956 BOOL WINAPI
ImmDestroyContext(HIMC hIMC
)
958 if (!IMM_IsDefaultContext(hIMC
) && !IMM_IsCrossThreadAccess(NULL
, hIMC
))
959 return IMM_DestroyContext(hIMC
);
964 /***********************************************************************
965 * ImmDisableIME (IMM32.@)
967 BOOL WINAPI
ImmDisableIME(DWORD dwThreadId
)
969 return NtUserDisableThreadIme(dwThreadId
);
972 /***********************************************************************
973 * ImmEnumRegisterWordA (IMM32.@)
975 UINT WINAPI
ImmEnumRegisterWordA(
976 HKL hKL
, REGISTERWORDENUMPROCA lpfnEnumProc
,
977 LPCSTR lpszReading
, DWORD dwStyle
,
978 LPCSTR lpszRegister
, LPVOID lpData
)
980 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
981 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL
, lpfnEnumProc
,
982 debugstr_a(lpszReading
), dwStyle
, debugstr_a(lpszRegister
), lpData
);
983 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
985 if (!is_kbd_ime_unicode(immHkl
))
986 return immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
987 (LPCWSTR
)lpszReading
, dwStyle
, (LPCWSTR
)lpszRegister
, lpData
);
990 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
991 LPWSTR lpszwRegister
= strdupAtoW(lpszRegister
);
994 rc
= immHkl
->pImeEnumRegisterWord((REGISTERWORDENUMPROCW
)lpfnEnumProc
,
995 lpszwReading
, dwStyle
, lpszwRegister
,
998 HeapFree(GetProcessHeap(),0,lpszwReading
);
999 HeapFree(GetProcessHeap(),0,lpszwRegister
);
1007 /***********************************************************************
1008 * ImmEnumRegisterWordW (IMM32.@)
1010 UINT WINAPI
ImmEnumRegisterWordW(
1011 HKL hKL
, REGISTERWORDENUMPROCW lpfnEnumProc
,
1012 LPCWSTR lpszReading
, DWORD dwStyle
,
1013 LPCWSTR lpszRegister
, LPVOID lpData
)
1015 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1016 TRACE("(%p, %p, %s, %d, %s, %p):\n", hKL
, lpfnEnumProc
,
1017 debugstr_w(lpszReading
), dwStyle
, debugstr_w(lpszRegister
), lpData
);
1018 if (immHkl
->hIME
&& immHkl
->pImeEnumRegisterWord
)
1020 if (is_kbd_ime_unicode(immHkl
))
1021 return immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, lpszReading
, dwStyle
,
1022 lpszRegister
, lpData
);
1025 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
1026 LPSTR lpszaRegister
= strdupWtoA(lpszRegister
);
1029 rc
= immHkl
->pImeEnumRegisterWord(lpfnEnumProc
, (LPCWSTR
)lpszaReading
,
1030 dwStyle
, (LPCWSTR
)lpszaRegister
, lpData
);
1032 HeapFree(GetProcessHeap(),0,lpszaReading
);
1033 HeapFree(GetProcessHeap(),0,lpszaRegister
);
1041 static inline BOOL
EscapeRequiresWA(UINT uEscape
)
1043 if (uEscape
== IME_ESC_GET_EUDC_DICTIONARY
||
1044 uEscape
== IME_ESC_SET_EUDC_DICTIONARY
||
1045 uEscape
== IME_ESC_IME_NAME
||
1046 uEscape
== IME_ESC_GETHELPFILENAME
)
1051 /***********************************************************************
1052 * ImmEscapeA (IMM32.@)
1054 LRESULT WINAPI
ImmEscapeA(
1056 UINT uEscape
, LPVOID lpData
)
1058 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1059 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1061 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1063 if (!EscapeRequiresWA(uEscape
) || !is_kbd_ime_unicode(immHkl
))
1064 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1067 WCHAR buffer
[81]; /* largest required buffer should be 80 */
1069 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1071 MultiByteToWideChar(CP_ACP
,0,lpData
,-1,buffer
,81);
1072 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1076 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1077 WideCharToMultiByte(CP_ACP
,0,buffer
,-1,lpData
,80, NULL
, NULL
);
1086 /***********************************************************************
1087 * ImmEscapeW (IMM32.@)
1089 LRESULT WINAPI
ImmEscapeW(
1091 UINT uEscape
, LPVOID lpData
)
1093 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
1094 TRACE("(%p, %p, %d, %p):\n", hKL
, hIMC
, uEscape
, lpData
);
1096 if (immHkl
->hIME
&& immHkl
->pImeEscape
)
1098 if (!EscapeRequiresWA(uEscape
) || is_kbd_ime_unicode(immHkl
))
1099 return immHkl
->pImeEscape(hIMC
,uEscape
,lpData
);
1102 CHAR buffer
[81]; /* largest required buffer should be 80 */
1104 if (uEscape
== IME_ESC_SET_EUDC_DICTIONARY
)
1106 WideCharToMultiByte(CP_ACP
,0,lpData
,-1,buffer
,81, NULL
, NULL
);
1107 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1111 rc
= immHkl
->pImeEscape(hIMC
,uEscape
,buffer
);
1112 MultiByteToWideChar(CP_ACP
,0,buffer
,-1,lpData
,80);
1121 #define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
1123 HANDLE g_hImm32Heap
= NULL
;
1124 DWORD g_dwImm32Flags
= 0;
1126 /* flags for g_dwImm32Flags */
1127 #define IMM32_FLAG_UNKNOWN 0x4
1128 #define IMM32_FLAG_CICERO_ENABLED 0x20
1130 LPVOID APIENTRY
Imm32HeapAlloc(DWORD dwFlags
, DWORD dwBytes
)
1134 g_hImm32Heap
= RtlGetProcessHeap();
1135 if (g_hImm32Heap
== NULL
)
1138 return HeapAlloc(g_hImm32Heap
, dwFlags
, dwBytes
);
1141 static DWORD_PTR APIENTRY
1142 Imm32GetThreadState(DWORD Routine
)
1144 return NtUserGetThreadState(Routine
);
1147 static DWORD_PTR APIENTRY
Imm32QueryWindow(HWND hWnd
, DWORD Index
)
1149 return NtUserQueryWindow(hWnd
, Index
);
1152 static DWORD APIENTRY
1153 Imm32UpdateInputContext(HIMC hIMC
, DWORD Unknown1
, PCLIENTIMC pClientImc
)
1155 return NtUserUpdateInputContext(hIMC
, Unknown1
, pClientImc
);
1158 static PCLIENTIMC APIENTRY
Imm32GetClientImcCache(void)
1160 // FIXME: Do something properly here
1164 static NTSTATUS APIENTRY
1165 Imm32BuildHimcList(DWORD dwThreadId
, DWORD dwCount
, HIMC
*phList
, LPDWORD pdwCount
)
1167 return NtUserBuildHimcList(dwThreadId
, dwCount
, phList
, pdwCount
);
1170 static DWORD APIENTRY
Imm32AllocAndBuildHimcList(DWORD dwThreadId
, HIMC
**pphList
)
1172 #define INITIAL_COUNT 0x40
1173 #define MAX_RETRY 10
1175 DWORD dwCount
= INITIAL_COUNT
, cRetry
= 0;
1178 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
1179 if (phNewList
== NULL
)
1182 Status
= Imm32BuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
1183 while (Status
== STATUS_BUFFER_TOO_SMALL
)
1185 HeapFree(g_hImm32Heap
, 0, phNewList
);
1186 if (cRetry
++ >= MAX_RETRY
)
1189 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
1190 if (phNewList
== NULL
)
1193 Status
= Imm32BuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
1196 if (NT_ERROR(Status
) || !dwCount
)
1198 HeapFree(g_hImm32Heap
, 0, phNewList
);
1202 *pphList
= phNewList
;
1204 #undef INITIAL_COUNT
1208 PCLIENTIMC WINAPI
ImmLockClientImc(HIMC hImc
)
1210 PCLIENTIMC pClientImc
;
1212 TRACE("ImmLockClientImc(%p)\n", hImc
);
1217 pClientImc
= Imm32GetClientImcCache();
1220 pClientImc
= Imm32HeapAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
1224 RtlInitializeCriticalSection(&pClientImc
->cs
);
1225 pClientImc
->unknown
= Imm32GetThreadState(THREADSTATE_UNKNOWN13
);
1227 if (!Imm32UpdateInputContext(hImc
, 0, pClientImc
))
1229 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1233 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN2
;
1237 if (pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN1
)
1241 InterlockedIncrement(&pClientImc
->cLockObj
);
1245 VOID WINAPI
ImmUnlockClientImc(PCLIENTIMC pClientImc
)
1250 TRACE("ImmUnlockClientImc(%p)\n", pClientImc
);
1252 cLocks
= InterlockedDecrement(&pClientImc
->cLockObj
);
1253 if (cLocks
!= 0 || !(pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN1
))
1256 hImc
= pClientImc
->hImc
;
1260 RtlDeleteCriticalSection(&pClientImc
->cs
);
1261 HeapFree(g_hImm32Heap
, 0, pClientImc
);
1264 static DWORD APIENTRY
1265 CandidateListWideToAnsi(const CANDIDATELIST
*pWideCL
, LPCANDIDATELIST pAnsiCL
, DWORD dwBufLen
,
1269 DWORD dwSize
, dwIndex
, cbGot
, cbLeft
;
1274 /* calculate total ansi size */
1275 if (pWideCL
->dwCount
> 0)
1277 dwSize
= sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1278 for (dwIndex
= 0; dwIndex
< pWideCL
->dwCount
; ++dwIndex
)
1280 pbWide
= (const BYTE
*)pWideCL
+ pWideCL
->dwOffset
[dwIndex
];
1281 cbGot
= WideCharToMultiByte(uCodePage
, 0, (LPCWSTR
)pbWide
, -1, NULL
, 0,
1282 NULL
, &bUsedDefault
);
1288 dwSize
= sizeof(CANDIDATELIST
);
1291 dwSize
= ROUNDUP4(dwSize
);
1294 if (dwBufLen
< dwSize
)
1298 pAnsiCL
->dwSize
= dwBufLen
;
1299 pAnsiCL
->dwStyle
= pWideCL
->dwStyle
;
1300 pAnsiCL
->dwCount
= pWideCL
->dwCount
;
1301 pAnsiCL
->dwSelection
= pWideCL
->dwSelection
;
1302 pAnsiCL
->dwPageStart
= pWideCL
->dwPageStart
;
1303 pAnsiCL
->dwPageSize
= pWideCL
->dwPageSize
;
1305 pibOffsets
= pAnsiCL
->dwOffset
;
1306 if (pWideCL
->dwCount
> 0)
1308 pibOffsets
[0] = sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1309 cbLeft
= dwBufLen
- pibOffsets
[0];
1311 for (dwIndex
= 0; dwIndex
< pWideCL
->dwCount
; ++dwIndex
)
1313 pbWide
= (const BYTE
*)pWideCL
+ pWideCL
->dwOffset
[dwIndex
];
1314 pbAnsi
= (LPBYTE
)pAnsiCL
+ pibOffsets
[dwIndex
];
1316 /* convert to ansi */
1317 cbGot
= WideCharToMultiByte(uCodePage
, 0, (LPCWSTR
)pbWide
, -1,
1318 (LPSTR
)pbAnsi
, cbLeft
, NULL
, &bUsedDefault
);
1321 if (dwIndex
< pWideCL
->dwCount
- 1)
1322 pibOffsets
[dwIndex
+ 1] = pibOffsets
[dwIndex
] + cbGot
;
1327 pibOffsets
[0] = sizeof(CANDIDATELIST
);
1333 static DWORD APIENTRY
1334 CandidateListAnsiToWide(const CANDIDATELIST
*pAnsiCL
, LPCANDIDATELIST pWideCL
, DWORD dwBufLen
,
1337 DWORD dwSize
, dwIndex
, cchGot
, cbGot
, cbLeft
;
1342 /* calculate total wide size */
1343 if (pAnsiCL
->dwCount
> 0)
1345 dwSize
= sizeof(CANDIDATELIST
) + ((pAnsiCL
->dwCount
- 1) * sizeof(DWORD
));
1346 for (dwIndex
= 0; dwIndex
< pAnsiCL
->dwCount
; ++dwIndex
)
1348 pbAnsi
= (const BYTE
*)pAnsiCL
+ pAnsiCL
->dwOffset
[dwIndex
];
1349 cchGot
= MultiByteToWideChar(uCodePage
, MB_PRECOMPOSED
, (LPCSTR
)pbAnsi
, -1, NULL
, 0);
1350 dwSize
+= cchGot
* sizeof(WCHAR
);
1355 dwSize
= sizeof(CANDIDATELIST
);
1358 dwSize
= ROUNDUP4(dwSize
);
1361 if (dwBufLen
< dwSize
)
1365 pWideCL
->dwSize
= dwBufLen
;
1366 pWideCL
->dwStyle
= pAnsiCL
->dwStyle
;
1367 pWideCL
->dwCount
= pAnsiCL
->dwCount
;
1368 pWideCL
->dwSelection
= pAnsiCL
->dwSelection
;
1369 pWideCL
->dwPageStart
= pAnsiCL
->dwPageStart
;
1370 pWideCL
->dwPageSize
= pAnsiCL
->dwPageSize
;
1372 pibOffsets
= pWideCL
->dwOffset
;
1373 if (pAnsiCL
->dwCount
> 0)
1375 pibOffsets
[0] = sizeof(CANDIDATELIST
) + ((pWideCL
->dwCount
- 1) * sizeof(DWORD
));
1376 cbLeft
= dwBufLen
- pibOffsets
[0];
1378 for (dwIndex
= 0; dwIndex
< pAnsiCL
->dwCount
; ++dwIndex
)
1380 pbAnsi
= (const BYTE
*)pAnsiCL
+ pAnsiCL
->dwOffset
[dwIndex
];
1381 pbWide
= (LPBYTE
)pWideCL
+ pibOffsets
[dwIndex
];
1383 /* convert to wide */
1384 cchGot
= MultiByteToWideChar(uCodePage
, MB_PRECOMPOSED
, (LPCSTR
)pbAnsi
, -1,
1385 (LPWSTR
)pbWide
, cbLeft
/ sizeof(WCHAR
));
1386 cbGot
= cchGot
* sizeof(WCHAR
);
1389 if (dwIndex
+ 1 < pAnsiCL
->dwCount
)
1390 pibOffsets
[dwIndex
+ 1] = pibOffsets
[dwIndex
] + cbGot
;
1395 pibOffsets
[0] = sizeof(CANDIDATELIST
);
1401 static DWORD APIENTRY
1402 ImmGetCandidateListAW(HIMC hIMC
, DWORD dwIndex
, LPCANDIDATELIST lpCandList
, DWORD dwBufLen
,
1407 PCLIENTIMC pClientImc
;
1408 LPCANDIDATEINFO pCI
;
1409 LPCANDIDATELIST pCL
;
1412 pClientImc
= ImmLockClientImc(hIMC
);
1416 pIC
= ImmLockIMC(hIMC
);
1419 ImmUnlockClientImc(pClientImc
);
1423 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
1427 ImmUnlockClientImc(pClientImc
);
1431 if (pCI
->dwSize
< sizeof(CANDIDATEINFO
) || pCI
->dwCount
<= dwIndex
)
1434 /* get required size */
1435 pCL
= (LPCANDIDATELIST
)((LPBYTE
)pCI
+ pCI
->dwOffset
[dwIndex
]);
1438 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1439 dwSize
= CandidateListAnsiToWide(pCL
, NULL
, 0, CP_ACP
);
1441 dwSize
= pCL
->dwSize
;
1445 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1446 dwSize
= pCL
->dwSize
;
1448 dwSize
= CandidateListWideToAnsi(pCL
, NULL
, 0, CP_ACP
);
1451 if (dwBufLen
!= 0 && dwSize
!= 0)
1453 if (lpCandList
== NULL
|| dwBufLen
< dwSize
)
1459 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1460 CandidateListAnsiToWide(pCL
, lpCandList
, dwSize
, CP_ACP
);
1462 RtlCopyMemory(lpCandList
, pCL
, dwSize
);
1466 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1467 RtlCopyMemory(lpCandList
, pCL
, dwSize
);
1469 CandidateListWideToAnsi(pCL
, lpCandList
, dwSize
, CP_ACP
);
1476 ImmUnlockIMCC(pIC
->hCandInfo
);
1478 ImmUnlockClientImc(pClientImc
);
1482 DWORD APIENTRY
ImmGetCandidateListCountAW(HIMC hIMC
, LPDWORD lpdwListCount
, BOOL bAnsi
)
1484 DWORD ret
= 0, cbGot
, dwIndex
;
1485 PCLIENTIMC pClientImc
;
1487 const CANDIDATEINFO
*pCI
;
1489 const CANDIDATELIST
*pCL
;
1490 const DWORD
*pdwOffsets
;
1492 if (lpdwListCount
== NULL
)
1497 pClientImc
= ImmLockClientImc(hIMC
);
1498 if (pClientImc
== NULL
)
1501 pIC
= ImmLockIMC(hIMC
);
1504 ImmUnlockClientImc(pClientImc
);
1508 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
1512 ImmUnlockClientImc(pClientImc
);
1516 if (pCI
->dwSize
< sizeof(CANDIDATEINFO
))
1519 *lpdwListCount
= pCI
->dwCount
; /* the number of candidate lists */
1521 /* calculate total size of candidate lists */
1524 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1526 ret
= ROUNDUP4(pCI
->dwPrivateSize
);
1527 pdwOffsets
= pCI
->dwOffset
;
1528 for (dwIndex
= 0; dwIndex
< pCI
->dwCount
; ++dwIndex
)
1530 pb
= (const BYTE
*)pCI
+ pdwOffsets
[dwIndex
];
1531 pCL
= (const CANDIDATELIST
*)pb
;
1532 cbGot
= CandidateListWideToAnsi(pCL
, NULL
, 0, CP_ACP
);
1543 if (pClientImc
->dwFlags
& CLIENTIMC_WIDE
)
1549 ret
= ROUNDUP4(pCI
->dwPrivateSize
);
1550 pdwOffsets
= pCI
->dwOffset
;
1551 for (dwIndex
= 0; dwIndex
< pCI
->dwCount
; ++dwIndex
)
1553 pb
= (const BYTE
*)pCI
+ pdwOffsets
[dwIndex
];
1554 pCL
= (const CANDIDATELIST
*)pb
;
1555 cbGot
= CandidateListAnsiToWide(pCL
, NULL
, 0, CP_ACP
);
1562 ImmUnlockIMCC(pIC
->hCandInfo
);
1564 ImmUnlockClientImc(pClientImc
);
1568 /***********************************************************************
1569 * ImmGetCandidateListA (IMM32.@)
1571 DWORD WINAPI
ImmGetCandidateListA(
1572 HIMC hIMC
, DWORD dwIndex
,
1573 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1575 return ImmGetCandidateListAW(hIMC
, dwIndex
, lpCandList
, dwBufLen
, TRUE
);
1578 /***********************************************************************
1579 * ImmGetCandidateListCountA (IMM32.@)
1581 DWORD WINAPI
ImmGetCandidateListCountA(
1582 HIMC hIMC
, LPDWORD lpdwListCount
)
1584 return ImmGetCandidateListCountAW(hIMC
, lpdwListCount
, TRUE
);
1587 /***********************************************************************
1588 * ImmGetCandidateListCountW (IMM32.@)
1590 DWORD WINAPI
ImmGetCandidateListCountW(
1591 HIMC hIMC
, LPDWORD lpdwListCount
)
1593 return ImmGetCandidateListCountAW(hIMC
, lpdwListCount
, FALSE
);
1596 /***********************************************************************
1597 * ImmGetCandidateListW (IMM32.@)
1599 DWORD WINAPI
ImmGetCandidateListW(
1600 HIMC hIMC
, DWORD dwIndex
,
1601 LPCANDIDATELIST lpCandList
, DWORD dwBufLen
)
1603 return ImmGetCandidateListAW(hIMC
, dwIndex
, lpCandList
, dwBufLen
, FALSE
);
1606 /***********************************************************************
1607 * ImmGetCandidateWindow (IMM32.@)
1609 BOOL WINAPI
ImmGetCandidateWindow(
1610 HIMC hIMC
, DWORD dwIndex
, LPCANDIDATEFORM lpCandidate
)
1614 LPCANDIDATEFORM pCF
;
1616 TRACE("ImmGetCandidateWindow(%p, %lu, %p)\n", hIMC
, dwIndex
, lpCandidate
);
1618 pIC
= ImmLockIMC(hIMC
);
1622 pCF
= &pIC
->cfCandForm
[dwIndex
];
1623 if (pCF
->dwIndex
!= IMM_INVALID_CANDFORM
)
1625 *lpCandidate
= *pCF
;
1633 static VOID APIENTRY
LogFontAnsiToWide(const LOGFONTA
*plfA
, LPLOGFONTW plfW
)
1636 RtlCopyMemory(plfW
, plfA
, offsetof(LOGFONTA
, lfFaceName
));
1637 StringCchLengthA(plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), &cch
);
1638 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, plfA
->lfFaceName
, (INT
)cch
,
1639 plfW
->lfFaceName
, _countof(plfW
->lfFaceName
));
1640 if (cch
> _countof(plfW
->lfFaceName
) - 1)
1641 cch
= _countof(plfW
->lfFaceName
) - 1;
1642 plfW
->lfFaceName
[cch
] = 0;
1645 static VOID APIENTRY
LogFontWideToAnsi(const LOGFONTW
*plfW
, LPLOGFONTA plfA
)
1648 RtlCopyMemory(plfA
, plfW
, offsetof(LOGFONTW
, lfFaceName
));
1649 StringCchLengthW(plfW
->lfFaceName
, _countof(plfW
->lfFaceName
), &cch
);
1650 cch
= WideCharToMultiByte(CP_ACP
, 0, plfW
->lfFaceName
, (INT
)cch
,
1651 plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), NULL
, NULL
);
1652 if (cch
> _countof(plfA
->lfFaceName
) - 1)
1653 cch
= _countof(plfA
->lfFaceName
) - 1;
1654 plfA
->lfFaceName
[cch
] = 0;
1657 /***********************************************************************
1658 * ImmGetCompositionFontA (IMM32.@)
1660 BOOL WINAPI
ImmGetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
1662 PCLIENTIMC pClientImc
;
1663 BOOL ret
= FALSE
, bWide
;
1666 TRACE("ImmGetCompositionFontA(%p, %p)\n", hIMC
, lplf
);
1668 pClientImc
= ImmLockClientImc(hIMC
);
1669 if (pClientImc
== NULL
)
1672 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1673 ImmUnlockClientImc(pClientImc
);
1675 pIC
= ImmLockIMC(hIMC
);
1679 if (pIC
->fdwInit
& INIT_LOGFONT
)
1682 LogFontWideToAnsi(&pIC
->lfFont
.W
, lplf
);
1684 *lplf
= pIC
->lfFont
.A
;
1693 /***********************************************************************
1694 * ImmGetCompositionFontW (IMM32.@)
1696 BOOL WINAPI
ImmGetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
1698 PCLIENTIMC pClientImc
;
1703 TRACE("ImmGetCompositionFontW(%p, %p)\n", hIMC
, lplf
);
1705 pClientImc
= ImmLockClientImc(hIMC
);
1706 if (pClientImc
== NULL
)
1709 bWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
1710 ImmUnlockClientImc(pClientImc
);
1712 pIC
= ImmLockIMC(hIMC
);
1716 if (pIC
->fdwInit
& INIT_LOGFONT
)
1719 *lplf
= pIC
->lfFont
.W
;
1721 LogFontAnsiToWide(&pIC
->lfFont
.A
, lplf
);
1731 /* Helpers for the GetCompositionString functions */
1733 /* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
1734 length is always in bytes. */
1735 static INT
CopyCompStringIMEtoClient(const InputContextData
*data
, const void *src
, INT src_len
, void *dst
,
1736 INT dst_len
, BOOL unicode
)
1738 int char_size
= unicode
? sizeof(WCHAR
) : sizeof(char);
1741 if (is_himc_ime_unicode(data
) ^ unicode
)
1744 ret
= MultiByteToWideChar(CP_ACP
, 0, src
, src_len
, dst
, dst_len
/ sizeof(WCHAR
));
1746 ret
= WideCharToMultiByte(CP_ACP
, 0, src
, src_len
, dst
, dst_len
, NULL
, NULL
);
1753 ret
= min(src_len
* char_size
, dst_len
);
1754 memcpy(dst
, src
, ret
);
1757 ret
= src_len
* char_size
;
1763 /* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
1764 passed mode. String length is in characters, attributes are in byte arrays. */
1765 static INT
CopyCompAttrIMEtoClient(const InputContextData
*data
, const BYTE
*src
, INT src_len
, const void *comp_string
,
1766 INT str_len
, BYTE
*dst
, INT dst_len
, BOOL unicode
)
1776 string
.str
= comp_string
;
1778 if (is_himc_ime_unicode(data
) && !unicode
)
1780 rc
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
, str_len
, NULL
, 0, NULL
, NULL
);
1783 int i
, j
= 0, k
= 0;
1787 for (i
= 0; i
< str_len
; ++i
)
1791 len
= WideCharToMultiByte(CP_ACP
, 0, string
.strW
+ i
, 1, NULL
, 0, NULL
, NULL
);
1792 for (; len
> 0; --len
)
1805 else if (!is_himc_ime_unicode(data
) && unicode
)
1807 rc
= MultiByteToWideChar(CP_ACP
, 0, string
.strA
, str_len
, NULL
, 0);
1814 for (i
= 0; i
< str_len
; ++i
)
1816 if (IsDBCSLeadByte(string
.strA
[i
]))
1829 memcpy(dst
, src
, min(src_len
, dst_len
));
1836 static INT
CopyCompClauseIMEtoClient(InputContextData
*data
, LPBYTE source
, INT slen
, LPBYTE ssource
,
1837 LPBYTE target
, INT tlen
, BOOL unicode
)
1841 if (is_himc_ime_unicode(data
) && !unicode
)
1849 tlen
/= sizeof (DWORD
);
1850 for (i
= 0; i
< tlen
; ++i
)
1852 ((DWORD
*)target
)[i
] = WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
,
1853 ((DWORD
*)source
)[i
],
1857 rc
= sizeof (DWORD
) * i
;
1862 else if (!is_himc_ime_unicode(data
) && unicode
)
1870 tlen
/= sizeof (DWORD
);
1871 for (i
= 0; i
< tlen
; ++i
)
1873 ((DWORD
*)target
)[i
] = MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
,
1874 ((DWORD
*)source
)[i
],
1877 rc
= sizeof (DWORD
) * i
;
1884 memcpy( target
, source
, min(slen
,tlen
));
1891 static INT
CopyCompOffsetIMEtoClient(InputContextData
*data
, DWORD offset
, LPBYTE ssource
, BOOL unicode
)
1895 if (is_himc_ime_unicode(data
) && !unicode
)
1897 rc
= WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)ssource
, offset
, NULL
, 0, NULL
, NULL
);
1899 else if (!is_himc_ime_unicode(data
) && unicode
)
1901 rc
= MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)ssource
, offset
, NULL
, 0);
1909 static LONG
ImmGetCompositionStringT( HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
,
1910 DWORD dwBufLen
, BOOL unicode
)
1913 InputContextData
*data
= get_imc_data(hIMC
);
1914 LPCOMPOSITIONSTRING compstr
;
1917 TRACE("(%p, 0x%x, %p, %d)\n", hIMC
, dwIndex
, lpBuf
, dwBufLen
);
1922 if (!data
->IMC
.hCompStr
)
1925 compdata
= ImmLockIMCC(data
->IMC
.hCompStr
);
1926 compstr
= (LPCOMPOSITIONSTRING
)compdata
;
1931 TRACE("GCS_RESULTSTR\n");
1932 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultStrOffset
, compstr
->dwResultStrLen
, lpBuf
, dwBufLen
, unicode
);
1935 TRACE("GCS_COMPSTR\n");
1936 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
, lpBuf
, dwBufLen
, unicode
);
1939 TRACE("GCS_COMPATTR\n");
1940 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompAttrOffset
, compstr
->dwCompAttrLen
,
1941 compdata
+ compstr
->dwCompStrOffset
, compstr
->dwCompStrLen
,
1942 lpBuf
, dwBufLen
, unicode
);
1944 case GCS_COMPCLAUSE
:
1945 TRACE("GCS_COMPCLAUSE\n");
1946 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompClauseOffset
,compstr
->dwCompClauseLen
,
1947 compdata
+ compstr
->dwCompStrOffset
,
1948 lpBuf
, dwBufLen
, unicode
);
1950 case GCS_RESULTCLAUSE
:
1951 TRACE("GCS_RESULTCLAUSE\n");
1952 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultClauseOffset
,compstr
->dwResultClauseLen
,
1953 compdata
+ compstr
->dwResultStrOffset
,
1954 lpBuf
, dwBufLen
, unicode
);
1956 case GCS_RESULTREADSTR
:
1957 TRACE("GCS_RESULTREADSTR\n");
1958 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwResultReadStrOffset
, compstr
->dwResultReadStrLen
, lpBuf
, dwBufLen
, unicode
);
1960 case GCS_RESULTREADCLAUSE
:
1961 TRACE("GCS_RESULTREADCLAUSE\n");
1962 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwResultReadClauseOffset
,compstr
->dwResultReadClauseLen
,
1963 compdata
+ compstr
->dwResultStrOffset
,
1964 lpBuf
, dwBufLen
, unicode
);
1966 case GCS_COMPREADSTR
:
1967 TRACE("GCS_COMPREADSTR\n");
1968 rc
= CopyCompStringIMEtoClient(data
, compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
, lpBuf
, dwBufLen
, unicode
);
1970 case GCS_COMPREADATTR
:
1971 TRACE("GCS_COMPREADATTR\n");
1972 rc
= CopyCompAttrIMEtoClient(data
, compdata
+ compstr
->dwCompReadAttrOffset
, compstr
->dwCompReadAttrLen
,
1973 compdata
+ compstr
->dwCompReadStrOffset
, compstr
->dwCompReadStrLen
,
1974 lpBuf
, dwBufLen
, unicode
);
1976 case GCS_COMPREADCLAUSE
:
1977 TRACE("GCS_COMPREADCLAUSE\n");
1978 rc
= CopyCompClauseIMEtoClient(data
, compdata
+ compstr
->dwCompReadClauseOffset
,compstr
->dwCompReadClauseLen
,
1979 compdata
+ compstr
->dwCompStrOffset
,
1980 lpBuf
, dwBufLen
, unicode
);
1983 TRACE("GCS_CURSORPOS\n");
1984 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwCursorPos
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
1986 case GCS_DELTASTART
:
1987 TRACE("GCS_DELTASTART\n");
1988 rc
= CopyCompOffsetIMEtoClient(data
, compstr
->dwDeltaStart
, compdata
+ compstr
->dwCompStrOffset
, unicode
);
1991 FIXME("Unhandled index 0x%x\n",dwIndex
);
1995 ImmUnlockIMCC(data
->IMC
.hCompStr
);
2000 /***********************************************************************
2001 * ImmGetCompositionStringA (IMM32.@)
2003 LONG WINAPI
ImmGetCompositionStringA(
2004 HIMC hIMC
, DWORD dwIndex
, LPVOID lpBuf
, DWORD dwBufLen
)
2006 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, FALSE
);
2010 /***********************************************************************
2011 * ImmGetCompositionStringW (IMM32.@)
2013 LONG WINAPI
ImmGetCompositionStringW(
2014 HIMC hIMC
, DWORD dwIndex
,
2015 LPVOID lpBuf
, DWORD dwBufLen
)
2017 return ImmGetCompositionStringT(hIMC
, dwIndex
, lpBuf
, dwBufLen
, TRUE
);
2020 /***********************************************************************
2021 * ImmGetCompositionWindow (IMM32.@)
2023 BOOL WINAPI
ImmGetCompositionWindow(HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
2028 TRACE("ImmGetCompositionWindow(%p, %p)\n", hIMC
, lpCompForm
);
2030 pIC
= ImmLockIMC(hIMC
);
2034 if (pIC
->fdwInit
& INIT_COMPFORM
)
2036 *lpCompForm
= pIC
->cfCompForm
;
2044 /***********************************************************************
2045 * ImmGetContext (IMM32.@)
2048 HIMC WINAPI
ImmGetContext(HWND hWnd
)
2052 TRACE("%p\n", hWnd
);
2054 if (!IsWindow(hWnd
))
2056 SetLastError(ERROR_INVALID_WINDOW_HANDLE
);
2060 rc
= GetPropW(hWnd
,szwWineIMCProperty
);
2063 else if (rc
== NULL
)
2064 rc
= get_default_context( hWnd
);
2068 InputContextData
*data
= rc
;
2069 data
->IMC
.hWnd
= hWnd
;
2072 TRACE("returning %p\n", rc
);
2077 /***********************************************************************
2078 * ImmGetConversionListA (IMM32.@)
2080 DWORD WINAPI
ImmGetConversionListA(
2082 LPCSTR pSrc
, LPCANDIDATELIST lpDst
,
2083 DWORD dwBufLen
, UINT uFlag
)
2085 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2086 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL
, hIMC
, debugstr_a(pSrc
), lpDst
,
2088 if (immHkl
->hIME
&& immHkl
->pImeConversionList
)
2090 if (!is_kbd_ime_unicode(immHkl
))
2091 return immHkl
->pImeConversionList(hIMC
,(LPCWSTR
)pSrc
,lpDst
,dwBufLen
,uFlag
);
2094 LPCANDIDATELIST lpwDst
;
2096 LPWSTR pwSrc
= strdupAtoW(pSrc
);
2098 len
= immHkl
->pImeConversionList(hIMC
, pwSrc
, NULL
, 0, uFlag
);
2099 lpwDst
= HeapAlloc(GetProcessHeap(), 0, len
);
2102 immHkl
->pImeConversionList(hIMC
, pwSrc
, lpwDst
, len
, uFlag
);
2103 ret
= convert_candidatelist_WtoA( lpwDst
, lpDst
, dwBufLen
);
2104 HeapFree(GetProcessHeap(), 0, lpwDst
);
2106 HeapFree(GetProcessHeap(), 0, pwSrc
);
2115 /***********************************************************************
2116 * ImmGetConversionListW (IMM32.@)
2118 DWORD WINAPI
ImmGetConversionListW(
2120 LPCWSTR pSrc
, LPCANDIDATELIST lpDst
,
2121 DWORD dwBufLen
, UINT uFlag
)
2123 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2124 TRACE("(%p, %p, %s, %p, %d, %d):\n", hKL
, hIMC
, debugstr_w(pSrc
), lpDst
,
2126 if (immHkl
->hIME
&& immHkl
->pImeConversionList
)
2128 if (is_kbd_ime_unicode(immHkl
))
2129 return immHkl
->pImeConversionList(hIMC
,pSrc
,lpDst
,dwBufLen
,uFlag
);
2132 LPCANDIDATELIST lpaDst
;
2134 LPSTR paSrc
= strdupWtoA(pSrc
);
2136 len
= immHkl
->pImeConversionList(hIMC
, (LPCWSTR
)paSrc
, NULL
, 0, uFlag
);
2137 lpaDst
= HeapAlloc(GetProcessHeap(), 0, len
);
2140 immHkl
->pImeConversionList(hIMC
, (LPCWSTR
)paSrc
, lpaDst
, len
, uFlag
);
2141 ret
= convert_candidatelist_AtoW( lpaDst
, lpDst
, dwBufLen
);
2142 HeapFree(GetProcessHeap(), 0, lpaDst
);
2144 HeapFree(GetProcessHeap(), 0, paSrc
);
2153 /***********************************************************************
2154 * ImmGetConversionStatus (IMM32.@)
2156 BOOL WINAPI
ImmGetConversionStatus(
2157 HIMC hIMC
, LPDWORD lpfdwConversion
, LPDWORD lpfdwSentence
)
2161 TRACE("ImmGetConversionStatus(%p %p %p)\n", hIMC
, lpfdwConversion
, lpfdwSentence
);
2163 pIC
= ImmLockIMC(hIMC
);
2167 if (lpfdwConversion
)
2168 *lpfdwConversion
= pIC
->fdwConversion
;
2170 *lpfdwSentence
= pIC
->fdwSentence
;
2176 static BOOL
needs_ime_window(HWND hwnd
)
2180 if (GetClassNameW(hwnd
, classW
, ARRAY_SIZE(classW
)) && !lstrcmpW(classW
, szwIME
))
2182 if (GetClassLongPtrW(hwnd
, GCL_STYLE
) & CS_IME
) return FALSE
;
2187 /***********************************************************************
2188 * __wine_register_window (IMM32.@)
2190 BOOL WINAPI
__wine_register_window(HWND hwnd
)
2193 IMMThreadData
*thread_data
;
2194 TRACE("(%p)\n", hwnd
);
2196 if (!needs_ime_window(hwnd
))
2199 thread_data
= IMM_GetThreadData(hwnd
, 0);
2203 if (thread_data
->disableIME
|| disable_ime
)
2205 TRACE("IME for this thread is disabled\n");
2206 LeaveCriticalSection(&threaddata_cs
);
2209 thread_data
->windowRefs
++;
2210 TRACE("windowRefs=%u, hwndDefault=%p\n",
2211 thread_data
->windowRefs
, thread_data
->hwndDefault
);
2213 /* Create default IME window */
2214 if (thread_data
->windowRefs
== 1)
2216 /* Do not create the window inside of a critical section */
2217 LeaveCriticalSection(&threaddata_cs
);
2218 new = CreateWindowExW( 0, szwIME
, szwDefaultIME
,
2219 WS_POPUP
| WS_DISABLED
| WS_CLIPSIBLINGS
,
2220 0, 0, 1, 1, 0, 0, 0, 0);
2221 /* thread_data is in the current thread so we can assume it's still valid */
2222 EnterCriticalSection(&threaddata_cs
);
2223 /* See if anyone beat us */
2224 if (thread_data
->hwndDefault
== NULL
)
2226 thread_data
->hwndDefault
= new;
2228 TRACE("Default is %p\n", thread_data
->hwndDefault
);
2232 LeaveCriticalSection(&threaddata_cs
);
2234 /* Clean up an unused new window outside of the critical section */
2240 /***********************************************************************
2241 * __wine_unregister_window (IMM32.@)
2243 void WINAPI
__wine_unregister_window(HWND hwnd
)
2245 HWND to_destroy
= 0;
2246 IMMThreadData
*thread_data
;
2247 TRACE("(%p)\n", hwnd
);
2249 thread_data
= IMM_GetThreadData(hwnd
, 0);
2250 if (!thread_data
) return;
2252 thread_data
->windowRefs
--;
2253 TRACE("windowRefs=%u, hwndDefault=%p\n",
2254 thread_data
->windowRefs
, thread_data
->hwndDefault
);
2256 /* Destroy default IME window */
2257 if (thread_data
->windowRefs
== 0 && thread_data
->hwndDefault
)
2259 to_destroy
= thread_data
->hwndDefault
;
2260 thread_data
->hwndDefault
= NULL
;
2262 LeaveCriticalSection(&threaddata_cs
);
2264 if (to_destroy
) DestroyWindow( to_destroy
);
2267 /***********************************************************************
2268 * ImmGetDefaultIMEWnd (IMM32.@)
2270 HWND WINAPI
ImmGetDefaultIMEWnd(HWND hWnd
)
2272 if (!(g_dwImm32Flags
& IMM32_FLAG_UNKNOWN
))
2276 return (HWND
)Imm32GetThreadState(THREADSTATE_ACTIVEWINDOW
);
2278 return (HWND
)Imm32QueryWindow(hWnd
, QUERY_WINDOW_DEFAULT_IME
);
2281 /***********************************************************************
2282 * CtfImmIsCiceroEnabled (IMM32.@)
2284 BOOL WINAPI
CtfImmIsCiceroEnabled(VOID
)
2286 return !!(g_dwImm32Flags
& IMM32_FLAG_CICERO_ENABLED
);
2289 /***********************************************************************
2290 * ImmGetDescriptionA (IMM32.@)
2292 UINT WINAPI
ImmGetDescriptionA(
2293 HKL hKL
, LPSTR lpszDescription
, UINT uBufLen
)
2298 TRACE("ImmGetDescriptionA(%p,%p,%d)\n", hKL
, lpszDescription
, uBufLen
);
2300 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2303 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
2304 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeDescription
, (INT
)cch
,
2305 lpszDescription
, uBufLen
, NULL
, NULL
);
2307 lpszDescription
[cch
] = 0;
2311 /***********************************************************************
2312 * ImmGetDescriptionW (IMM32.@)
2314 UINT WINAPI
ImmGetDescriptionW(HKL hKL
, LPWSTR lpszDescription
, UINT uBufLen
)
2319 TRACE("ImmGetDescriptionW(%p, %p, %d)\n", hKL
, lpszDescription
, uBufLen
);
2321 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2325 StringCchCopyW(lpszDescription
, uBufLen
, info
.wszImeDescription
);
2327 StringCchLengthW(info
.wszImeDescription
, _countof(info
.wszImeDescription
), &cch
);
2331 /***********************************************************************
2332 * ImmGetGuideLineA (IMM32.@)
2334 DWORD WINAPI
ImmGetGuideLineA(
2335 HIMC hIMC
, DWORD dwIndex
, LPSTR lpBuf
, DWORD dwBufLen
)
2337 FIXME("(%p, %d, %s, %d): stub\n",
2338 hIMC
, dwIndex
, debugstr_a(lpBuf
), dwBufLen
2340 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2344 /***********************************************************************
2345 * ImmGetGuideLineW (IMM32.@)
2347 DWORD WINAPI
ImmGetGuideLineW(HIMC hIMC
, DWORD dwIndex
, LPWSTR lpBuf
, DWORD dwBufLen
)
2349 FIXME("(%p, %d, %s, %d): stub\n",
2350 hIMC
, dwIndex
, debugstr_w(lpBuf
), dwBufLen
2352 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2356 /***********************************************************************
2357 * ImmGetIMEFileNameA (IMM32.@)
2359 UINT WINAPI
ImmGetIMEFileNameA( HKL hKL
, LPSTR lpszFileName
, UINT uBufLen
)
2365 TRACE("ImmGetIMEFileNameA(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
2367 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2370 lpszFileName
[0] = 0;
2374 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
2376 cch
= WideCharToMultiByte(CP_ACP
, 0, info
.wszImeFile
, (INT
)cch
,
2377 lpszFileName
, uBufLen
, NULL
, &bDefUsed
);
2381 if (cch
> uBufLen
- 1)
2384 lpszFileName
[cch
] = 0;
2388 /***********************************************************************
2389 * ImmGetIMEFileNameW (IMM32.@)
2391 UINT WINAPI
ImmGetIMEFileNameW(HKL hKL
, LPWSTR lpszFileName
, UINT uBufLen
)
2396 TRACE("ImmGetIMEFileNameW(%p, %p, %u)\n", hKL
, lpszFileName
, uBufLen
);
2398 if (!ImmGetImeInfoEx(&info
, ImeInfoExKeyboardLayout
, &hKL
) || !IS_IME_HKL(hKL
))
2401 lpszFileName
[0] = 0;
2405 StringCchLengthW(info
.wszImeFile
, _countof(info
.wszImeFile
), &cch
);
2409 StringCchCopyNW(lpszFileName
, uBufLen
, info
.wszImeFile
, cch
);
2411 if (cch
> uBufLen
- 1)
2414 lpszFileName
[cch
] = 0;
2418 /***********************************************************************
2419 * ImmGetOpenStatus (IMM32.@)
2421 BOOL WINAPI
ImmGetOpenStatus(HIMC hIMC
)
2426 TRACE("ImmGetOpenStatus(%p)\n", hIMC
);
2431 pIC
= ImmLockIMC(hIMC
);
2441 /***********************************************************************
2442 * ImmGetProperty (IMM32.@)
2444 DWORD WINAPI
ImmGetProperty(HKL hKL
, DWORD fdwIndex
)
2449 TRACE("(%p, %d)\n", hKL
, fdwIndex
);
2450 kbd
= IMM_GetImmHkl(hKL
);
2452 if (kbd
&& kbd
->hIME
)
2456 case IGP_PROPERTY
: rc
= kbd
->imeInfo
.fdwProperty
; break;
2457 case IGP_CONVERSION
: rc
= kbd
->imeInfo
.fdwConversionCaps
; break;
2458 case IGP_SENTENCE
: rc
= kbd
->imeInfo
.fdwSentenceCaps
; break;
2459 case IGP_SETCOMPSTR
: rc
= kbd
->imeInfo
.fdwSCSCaps
; break;
2460 case IGP_SELECT
: rc
= kbd
->imeInfo
.fdwSelectCaps
; break;
2461 case IGP_GETIMEVERSION
: rc
= IMEVER_0400
; break;
2462 case IGP_UI
: rc
= 0; break;
2469 /***********************************************************************
2470 * ImmGetRegisterWordStyleA (IMM32.@)
2472 UINT WINAPI
ImmGetRegisterWordStyleA(
2473 HKL hKL
, UINT nItem
, LPSTYLEBUFA lpStyleBuf
)
2475 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2476 TRACE("(%p, %d, %p):\n", hKL
, nItem
, lpStyleBuf
);
2477 if (immHkl
->hIME
&& immHkl
->pImeGetRegisterWordStyle
)
2479 if (!is_kbd_ime_unicode(immHkl
))
2480 return immHkl
->pImeGetRegisterWordStyle(nItem
,(LPSTYLEBUFW
)lpStyleBuf
);
2486 rc
= immHkl
->pImeGetRegisterWordStyle(nItem
,&sbw
);
2487 WideCharToMultiByte(CP_ACP
, 0, sbw
.szDescription
, -1,
2488 lpStyleBuf
->szDescription
, 32, NULL
, NULL
);
2489 lpStyleBuf
->dwStyle
= sbw
.dwStyle
;
2497 /***********************************************************************
2498 * ImmGetRegisterWordStyleW (IMM32.@)
2500 UINT WINAPI
ImmGetRegisterWordStyleW(
2501 HKL hKL
, UINT nItem
, LPSTYLEBUFW lpStyleBuf
)
2503 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2504 TRACE("(%p, %d, %p):\n", hKL
, nItem
, lpStyleBuf
);
2505 if (immHkl
->hIME
&& immHkl
->pImeGetRegisterWordStyle
)
2507 if (is_kbd_ime_unicode(immHkl
))
2508 return immHkl
->pImeGetRegisterWordStyle(nItem
,lpStyleBuf
);
2514 rc
= immHkl
->pImeGetRegisterWordStyle(nItem
,(LPSTYLEBUFW
)&sba
);
2515 MultiByteToWideChar(CP_ACP
, 0, sba
.szDescription
, -1,
2516 lpStyleBuf
->szDescription
, 32);
2517 lpStyleBuf
->dwStyle
= sba
.dwStyle
;
2525 /***********************************************************************
2526 * ImmGetStatusWindowPos (IMM32.@)
2528 BOOL WINAPI
ImmGetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
2533 TRACE("ImmGetStatusWindowPos(%p, %p)\n", hIMC
, lpptPos
);
2535 pIC
= ImmLockIMC(hIMC
);
2539 ret
= !!(pIC
->fdwInit
& INIT_STATUSWNDPOS
);
2541 *lpptPos
= pIC
->ptStatusWndPos
;
2547 /***********************************************************************
2548 * ImmGetVirtualKey (IMM32.@)
2550 UINT WINAPI
ImmGetVirtualKey(HWND hWnd
)
2552 OSVERSIONINFOA version
;
2553 InputContextData
*data
= ImmGetContext( hWnd
);
2554 TRACE("%p\n", hWnd
);
2557 return data
->lastVK
;
2559 version
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
2560 GetVersionExA( &version
);
2561 switch(version
.dwPlatformId
)
2563 case VER_PLATFORM_WIN32_WINDOWS
:
2564 return VK_PROCESSKEY
;
2565 case VER_PLATFORM_WIN32_NT
:
2568 FIXME("%d not supported\n",version
.dwPlatformId
);
2569 return VK_PROCESSKEY
;
2573 /***********************************************************************
2574 * ImmInstallIMEA (IMM32.@)
2576 HKL WINAPI
ImmInstallIMEA(
2577 LPCSTR lpszIMEFileName
, LPCSTR lpszLayoutText
)
2579 LPWSTR lpszwIMEFileName
;
2580 LPWSTR lpszwLayoutText
;
2583 TRACE ("(%s, %s)\n", debugstr_a(lpszIMEFileName
),
2584 debugstr_a(lpszLayoutText
));
2586 lpszwIMEFileName
= strdupAtoW(lpszIMEFileName
);
2587 lpszwLayoutText
= strdupAtoW(lpszLayoutText
);
2589 hkl
= ImmInstallIMEW(lpszwIMEFileName
, lpszwLayoutText
);
2591 HeapFree(GetProcessHeap(),0,lpszwIMEFileName
);
2592 HeapFree(GetProcessHeap(),0,lpszwLayoutText
);
2596 /***********************************************************************
2597 * ImmInstallIMEW (IMM32.@)
2599 HKL WINAPI
ImmInstallIMEW(
2600 LPCWSTR lpszIMEFileName
, LPCWSTR lpszLayoutText
)
2602 INT lcid
= GetUserDefaultLCID();
2607 WCHAR regKey
[ARRAY_SIZE(szImeRegFmt
)+8];
2609 TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName
),
2610 debugstr_w(lpszLayoutText
));
2612 /* Start with 2. e001 will be blank and so default to the wine internal IME */
2615 while (count
< 0xfff)
2617 DWORD disposition
= 0;
2619 hkl
= (HKL
)MAKELPARAM( lcid
, 0xe000 | count
);
2620 wsprintfW( regKey
, szImeRegFmt
, (ULONG_PTR
)hkl
);
2622 rc
= RegCreateKeyExW(HKEY_LOCAL_MACHINE
, regKey
, 0, NULL
, 0, KEY_WRITE
, NULL
, &hkey
, &disposition
);
2623 if (rc
== ERROR_SUCCESS
&& disposition
== REG_CREATED_NEW_KEY
)
2625 else if (rc
== ERROR_SUCCESS
)
2633 WARN("Unable to find slot to install IME\n");
2637 if (rc
== ERROR_SUCCESS
)
2639 rc
= RegSetValueExW(hkey
, szImeFileW
, 0, REG_SZ
, (const BYTE
*)lpszIMEFileName
,
2640 (lstrlenW(lpszIMEFileName
) + 1) * sizeof(WCHAR
));
2641 if (rc
== ERROR_SUCCESS
)
2642 rc
= RegSetValueExW(hkey
, szLayoutTextW
, 0, REG_SZ
, (const BYTE
*)lpszLayoutText
,
2643 (lstrlenW(lpszLayoutText
) + 1) * sizeof(WCHAR
));
2649 WARN("Unable to set IME registry values\n");
2654 /***********************************************************************
2655 * ImmIsIME (IMM32.@)
2657 BOOL WINAPI
ImmIsIME(HKL hKL
)
2660 TRACE("ImmIsIME(%p)\n", hKL
);
2661 return !!ImmGetImeInfoEx(&info
, ImeInfoExImeWindow
, &hKL
);
2664 /***********************************************************************
2665 * ImmIsUIMessageA (IMM32.@)
2667 BOOL WINAPI
ImmIsUIMessageA(
2668 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2670 TRACE("(%p, %x, %ld, %ld)\n", hWndIME
, msg
, wParam
, lParam
);
2671 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
2672 (msg
== WM_IME_SETCONTEXT
) ||
2673 (msg
== WM_IME_NOTIFY
) ||
2674 (msg
== WM_IME_COMPOSITIONFULL
) ||
2675 (msg
== WM_IME_SELECT
) ||
2676 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
2679 SendMessageA(hWndIME
, msg
, wParam
, lParam
);
2686 /***********************************************************************
2687 * ImmIsUIMessageW (IMM32.@)
2689 BOOL WINAPI
ImmIsUIMessageW(
2690 HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
2692 TRACE("(%p, %x, %ld, %ld)\n", hWndIME
, msg
, wParam
, lParam
);
2693 if ((msg
>= WM_IME_STARTCOMPOSITION
&& msg
<= WM_IME_KEYLAST
) ||
2694 (msg
== WM_IME_SETCONTEXT
) ||
2695 (msg
== WM_IME_NOTIFY
) ||
2696 (msg
== WM_IME_COMPOSITIONFULL
) ||
2697 (msg
== WM_IME_SELECT
) ||
2698 (msg
== 0x287 /* FIXME: WM_IME_SYSTEM */))
2701 SendMessageW(hWndIME
, msg
, wParam
, lParam
);
2708 /***********************************************************************
2709 * ImmNotifyIME (IMM32.@)
2711 BOOL WINAPI
ImmNotifyIME(
2712 HIMC hIMC
, DWORD dwAction
, DWORD dwIndex
, DWORD dwValue
)
2714 DWORD dwImeThreadId
, dwThreadId
;
2719 TRACE("ImmNotifyIME(%p, %lu, %lu, %lu)\n", hIMC
, dwAction
, dwIndex
, dwValue
);
2723 dwImeThreadId
= Imm32QueryWindow(hIMC
, QUERY_WINDOW_UNIQUE_THREAD_ID
);
2724 dwThreadId
= GetCurrentThreadId();
2725 if (dwImeThreadId
!= dwThreadId
)
2729 hKL
= GetKeyboardLayout(0);
2730 pImeDpi
= ImmLockImeDpi(hKL
);
2731 if (pImeDpi
== NULL
)
2734 ret
= pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
2735 ImmUnlockImeDpi(pImeDpi
);
2739 /***********************************************************************
2740 * ImmRegisterWordA (IMM32.@)
2742 BOOL WINAPI
ImmRegisterWordA(
2743 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszRegister
)
2745 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2746 TRACE("(%p, %s, %d, %s):\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
2747 debugstr_a(lpszRegister
));
2748 if (immHkl
->hIME
&& immHkl
->pImeRegisterWord
)
2750 if (!is_kbd_ime_unicode(immHkl
))
2751 return immHkl
->pImeRegisterWord((LPCWSTR
)lpszReading
,dwStyle
,
2752 (LPCWSTR
)lpszRegister
);
2755 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
2756 LPWSTR lpszwRegister
= strdupAtoW(lpszRegister
);
2759 rc
= immHkl
->pImeRegisterWord(lpszwReading
,dwStyle
,lpszwRegister
);
2760 HeapFree(GetProcessHeap(),0,lpszwReading
);
2761 HeapFree(GetProcessHeap(),0,lpszwRegister
);
2769 /***********************************************************************
2770 * ImmRegisterWordW (IMM32.@)
2772 BOOL WINAPI
ImmRegisterWordW(
2773 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszRegister
)
2775 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
2776 TRACE("(%p, %s, %d, %s):\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
2777 debugstr_w(lpszRegister
));
2778 if (immHkl
->hIME
&& immHkl
->pImeRegisterWord
)
2780 if (is_kbd_ime_unicode(immHkl
))
2781 return immHkl
->pImeRegisterWord(lpszReading
,dwStyle
,lpszRegister
);
2784 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
2785 LPSTR lpszaRegister
= strdupWtoA(lpszRegister
);
2788 rc
= immHkl
->pImeRegisterWord((LPCWSTR
)lpszaReading
,dwStyle
,
2789 (LPCWSTR
)lpszaRegister
);
2790 HeapFree(GetProcessHeap(),0,lpszaReading
);
2791 HeapFree(GetProcessHeap(),0,lpszaRegister
);
2799 /***********************************************************************
2800 * ImmReleaseContext (IMM32.@)
2802 BOOL WINAPI
ImmReleaseContext(HWND hWnd
, HIMC hIMC
)
2804 static BOOL shown
= FALSE
;
2807 FIXME("(%p, %p): stub\n", hWnd
, hIMC
);
2813 /***********************************************************************
2814 * ImmRequestMessageA(IMM32.@)
2816 LRESULT WINAPI
ImmRequestMessageA(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
2818 InputContextData
*data
= get_imc_data(hIMC
);
2820 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
2822 if (data
) return SendMessageA(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
2824 SetLastError(ERROR_INVALID_HANDLE
);
2828 /***********************************************************************
2829 * ImmRequestMessageW(IMM32.@)
2831 LRESULT WINAPI
ImmRequestMessageW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
2833 InputContextData
*data
= get_imc_data(hIMC
);
2835 TRACE("%p %ld %ld\n", hIMC
, wParam
, wParam
);
2837 if (data
) return SendMessageW(data
->IMC
.hWnd
, WM_IME_REQUEST
, wParam
, lParam
);
2839 SetLastError(ERROR_INVALID_HANDLE
);
2843 /***********************************************************************
2844 * ImmSetCandidateWindow (IMM32.@)
2846 BOOL WINAPI
ImmSetCandidateWindow(
2847 HIMC hIMC
, LPCANDIDATEFORM lpCandidate
)
2849 InputContextData
*data
= get_imc_data(hIMC
);
2851 TRACE("(%p, %p)\n", hIMC
, lpCandidate
);
2853 if (!data
|| !lpCandidate
)
2856 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2859 TRACE("\t%x, %x, %s, %s\n",
2860 lpCandidate
->dwIndex
, lpCandidate
->dwStyle
,
2861 wine_dbgstr_point(&lpCandidate
->ptCurrentPos
),
2862 wine_dbgstr_rect(&lpCandidate
->rcArea
));
2864 if (lpCandidate
->dwIndex
>= ARRAY_SIZE(data
->IMC
.cfCandForm
))
2867 data
->IMC
.cfCandForm
[lpCandidate
->dwIndex
] = *lpCandidate
;
2868 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCANDIDATEPOS
);
2869 ImmInternalSendIMENotify(data
, IMN_SETCANDIDATEPOS
, 1 << lpCandidate
->dwIndex
);
2874 /***********************************************************************
2875 * ImmSetCompositionFontA (IMM32.@)
2877 BOOL WINAPI
ImmSetCompositionFontA(HIMC hIMC
, LPLOGFONTA lplf
)
2879 InputContextData
*data
= get_imc_data(hIMC
);
2880 TRACE("(%p, %p)\n", hIMC
, lplf
);
2884 SetLastError(ERROR_INVALID_HANDLE
);
2888 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2891 memcpy(&data
->IMC
.lfFont
.W
,lplf
,sizeof(LOGFONTA
));
2892 MultiByteToWideChar(CP_ACP
, 0, lplf
->lfFaceName
, -1, data
->IMC
.lfFont
.W
.lfFaceName
,
2894 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
);
2895 ImmInternalSendIMENotify(data
, IMN_SETCOMPOSITIONFONT
, 0);
2900 /***********************************************************************
2901 * ImmSetCompositionFontW (IMM32.@)
2903 BOOL WINAPI
ImmSetCompositionFontW(HIMC hIMC
, LPLOGFONTW lplf
)
2905 InputContextData
*data
= get_imc_data(hIMC
);
2906 TRACE("(%p, %p)\n", hIMC
, lplf
);
2910 SetLastError(ERROR_INVALID_HANDLE
);
2914 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
2917 data
->IMC
.lfFont
.W
= *lplf
;
2918 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, 0, IMC_SETCOMPOSITIONFONT
);
2919 ImmInternalSendIMENotify(data
, IMN_SETCOMPOSITIONFONT
, 0);
2924 /***********************************************************************
2925 * ImmSetCompositionStringA (IMM32.@)
2927 BOOL WINAPI
ImmSetCompositionStringA(
2928 HIMC hIMC
, DWORD dwIndex
,
2929 LPCVOID lpComp
, DWORD dwCompLen
,
2930 LPCVOID lpRead
, DWORD dwReadLen
)
2934 WCHAR
*CompBuffer
= NULL
;
2935 WCHAR
*ReadBuffer
= NULL
;
2937 InputContextData
*data
= get_imc_data(hIMC
);
2939 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2940 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
2945 if (!(dwIndex
== SCS_SETSTR
||
2946 dwIndex
== SCS_CHANGEATTR
||
2947 dwIndex
== SCS_CHANGECLAUSE
||
2948 dwIndex
== SCS_SETRECONVERTSTRING
||
2949 dwIndex
== SCS_QUERYRECONVERTSTRING
))
2952 if (!is_himc_ime_unicode(data
))
2953 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
2954 dwCompLen
, lpRead
, dwReadLen
);
2956 comp_len
= MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0);
2959 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
* sizeof(WCHAR
));
2960 MultiByteToWideChar(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
);
2963 read_len
= MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0);
2966 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
* sizeof(WCHAR
));
2967 MultiByteToWideChar(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
);
2970 rc
= ImmSetCompositionStringW(hIMC
, dwIndex
, CompBuffer
, comp_len
,
2971 ReadBuffer
, read_len
);
2973 HeapFree(GetProcessHeap(), 0, CompBuffer
);
2974 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
2979 /***********************************************************************
2980 * ImmSetCompositionStringW (IMM32.@)
2982 BOOL WINAPI
ImmSetCompositionStringW(
2983 HIMC hIMC
, DWORD dwIndex
,
2984 LPCVOID lpComp
, DWORD dwCompLen
,
2985 LPCVOID lpRead
, DWORD dwReadLen
)
2989 CHAR
*CompBuffer
= NULL
;
2990 CHAR
*ReadBuffer
= NULL
;
2992 InputContextData
*data
= get_imc_data(hIMC
);
2994 TRACE("(%p, %d, %p, %d, %p, %d):\n",
2995 hIMC
, dwIndex
, lpComp
, dwCompLen
, lpRead
, dwReadLen
);
3000 if (!(dwIndex
== SCS_SETSTR
||
3001 dwIndex
== SCS_CHANGEATTR
||
3002 dwIndex
== SCS_CHANGECLAUSE
||
3003 dwIndex
== SCS_SETRECONVERTSTRING
||
3004 dwIndex
== SCS_QUERYRECONVERTSTRING
))
3007 if (is_himc_ime_unicode(data
))
3008 return data
->immKbd
->pImeSetCompositionString(hIMC
, dwIndex
, lpComp
,
3009 dwCompLen
, lpRead
, dwReadLen
);
3011 comp_len
= WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, NULL
, 0, NULL
,
3015 CompBuffer
= HeapAlloc(GetProcessHeap(),0,comp_len
);
3016 WideCharToMultiByte(CP_ACP
, 0, lpComp
, dwCompLen
, CompBuffer
, comp_len
,
3020 read_len
= WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, NULL
, 0, NULL
,
3024 ReadBuffer
= HeapAlloc(GetProcessHeap(),0,read_len
);
3025 WideCharToMultiByte(CP_ACP
, 0, lpRead
, dwReadLen
, ReadBuffer
, read_len
,
3029 rc
= ImmSetCompositionStringA(hIMC
, dwIndex
, CompBuffer
, comp_len
,
3030 ReadBuffer
, read_len
);
3032 HeapFree(GetProcessHeap(), 0, CompBuffer
);
3033 HeapFree(GetProcessHeap(), 0, ReadBuffer
);
3038 /***********************************************************************
3039 * ImmSetCompositionWindow (IMM32.@)
3041 BOOL WINAPI
ImmSetCompositionWindow(
3042 HIMC hIMC
, LPCOMPOSITIONFORM lpCompForm
)
3044 DWORD dwImeThreadId
, dwThreadId
;
3048 dwImeThreadId
= NtUserQueryInputContext(hIMC
, 1);
3049 dwThreadId
= GetCurrentThreadId();
3050 if (dwImeThreadId
!= dwThreadId
)
3053 pIC
= ImmLockIMC(hIMC
);
3057 pIC
->cfCompForm
= *lpCompForm
;
3058 pIC
->fdwInit
|= INIT_COMPFORM
;
3064 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
3065 IMC_SETCOMPOSITIONWINDOW
, IMN_SETCOMPOSITIONWINDOW
, 0);
3069 /***********************************************************************
3070 * ImmSetConversionStatus (IMM32.@)
3072 BOOL WINAPI
ImmSetConversionStatus(
3073 HIMC hIMC
, DWORD fdwConversion
, DWORD fdwSentence
)
3075 DWORD oldConversion
, oldSentence
;
3076 InputContextData
*data
= get_imc_data(hIMC
);
3078 TRACE("%p %d %d\n", hIMC
, fdwConversion
, fdwSentence
);
3082 SetLastError(ERROR_INVALID_HANDLE
);
3086 if (IMM_IsCrossThreadAccess(NULL
, hIMC
))
3089 if ( fdwConversion
!= data
->IMC
.fdwConversion
)
3091 oldConversion
= data
->IMC
.fdwConversion
;
3092 data
->IMC
.fdwConversion
= fdwConversion
;
3093 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, oldConversion
, IMC_SETCONVERSIONMODE
);
3094 ImmInternalSendIMENotify(data
, IMN_SETCONVERSIONMODE
, 0);
3096 if ( fdwSentence
!= data
->IMC
.fdwSentence
)
3098 oldSentence
= data
->IMC
.fdwSentence
;
3099 data
->IMC
.fdwSentence
= fdwSentence
;
3100 ImmNotifyIME(hIMC
, NI_CONTEXTUPDATED
, oldSentence
, IMC_SETSENTENCEMODE
);
3101 ImmInternalSendIMENotify(data
, IMN_SETSENTENCEMODE
, 0);
3107 /***********************************************************************
3108 * ImmLockImeDpi (IMM32.@)
3110 PIMEDPI WINAPI
ImmLockImeDpi(HKL hKL
)
3112 PIMEDPI pImeDpi
= NULL
;
3114 TRACE("ImmLockImeDpi(%p)\n", hKL
);
3116 RtlEnterCriticalSection(&g_csImeDpi
);
3119 for (pImeDpi
= g_pImeDpiList
; pImeDpi
; pImeDpi
= pImeDpi
->pNext
)
3121 if (pImeDpi
->hKL
== hKL
) /* found */
3123 /* lock if possible */
3124 if (pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
)
3127 ++(pImeDpi
->cLockObj
);
3132 RtlLeaveCriticalSection(&g_csImeDpi
);
3136 /***********************************************************************
3137 * ImmUnlockImeDpi (IMM32.@)
3139 VOID WINAPI
ImmUnlockImeDpi(PIMEDPI pImeDpi
)
3143 TRACE("ImmUnlockImeDpi(%p)\n", pImeDpi
);
3145 if (pImeDpi
== NULL
)
3148 RtlEnterCriticalSection(&g_csImeDpi
);
3151 --(pImeDpi
->cLockObj
);
3152 if (pImeDpi
->cLockObj
!= 0)
3154 RtlLeaveCriticalSection(&g_csImeDpi
);
3158 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN
) == 0)
3160 if ((pImeDpi
->dwFlags
& IMEDPI_FLAG_UNKNOWN2
) == 0 ||
3161 (pImeDpi
->dwUnknown1
& 1) == 0)
3163 RtlLeaveCriticalSection(&g_csImeDpi
);
3168 /* Remove from list */
3169 for (ppEntry
= &g_pImeDpiList
; *ppEntry
; ppEntry
= &((*ppEntry
)->pNext
))
3171 if (*ppEntry
== pImeDpi
) /* found */
3173 *ppEntry
= pImeDpi
->pNext
;
3178 Imm32FreeImeDpi(pImeDpi
, TRUE
);
3179 HeapFree(g_hImm32Heap
, 0, pImeDpi
);
3181 RtlLeaveCriticalSection(&g_csImeDpi
);
3184 /***********************************************************************
3185 * ImmSetOpenStatus (IMM32.@)
3187 BOOL WINAPI
ImmSetOpenStatus(HIMC hIMC
, BOOL fOpen
)
3189 DWORD dwImeThreadId
, dwThreadId
, dwConversion
;
3192 BOOL bHasChange
= FALSE
;
3194 TRACE("ImmSetOpenStatus(%p, %d)\n", hIMC
, fOpen
);
3196 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
3197 dwThreadId
= GetCurrentThreadId();
3198 if (dwImeThreadId
!= dwThreadId
)
3201 pIC
= ImmLockIMC(hIMC
);
3205 if (pIC
->fOpen
!= fOpen
)
3209 dwConversion
= pIC
->fdwConversion
;
3217 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
3218 IMC_SETOPENSTATUS
, IMN_SETOPENSTATUS
, 0);
3219 Imm32NotifyIMEStatus(hWnd
, hIMC
, dwConversion
);
3225 /***********************************************************************
3226 * ImmSetStatusWindowPos (IMM32.@)
3228 BOOL WINAPI
ImmSetStatusWindowPos(HIMC hIMC
, LPPOINT lpptPos
)
3232 DWORD dwImeThreadId
, dwThreadId
;
3234 TRACE("ImmSetStatusWindowPos(%p, {%ld, %ld})\n", hIMC
, lpptPos
->x
, lpptPos
->y
);
3236 dwImeThreadId
= Imm32QueryInputContext(hIMC
, 1);
3237 dwThreadId
= GetCurrentThreadId();
3238 if (dwImeThreadId
!= dwThreadId
)
3241 pIC
= ImmLockIMC(hIMC
);
3246 pIC
->ptStatusWndPos
= *lpptPos
;
3247 pIC
->fdwInit
|= INIT_STATUSWNDPOS
;
3251 Imm32NotifyAction(hIMC
, hWnd
, NI_CONTEXTUPDATED
, 0,
3252 IMC_SETSTATUSWINDOWPOS
, IMN_SETSTATUSWINDOWPOS
, 0);
3256 /***********************************************************************
3257 * ImmCreateSoftKeyboard(IMM32.@)
3259 HWND WINAPI
ImmCreateSoftKeyboard(UINT uType
, UINT hOwner
, int x
, int y
)
3261 FIXME("(%d, %d, %d, %d): stub\n", uType
, hOwner
, x
, y
);
3262 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3266 /***********************************************************************
3267 * ImmDestroySoftKeyboard(IMM32.@)
3269 BOOL WINAPI
ImmDestroySoftKeyboard(HWND hSoftWnd
)
3271 TRACE("(%p)\n", hSoftWnd
);
3272 return DestroyWindow(hSoftWnd
);
3275 /***********************************************************************
3276 * ImmShowSoftKeyboard(IMM32.@)
3278 BOOL WINAPI
ImmShowSoftKeyboard(HWND hSoftWnd
, int nCmdShow
)
3280 TRACE("(%p, %d)\n", hSoftWnd
, nCmdShow
);
3282 return ShowWindow(hSoftWnd
, nCmdShow
);
3286 /***********************************************************************
3287 * ImmSimulateHotKey (IMM32.@)
3289 BOOL WINAPI
ImmSimulateHotKey(HWND hWnd
, DWORD dwHotKeyID
)
3291 FIXME("(%p, %d): stub\n", hWnd
, dwHotKeyID
);
3292 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3296 /***********************************************************************
3297 * ImmUnregisterWordA (IMM32.@)
3299 BOOL WINAPI
ImmUnregisterWordA(
3300 HKL hKL
, LPCSTR lpszReading
, DWORD dwStyle
, LPCSTR lpszUnregister
)
3302 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
3303 TRACE("(%p, %s, %d, %s):\n", hKL
, debugstr_a(lpszReading
), dwStyle
,
3304 debugstr_a(lpszUnregister
));
3305 if (immHkl
->hIME
&& immHkl
->pImeUnregisterWord
)
3307 if (!is_kbd_ime_unicode(immHkl
))
3308 return immHkl
->pImeUnregisterWord((LPCWSTR
)lpszReading
,dwStyle
,
3309 (LPCWSTR
)lpszUnregister
);
3312 LPWSTR lpszwReading
= strdupAtoW(lpszReading
);
3313 LPWSTR lpszwUnregister
= strdupAtoW(lpszUnregister
);
3316 rc
= immHkl
->pImeUnregisterWord(lpszwReading
,dwStyle
,lpszwUnregister
);
3317 HeapFree(GetProcessHeap(),0,lpszwReading
);
3318 HeapFree(GetProcessHeap(),0,lpszwUnregister
);
3326 /***********************************************************************
3327 * ImmUnregisterWordW (IMM32.@)
3329 BOOL WINAPI
ImmUnregisterWordW(
3330 HKL hKL
, LPCWSTR lpszReading
, DWORD dwStyle
, LPCWSTR lpszUnregister
)
3332 ImmHkl
*immHkl
= IMM_GetImmHkl(hKL
);
3333 TRACE("(%p, %s, %d, %s):\n", hKL
, debugstr_w(lpszReading
), dwStyle
,
3334 debugstr_w(lpszUnregister
));
3335 if (immHkl
->hIME
&& immHkl
->pImeUnregisterWord
)
3337 if (is_kbd_ime_unicode(immHkl
))
3338 return immHkl
->pImeUnregisterWord(lpszReading
,dwStyle
,lpszUnregister
);
3341 LPSTR lpszaReading
= strdupWtoA(lpszReading
);
3342 LPSTR lpszaUnregister
= strdupWtoA(lpszUnregister
);
3345 rc
= immHkl
->pImeUnregisterWord((LPCWSTR
)lpszaReading
,dwStyle
,
3346 (LPCWSTR
)lpszaUnregister
);
3347 HeapFree(GetProcessHeap(),0,lpszaReading
);
3348 HeapFree(GetProcessHeap(),0,lpszaUnregister
);
3356 /***********************************************************************
3357 * ImmGetImeMenuItemsA (IMM32.@)
3359 DWORD WINAPI
ImmGetImeMenuItemsA( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
3360 LPIMEMENUITEMINFOA lpImeParentMenu
, LPIMEMENUITEMINFOA lpImeMenu
,
3363 InputContextData
*data
= get_imc_data(hIMC
);
3364 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
3365 lpImeParentMenu
, lpImeMenu
, dwSize
);
3369 SetLastError(ERROR_INVALID_HANDLE
);
3373 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
3375 if (!is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
3376 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
3377 (IMEMENUITEMINFOW
*)lpImeParentMenu
,
3378 (IMEMENUITEMINFOW
*)lpImeMenu
, dwSize
);
3381 IMEMENUITEMINFOW lpImeParentMenuW
;
3382 IMEMENUITEMINFOW
*lpImeMenuW
, *parent
= NULL
;
3385 if (lpImeParentMenu
)
3386 parent
= &lpImeParentMenuW
;
3389 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOA
);
3390 dwSize
= count
* sizeof(IMEMENUITEMINFOW
);
3391 lpImeMenuW
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
3396 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
3397 parent
, lpImeMenuW
, dwSize
);
3399 if (lpImeParentMenu
)
3401 memcpy(lpImeParentMenu
,&lpImeParentMenuW
,sizeof(IMEMENUITEMINFOA
));
3402 lpImeParentMenu
->hbmpItem
= lpImeParentMenuW
.hbmpItem
;
3403 WideCharToMultiByte(CP_ACP
, 0, lpImeParentMenuW
.szString
,
3404 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
,
3407 if (lpImeMenu
&& rc
)
3410 for (i
= 0; i
< rc
; i
++)
3412 memcpy(&lpImeMenu
[i
],&lpImeMenuW
[1],sizeof(IMEMENUITEMINFOA
));
3413 lpImeMenu
[i
].hbmpItem
= lpImeMenuW
[i
].hbmpItem
;
3414 WideCharToMultiByte(CP_ACP
, 0, lpImeMenuW
[i
].szString
,
3415 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
,
3419 HeapFree(GetProcessHeap(),0,lpImeMenuW
);
3427 /***********************************************************************
3428 * ImmGetImeMenuItemsW (IMM32.@)
3430 DWORD WINAPI
ImmGetImeMenuItemsW( HIMC hIMC
, DWORD dwFlags
, DWORD dwType
,
3431 LPIMEMENUITEMINFOW lpImeParentMenu
, LPIMEMENUITEMINFOW lpImeMenu
,
3434 InputContextData
*data
= get_imc_data(hIMC
);
3435 TRACE("(%p, %i, %i, %p, %p, %i):\n", hIMC
, dwFlags
, dwType
,
3436 lpImeParentMenu
, lpImeMenu
, dwSize
);
3440 SetLastError(ERROR_INVALID_HANDLE
);
3444 if (data
->immKbd
->hIME
&& data
->immKbd
->pImeGetImeMenuItems
)
3446 if (is_himc_ime_unicode(data
) || (!lpImeParentMenu
&& !lpImeMenu
))
3447 return data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
3448 lpImeParentMenu
, lpImeMenu
, dwSize
);
3451 IMEMENUITEMINFOA lpImeParentMenuA
;
3452 IMEMENUITEMINFOA
*lpImeMenuA
, *parent
= NULL
;
3455 if (lpImeParentMenu
)
3456 parent
= &lpImeParentMenuA
;
3459 int count
= dwSize
/ sizeof(LPIMEMENUITEMINFOW
);
3460 dwSize
= count
* sizeof(IMEMENUITEMINFOA
);
3461 lpImeMenuA
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
3466 rc
= data
->immKbd
->pImeGetImeMenuItems(hIMC
, dwFlags
, dwType
,
3467 (IMEMENUITEMINFOW
*)parent
,
3468 (IMEMENUITEMINFOW
*)lpImeMenuA
, dwSize
);
3470 if (lpImeParentMenu
)
3472 memcpy(lpImeParentMenu
,&lpImeParentMenuA
,sizeof(IMEMENUITEMINFOA
));
3473 lpImeParentMenu
->hbmpItem
= lpImeParentMenuA
.hbmpItem
;
3474 MultiByteToWideChar(CP_ACP
, 0, lpImeParentMenuA
.szString
,
3475 -1, lpImeParentMenu
->szString
, IMEMENUITEM_STRING_SIZE
);
3477 if (lpImeMenu
&& rc
)
3480 for (i
= 0; i
< rc
; i
++)
3482 memcpy(&lpImeMenu
[i
],&lpImeMenuA
[1],sizeof(IMEMENUITEMINFOA
));
3483 lpImeMenu
[i
].hbmpItem
= lpImeMenuA
[i
].hbmpItem
;
3484 MultiByteToWideChar(CP_ACP
, 0, lpImeMenuA
[i
].szString
,
3485 -1, lpImeMenu
[i
].szString
, IMEMENUITEM_STRING_SIZE
);
3488 HeapFree(GetProcessHeap(),0,lpImeMenuA
);
3496 /***********************************************************************
3497 * ImmLockIMC(IMM32.@)
3499 LPINPUTCONTEXT WINAPI
ImmLockIMC(HIMC hIMC
)
3501 InputContextData
*data
= get_imc_data(hIMC
);
3509 /***********************************************************************
3510 * ImmUnlockIMC(IMM32.@)
3512 BOOL WINAPI
ImmUnlockIMC(HIMC hIMC
)
3514 PCLIENTIMC pClientImc
;
3517 pClientImc
= ImmLockClientImc(hIMC
);
3518 if (pClientImc
== NULL
)
3521 hClientImc
= pClientImc
->hImc
;
3523 LocalUnlock(hClientImc
);
3525 InterlockedDecrement(&pClientImc
->cLockObj
);
3526 ImmUnlockClientImc(pClientImc
);
3530 /***********************************************************************
3531 * ImmGetIMCLockCount(IMM32.@)
3533 DWORD WINAPI
ImmGetIMCLockCount(HIMC hIMC
)
3537 PCLIENTIMC pClientImc
;
3539 pClientImc
= ImmLockClientImc(hIMC
);
3540 if (pClientImc
== NULL
)
3544 hClientImc
= pClientImc
->hImc
;
3546 ret
= (LocalFlags(hClientImc
) & LMEM_LOCKCOUNT
);
3548 ImmUnlockClientImc(pClientImc
);
3552 /***********************************************************************
3553 * ImmCreateIMCC(IMM32.@)
3555 HIMCC WINAPI
ImmCreateIMCC(DWORD size
)
3559 return LocalAlloc(LHND
, size
);
3562 /***********************************************************************
3563 * ImmDestroyIMCC(IMM32.@)
3565 HIMCC WINAPI
ImmDestroyIMCC(HIMCC block
)
3568 return LocalFree(block
);
3572 /***********************************************************************
3573 * ImmLockIMCC(IMM32.@)
3575 LPVOID WINAPI
ImmLockIMCC(HIMCC imcc
)
3578 return LocalLock(imcc
);
3582 /***********************************************************************
3583 * ImmUnlockIMCC(IMM32.@)
3585 BOOL WINAPI
ImmUnlockIMCC(HIMCC imcc
)
3588 return LocalUnlock(imcc
);
3592 /***********************************************************************
3593 * ImmGetIMCCLockCount(IMM32.@)
3595 DWORD WINAPI
ImmGetIMCCLockCount(HIMCC imcc
)
3597 return LocalFlags(imcc
) & LMEM_LOCKCOUNT
;
3600 /***********************************************************************
3601 * ImmReSizeIMCC(IMM32.@)
3603 HIMCC WINAPI
ImmReSizeIMCC(HIMCC imcc
, DWORD size
)
3607 return LocalReAlloc(imcc
, size
, LHND
);
3610 /***********************************************************************
3611 * ImmGetIMCCSize(IMM32.@)
3613 DWORD WINAPI
ImmGetIMCCSize(HIMCC imcc
)
3616 return LocalSize(imcc
);
3620 /***********************************************************************
3621 * ImmGenerateMessage(IMM32.@)
3623 BOOL WINAPI
ImmGenerateMessage(HIMC hIMC
)
3625 InputContextData
*data
= get_imc_data(hIMC
);
3629 SetLastError(ERROR_INVALID_HANDLE
);
3633 TRACE("%i messages queued\n",data
->IMC
.dwNumMsgBuf
);
3634 if (data
->IMC
.dwNumMsgBuf
> 0)
3636 LPTRANSMSG lpTransMsg
;
3638 DWORD i
, dwNumMsgBuf
;
3640 /* We are going to detach our hMsgBuff so that if processing messages
3641 generates new messages they go into a new buffer */
3642 hMsgBuf
= data
->IMC
.hMsgBuf
;
3643 dwNumMsgBuf
= data
->IMC
.dwNumMsgBuf
;
3645 data
->IMC
.hMsgBuf
= ImmCreateIMCC(0);
3646 data
->IMC
.dwNumMsgBuf
= 0;
3648 lpTransMsg
= ImmLockIMCC(hMsgBuf
);
3649 for (i
= 0; i
< dwNumMsgBuf
; i
++)
3650 ImmInternalSendIMEMessage(data
, lpTransMsg
[i
].message
, lpTransMsg
[i
].wParam
, lpTransMsg
[i
].lParam
);
3652 ImmUnlockIMCC(hMsgBuf
);
3653 ImmDestroyIMCC(hMsgBuf
);
3659 /***********************************************************************
3660 * ImmTranslateMessage(IMM32.@)
3661 * ( Undocumented, call internally and from user32.dll )
3663 BOOL WINAPI
ImmTranslateMessage(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lKeyData
)
3665 InputContextData
*data
;
3666 HIMC imc
= ImmGetContext(hwnd
);
3672 static const DWORD list_count
= 10;
3674 TRACE("%p %x %x %x\n",hwnd
, msg
, (UINT
)wParam
, (UINT
)lKeyData
);
3681 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeToAsciiEx
)
3684 GetKeyboardState(state
);
3685 scancode
= lKeyData
>> 0x10 & 0xff;
3687 list
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, list_count
* sizeof(TRANSMSG
) + sizeof(DWORD
));
3688 ((DWORD
*)list
)[0] = list_count
;
3690 if (data
->immKbd
->imeInfo
.fdwProperty
& IME_PROP_KBD_CHAR_FIRST
)
3694 if (!is_himc_ime_unicode(data
))
3695 ToAscii(data
->lastVK
, scancode
, state
, &chr
, 0);
3697 ToUnicodeEx(data
->lastVK
, scancode
, state
, &chr
, 1, 0, GetKeyboardLayout(0));
3698 uVirtKey
= MAKELONG(data
->lastVK
,chr
);
3701 uVirtKey
= data
->lastVK
;
3703 msg_count
= data
->immKbd
->pImeToAsciiEx(uVirtKey
, scancode
, state
, list
, 0, imc
);
3704 TRACE("%i messages generated\n",msg_count
);
3705 if (msg_count
&& msg_count
<= list_count
)
3708 LPTRANSMSG msgs
= (LPTRANSMSG
)((LPBYTE
)list
+ sizeof(DWORD
));
3710 for (i
= 0; i
< msg_count
; i
++)
3711 ImmInternalPostIMEMessage(data
, msgs
[i
].message
, msgs
[i
].wParam
, msgs
[i
].lParam
);
3713 else if (msg_count
> list_count
)
3714 ImmGenerateMessage(imc
);
3716 HeapFree(GetProcessHeap(),0,list
);
3718 data
->lastVK
= VK_PROCESSKEY
;
3720 return (msg_count
> 0);
3723 /***********************************************************************
3724 * ImmProcessKey(IMM32.@)
3725 * ( Undocumented, called from user32.dll )
3727 BOOL WINAPI
ImmProcessKey(HWND hwnd
, HKL hKL
, UINT vKey
, LPARAM lKeyData
, DWORD unknown
)
3729 InputContextData
*data
;
3730 HIMC imc
= ImmGetContext(hwnd
);
3733 TRACE("%p %p %x %x %x\n",hwnd
, hKL
, vKey
, (UINT
)lKeyData
, unknown
);
3740 /* Make sure we are inputting to the correct keyboard */
3741 if (data
->immKbd
->hkl
!= hKL
)
3743 ImmHkl
*new_hkl
= IMM_GetImmHkl(hKL
);
3746 data
->immKbd
->pImeSelect(imc
, FALSE
);
3747 data
->immKbd
->uSelected
--;
3748 data
->immKbd
= new_hkl
;
3749 data
->immKbd
->pImeSelect(imc
, TRUE
);
3750 data
->immKbd
->uSelected
++;
3756 if (!data
->immKbd
->hIME
|| !data
->immKbd
->pImeProcessKey
)
3759 GetKeyboardState(state
);
3760 if (data
->immKbd
->pImeProcessKey(imc
, vKey
, lKeyData
, state
))
3762 data
->lastVK
= vKey
;
3766 data
->lastVK
= VK_PROCESSKEY
;
3770 /***********************************************************************
3771 * ImmDisableTextFrameService(IMM32.@)
3773 BOOL WINAPI
ImmDisableTextFrameService(DWORD dwThreadId
)
3779 /***********************************************************************
3780 * ImmEnumInputContext(IMM32.@)
3782 BOOL WINAPI
ImmEnumInputContext(DWORD dwThreadId
, IMCENUMPROC lpfn
, LPARAM lParam
)
3785 DWORD dwIndex
, dwCount
;
3789 TRACE("ImmEnumInputContext(%lu, %p, %p)\n", dwThreadId
, lpfn
, lParam
);
3791 dwCount
= Imm32AllocAndBuildHimcList(dwThreadId
, &phList
);
3795 for (dwIndex
= 0; dwIndex
< dwCount
; ++dwIndex
)
3797 hIMC
= phList
[dwIndex
];
3798 ret
= (*lpfn
)(hIMC
, lParam
);
3803 HeapFree(g_hImm32Heap
, 0, phList
);
3807 /***********************************************************************
3808 * ImmGetHotKey(IMM32.@)
3812 ImmGetHotKey(IN DWORD dwHotKey
,
3813 OUT LPUINT lpuModifiers
,
3817 TRACE("%lx, %p, %p, %p\n", dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
3818 if (lpuModifiers
&& lpuVKey
)
3819 return NtUserGetImeHotKey(dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
3823 /***********************************************************************
3824 * ImmDisableLegacyIME(IMM32.@)
3826 BOOL WINAPI
ImmDisableLegacyIME(void)
3832 /***********************************************************************
3833 * ImmSetActiveContext(IMM32.@)
3835 BOOL WINAPI
ImmSetActiveContext(HWND hwnd
, HIMC hIMC
, BOOL fFlag
)
3837 FIXME("(%p, %p, %d): stub\n", hwnd
, hIMC
, fFlag
);
3841 /***********************************************************************
3842 * ImmSetActiveContextConsoleIME(IMM32.@)
3844 BOOL WINAPI
ImmSetActiveContextConsoleIME(HWND hwnd
, BOOL fFlag
)
3847 TRACE("(%p, %d)\n", hwnd
, fFlag
);
3849 hIMC
= ImmGetContext(hwnd
);
3851 return ImmSetActiveContext(hwnd
, hIMC
, fFlag
);
3855 /***********************************************************************
3856 * ImmRegisterClient(IMM32.@)
3857 * ( Undocumented, called from user32.dll )
3859 BOOL WINAPI
ImmRegisterClient(PVOID ptr
, /* FIXME: should point to SHAREDINFO structure */
3866 /***********************************************************************
3867 * CtfImmIsTextFrameServiceDisabled(IMM32.@)
3869 BOOL WINAPI
CtfImmIsTextFrameServiceDisabled(VOID
)
3871 PTEB pTeb
= NtCurrentTeb();
3872 if (((PW32CLIENTINFO
)pTeb
->Win32ClientInfo
)->CI_flags
& CI_TFSDISABLED
)
3877 /***********************************************************************
3878 * ImmGetImeInfoEx (IMM32.@)
3881 static BOOL APIENTRY
Imm32GetImeInfoEx(PIMEINFOEX pImeInfoEx
, IMEINFOEXCLASS SearchType
)
3883 return NtUserGetImeInfoEx(pImeInfoEx
, SearchType
);
3887 ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx
,
3888 IMEINFOEXCLASS SearchType
,
3891 BOOL bDisabled
= FALSE
;
3897 case ImeInfoExKeyboardLayout
:
3900 case ImeInfoExImeWindow
:
3901 bDisabled
= CtfImmIsTextFrameServiceDisabled();
3902 SearchType
= ImeInfoExKeyboardLayout
;
3905 case ImeInfoExImeFileName
:
3906 StringCchCopyW(pImeInfoEx
->wszImeFile
, _countof(pImeInfoEx
->wszImeFile
),
3911 hKL
= *(HKL
*)pvSearchKey
;
3912 pImeInfoEx
->hkl
= hKL
;
3914 if (!IS_IME_HKL(hKL
))
3916 if (g_dwImm32Flags
& IMM32_FLAG_CICERO_ENABLED
)
3918 pTeb
= NtCurrentTeb();
3919 if (((PW32CLIENTINFO
)pTeb
->Win32ClientInfo
)->W32ClientInfo
[0] & 2)
3928 return Imm32GetImeInfoEx(pImeInfoEx
, SearchType
);