https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f4bc74edc34cb20fff0c7…
commit f4bc74edc34cb20fff0c72f1ab706b2e0841ad0a
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Wed Aug 18 08:42:12 2021 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Wed Aug 18 08:42:12 2021 +0900
[IMM32] ImmGenerateMessage and ImmTranslateMessage (#3914)
- Rewrite `ImmGenerateMessage` and `ImmTranslateMessage` functions.
- Rename `INPUTCONTEXTDX.bHasVKey` as `bNeedsTrans`.
- Move `TRANSMSG` structure into `ntuser.h`.
- Add `TRANSMSGLIST` structure into `ntuser.h`.
- Add `UNDETERMINESTRUCT` structure to `ddk/imm.h`.
- Modify `NtUserGetAppImeLevel` prototype.
CORE-11700
---
dll/win32/imm32/imm.c | 551 +++++++++++++++++++++++++++++--------
dll/win32/imm32/imm32.spec | 2 +-
sdk/include/reactos/wine/ddk/imm.h | 22 +-
win32ss/include/imetable.h | 2 +-
win32ss/include/ntuser.h | 14 +-
win32ss/user/ntuser/ime.c | 3 +-
6 files changed, 472 insertions(+), 122 deletions(-)
diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c
index 01e656c454b..a2e16e46bf6 100644
--- a/dll/win32/imm32/imm.c
+++ b/dll/win32/imm32/imm.c
@@ -1,22 +1,13 @@
/*
- * IMM32 library
- *
- * Copyright 1998 Patrik Stridvall
- * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ * PROJECT: ReactOS IMM32
+ * LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE: Implementing Far-Eastern languages input
+ * COPYRIGHT: Copyright 1998 Patrik Stridvall
+ * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
+ * Copyright 2017 James Tabor <james.tabor(a)reactos.org>
+ * Copyright 2018 Amine Khaldi <amine.khaldi(a)reactos.org>
+ * Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013(a)yandex.ua>
+ * Copyright 2020-2021 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
*/
#include <stdarg.h>
@@ -48,6 +39,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
#define IMM_INIT_MAGIC 0x19650412
#define IMM_INVALID_CANDFORM ULONG_MAX
+#define MAX_CANDIDATEFORM 4
+
#define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
#define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
@@ -199,7 +192,7 @@ static BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
DWORD dwSysInfoFlags = 0; // TODO: ???
LPIMEINFO pImeInfo = &pImeDpi->ImeInfo;
- // TODO: NtUserGetThreadState(THREADSTATE_UNKNOWN16);
+ // TODO: NtUserGetThreadState(16);
if (!IS_IME_HKL(pImeDpi->hKL))
{
@@ -342,6 +335,199 @@ Failed:
return FALSE;
}
+#ifdef IMP_SUPPORT /* 3.x support */
+static DWORD APIENTRY
+ImpJTransCompA(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
+ const TRANSMSG *pSrc, LPTRANSMSG pDest)
+{
+ // FIXME
+ *pDest = *pSrc;
+ return 1;
+}
+
+static DWORD APIENTRY
+ImpJTransCompW(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
+ const TRANSMSG *pSrc, LPTRANSMSG pDest)
+{
+ // FIXME
+ *pDest = *pSrc;
+ return 1;
+}
+
+typedef LRESULT (WINAPI *FN_SendMessage)(HWND, UINT, WPARAM, LPARAM);
+
+static DWORD APIENTRY
+ImpJTrans(DWORD dwCount, LPTRANSMSG pTrans, LPINPUTCONTEXTDX pIC,
+ LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
+{
+ DWORD ret = 0;
+ HWND hWnd, hwndDefIME;
+ LPTRANSMSG pTempList, pEntry, pNext;
+ DWORD dwIndex, iCandForm, dwNumber, cbTempList;
+ HGLOBAL hGlobal;
+ CANDIDATEFORM CandForm;
+ FN_SendMessage pSendMessage;
+
+ hWnd = pIC->hWnd;
+ hwndDefIME = ImmGetDefaultIMEWnd(hWnd);
+ pSendMessage = (IsWindowUnicode(hWnd) ? SendMessageW : SendMessageA);
+
+ // clone the message list
+ cbTempList = (dwCount + 1) * sizeof(TRANSMSG);
+ pTempList = Imm32HeapAlloc(HEAP_ZERO_MEMORY, cbTempList);
+ if (pTempList == NULL)
+ return 0;
+ RtlCopyMemory(pTempList, pTrans, dwCount * sizeof(TRANSMSG));
+
+ if (pIC->dwUIFlags & 0x2)
+ {
+ // find WM_IME_ENDCOMPOSITION
+ pEntry = pTempList;
+ for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pEntry)
+ {
+ if (pEntry->message == WM_IME_ENDCOMPOSITION)
+ break;
+ }
+
+ if (pEntry->message == WM_IME_ENDCOMPOSITION) // if found
+ {
+ // move WM_IME_ENDCOMPOSITION to the end of the list
+ for (pNext = pEntry + 1; pNext->message != 0; ++pEntry, ++pNext)
+ *pEntry = *pNext;
+
+ pEntry->message = WM_IME_ENDCOMPOSITION;
+ pEntry->wParam = 0;
+ pEntry->lParam = 0;
+ }
+ }
+
+ for (pEntry = pTempList; pEntry->message != 0; ++pEntry)
+ {
+ switch (pEntry->message)
+ {
+ case WM_IME_STARTCOMPOSITION:
+ if (!(pIC->dwUIFlags & 0x2))
+ {
+ // send IR_OPENCONVERT
+ if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
+ pSendMessage(hWnd, WM_IME_REPORT, IR_OPENCONVERT, 0);
+
+ goto DoDefault;
+ }
+ break;
+
+ case WM_IME_ENDCOMPOSITION:
+ if (pIC->dwUIFlags & 0x2)
+ {
+ // send IR_UNDETERMINE
+ hGlobal = GlobalAlloc(GHND | GMEM_SHARE, sizeof(UNDETERMINESTRUCT));
+ if (hGlobal)
+ {
+ pSendMessage(hWnd, WM_IME_REPORT, IR_UNDETERMINE,
(LPARAM)hGlobal);
+ GlobalFree(hGlobal);
+ }
+ }
+ else
+ {
+ // send IR_CLOSECONVERT
+ if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
+ pSendMessage(hWnd, WM_IME_REPORT, IR_CLOSECONVERT, 0);
+
+ goto DoDefault;
+ }
+ break;
+
+ case WM_IME_COMPOSITION:
+ if (bAnsi)
+ dwNumber = ImpJTransCompA(pIC, pCS, pEntry, pTrans);
+ else
+ dwNumber = ImpJTransCompW(pIC, pCS, pEntry, pTrans);
+
+ ret += dwNumber;
+ pTrans += dwNumber;
+
+ // send IR_CHANGECONVERT
+ if (!(pIC->dwUIFlags & 0x2))
+ {
+ if (pIC->cfCompForm.dwStyle != CFS_DEFAULT)
+ pSendMessage(hWnd, WM_IME_REPORT, IR_CHANGECONVERT, 0);
+ }
+ break;
+
+ case WM_IME_NOTIFY:
+ if (pEntry->wParam == IMN_OPENCANDIDATE)
+ {
+ if (IsWindow(hWnd) && (pIC->dwUIFlags & 0x2))
+ {
+ // send IMC_SETCANDIDATEPOS
+ for (iCandForm = 0; iCandForm < MAX_CANDIDATEFORM;
++iCandForm)
+ {
+ if (!(pEntry->lParam & (1 << iCandForm)))
+ continue;
+
+ CandForm.dwIndex = iCandForm;
+ CandForm.dwStyle = CFS_EXCLUDE;
+ CandForm.ptCurrentPos = pIC->cfCompForm.ptCurrentPos;
+ CandForm.rcArea = pIC->cfCompForm.rcArea;
+ pSendMessage(hwndDefIME, WM_IME_CONTROL,
IMC_SETCANDIDATEPOS,
+ (LPARAM)&CandForm);
+ }
+ }
+ }
+
+ if (!(pIC->dwUIFlags & 0x2))
+ goto DoDefault;
+
+ // send a WM_IME_NOTIFY notification to the default ime window
+ pSendMessage(hwndDefIME, pEntry->message, pEntry->wParam,
pEntry->lParam);
+ break;
+
+DoDefault:
+ default:
+ // default processing
+ *pTrans++ = *pEntry;
+ ++ret;
+ break;
+ }
+ }
+
+ HeapFree(g_hImm32Heap, 0, pTempList);
+ return ret;
+}
+
+static DWORD APIENTRY
+ImpKTrans(DWORD dwCount, LPTRANSMSG pEntries, LPINPUTCONTEXTDX pIC,
+ LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
+{
+ return dwCount; // FIXME
+}
+
+static DWORD APIENTRY
+ImpTrans(DWORD dwCount, LPTRANSMSG pEntries, HIMC hIMC, BOOL bAnsi, WORD wLang)
+{
+ BOOL ret = FALSE;
+ LPINPUTCONTEXTDX pIC;
+ LPCOMPOSITIONSTRING pCS;
+
+ pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
+ if (pIC == NULL)
+ return 0;
+
+ pCS = ImmLockIMCC(pIC->hCompStr);
+ if (pCS)
+ {
+ if (wLang == LANG_JAPANESE)
+ ret = ImpJTrans(dwCount, pEntries, pIC, pCS, bAnsi);
+ else if (wLang == LANG_KOREAN)
+ ret = ImpKTrans(dwCount, pEntries, pIC, pCS, bAnsi);
+ ImmUnlockIMCC(pIC->hCompStr);
+ }
+
+ ImmUnlockIMC(hIMC);
+ return ret;
+}
+#endif /* def IMP_SUPPORT */
+
static PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
{
IMEINFOEX ImeInfoEx;
@@ -547,12 +733,6 @@ typedef struct tagInputContextData
#define WINE_IMC_VALID_MAGIC 0x56434D49
-typedef struct _tagTRANSMSG {
- UINT message;
- WPARAM wParam;
- LPARAM lParam;
-} TRANSMSG, *LPTRANSMSG;
-
typedef struct _tagIMMThreadData {
struct list entry;
DWORD threadID;
@@ -721,26 +901,6 @@ static ImmHkl *IMM_GetImmHkl(HKL hkl)
}
#undef LOAD_FUNCPTR
-/* for posting messages as the IME */
-static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam,
LPARAM lParam)
-{
- HWND target = GetFocus();
- if (!target)
- PostMessageW(data->IMC.hWnd,msg,wParam,lParam);
- else
- PostMessageW(target, msg, wParam, lParam);
-}
-
-/* for sending messages as the IME */
-static void ImmInternalSendIMEMessage(InputContextData *data, UINT msg, WPARAM wParam,
LPARAM lParam)
-{
- HWND target = GetFocus();
- if (!target)
- SendMessageW(data->IMC.hWnd,msg,wParam,lParam);
- else
- SendMessageW(target, msg, wParam, lParam);
-}
-
static InputContextData* get_imc_data(HIMC hIMC)
{
InputContextData *data = (InputContextData *)hIMC;
@@ -980,7 +1140,10 @@ HIMC WINAPI ImmCreateContext(void)
}
RtlInitializeCriticalSection(&pClientImc->cs);
- pClientImc->unknown = NtUserGetThreadState(THREADSTATE_UNKNOWN13);
+
+ // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
+ pClientImc->unknown = NtUserGetThreadState(13);
+
return hIMC;
}
@@ -1654,7 +1817,9 @@ PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
return NULL;
RtlInitializeCriticalSection(&pClientImc->cs);
- pClientImc->unknown = NtUserGetThreadState(THREADSTATE_UNKNOWN13);
+
+ // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
+ pClientImc->unknown = NtUserGetThreadState(13);
if (!NtUserUpdateInputContext(hImc, 0, pClientImc))
{
@@ -2655,8 +2820,9 @@ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
return NULL;
+ // FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
if (hWnd == NULL)
- return (HWND)NtUserGetThreadState(THREADSTATE_ACTIVEWINDOW);
+ return (HWND)NtUserGetThreadState(3);
return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME);
}
@@ -3189,7 +3355,7 @@ UINT WINAPI ImmGetVirtualKey(HWND hWnd)
if (!pIC)
return ret;
- if (pIC->bHasVKey)
+ if (pIC->bNeedsTrans)
ret = pIC->nVKey;
ImmUnlockIMC(hIMC);
@@ -3510,7 +3676,6 @@ LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM
lParam)
BOOL WINAPI ImmSetCandidateWindow(
HIMC hIMC, LPCANDIDATEFORM lpCandidate)
{
-#define MAX_CANDIDATEFORM 4
HWND hWnd;
LPINPUTCONTEXT pIC;
@@ -3534,7 +3699,6 @@ BOOL WINAPI ImmSetCandidateWindow(
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS,
IMN_SETCANDIDATEPOS, (1 << lpCandidate->dwIndex));
return TRUE;
-#undef MAX_CANDIDATEFORM
}
static VOID APIENTRY WideToAnsiLogFont(const LOGFONTW *plfW, LPLOGFONTA plfA)
@@ -4444,38 +4608,136 @@ DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
*/
BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
{
- InputContextData *data = get_imc_data(hIMC);
+ PCLIENTIMC pClientImc;
+ LPINPUTCONTEXT pIC;
+ LPTRANSMSG pMsgs, pTrans = NULL, pItem;
+ HWND hWnd;
+ DWORD dwIndex, dwCount, cbTrans;
+ HIMCC hMsgBuf = NULL;
+ BOOL bAnsi;
- if (!data)
- {
- SetLastError(ERROR_INVALID_HANDLE);
+ TRACE("(%p)\n", hIMC);
+
+ if (Imm32IsCrossThreadAccess(hIMC))
return FALSE;
+
+ pClientImc = ImmLockClientImc(hIMC);
+ if (pClientImc == NULL)
+ return FALSE;
+
+ bAnsi = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
+ ImmUnlockClientImc(pClientImc);
+
+ pIC = ImmLockIMC(hIMC);
+ if (pIC == NULL)
+ return FALSE;
+
+ dwCount = pIC->dwNumMsgBuf;
+ if (dwCount == 0)
+ goto Quit;
+
+ hMsgBuf = pIC->hMsgBuf;
+ pMsgs = ImmLockIMCC(hMsgBuf);
+ if (pMsgs == NULL)
+ goto Quit;
+
+ cbTrans = dwCount * sizeof(TRANSMSG);
+ pTrans = Imm32HeapAlloc(0, cbTrans);
+ if (pTrans == NULL)
+ goto Quit;
+
+ RtlCopyMemory(pTrans, pMsgs, cbTrans);
+
+#ifdef IMP_SUPPORT
+ if (GetWin32ClientInfo()->dwExpWinVer < 0x400) /* old version (3.x)? */
+ {
+ LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
+ WORD wLang = PRIMARYLANGID(LangID);
+
+ /* translate the messages if Japanese or Korean */
+ if (wLang == LANG_JAPANESE ||
+ (wLang == LANG_KOREAN && NtUserGetAppImeLevel(pIC->hWnd) == 3))
+ {
+ dwCount = ImpTrans(dwCount, pTrans, hIMC, bAnsi, wLang);
+ }
}
+#endif
- TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf);
- if (data->IMC.dwNumMsgBuf > 0)
+ /* send them */
+ hWnd = pIC->hWnd;
+ pItem = pTrans;
+ for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pItem)
{
- LPTRANSMSG lpTransMsg;
- HIMCC hMsgBuf;
- DWORD i, dwNumMsgBuf;
+ if (bAnsi)
+ SendMessageA(hWnd, pItem->message, pItem->wParam, pItem->lParam);
+ else
+ SendMessageW(hWnd, pItem->message, pItem->wParam, pItem->lParam);
+ }
+
+Quit:
+ if (pTrans)
+ HeapFree(g_hImm32Heap, 0, pTrans);
+ if (hMsgBuf)
+ ImmUnlockIMCC(hMsgBuf);
+ pIC->dwNumMsgBuf = 0; /* done */
+ ImmUnlockIMC(hIMC);
+ return TRUE;
+}
+
+static VOID APIENTRY
+Imm32PostMessages(HWND hwnd, HIMC hIMC, DWORD dwCount, LPTRANSMSG lpTransMsg)
+{
+ DWORD dwIndex;
+ PCLIENTIMC pClientImc;
+ LPTRANSMSG pNewTransMsg = lpTransMsg, pItem;
+ BOOL bAnsi;
- /* We are going to detach our hMsgBuff so that if processing messages
- generates new messages they go into a new buffer */
- hMsgBuf = data->IMC.hMsgBuf;
- dwNumMsgBuf = data->IMC.dwNumMsgBuf;
+ pClientImc = ImmLockClientImc(hIMC);
+ if (pClientImc == NULL)
+ return;
- data->IMC.hMsgBuf = ImmCreateIMCC(0);
- data->IMC.dwNumMsgBuf = 0;
+ bAnsi = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
+ ImmUnlockClientImc(pClientImc);
- lpTransMsg = ImmLockIMCC(hMsgBuf);
- for (i = 0; i < dwNumMsgBuf; i++)
- ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam,
lpTransMsg[i].lParam);
+#ifdef IMP_SUPPORT
+ if (GetWin32ClientInfo()->dwExpWinVer < 0x400) /* old version (3.x)? */
+ {
+ LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
+ WORD Lang = PRIMARYLANGID(LangID);
- ImmUnlockIMCC(hMsgBuf);
- ImmDestroyIMCC(hMsgBuf);
+ /* translate the messages if Japanese or Korean */
+ if (Lang == LANG_JAPANESE ||
+ (Lang == LANG_KOREAN && NtUserGetAppImeLevel(hwnd) == 3))
+ {
+ DWORD cbTransMsg = dwCount * sizeof(TRANSMSG);
+ pNewTransMsg = Imm32HeapAlloc(0, cbTransMsg);
+ if (pNewTransMsg)
+ {
+ RtlCopyMemory(pNewTransMsg, lpTransMsg, cbTransMsg);
+ dwCount = ImpTrans(dwCount, pNewTransMsg, hIMC, bAnsi, Lang);
+ }
+ else
+ {
+ pNewTransMsg = lpTransMsg;
+ }
+ }
}
+#endif
- return TRUE;
+ /* post them */
+ pItem = pNewTransMsg;
+ for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pItem)
+ {
+ if (bAnsi)
+ PostMessageA(hwnd, pItem->message, pItem->wParam, pItem->lParam);
+ else
+ PostMessageW(hwnd, pItem->message, pItem->wParam, pItem->lParam);
+ }
+
+#ifdef IMP_SUPPORT
+ if (pNewTransMsg && pNewTransMsg != lpTransMsg)
+ HeapFree(g_hImm32Heap, 0, pNewTransMsg);
+#endif
}
/***********************************************************************
@@ -4484,62 +4746,123 @@ BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
*/
BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
{
- InputContextData *data;
- HIMC imc = ImmGetContext(hwnd);
- BYTE state[256];
- UINT scancode;
- LPVOID list = 0;
- UINT msg_count;
- UINT uVirtKey;
- static const DWORD list_count = 10;
+#define MSG_COUNT 0x100
+ BOOL ret = FALSE;
+ INT kret;
+ LPINPUTCONTEXTDX pIC;
+ PIMEDPI pImeDpi = NULL;
+ LPTRANSMSGLIST pList = NULL;
+ LPTRANSMSG pTransMsg;
+ BYTE abKeyState[256];
+ HIMC hIMC;
+ HKL hKL;
+ UINT vk;
+ DWORD dwThreadId, dwCount, cbList;
+ WCHAR wch;
+ WORD wChar;
- TRACE("%p %x %x %x\n",hwnd, msg, (UINT)wParam, (UINT)lKeyData);
+ TRACE("(%p, 0x%X, %p, %p)\n", hwnd, msg, wParam, lKeyData);
- if (imc)
- data = (InputContextData *)imc;
- else
- return FALSE;
+ /* filter the message */
+ switch (msg)
+ {
+ case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP:
+ break;
+ default:
+ return FALSE;
+ }
- if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
+ hIMC = ImmGetContext(hwnd);
+ pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
+ if (pIC == NULL)
+ {
+ ImmReleaseContext(hwnd, hIMC);
return FALSE;
+ }
- GetKeyboardState(state);
- scancode = lKeyData >> 0x10 & 0xff;
-
- list = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, list_count * sizeof(TRANSMSG) +
sizeof(DWORD));
- ((DWORD*)list)[0] = list_count;
-
- if (data->immKbd->imeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
+ if (!pIC->bNeedsTrans) /* is translation needed? */
{
- WCHAR chr;
+ /* directly post them */
+ dwCount = pIC->dwNumMsgBuf;
+ if (dwCount == 0)
+ goto Quit;
- if (!is_himc_ime_unicode(data))
- ToAscii(data->lastVK, scancode, state, &chr, 0);
- else
- ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0,
GetKeyboardLayout(0));
- uVirtKey = MAKELONG(data->lastVK,chr);
+ pTransMsg = ImmLockIMCC(pIC->hMsgBuf);
+ if (pTransMsg)
+ {
+ Imm32PostMessages(hwnd, hIMC, dwCount, pTransMsg);
+ ImmUnlockIMCC(pIC->hMsgBuf);
+ ret = TRUE;
+ }
+ pIC->dwNumMsgBuf = 0; /* done */
+ goto Quit;
}
- else
- uVirtKey = data->lastVK;
+ pIC->bNeedsTrans = FALSE; /* clear the flag */
- msg_count = data->immKbd->pImeToAsciiEx(uVirtKey, scancode, state, list, 0,
imc);
- TRACE("%i messages generated\n",msg_count);
- if (msg_count && msg_count <= list_count)
- {
- UINT i;
- LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD));
+ dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
+ hKL = GetKeyboardLayout(dwThreadId);
+ pImeDpi = ImmLockImeDpi(hKL);
+ if (pImeDpi == NULL)
+ goto Quit;
- for (i = 0; i < msg_count; i++)
- ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam,
msgs[i].lParam);
+ if (!GetKeyboardState(abKeyState)) /* get keyboard ON/OFF status */
+ goto Quit;
+
+ /* convert a virtual key if IME_PROP_KBD_CHAR_FIRST */
+ vk = pIC->nVKey;
+ if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_KBD_CHAR_FIRST)
+ {
+ if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
+ {
+ wch = 0;
+ kret = ToUnicode(vk, HIWORD(lKeyData), abKeyState, &wch, 1, 0);
+ if (kret == 1)
+ vk = MAKELONG(LOBYTE(vk), wch);
+ }
+ else
+ {
+ wChar = 0;
+ kret = ToAsciiEx(vk, HIWORD(lKeyData), abKeyState, &wChar, 0, hKL);
+ if (kret > 0)
+ vk = MAKEWORD(vk, wChar);
+ }
}
- else if (msg_count > list_count)
- ImmGenerateMessage(imc);
- HeapFree(GetProcessHeap(),0,list);
+ /* allocate a list */
+ cbList = offsetof(TRANSMSGLIST, TransMsg) + MSG_COUNT * sizeof(TRANSMSG);
+ pList = Imm32HeapAlloc(0, cbList);
+ if (!pList)
+ goto Quit;
- data->lastVK = VK_PROCESSKEY;
+ /* use IME conversion engine and convert the list */
+ pList->uMsgCount = MSG_COUNT;
+ kret = pImeDpi->ImeToAsciiEx(vk, HIWORD(lKeyData), abKeyState, pList, 0, hIMC);
+ if (kret <= 0)
+ goto Quit;
- return (msg_count > 0);
+ /* post them */
+ if (kret <= MSG_COUNT)
+ {
+ Imm32PostMessages(hwnd, hIMC, kret, pList->TransMsg);
+ ret = TRUE;
+ }
+ else
+ {
+ pTransMsg = ImmLockIMCC(pIC->hMsgBuf);
+ if (pTransMsg == NULL)
+ goto Quit;
+ Imm32PostMessages(hwnd, hIMC, kret, pTransMsg);
+ ImmUnlockIMCC(pIC->hMsgBuf);
+ }
+
+Quit:
+ if (pList)
+ HeapFree(g_hImm32Heap, 0, pList);
+ ImmUnlockImeDpi(pImeDpi);
+ ImmUnlockIMC(hIMC);
+ ImmReleaseContext(hwnd, hIMC);
+ return ret;
+#undef MSG_COUNT
}
/***********************************************************************
diff --git a/dll/win32/imm32/imm32.spec b/dll/win32/imm32/imm32.spec
index bca6da02f8a..e5d9cfa72fb 100644
--- a/dll/win32/imm32/imm32.spec
+++ b/dll/win32/imm32/imm32.spec
@@ -103,7 +103,7 @@
@ stdcall ImmShowSoftKeyboard(ptr long)
@ stdcall ImmSimulateHotKey(ptr long)
@ stdcall -stub ImmSystemHandler(ptr long long)
-@ stdcall ImmTranslateMessage(ptr long long long)
+@ stdcall ImmTranslateMessage(ptr long ptr ptr)
@ stdcall ImmUnlockClientImc(ptr)
@ stdcall ImmUnlockIMC(ptr)
@ stdcall ImmUnlockIMCC(ptr)
diff --git a/sdk/include/reactos/wine/ddk/imm.h b/sdk/include/reactos/wine/ddk/imm.h
index 81d665dc7dc..f5b45fc6d1a 100644
--- a/sdk/include/reactos/wine/ddk/imm.h
+++ b/sdk/include/reactos/wine/ddk/imm.h
@@ -91,7 +91,7 @@ typedef struct INPUTCONTEXTDX /* unconfirmed */
{
INPUTCONTEXT;
UINT nVKey;
- BOOL bHasVKey;
+ BOOL bNeedsTrans;
DWORD dwUnknownCat;
DWORD dwUIFlags;
DWORD dwUnknownDog;
@@ -101,7 +101,7 @@ typedef struct INPUTCONTEXTDX /* unconfirmed */
#ifndef _WIN64
C_ASSERT(offsetof(INPUTCONTEXTDX, nVKey) == 0x140);
-C_ASSERT(offsetof(INPUTCONTEXTDX, bHasVKey) == 0x144);
+C_ASSERT(offsetof(INPUTCONTEXTDX, bNeedsTrans) == 0x144);
C_ASSERT(offsetof(INPUTCONTEXTDX, dwUIFlags) == 0x14c);
#endif
@@ -131,6 +131,24 @@ C_ASSERT(offsetof(INPUTCONTEXTDX, dwUIFlags) == 0x14c);
#define IR_STRINGEX 0x180
#define IR_MODEINFO 0x190
+// for IR_UNDETERMINE
+typedef struct tagUNDETERMINESTRUCT
+{
+ DWORD dwSize;
+ UINT uDefIMESize;
+ UINT uDefIMEPos;
+ UINT uUndetTextLen;
+ UINT uUndetTextPos;
+ UINT uUndetAttrPos;
+ UINT uCursorPos;
+ UINT uDeltaStart;
+ UINT uDetermineTextLen;
+ UINT uDetermineTextPos;
+ UINT uDetermineDelimPos;
+ UINT uYomiTextLen;
+ UINT uYomiTextPos;
+ UINT uYomiDelimPos;
+} UNDETERMINESTRUCT, *PUNDETERMINESTRUCT, *LPUNDETERMINESTRUCT;
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC);
diff --git a/win32ss/include/imetable.h b/win32ss/include/imetable.h
index 1b47380e954..0574fce48f0 100644
--- a/win32ss/include/imetable.h
+++ b/win32ss/include/imetable.h
@@ -11,7 +11,7 @@ DEFINE_IME_ENTRY(LRESULT, ImeEscape, (HIMC hIMC, UINT uEscape, LPVOID
lpData), F
DEFINE_IME_ENTRY(BOOL, ImeSelect, (HIMC hIMC, BOOL fSelect), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeProcessKey, (HIMC hIMC, UINT uVirKey, DWORD lParam, CONST
LPBYTE lpbKeyState), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeSetActiveContext, (HIMC hIMC, BOOL fFlag), FALSE)
-DEFINE_IME_ENTRY(UINT, ImeToAsciiEx, (UINT uVirKey, UINT uScanCode, CONST LPBYTE
lpbKeyState, /*FIXME: LPTRANSMSGLIST*/ LPVOID lpTransMsgList, UINT fuState, HIMC hIMC),
FALSE)
+DEFINE_IME_ENTRY(UINT, ImeToAsciiEx, (UINT uVirKey, UINT uScanCode, CONST LPBYTE
lpbKeyState, LPTRANSMSGLIST lpTransMsgList, UINT fuState, HIMC hIMC), FALSE)
DEFINE_IME_ENTRY(BOOL, NotifyIME, (HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD
dwValue), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeSetCompositionString, (HIMC hIMC, DWORD dwIndex, LPCVOID
lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen), FALSE)
DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD dwType,
LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize), FALSE)
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index 3147acfac6f..782af6d0df4 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -1211,6 +1211,17 @@ typedef struct _IMEWND
PIMEUI pimeui;
} IMEWND, *PIMEWND;
+typedef struct tagTRANSMSG {
+ UINT message;
+ WPARAM wParam;
+ LPARAM lParam;
+} TRANSMSG, *PTRANSMSG, *LPTRANSMSG;
+
+typedef struct tagTRANSMSGLIST {
+ UINT uMsgCount;
+ TRANSMSG TransMsg[1];
+} TRANSMSGLIST, *PTRANSMSGLIST, *LPTRANSMSGLIST;
+
#define DEFINE_IME_ENTRY(type, name, params, extended) typedef type (WINAPI *FN_##name)
params;
#include "imetable.h"
#undef DEFINE_IME_ENTRY
@@ -2203,8 +2214,7 @@ NtUserGetAncestor(
DWORD
NTAPI
-NtUserGetAppImeLevel(
- DWORD dwUnknown1);
+NtUserGetAppImeLevel(HWND hWnd);
SHORT
NTAPI
diff --git a/win32ss/user/ntuser/ime.c b/win32ss/user/ntuser/ime.c
index cac0d64b662..031dc09ec64 100644
--- a/win32ss/user/ntuser/ime.c
+++ b/win32ss/user/ntuser/ime.c
@@ -95,8 +95,7 @@ NtUserDisableThreadIme(
DWORD
APIENTRY
-NtUserGetAppImeLevel(
- DWORD dwUnknown1)
+NtUserGetAppImeLevel(HWND hWnd)
{
STUB;
return 0;