2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IMM32 keys and messages
5 * COPYRIGHT: Copyright 1998 Patrik Stridvall
6 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * Copyright 2017 James Tabor <james.tabor@reactos.org>
8 * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
9 * Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
10 * Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
15 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
17 BOOL APIENTRY
Imm32ImeNonImeToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
, LANGID LangID
)
25 if (!IS_IME_HKL(hKL
) || LOWORD(hKL
) != LangID
)
27 FIXME("We have to do something here\n");
31 pIC
= ImmLockIMC(hIMC
);
40 ImmSetOpenStatus(hIMC
, TRUE
);
44 FIXME("We have to do something here\n");
48 BOOL APIENTRY
Imm32CShapeToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
)
52 DWORD dwConversion
, dwSentence
;
54 if (hWnd
== NULL
|| !IS_IME_HKL(hKL
))
57 pIC
= ImmLockIMC(hIMC
);
64 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_FULLSHAPE
);
65 dwSentence
= pIC
->fdwSentence
;
71 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
73 ImmSetOpenStatus(hIMC
, TRUE
);
78 BOOL APIENTRY
Imm32CSymbolToggle(HIMC hIMC
, HKL hKL
, HWND hWnd
)
82 DWORD dwConversion
, dwSentence
;
84 if (hWnd
== NULL
|| !IS_IME_HKL(hKL
))
87 pIC
= ImmLockIMC(hIMC
);
94 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_SYMBOL
);
95 dwSentence
= pIC
->fdwSentence
;
101 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
103 ImmSetOpenStatus(hIMC
, TRUE
);
108 BOOL APIENTRY
Imm32JCloseOpen(HIMC hIMC
, HKL hKL
, HWND hWnd
)
112 if (ImmIsIME(hKL
) && LOWORD(hKL
) == LANGID_JAPANESE
)
114 fOpen
= ImmGetOpenStatus(hIMC
);
115 ImmSetOpenStatus(hIMC
, !fOpen
);
119 FIXME("We have to do something here\n");
123 BOOL APIENTRY
Imm32KShapeToggle(HIMC hIMC
)
126 DWORD dwConversion
, dwSentence
;
128 pIC
= ImmLockIMC(hIMC
);
132 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_FULLSHAPE
);
133 dwSentence
= pIC
->fdwSentence
;
134 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
136 if (pIC
->fdwConversion
& (IME_CMODE_FULLSHAPE
| IME_CMODE_NATIVE
))
137 ImmSetOpenStatus(hIMC
, TRUE
);
139 ImmSetOpenStatus(hIMC
, FALSE
);
145 BOOL APIENTRY
Imm32KHanjaConvert(HIMC hIMC
)
148 DWORD dwConversion
, dwSentence
;
150 pIC
= ImmLockIMC(hIMC
);
154 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_HANJACONVERT
);
155 dwSentence
= pIC
->fdwSentence
;
158 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
162 BOOL APIENTRY
Imm32KEnglish(HIMC hIMC
)
165 DWORD dwConversion
, dwSentence
;
168 pIC
= ImmLockIMC(hIMC
);
172 dwConversion
= (pIC
->fdwConversion
^ IME_CMODE_NATIVE
);
173 dwSentence
= pIC
->fdwSentence
;
174 ImmSetConversionStatus(hIMC
, dwConversion
, dwSentence
);
176 fOpen
= ((pIC
->fdwConversion
& (IME_CMODE_FULLSHAPE
| IME_CMODE_NATIVE
)) != 0);
177 ImmSetOpenStatus(hIMC
, fOpen
);
183 BOOL APIENTRY
Imm32ProcessHotKey(HWND hWnd
, HIMC hIMC
, HKL hKL
, DWORD dwHotKeyID
)
188 if (hIMC
&& Imm32IsCrossThreadAccess(hIMC
))
193 case IME_CHOTKEY_IME_NONIME_TOGGLE
:
194 return Imm32ImeNonImeToggle(hIMC
, hKL
, hWnd
, LANGID_CHINESE_SIMPLIFIED
);
196 case IME_CHOTKEY_SHAPE_TOGGLE
:
197 return Imm32CShapeToggle(hIMC
, hKL
, hWnd
);
199 case IME_CHOTKEY_SYMBOL_TOGGLE
:
200 return Imm32CSymbolToggle(hIMC
, hKL
, hWnd
);
202 case IME_JHOTKEY_CLOSE_OPEN
:
203 return Imm32JCloseOpen(hIMC
, hKL
, hWnd
);
205 case IME_KHOTKEY_SHAPE_TOGGLE
:
206 return Imm32KShapeToggle(hIMC
);
208 case IME_KHOTKEY_HANJACONVERT
:
209 return Imm32KHanjaConvert(hIMC
);
211 case IME_KHOTKEY_ENGLISH
:
212 return Imm32KEnglish(hIMC
);
214 case IME_THOTKEY_IME_NONIME_TOGGLE
:
215 return Imm32ImeNonImeToggle(hIMC
, hKL
, hWnd
, LANGID_CHINESE_TRADITIONAL
);
217 case IME_THOTKEY_SHAPE_TOGGLE
:
218 return Imm32CShapeToggle(hIMC
, hKL
, hWnd
);
220 case IME_THOTKEY_SYMBOL_TOGGLE
:
221 return Imm32CSymbolToggle(hIMC
, hKL
, hWnd
);
227 if (dwHotKeyID
< IME_HOTKEY_PRIVATE_FIRST
|| IME_HOTKEY_PRIVATE_LAST
< dwHotKeyID
)
230 pImeDpi
= ImmLockImeDpi(hKL
);
234 ret
= (BOOL
)pImeDpi
->ImeEscape(hIMC
, IME_ESC_PRIVATE_HOTKEY
, &dwHotKeyID
);
235 ImmUnlockImeDpi(pImeDpi
);
240 ImmIsUIMessageAW(HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
, BOOL bAnsi
)
244 case WM_IME_STARTCOMPOSITION
: case WM_IME_ENDCOMPOSITION
:
245 case WM_IME_COMPOSITION
: case WM_IME_SETCONTEXT
: case WM_IME_NOTIFY
:
246 case WM_IME_COMPOSITIONFULL
: case WM_IME_SELECT
: case WM_IME_SYSTEM
:
256 SendMessageA(hWndIME
, msg
, wParam
, lParam
);
258 SendMessageW(hWndIME
, msg
, wParam
, lParam
);
263 typedef struct IMM_UNKNOWN_PROCESS1
267 } IMM_UNKNOWN_PROCESS1
, *PIMM_UNKNOWN_PROCESS1
;
269 static DWORD WINAPI
Imm32UnknownProcess1Proc(LPVOID arg
)
274 PIMM_UNKNOWN_PROCESS1 pUnknown
= arg
;
277 hwndDefIME
= ImmGetDefaultIMEWnd(pUnknown
->hWnd
);
280 uValue
= (pUnknown
->fFlag
? 0x23 : 0x24);
281 SendMessageTimeoutW(hwndDefIME
, WM_IME_SYSTEM
, uValue
, (LPARAM
)pUnknown
->hWnd
,
282 SMTO_BLOCK
| SMTO_ABORTIFHUNG
, 5000, &lResult
);
284 Imm32HeapFree(pUnknown
);
288 LRESULT APIENTRY
Imm32UnknownProcess1(HWND hWnd
, BOOL fFlag
)
292 PIMM_UNKNOWN_PROCESS1 pUnknown1
;
293 DWORD_PTR lResult
= 0;
296 pWnd
= ValidateHwndNoErr(hWnd
);
301 if (pWnd
->state2
& WNDS2_WMCREATEMSGPROCESSED
)
303 SendMessageTimeoutW(hWnd
, 0x505, 0, fFlag
, 3, 5000, &lResult
);
307 pUnknown1
= Imm32HeapAlloc(0, sizeof(IMM_UNKNOWN_PROCESS1
));
311 pUnknown1
->hWnd
= hWnd
;
312 pUnknown1
->fFlag
= fFlag
;
314 hThread
= CreateThread(NULL
, 0, Imm32UnknownProcess1Proc
, pUnknown1
, 0, NULL
);
316 CloseHandle(hThread
);
320 static BOOL CALLBACK
Imm32SendChangeProc(HIMC hIMC
, LPARAM lParam
)
323 LPINPUTCONTEXTDX pIC
;
325 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
333 if (pIC
->dwChange
& INPUTCONTEXTDX_CHANGE_OPEN
)
334 SendMessageW(hWnd
, WM_IME_NOTIFY
, IMN_SETOPENSTATUS
, 0);
335 if (pIC
->dwChange
& INPUTCONTEXTDX_CHANGE_CONVERSION
)
336 SendMessageW(hWnd
, WM_IME_NOTIFY
, IMN_SETCONVERSIONMODE
, 0);
337 if (pIC
->dwChange
& (INPUTCONTEXTDX_CHANGE_OPEN
| INPUTCONTEXTDX_CHANGE_CONVERSION
))
338 NtUserNotifyIMEStatus(hWnd
, pIC
->fOpen
, pIC
->fdwConversion
);
339 if (pIC
->dwChange
& INPUTCONTEXTDX_CHANGE_SENTENCE
)
340 SendMessageW(hWnd
, WM_IME_NOTIFY
, IMN_SETSENTENCEMODE
, 0);
343 ImmUnlockIMC(hIMC
); // ??? Windows doesn't unlock here
347 BOOL APIENTRY
Imm32SendChange(BOOL bProcess
)
349 return ImmEnumInputContext((bProcess
? -1 : 0), Imm32SendChangeProc
, 0);
352 VOID APIENTRY
Imm32RequestError(DWORD dwError
)
355 SetLastError(dwError
);
359 Imm32ProcessRequest(HIMC hIMC
, PWND pWnd
, DWORD dwCommand
, LPVOID pData
, BOOL bAnsiAPI
)
362 DWORD ret
= 0, dwCharPos
, cchCompStr
;
363 LPVOID pCS
, pTempData
= pData
;
364 LPRECONVERTSTRING pRS
;
365 LPIMECHARPOSITION pICP
;
366 PCLIENTIMC pClientImc
;
367 UINT uCodePage
= CP_ACP
;
368 BOOL bAnsiWnd
= !!(pWnd
->state
& WNDS_ANSIWINDOWPROC
);
369 static const size_t acbData
[7 * 2] =
372 sizeof(COMPOSITIONFORM
), sizeof(CANDIDATEFORM
), sizeof(LOGFONTW
),
373 sizeof(RECONVERTSTRING
), sizeof(RECONVERTSTRING
),
374 sizeof(IMECHARPOSITION
), sizeof(RECONVERTSTRING
),
376 sizeof(COMPOSITIONFORM
), sizeof(CANDIDATEFORM
), sizeof(LOGFONTA
),
377 sizeof(RECONVERTSTRING
), sizeof(RECONVERTSTRING
),
378 sizeof(IMECHARPOSITION
), sizeof(RECONVERTSTRING
),
381 if (dwCommand
== 0 || dwCommand
> IMR_DOCUMENTFEED
)
382 return 0; /* Out of range */
384 if (pData
&& IsBadWritePtr(pData
, acbData
[bAnsiAPI
* 7 + dwCommand
- 1]))
385 return 0; /* Invalid pointer */
390 case IMR_RECONVERTSTRING
: case IMR_DOCUMENTFEED
:
392 if (pRS
&& (pRS
->dwVersion
!= 0 || pRS
->dwSize
< sizeof(RECONVERTSTRING
)))
394 Imm32RequestError(ERROR_INVALID_PARAMETER
);
399 case IMR_CONFIRMRECONVERTSTRING
:
401 if (!pRS
|| pRS
->dwVersion
!= 0)
403 Imm32RequestError(ERROR_INVALID_PARAMETER
);
411 Imm32RequestError(ERROR_INVALID_PARAMETER
);
417 pClientImc
= ImmLockClientImc(hIMC
);
420 uCodePage
= pClientImc
->uCodePage
;
421 ImmUnlockClientImc(pClientImc
);
427 case IMR_COMPOSITIONFONT
:
428 if (bAnsiAPI
== bAnsiWnd
)
431 pTempData
= Imm32HeapAlloc(0, sizeof(LOGFONTA
));
433 pTempData
= Imm32HeapAlloc(0, sizeof(LOGFONTW
));
438 case IMR_RECONVERTSTRING
: case IMR_CONFIRMRECONVERTSTRING
: case IMR_DOCUMENTFEED
:
439 if (bAnsiAPI
== bAnsiWnd
|| !pData
)
443 ret
= Imm32ReconvertAnsiFromWide(NULL
, pData
, uCodePage
);
445 ret
= Imm32ReconvertWideFromAnsi(NULL
, pData
, uCodePage
);
447 pTempData
= Imm32HeapAlloc(0, ret
+ sizeof(WCHAR
));
455 if (dwCommand
== IMR_CONFIRMRECONVERTSTRING
)
458 ret
= Imm32ReconvertAnsiFromWide(pTempData
, pData
, uCodePage
);
460 ret
= Imm32ReconvertWideFromAnsi(pTempData
, pData
, uCodePage
);
464 case IMR_QUERYCHARPOSITION
:
465 if (bAnsiAPI
== bAnsiWnd
)
469 dwCharPos
= pICP
->dwCharPos
;
473 cchCompStr
= ImmGetCompositionStringA(hIMC
, GCS_COMPSTR
, NULL
, 0);
477 pCS
= Imm32HeapAlloc(0, (cchCompStr
+ 1) * sizeof(CHAR
));
481 ImmGetCompositionStringA(hIMC
, GCS_COMPSTR
, pCS
, cchCompStr
);
482 pICP
->dwCharPos
= IchWideFromAnsi(pICP
->dwCharPos
, pCS
, uCodePage
);
486 cchCompStr
= ImmGetCompositionStringW(hIMC
, GCS_COMPSTR
, NULL
, 0);
490 pCS
= Imm32HeapAlloc(0, (cchCompStr
+ 1) * sizeof(WCHAR
));
494 ImmGetCompositionStringW(hIMC
, GCS_COMPSTR
, pCS
, cchCompStr
);
495 pICP
->dwCharPos
= IchAnsiFromWide(pICP
->dwCharPos
, pCS
, uCodePage
);
509 ret
= SendMessageA(hWnd
, WM_IME_REQUEST
, dwCommand
, (LPARAM
)pTempData
);
511 ret
= SendMessageW(hWnd
, WM_IME_REQUEST
, dwCommand
, (LPARAM
)pTempData
);
513 if (bAnsiAPI
== bAnsiWnd
)
516 /* Get back to caller */
519 case IMR_COMPOSITIONFONT
:
521 LogFontWideToAnsi(pTempData
, pData
);
523 LogFontAnsiToWide(pTempData
, pData
);
526 case IMR_RECONVERTSTRING
: case IMR_DOCUMENTFEED
:
530 if (ret
< sizeof(RECONVERTSTRING
))
539 ret
= Imm32ReconvertWideFromAnsi(pData
, pTempData
, uCodePage
);
541 ret
= Imm32ReconvertAnsiFromWide(pData
, pTempData
, uCodePage
);
545 case IMR_QUERYCHARPOSITION
:
546 pICP
->dwCharPos
= dwCharPos
;
554 if (pTempData
!= pData
)
555 Imm32HeapFree(pTempData
);
559 LRESULT APIENTRY
Imm32RequestMessageAW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
, BOOL bAnsi
)
566 if (!hIMC
|| Imm32IsCrossThreadAccess(hIMC
))
569 pIC
= ImmLockIMC(hIMC
);
575 pWnd
= ValidateHwndNoErr(hWnd
);
577 if (pWnd
&& pWnd
->head
.pti
== NtCurrentTeb()->Win32ThreadInfo
)
578 ret
= Imm32ProcessRequest(hIMC
, pWnd
, (DWORD
)wParam
, (LPVOID
)lParam
, bAnsi
);
584 /***********************************************************************
585 * ImmIsUIMessageA (IMM32.@)
587 BOOL WINAPI
ImmIsUIMessageA(HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
589 TRACE("(%p, 0x%X, %p, %p)\n", hWndIME
, msg
, wParam
, lParam
);
590 return ImmIsUIMessageAW(hWndIME
, msg
, wParam
, lParam
, TRUE
);
593 /***********************************************************************
594 * ImmIsUIMessageW (IMM32.@)
596 BOOL WINAPI
ImmIsUIMessageW(HWND hWndIME
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
598 TRACE("(%p, 0x%X, %p, %p)\n", hWndIME
, msg
, wParam
, lParam
);
599 return ImmIsUIMessageAW(hWndIME
, msg
, wParam
, lParam
, FALSE
);
602 /***********************************************************************
603 * ImmGetHotKey(IMM32.@)
606 ImmGetHotKey(IN DWORD dwHotKey
, OUT LPUINT lpuModifiers
, OUT LPUINT lpuVKey
,
609 TRACE("(0x%lX, %p, %p, %p)\n", dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
610 if (lpuModifiers
&& lpuVKey
)
611 return NtUserGetImeHotKey(dwHotKey
, lpuModifiers
, lpuVKey
, lphKL
);
615 /***********************************************************************
616 * ImmWINNLSGetIMEHotkey (IMM32.@)
618 UINT WINAPI
ImmWINNLSGetIMEHotkey(HWND hwndIme
)
620 TRACE("(%p)\n", hwndIme
);
621 UNREFERENCED_PARAMETER(hwndIme
);
622 return 0; /* This is correct. This function of Windows just returns zero. */
625 /***********************************************************************
626 * ImmSimulateHotKey (IMM32.@)
628 BOOL WINAPI
ImmSimulateHotKey(HWND hWnd
, DWORD dwHotKeyID
)
635 TRACE("(%p, 0x%lX)\n", hWnd
, dwHotKeyID
);
637 hIMC
= ImmGetContext(hWnd
);
638 dwThreadId
= GetWindowThreadProcessId(hWnd
, NULL
);
639 hKL
= GetKeyboardLayout(dwThreadId
);
640 ret
= Imm32ProcessHotKey(hWnd
, hIMC
, hKL
, dwHotKeyID
);
641 ImmReleaseContext(hWnd
, hIMC
);
645 /***********************************************************************
646 * ImmGetVirtualKey (IMM32.@)
648 UINT WINAPI
ImmGetVirtualKey(HWND hWnd
)
651 LPINPUTCONTEXTDX pIC
;
652 UINT ret
= VK_PROCESSKEY
;
654 TRACE("(%p)\n", hWnd
);
656 hIMC
= ImmGetContext(hWnd
);
657 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
661 if (pIC
->bNeedsTrans
)
668 /***********************************************************************
669 * ImmProcessKey(IMM32.@)
670 * ( Undocumented, called from user32.dll )
673 ImmProcessKey(HWND hWnd
, HKL hKL
, UINT vKey
, LPARAM lParam
, DWORD dwHotKeyID
)
678 LPINPUTCONTEXTDX pIC
;
681 BOOL bUseIme
= TRUE
, bSkipThisKey
= FALSE
, bLowWordOnly
= FALSE
;
683 TRACE("(%p, %p, 0x%X, %p, 0x%lX)\n", hWnd
, hKL
, vKey
, lParam
, dwHotKeyID
);
685 hIMC
= ImmGetContext(hWnd
);
686 pImeDpi
= ImmLockImeDpi(hKL
);
689 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
692 if (LOBYTE(vKey
) == VK_PACKET
&&
693 !(pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_ACCEPT_WIDE_VKEY
))
695 if (ImeDpi_IsUnicode(pImeDpi
))
709 if (GetKeyboardState(KeyState
))
711 vk
= (bLowWordOnly
? LOWORD(vKey
) : vKey
);
712 if (pImeDpi
->ImeProcessKey(hIMC
, vk
, lParam
, KeyState
))
714 pIC
->bNeedsTrans
= TRUE
;
716 ret
|= IPHK_PROCESSBYIME
;
720 else if (bSkipThisKey
)
722 ret
|= IPHK_SKIPTHISKEY
;
728 ImmUnlockImeDpi(pImeDpi
);
731 if (dwHotKeyID
!= INVALID_HOTKEY_ID
)
733 if (Imm32ProcessHotKey(hWnd
, hIMC
, hKL
, dwHotKeyID
))
735 if (vKey
!= VK_KANJI
|| dwHotKeyID
!= IME_JHOTKEY_CLOSE_OPEN
)
740 if (ret
& IPHK_PROCESSBYIME
)
742 FIXME("TODO: We have to do something here.\n");
745 ImmReleaseContext(hWnd
, hIMC
);
749 /***********************************************************************
750 * ImmSystemHandler(IMM32.@)
752 LRESULT WINAPI
ImmSystemHandler(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
754 TRACE("(%p, %p, %p)\n", hIMC
, wParam
, lParam
);
759 Imm32SendChange((BOOL
)lParam
);
763 ImmNotifyIME(hIMC
, NI_COMPOSITIONSTR
, CPS_COMPLETE
, 0);
766 case 0x23: case 0x24:
767 return Imm32UnknownProcess1((HWND
)lParam
, (wParam
== 0x23));
774 /***********************************************************************
775 * ImmGenerateMessage(IMM32.@)
777 BOOL WINAPI
ImmGenerateMessage(HIMC hIMC
)
779 PCLIENTIMC pClientImc
;
781 LPTRANSMSG pMsgs
, pTrans
= NULL
, pItem
;
783 DWORD dwIndex
, dwCount
, cbTrans
;
784 HIMCC hMsgBuf
= NULL
;
787 TRACE("(%p)\n", hIMC
);
789 if (Imm32IsCrossThreadAccess(hIMC
))
792 pClientImc
= ImmLockClientImc(hIMC
);
793 if (pClientImc
== NULL
)
796 bAnsi
= !(pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
797 ImmUnlockClientImc(pClientImc
);
799 pIC
= ImmLockIMC(hIMC
);
803 dwCount
= pIC
->dwNumMsgBuf
;
807 hMsgBuf
= pIC
->hMsgBuf
;
808 pMsgs
= ImmLockIMCC(hMsgBuf
);
812 cbTrans
= dwCount
* sizeof(TRANSMSG
);
813 pTrans
= Imm32HeapAlloc(0, cbTrans
);
817 RtlCopyMemory(pTrans
, pMsgs
, cbTrans
);
819 #ifdef IMM_WIN3_SUPPORT
820 if (GetWin32ClientInfo()->dwExpWinVer
< _WIN32_WINNT_NT4
) /* old version (3.x)? */
822 LANGID LangID
= LANGIDFROMLCID(GetSystemDefaultLCID());
823 WORD wLang
= PRIMARYLANGID(LangID
);
825 /* translate the messages if Japanese or Korean */
826 if (wLang
== LANG_JAPANESE
||
827 (wLang
== LANG_KOREAN
&& NtUserGetAppImeLevel(pIC
->hWnd
) == 3))
829 dwCount
= ImmNt3Trans(dwCount
, pTrans
, hIMC
, bAnsi
, wLang
);
837 for (dwIndex
= 0; dwIndex
< dwCount
; ++dwIndex
, ++pItem
)
840 SendMessageA(hWnd
, pItem
->message
, pItem
->wParam
, pItem
->lParam
);
842 SendMessageW(hWnd
, pItem
->message
, pItem
->wParam
, pItem
->lParam
);
846 Imm32HeapFree(pTrans
);
848 ImmUnlockIMCC(hMsgBuf
);
849 pIC
->dwNumMsgBuf
= 0; /* done */
855 Imm32PostMessages(HWND hwnd
, HIMC hIMC
, DWORD dwCount
, LPTRANSMSG lpTransMsg
)
858 PCLIENTIMC pClientImc
;
859 LPTRANSMSG pNewTransMsg
= lpTransMsg
, pItem
;
862 pClientImc
= ImmLockClientImc(hIMC
);
863 if (pClientImc
== NULL
)
866 bAnsi
= !(pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
867 ImmUnlockClientImc(pClientImc
);
869 #ifdef IMM_WIN3_SUPPORT
870 if (GetWin32ClientInfo()->dwExpWinVer
< _WIN32_WINNT_NT4
) /* old version (3.x)? */
872 LANGID LangID
= LANGIDFROMLCID(GetSystemDefaultLCID());
873 WORD Lang
= PRIMARYLANGID(LangID
);
875 /* translate the messages if Japanese or Korean */
876 if (Lang
== LANG_JAPANESE
||
877 (Lang
== LANG_KOREAN
&& NtUserGetAppImeLevel(hwnd
) == 3))
879 DWORD cbTransMsg
= dwCount
* sizeof(TRANSMSG
);
880 pNewTransMsg
= Imm32HeapAlloc(0, cbTransMsg
);
883 RtlCopyMemory(pNewTransMsg
, lpTransMsg
, cbTransMsg
);
884 dwCount
= ImmNt3Trans(dwCount
, pNewTransMsg
, hIMC
, bAnsi
, Lang
);
888 pNewTransMsg
= lpTransMsg
;
895 pItem
= pNewTransMsg
;
896 for (dwIndex
= 0; dwIndex
< dwCount
; ++dwIndex
, ++pItem
)
899 PostMessageA(hwnd
, pItem
->message
, pItem
->wParam
, pItem
->lParam
);
901 PostMessageW(hwnd
, pItem
->message
, pItem
->wParam
, pItem
->lParam
);
904 #ifdef IMM_WIN3_SUPPORT
905 if (pNewTransMsg
!= lpTransMsg
)
906 Imm32HeapFree(pNewTransMsg
);
910 /***********************************************************************
911 * ImmTranslateMessage(IMM32.@)
912 * ( Undocumented, call internally and from user32.dll )
914 BOOL WINAPI
ImmTranslateMessage(HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lKeyData
)
916 #define MSG_COUNT 0x100
919 LPINPUTCONTEXTDX pIC
;
920 PIMEDPI pImeDpi
= NULL
;
921 LPTRANSMSGLIST pList
= NULL
;
922 LPTRANSMSG pTransMsg
;
923 BYTE abKeyState
[256];
927 DWORD dwThreadId
, dwCount
, cbList
;
931 TRACE("(%p, 0x%X, %p, %p)\n", hwnd
, msg
, wParam
, lKeyData
);
933 /* filter the message */
936 case WM_KEYDOWN
: case WM_KEYUP
: case WM_SYSKEYDOWN
: case WM_SYSKEYUP
:
942 hIMC
= ImmGetContext(hwnd
);
943 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
946 ImmReleaseContext(hwnd
, hIMC
);
950 if (!pIC
->bNeedsTrans
) /* is translation needed? */
952 /* directly post them */
953 dwCount
= pIC
->dwNumMsgBuf
;
957 pTransMsg
= ImmLockIMCC(pIC
->hMsgBuf
);
960 Imm32PostMessages(hwnd
, hIMC
, dwCount
, pTransMsg
);
961 ImmUnlockIMCC(pIC
->hMsgBuf
);
964 pIC
->dwNumMsgBuf
= 0; /* done */
967 pIC
->bNeedsTrans
= FALSE
; /* clear the flag */
969 dwThreadId
= GetWindowThreadProcessId(hwnd
, NULL
);
970 hKL
= GetKeyboardLayout(dwThreadId
);
971 pImeDpi
= ImmLockImeDpi(hKL
);
975 if (!GetKeyboardState(abKeyState
)) /* get keyboard ON/OFF status */
978 /* convert a virtual key if IME_PROP_KBD_CHAR_FIRST */
980 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_KBD_CHAR_FIRST
)
982 if (ImeDpi_IsUnicode(pImeDpi
))
985 kret
= ToUnicode(vk
, HIWORD(lKeyData
), abKeyState
, &wch
, 1, 0);
987 vk
= MAKELONG(LOBYTE(vk
), wch
);
992 kret
= ToAsciiEx(vk
, HIWORD(lKeyData
), abKeyState
, &wChar
, 0, hKL
);
994 vk
= MAKEWORD(vk
, wChar
);
998 /* allocate a list */
999 cbList
= offsetof(TRANSMSGLIST
, TransMsg
) + MSG_COUNT
* sizeof(TRANSMSG
);
1000 pList
= Imm32HeapAlloc(0, cbList
);
1004 /* use IME conversion engine and convert the list */
1005 pList
->uMsgCount
= MSG_COUNT
;
1006 kret
= pImeDpi
->ImeToAsciiEx(vk
, HIWORD(lKeyData
), abKeyState
, pList
, 0, hIMC
);
1011 if (kret
<= MSG_COUNT
)
1013 Imm32PostMessages(hwnd
, hIMC
, kret
, pList
->TransMsg
);
1018 pTransMsg
= ImmLockIMCC(pIC
->hMsgBuf
);
1019 if (pTransMsg
== NULL
)
1021 Imm32PostMessages(hwnd
, hIMC
, kret
, pTransMsg
);
1022 ImmUnlockIMCC(pIC
->hMsgBuf
);
1026 Imm32HeapFree(pList
);
1027 ImmUnlockImeDpi(pImeDpi
);
1029 ImmReleaseContext(hwnd
, hIMC
);
1034 /***********************************************************************
1035 * ImmRequestMessageA(IMM32.@)
1037 LRESULT WINAPI
ImmRequestMessageA(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
1039 TRACE("(%p, %p, %p)\n", hIMC
, wParam
, lParam
);
1040 return Imm32RequestMessageAW(hIMC
, wParam
, lParam
, TRUE
);
1043 /***********************************************************************
1044 * ImmRequestMessageW(IMM32.@)
1046 LRESULT WINAPI
ImmRequestMessageW(HIMC hIMC
, WPARAM wParam
, LPARAM lParam
)
1048 TRACE("(%p, %p, %p)\n", hIMC
, wParam
, lParam
);
1049 return Imm32RequestMessageAW(hIMC
, wParam
, lParam
, FALSE
);