mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
[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:
parent
db8dd3b35e
commit
f4bc74edc3
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -95,8 +95,7 @@ NtUserDisableThreadIme(
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtUserGetAppImeLevel(
|
NtUserGetAppImeLevel(HWND hWnd)
|
||||||
DWORD dwUnknown1)
|
|
||||||
{
|
{
|
||||||
STUB;
|
STUB;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue