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 + * Copyright 2018 Amine Khaldi + * Copyright 2020 Oleg Dubinskiy + * Copyright 2020-2021 Katayama Hirofumi MZ */ #include @@ -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,102 +4608,261 @@ 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; - } - TRACE("%i messages queued\n",data->IMC.dwNumMsgBuf); - if (data->IMC.dwNumMsgBuf > 0) + 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)? */ { - LPTRANSMSG lpTransMsg; - HIMCC hMsgBuf; - DWORD i, dwNumMsgBuf; + LANGID LangID = LANGIDFROMLCID(GetSystemDefaultLCID()); + WORD wLang = PRIMARYLANGID(LangID); - /* 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; + /* 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 - data->IMC.hMsgBuf = ImmCreateIMCC(0); - data->IMC.dwNumMsgBuf = 0; - - lpTransMsg = ImmLockIMCC(hMsgBuf); - for (i = 0; i < dwNumMsgBuf; i++) - ImmInternalSendIMEMessage(data, lpTransMsg[i].message, lpTransMsg[i].wParam, lpTransMsg[i].lParam); - - ImmUnlockIMCC(hMsgBuf); - ImmDestroyIMCC(hMsgBuf); + /* send them */ + hWnd = pIC->hWnd; + pItem = pTrans; + for (dwIndex = 0; dwIndex < dwCount; ++dwIndex, ++pItem) + { + 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; + + 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.@) * ( Undocumented, call internally and from user32.dll ) */ 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; - - 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) + /* filter the message */ + switch (msg) { - WCHAR chr; + case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP: + break; + default: + return FALSE; + } - if (!is_himc_ime_unicode(data)) - ToAscii(data->lastVK, scancode, state, &chr, 0); + hIMC = ImmGetContext(hwnd); + 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 - 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 - 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; - LPTRANSMSG msgs = (LPTRANSMSG)((LPBYTE)list + sizeof(DWORD)); - - for (i = 0; i < msg_count; i++) - ImmInternalPostIMEMessage(data, msgs[i].message, msgs[i].wParam, msgs[i].lParam); + pTransMsg = ImmLockIMCC(pIC->hMsgBuf); + if (pTransMsg == NULL) + goto Quit; + Imm32PostMessages(hwnd, hIMC, kret, pTransMsg); + ImmUnlockIMCC(pIC->hMsgBuf); } - else if (msg_count > list_count) - ImmGenerateMessage(imc); - HeapFree(GetProcessHeap(),0,list); - - data->lastVK = VK_PROCESSKEY; - - return (msg_count > 0); +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;