[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
This commit is contained in:
Katayama Hirofumi MZ 2021-08-18 08:42:12 +09:00 committed by GitHub
parent db8dd3b35e
commit f4bc74edc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 478 additions and 128 deletions

View file

@ -1,22 +1,13 @@
/* /*
* IMM32 library * PROJECT: ReactOS IMM32
* * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* Copyright 1998 Patrik Stridvall * PURPOSE: Implementing Far-Eastern languages input
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart * COPYRIGHT: Copyright 1998 Patrik Stridvall
* * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
* This library is free software; you can redistribute it and/or * Copyright 2017 James Tabor <james.tabor@reactos.org>
* modify it under the terms of the GNU Lesser General Public * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
* License as published by the Free Software Foundation; either * Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
* version 2.1 of the License, or (at your option) any later version. * Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*
* 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
*/ */
#include <stdarg.h> #include <stdarg.h>
@ -48,6 +39,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
#define IMM_INIT_MAGIC 0x19650412 #define IMM_INIT_MAGIC 0x19650412
#define IMM_INVALID_CANDFORM ULONG_MAX #define IMM_INVALID_CANDFORM ULONG_MAX
#define MAX_CANDIDATEFORM 4
#define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) #define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) #define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
#define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT) #define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
@ -199,7 +192,7 @@ static BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
DWORD dwSysInfoFlags = 0; // TODO: ??? DWORD dwSysInfoFlags = 0; // TODO: ???
LPIMEINFO pImeInfo = &pImeDpi->ImeInfo; LPIMEINFO pImeInfo = &pImeDpi->ImeInfo;
// TODO: NtUserGetThreadState(THREADSTATE_UNKNOWN16); // TODO: NtUserGetThreadState(16);
if (!IS_IME_HKL(pImeDpi->hKL)) if (!IS_IME_HKL(pImeDpi->hKL))
{ {
@ -342,6 +335,199 @@ Failed:
return FALSE; 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) static PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
{ {
IMEINFOEX ImeInfoEx; IMEINFOEX ImeInfoEx;
@ -547,12 +733,6 @@ typedef struct tagInputContextData
#define WINE_IMC_VALID_MAGIC 0x56434D49 #define WINE_IMC_VALID_MAGIC 0x56434D49
typedef struct _tagTRANSMSG {
UINT message;
WPARAM wParam;
LPARAM lParam;
} TRANSMSG, *LPTRANSMSG;
typedef struct _tagIMMThreadData { typedef struct _tagIMMThreadData {
struct list entry; struct list entry;
DWORD threadID; DWORD threadID;
@ -721,26 +901,6 @@ static ImmHkl *IMM_GetImmHkl(HKL hkl)
} }
#undef LOAD_FUNCPTR #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) static InputContextData* get_imc_data(HIMC hIMC)
{ {
InputContextData *data = (InputContextData *)hIMC; InputContextData *data = (InputContextData *)hIMC;
@ -980,7 +1140,10 @@ HIMC WINAPI ImmCreateContext(void)
} }
RtlInitializeCriticalSection(&pClientImc->cs); RtlInitializeCriticalSection(&pClientImc->cs);
pClientImc->unknown = NtUserGetThreadState(THREADSTATE_UNKNOWN13);
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
pClientImc->unknown = NtUserGetThreadState(13);
return hIMC; return hIMC;
} }
@ -1654,7 +1817,9 @@ PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
return NULL; return NULL;
RtlInitializeCriticalSection(&pClientImc->cs); RtlInitializeCriticalSection(&pClientImc->cs);
pClientImc->unknown = NtUserGetThreadState(THREADSTATE_UNKNOWN13);
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
pClientImc->unknown = NtUserGetThreadState(13);
if (!NtUserUpdateInputContext(hImc, 0, pClientImc)) if (!NtUserUpdateInputContext(hImc, 0, pClientImc))
{ {
@ -2655,8 +2820,9 @@ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32)) if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
return NULL; return NULL;
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
if (hWnd == NULL) if (hWnd == NULL)
return (HWND)NtUserGetThreadState(THREADSTATE_ACTIVEWINDOW); return (HWND)NtUserGetThreadState(3);
return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME); return (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_IME);
} }
@ -3189,7 +3355,7 @@ UINT WINAPI ImmGetVirtualKey(HWND hWnd)
if (!pIC) if (!pIC)
return ret; return ret;
if (pIC->bHasVKey) if (pIC->bNeedsTrans)
ret = pIC->nVKey; ret = pIC->nVKey;
ImmUnlockIMC(hIMC); ImmUnlockIMC(hIMC);
@ -3510,7 +3676,6 @@ LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
BOOL WINAPI ImmSetCandidateWindow( BOOL WINAPI ImmSetCandidateWindow(
HIMC hIMC, LPCANDIDATEFORM lpCandidate) HIMC hIMC, LPCANDIDATEFORM lpCandidate)
{ {
#define MAX_CANDIDATEFORM 4
HWND hWnd; HWND hWnd;
LPINPUTCONTEXT pIC; LPINPUTCONTEXT pIC;
@ -3534,7 +3699,6 @@ BOOL WINAPI ImmSetCandidateWindow(
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS, Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS,
IMN_SETCANDIDATEPOS, (1 << lpCandidate->dwIndex)); IMN_SETCANDIDATEPOS, (1 << lpCandidate->dwIndex));
return TRUE; return TRUE;
#undef MAX_CANDIDATEFORM
} }
static VOID APIENTRY WideToAnsiLogFont(const LOGFONTW *plfW, LPLOGFONTA plfA) static VOID APIENTRY WideToAnsiLogFont(const LOGFONTW *plfW, LPLOGFONTA plfA)
@ -4444,102 +4608,261 @@ DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
*/ */
BOOL WINAPI ImmGenerateMessage(HIMC hIMC) 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) TRACE("(%p)\n", hIMC);
{
SetLastError(ERROR_INVALID_HANDLE); if (Imm32IsCrossThreadAccess(hIMC))
return FALSE; return FALSE;
}
TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf); pClientImc = ImmLockClientImc(hIMC);
if (data->IMC.dwNumMsgBuf > 0) 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)? */
{ {
LPTRANSMSG lpTransMsg; LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
HIMCC hMsgBuf; WORD wLang = PRIMARYLANGID(LangID);
DWORD i, dwNumMsgBuf;
/* We are going to detach our hMsgBuff so that if processing messages /* translate the messages if Japanese or Korean */
generates new messages they go into a new buffer */ if (wLang == LANG_JAPANESE ||
hMsgBuf = data->IMC.hMsgBuf; (wLang == LANG_KOREAN && NtUserGetAppImeLevel(pIC->hWnd) == 3))
dwNumMsgBuf = data->IMC.dwNumMsgBuf; {
dwCount = ImpTrans(dwCount, pTrans, hIMC, bAnsi, wLang);
}
}
#endif
data->IMC.hMsgBuf = ImmCreateIMCC(0); /* send them */
data->IMC.dwNumMsgBuf = 0; hWnd = pIC->hWnd;
pItem = pTrans;
lpTransMsg = ImmLockIMCC(hMsgBuf); for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pItem)
for (i = 0; i < dwNumMsgBuf; i++) {
ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam); if (bAnsi)
SendMessageA(hWnd, pItem->message, pItem->wParam, pItem->lParam);
ImmUnlockIMCC(hMsgBuf); else
ImmDestroyIMCC(hMsgBuf); 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; return TRUE;
} }
static VOID APIENTRY
Imm32PostMessages(HWND hwnd, HIMC hIMC, DWORD dwCount, LPTRANSMSG lpTransMsg)
{
DWORD dwIndex;
PCLIENTIMC pClientImc;
LPTRANSMSG pNewTransMsg = lpTransMsg, pItem;
BOOL bAnsi;
pClientImc = ImmLockClientImc(hIMC);
if (pClientImc == NULL)
return;
bAnsi = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
ImmUnlockClientImc(pClientImc);
#ifdef IMP_SUPPORT
if (GetWin32ClientInfo()->dwExpWinVer < 0x400) /* old version (3.x)? */
{
LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
WORD Lang = PRIMARYLANGID(LangID);
/* 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
/* 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
}
/*********************************************************************** /***********************************************************************
* ImmTranslateMessage(IMM32.@) * ImmTranslateMessage(IMM32.@)
* ( Undocumented, call internally and from user32.dll ) * ( Undocumented, call internally and from user32.dll )
*/ */
BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData) BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyData)
{ {
InputContextData *data; #define MSG_COUNT 0x100
HIMC imc = ImmGetContext(hwnd); BOOL ret = FALSE;
BYTE state[256]; INT kret;
UINT scancode; LPINPUTCONTEXTDX pIC;
LPVOID list = 0; PIMEDPI pImeDpi = NULL;
UINT msg_count; LPTRANSMSGLIST pList = NULL;
UINT uVirtKey; LPTRANSMSG pTransMsg;
static const DWORD list_count = 10; 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) /* filter the message */
data = (InputContextData *)imc; switch (msg)
else
return FALSE;
if (!data->immKbd->hIME || !data->immKbd->pImeToAsciiEx)
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)
{ {
WCHAR chr; case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP:
break;
default:
return FALSE;
}
if (!is_himc_ime_unicode(data)) hIMC = ImmGetContext(hwnd);
ToAscii(data->lastVK, scancode, state, &chr, 0); pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
if (pIC == NULL)
{
ImmReleaseContext(hwnd, hIMC);
return FALSE;
}
if (!pIC->bNeedsTrans) /* is translation needed? */
{
/* directly post them */
dwCount = pIC->dwNumMsgBuf;
if (dwCount == 0)
goto Quit;
pTransMsg = ImmLockIMCC(pIC->hMsgBuf);
if (pTransMsg)
{
Imm32PostMessages(hwnd, hIMC, dwCount, pTransMsg);
ImmUnlockIMCC(pIC->hMsgBuf);
ret = TRUE;
}
pIC->dwNumMsgBuf = 0; /* done */
goto Quit;
}
pIC->bNeedsTrans = FALSE; /* clear the flag */
dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
hKL = GetKeyboardLayout(dwThreadId);
pImeDpi = ImmLockImeDpi(hKL);
if (pImeDpi == NULL)
goto Quit;
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 else
ToUnicodeEx(data->lastVK, scancode, state, &chr, 1, 0, GetKeyboardLayout(0)); {
uVirtKey = MAKELONG(data->lastVK,chr); wChar = 0;
kret = ToAsciiEx(vk, HIWORD(lKeyData), abKeyState, &wChar, 0, hKL);
if (kret > 0)
vk = MAKEWORD(vk, wChar);
}
}
/* allocate a list */
cbList = offsetof(TRANSMSGLIST, TransMsg) + MSG_COUNT * sizeof(TRANSMSG);
pList = Imm32HeapAlloc(0, cbList);
if (!pList)
goto Quit;
/* 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;
/* post them */
if (kret <= MSG_COUNT)
{
Imm32PostMessages(hwnd, hIMC, kret, pList->TransMsg);
ret = TRUE;
} }
else else
uVirtKey = data->lastVK;
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; pTransMsg = ImmLockIMCC(pIC->hMsgBuf);
LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD)); if (pTransMsg == NULL)
goto Quit;
for (i = 0; i < msg_count; i++) Imm32PostMessages(hwnd, hIMC, kret, pTransMsg);
ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam); ImmUnlockIMCC(pIC->hMsgBuf);
} }
else if (msg_count > list_count)
ImmGenerateMessage(imc);
HeapFree(GetProcessHeap(),0,list); Quit:
if (pList)
data->lastVK = VK_PROCESSKEY; HeapFree(g_hImm32Heap, 0, pList);
ImmUnlockImeDpi(pImeDpi);
return (msg_count > 0); ImmUnlockIMC(hIMC);
ImmReleaseContext(hwnd, hIMC);
return ret;
#undef MSG_COUNT
} }
/*********************************************************************** /***********************************************************************

View file

@ -103,7 +103,7 @@
@ stdcall ImmShowSoftKeyboard(ptr long) @ stdcall ImmShowSoftKeyboard(ptr long)
@ stdcall ImmSimulateHotKey(ptr long) @ stdcall ImmSimulateHotKey(ptr long)
@ stdcall -stub ImmSystemHandler(ptr long long) @ stdcall -stub ImmSystemHandler(ptr long long)
@ stdcall ImmTranslateMessage(ptr long long long) @ stdcall ImmTranslateMessage(ptr long ptr ptr)
@ stdcall ImmUnlockClientImc(ptr) @ stdcall ImmUnlockClientImc(ptr)
@ stdcall ImmUnlockIMC(ptr) @ stdcall ImmUnlockIMC(ptr)
@ stdcall ImmUnlockIMCC(ptr) @ stdcall ImmUnlockIMCC(ptr)

View file

@ -91,7 +91,7 @@ typedef struct INPUTCONTEXTDX /* unconfirmed */
{ {
INPUTCONTEXT; INPUTCONTEXT;
UINT nVKey; UINT nVKey;
BOOL bHasVKey; BOOL bNeedsTrans;
DWORD dwUnknownCat; DWORD dwUnknownCat;
DWORD dwUIFlags; DWORD dwUIFlags;
DWORD dwUnknownDog; DWORD dwUnknownDog;
@ -101,7 +101,7 @@ typedef struct INPUTCONTEXTDX /* unconfirmed */
#ifndef _WIN64 #ifndef _WIN64
C_ASSERT(offsetof(INPUTCONTEXTDX, nVKey) == 0x140); C_ASSERT(offsetof(INPUTCONTEXTDX, nVKey) == 0x140);
C_ASSERT(offsetof(INPUTCONTEXTDX, bHasVKey) == 0x144); C_ASSERT(offsetof(INPUTCONTEXTDX, bNeedsTrans) == 0x144);
C_ASSERT(offsetof(INPUTCONTEXTDX, dwUIFlags) == 0x14c); C_ASSERT(offsetof(INPUTCONTEXTDX, dwUIFlags) == 0x14c);
#endif #endif
@ -131,6 +131,24 @@ C_ASSERT(offsetof(INPUTCONTEXTDX, dwUIFlags) == 0x14c);
#define IR_STRINGEX 0x180 #define IR_STRINGEX 0x180
#define IR_MODEINFO 0x190 #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); LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC);

View file

@ -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, 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, ImeProcessKey, (HIMC hIMC, UINT uVirKey, DWORD lParam, CONST LPBYTE lpbKeyState), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeSetActiveContext, (HIMC hIMC, BOOL fFlag), 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, 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(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) DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize), FALSE)

View file

@ -1211,6 +1211,17 @@ typedef struct _IMEWND
PIMEUI pimeui; PIMEUI pimeui;
} IMEWND, *PIMEWND; } 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; #define DEFINE_IME_ENTRY(type, name, params, extended) typedef type (WINAPI *FN_##name) params;
#include "imetable.h" #include "imetable.h"
#undef DEFINE_IME_ENTRY #undef DEFINE_IME_ENTRY
@ -2203,8 +2214,7 @@ NtUserGetAncestor(
DWORD DWORD
NTAPI NTAPI
NtUserGetAppImeLevel( NtUserGetAppImeLevel(HWND hWnd);
DWORD dwUnknown1);
SHORT SHORT
NTAPI NTAPI

View file

@ -95,8 +95,7 @@ NtUserDisableThreadIme(
DWORD DWORD
APIENTRY APIENTRY
NtUserGetAppImeLevel( NtUserGetAppImeLevel(HWND hWnd)
DWORD dwUnknown1)
{ {
STUB; STUB;
return 0; return 0;