mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
[IMM32] Restructure! (Retry) (#3952)
The imm.c file became big and bloated, so we split the source file. CORE-11700 - Split the IMM32 code and do formatting.
This commit is contained in:
parent
ce7ac73f89
commit
b4557a60a9
|
@ -1,14 +1,21 @@
|
|||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine)
|
||||
include_directories(
|
||||
${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine
|
||||
${REACTOS_SOURCE_DIR}/win32ss/include)
|
||||
|
||||
add_definitions(-D__WINESRC__)
|
||||
|
||||
remove_definitions(-D_WIN32_WINNT=0x502)
|
||||
add_definitions(-D_WIN32_WINNT=0x600)
|
||||
|
||||
spec2def(imm32.dll imm32.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
candidate.c
|
||||
guideline.c
|
||||
ime.c
|
||||
imm.c
|
||||
keymsg.c
|
||||
nt3.c
|
||||
regword.c
|
||||
utils.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/imm32_stubs.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/imm32.def)
|
||||
|
||||
|
|
406
dll/win32/imm32/candidate.c
Normal file
406
dll/win32/imm32/candidate.c
Normal file
|
@ -0,0 +1,406 @@
|
|||
/*
|
||||
* PROJECT: ReactOS IMM32
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Implementing IMM32 candidate lists
|
||||
* COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||
|
||||
DWORD APIENTRY
|
||||
CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen,
|
||||
UINT uCodePage)
|
||||
{
|
||||
BOOL bUsedDefault;
|
||||
DWORD dwSize, dwIndex, cbGot, cbLeft;
|
||||
const BYTE *pbWide;
|
||||
LPBYTE pbAnsi;
|
||||
LPDWORD pibOffsets;
|
||||
|
||||
/* calculate total ansi size */
|
||||
if (pWideCL->dwCount > 0)
|
||||
{
|
||||
dwSize = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
|
||||
for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
|
||||
{
|
||||
pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
|
||||
cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1, NULL, 0,
|
||||
NULL, &bUsedDefault);
|
||||
dwSize += cbGot;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwSize = sizeof(CANDIDATELIST);
|
||||
}
|
||||
|
||||
dwSize = ROUNDUP4(dwSize);
|
||||
if (dwBufLen == 0)
|
||||
return dwSize;
|
||||
if (dwBufLen < dwSize)
|
||||
return 0;
|
||||
|
||||
/* store to ansi */
|
||||
pAnsiCL->dwSize = dwBufLen;
|
||||
pAnsiCL->dwStyle = pWideCL->dwStyle;
|
||||
pAnsiCL->dwCount = pWideCL->dwCount;
|
||||
pAnsiCL->dwSelection = pWideCL->dwSelection;
|
||||
pAnsiCL->dwPageStart = pWideCL->dwPageStart;
|
||||
pAnsiCL->dwPageSize = pWideCL->dwPageSize;
|
||||
|
||||
pibOffsets = pAnsiCL->dwOffset;
|
||||
if (pWideCL->dwCount > 0)
|
||||
{
|
||||
pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
|
||||
cbLeft = dwBufLen - pibOffsets[0];
|
||||
|
||||
for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
|
||||
{
|
||||
pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
|
||||
pbAnsi = (LPBYTE)pAnsiCL + pibOffsets[dwIndex];
|
||||
|
||||
/* convert to ansi */
|
||||
cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1,
|
||||
(LPSTR)pbAnsi, cbLeft, NULL, &bUsedDefault);
|
||||
cbLeft -= cbGot;
|
||||
|
||||
if (dwIndex < pWideCL->dwCount - 1)
|
||||
pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pibOffsets[0] = sizeof(CANDIDATELIST);
|
||||
}
|
||||
|
||||
return dwBufLen;
|
||||
}
|
||||
|
||||
DWORD APIENTRY
|
||||
CandidateListAnsiToWide(const CANDIDATELIST *pAnsiCL, LPCANDIDATELIST pWideCL, DWORD dwBufLen,
|
||||
UINT uCodePage)
|
||||
{
|
||||
DWORD dwSize, dwIndex, cchGot, cbGot, cbLeft;
|
||||
const BYTE *pbAnsi;
|
||||
LPBYTE pbWide;
|
||||
LPDWORD pibOffsets;
|
||||
|
||||
/* calculate total wide size */
|
||||
if (pAnsiCL->dwCount > 0)
|
||||
{
|
||||
dwSize = sizeof(CANDIDATELIST) + ((pAnsiCL->dwCount - 1) * sizeof(DWORD));
|
||||
for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
|
||||
{
|
||||
pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
|
||||
cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1, NULL, 0);
|
||||
dwSize += cchGot * sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dwSize = sizeof(CANDIDATELIST);
|
||||
}
|
||||
|
||||
dwSize = ROUNDUP4(dwSize);
|
||||
if (dwBufLen == 0)
|
||||
return dwSize;
|
||||
if (dwBufLen < dwSize)
|
||||
return 0;
|
||||
|
||||
/* store to wide */
|
||||
pWideCL->dwSize = dwBufLen;
|
||||
pWideCL->dwStyle = pAnsiCL->dwStyle;
|
||||
pWideCL->dwCount = pAnsiCL->dwCount;
|
||||
pWideCL->dwSelection = pAnsiCL->dwSelection;
|
||||
pWideCL->dwPageStart = pAnsiCL->dwPageStart;
|
||||
pWideCL->dwPageSize = pAnsiCL->dwPageSize;
|
||||
|
||||
pibOffsets = pWideCL->dwOffset;
|
||||
if (pAnsiCL->dwCount > 0)
|
||||
{
|
||||
pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
|
||||
cbLeft = dwBufLen - pibOffsets[0];
|
||||
|
||||
for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
|
||||
{
|
||||
pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
|
||||
pbWide = (LPBYTE)pWideCL + pibOffsets[dwIndex];
|
||||
|
||||
/* convert to wide */
|
||||
cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1,
|
||||
(LPWSTR)pbWide, cbLeft / sizeof(WCHAR));
|
||||
cbGot = cchGot * sizeof(WCHAR);
|
||||
cbLeft -= cbGot;
|
||||
|
||||
if (dwIndex + 1 < pAnsiCL->dwCount)
|
||||
pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pibOffsets[0] = sizeof(CANDIDATELIST);
|
||||
}
|
||||
|
||||
return dwBufLen;
|
||||
}
|
||||
|
||||
static DWORD APIENTRY
|
||||
ImmGetCandidateListAW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen,
|
||||
BOOL bAnsi)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
LPINPUTCONTEXT pIC;
|
||||
PCLIENTIMC pClientImc;
|
||||
LPCANDIDATEINFO pCI;
|
||||
LPCANDIDATELIST pCL;
|
||||
DWORD dwSize;
|
||||
|
||||
pClientImc = ImmLockClientImc(hIMC);
|
||||
if (!pClientImc)
|
||||
return 0;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
{
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCI = ImmLockIMCC(pIC->hCandInfo);
|
||||
if (pCI == NULL)
|
||||
{
|
||||
ImmUnlockIMC(hIMC);
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pCI->dwSize < sizeof(CANDIDATEINFO) || pCI->dwCount <= dwIndex)
|
||||
goto Quit;
|
||||
|
||||
/* get required size */
|
||||
pCL = (LPCANDIDATELIST)((LPBYTE)pCI + pCI->dwOffset[dwIndex]);
|
||||
if (bAnsi)
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
dwSize = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
|
||||
else
|
||||
dwSize = pCL->dwSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
dwSize = pCL->dwSize;
|
||||
else
|
||||
dwSize = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
|
||||
}
|
||||
|
||||
if (dwBufLen != 0 && dwSize != 0)
|
||||
{
|
||||
if (lpCandList == NULL || dwBufLen < dwSize)
|
||||
goto Quit;
|
||||
|
||||
/* store */
|
||||
if (bAnsi)
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
CandidateListAnsiToWide(pCL, lpCandList, dwSize, CP_ACP);
|
||||
else
|
||||
RtlCopyMemory(lpCandList, pCL, dwSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
RtlCopyMemory(lpCandList, pCL, dwSize);
|
||||
else
|
||||
CandidateListWideToAnsi(pCL, lpCandList, dwSize, CP_ACP);
|
||||
}
|
||||
}
|
||||
|
||||
ret = dwSize;
|
||||
|
||||
Quit:
|
||||
ImmUnlockIMCC(pIC->hCandInfo);
|
||||
ImmUnlockIMC(hIMC);
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DWORD APIENTRY
|
||||
ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, BOOL bAnsi)
|
||||
{
|
||||
DWORD ret = 0, cbGot, dwIndex;
|
||||
PCLIENTIMC pClientImc;
|
||||
LPINPUTCONTEXT pIC;
|
||||
const CANDIDATEINFO *pCI;
|
||||
const BYTE *pb;
|
||||
const CANDIDATELIST *pCL;
|
||||
const DWORD *pdwOffsets;
|
||||
|
||||
if (lpdwListCount == NULL)
|
||||
return 0;
|
||||
|
||||
*lpdwListCount = 0;
|
||||
|
||||
pClientImc = ImmLockClientImc(hIMC);
|
||||
if (pClientImc == NULL)
|
||||
return 0;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
{
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pCI = ImmLockIMCC(pIC->hCandInfo);
|
||||
if (pCI == NULL)
|
||||
{
|
||||
ImmUnlockIMC(hIMC);
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pCI->dwSize < sizeof(CANDIDATEINFO))
|
||||
goto Quit;
|
||||
|
||||
*lpdwListCount = pCI->dwCount; /* the number of candidate lists */
|
||||
|
||||
/* calculate total size of candidate lists */
|
||||
if (bAnsi)
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
{
|
||||
ret = ROUNDUP4(pCI->dwPrivateSize);
|
||||
pdwOffsets = pCI->dwOffset;
|
||||
for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
|
||||
{
|
||||
pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
|
||||
pCL = (const CANDIDATELIST *)pb;
|
||||
cbGot = CandidateListWideToAnsi(pCL, NULL, 0, CP_ACP);
|
||||
ret += cbGot;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = pCI->dwSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
{
|
||||
ret = pCI->dwSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ROUNDUP4(pCI->dwPrivateSize);
|
||||
pdwOffsets = pCI->dwOffset;
|
||||
for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
|
||||
{
|
||||
pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
|
||||
pCL = (const CANDIDATELIST *)pb;
|
||||
cbGot = CandidateListAnsiToWide(pCL, NULL, 0, CP_ACP);
|
||||
ret += cbGot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Quit:
|
||||
ImmUnlockIMCC(pIC->hCandInfo);
|
||||
ImmUnlockIMC(hIMC);
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetCandidateListA (IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI
|
||||
ImmGetCandidateListA(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
|
||||
{
|
||||
return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, TRUE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetCandidateListCountA (IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI ImmGetCandidateListCountA(HIMC hIMC, LPDWORD lpdwListCount)
|
||||
{
|
||||
return ImmGetCandidateListCountAW(hIMC, lpdwListCount, TRUE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetCandidateListCountW (IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI ImmGetCandidateListCountW(HIMC hIMC, LPDWORD lpdwListCount)
|
||||
{
|
||||
return ImmGetCandidateListCountAW(hIMC, lpdwListCount, FALSE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetCandidateListW (IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI
|
||||
ImmGetCandidateListW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
|
||||
{
|
||||
return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, FALSE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetCandidateWindow (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ImmGetCandidateWindow(HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
LPINPUTCONTEXT pIC;
|
||||
LPCANDIDATEFORM pCF;
|
||||
|
||||
TRACE("(%p, %lu, %p)\n", hIMC, dwIndex, lpCandidate);
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
return FALSE;
|
||||
|
||||
pCF = &pIC->cfCandForm[dwIndex];
|
||||
if (pCF->dwIndex != IMM_INVALID_CANDFORM)
|
||||
{
|
||||
*lpCandidate = *pCF;
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmSetCandidateWindow (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI ImmSetCandidateWindow(HIMC hIMC, LPCANDIDATEFORM lpCandidate)
|
||||
{
|
||||
HWND hWnd;
|
||||
LPINPUTCONTEXT pIC;
|
||||
|
||||
TRACE("(%p, %p)\n", hIMC, lpCandidate);
|
||||
|
||||
if (lpCandidate->dwIndex >= MAX_CANDIDATEFORM)
|
||||
return FALSE;
|
||||
|
||||
if (Imm32IsCrossThreadAccess(hIMC))
|
||||
return FALSE;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
return FALSE;
|
||||
|
||||
hWnd = pIC->hWnd;
|
||||
pIC->cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
|
||||
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS,
|
||||
IMN_SETCANDIDATEPOS, (1 << (BYTE)lpCandidate->dwIndex));
|
||||
return TRUE;
|
||||
}
|
198
dll/win32/imm32/guideline.c
Normal file
198
dll/win32/imm32/guideline.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* PROJECT: ReactOS IMM32
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Implementing IMM32 guidelines
|
||||
* COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||
|
||||
DWORD APIENTRY
|
||||
ImmGetGuideLineAW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsi)
|
||||
{
|
||||
PCLIENTIMC pClientImc;
|
||||
LPINPUTCONTEXT pIC;
|
||||
LPGUIDELINE pGuideLine;
|
||||
DWORD cb, ret = 0;
|
||||
LPVOID pvStr, pvPrivate;
|
||||
BOOL bUsedDefault;
|
||||
|
||||
pClientImc = ImmLockClientImc(hIMC);
|
||||
if (!pClientImc)
|
||||
return 0;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (!pIC)
|
||||
{
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pGuideLine = ImmLockIMCC(pIC->hGuideLine);
|
||||
if (!pGuideLine)
|
||||
{
|
||||
ImmUnlockIMC(hIMC);
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dwIndex == GGL_LEVEL)
|
||||
{
|
||||
ret = pGuideLine->dwLevel;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (dwIndex == GGL_INDEX)
|
||||
{
|
||||
ret = pGuideLine->dwIndex;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (dwIndex == GGL_STRING)
|
||||
{
|
||||
pvStr = (LPBYTE)pGuideLine + pGuideLine->dwStrOffset;
|
||||
|
||||
/* get size */
|
||||
if (bAnsi)
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
{
|
||||
cb = WideCharToMultiByte(CP_ACP, 0, pvStr, pGuideLine->dwStrLen,
|
||||
NULL, 0, NULL, &bUsedDefault);
|
||||
}
|
||||
else
|
||||
{
|
||||
cb = pGuideLine->dwStrLen * sizeof(CHAR);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
{
|
||||
cb = pGuideLine->dwStrLen * sizeof(WCHAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
cb = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, pGuideLine->dwStrLen,
|
||||
NULL, 0) * sizeof(WCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
|
||||
{
|
||||
ret = cb;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* store to buffer */
|
||||
if (bAnsi)
|
||||
{
|
||||
if (pClientImc->dwFlags & CLIENTIMC_WIDE)
|
||||
{
|
||||
ret = WideCharToMultiByte(CP_ACP, 0, pvStr, pGuideLine->dwStrLen,
|
||||
lpBuf, dwBufLen, NULL, &bUsedDefault);
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(pClientImc->dwFlags & CLIENTIMC_WIDE))
|
||||
{
|
||||
ret = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pvStr, pGuideLine->dwStrLen,
|
||||
lpBuf, dwBufLen) * sizeof(WCHAR);
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
|
||||
RtlCopyMemory(lpBuf, pvStr, cb);
|
||||
ret = cb;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (dwIndex == GGL_PRIVATE)
|
||||
{
|
||||
pvPrivate = (LPBYTE)pGuideLine + pGuideLine->dwPrivateOffset;
|
||||
|
||||
/* get size */
|
||||
if (bAnsi)
|
||||
{
|
||||
if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
|
||||
pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
|
||||
{
|
||||
cb = CandidateListWideToAnsi(pvPrivate, NULL, 0, CP_ACP);
|
||||
}
|
||||
else
|
||||
{
|
||||
cb = pGuideLine->dwPrivateSize;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
|
||||
pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
|
||||
{
|
||||
cb = CandidateListAnsiToWide(pvPrivate, NULL, 0, CP_ACP);
|
||||
}
|
||||
else
|
||||
{
|
||||
cb = pGuideLine->dwPrivateSize;
|
||||
}
|
||||
}
|
||||
|
||||
if (dwBufLen == 0 || cb == 0 || lpBuf == NULL || dwBufLen < cb)
|
||||
{
|
||||
ret = cb;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
/* store to buffer */
|
||||
if (bAnsi)
|
||||
{
|
||||
if ((pClientImc->dwFlags & CLIENTIMC_WIDE) &&
|
||||
pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
|
||||
{
|
||||
ret = CandidateListWideToAnsi(pvPrivate, lpBuf, cb, CP_ACP);
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(pClientImc->dwFlags & CLIENTIMC_WIDE) &&
|
||||
pGuideLine->dwIndex == GL_ID_REVERSECONVERSION)
|
||||
{
|
||||
ret = CandidateListAnsiToWide(pvPrivate, lpBuf, cb, CP_ACP);
|
||||
goto Quit;
|
||||
}
|
||||
}
|
||||
|
||||
RtlCopyMemory(lpBuf, pvPrivate, cb);
|
||||
ret = cb;
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
Quit:
|
||||
ImmUnlockIMCC(pIC->hGuideLine);
|
||||
ImmUnlockIMC(hIMC);
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetGuideLineA (IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI ImmGetGuideLineA(HIMC hIMC, DWORD dwIndex, LPSTR lpBuf, DWORD dwBufLen)
|
||||
{
|
||||
TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
|
||||
return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetGuideLineW (IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI ImmGetGuideLineW(HIMC hIMC, DWORD dwIndex, LPWSTR lpBuf, DWORD dwBufLen)
|
||||
{
|
||||
TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
|
||||
return ImmGetGuideLineAW(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
|
||||
}
|
1201
dll/win32/imm32/ime.c
Normal file
1201
dll/win32/imm32/ime.c
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
688
dll/win32/imm32/keymsg.c
Normal file
688
dll/win32/imm32/keymsg.c
Normal file
|
@ -0,0 +1,688 @@
|
|||
/*
|
||||
* PROJECT: ReactOS IMM32
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Implementing IMM32 keys and messages
|
||||
* COPYRIGHT: Copyright 1998 Patrik Stridvall
|
||||
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
|
||||
* Copyright 2017 James Tabor <james.tabor@reactos.org>
|
||||
* Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
|
||||
* Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
|
||||
* Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||
|
||||
BOOL APIENTRY Imm32ImeNonImeToggle(HIMC hIMC, HKL hKL, HWND hWnd, LANGID LangID)
|
||||
{
|
||||
LPINPUTCONTEXT pIC;
|
||||
BOOL fOpen;
|
||||
|
||||
if (hWnd != NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!IS_IME_HKL(hKL) || LOWORD(hKL) != LangID)
|
||||
{
|
||||
FIXME("We have to do something here\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
return TRUE;
|
||||
|
||||
fOpen = pIC->fOpen;
|
||||
ImmUnlockIMC(hIMC);
|
||||
|
||||
if (!fOpen)
|
||||
{
|
||||
ImmSetOpenStatus(hIMC, TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
FIXME("We have to do something here\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY Imm32CShapeToggle(HIMC hIMC, HKL hKL, HWND hWnd)
|
||||
{
|
||||
LPINPUTCONTEXT pIC;
|
||||
BOOL fOpen;
|
||||
DWORD dwConversion, dwSentence;
|
||||
|
||||
if (hWnd == NULL || !IS_IME_HKL(hKL))
|
||||
return FALSE;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
return TRUE;
|
||||
|
||||
fOpen = pIC->fOpen;
|
||||
if (fOpen)
|
||||
{
|
||||
dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
|
||||
dwSentence = pIC->fdwSentence;
|
||||
}
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
|
||||
if (fOpen)
|
||||
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
||||
else
|
||||
ImmSetOpenStatus(hIMC, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY Imm32CSymbolToggle(HIMC hIMC, HKL hKL, HWND hWnd)
|
||||
{
|
||||
LPINPUTCONTEXT pIC;
|
||||
BOOL fOpen;
|
||||
DWORD dwConversion, dwSentence;
|
||||
|
||||
if (hWnd == NULL || !IS_IME_HKL(hKL))
|
||||
return FALSE;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
return TRUE;
|
||||
|
||||
fOpen = pIC->fOpen;
|
||||
if (fOpen)
|
||||
{
|
||||
dwConversion = (pIC->fdwConversion ^ IME_CMODE_SYMBOL);
|
||||
dwSentence = pIC->fdwSentence;
|
||||
}
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
|
||||
if (fOpen)
|
||||
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
||||
else
|
||||
ImmSetOpenStatus(hIMC, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY Imm32JCloseOpen(HIMC hIMC, HKL hKL, HWND hWnd)
|
||||
{
|
||||
BOOL fOpen;
|
||||
|
||||
if (ImmIsIME(hKL) && LOWORD(hKL) == LANGID_JAPANESE)
|
||||
{
|
||||
fOpen = ImmGetOpenStatus(hIMC);
|
||||
ImmSetOpenStatus(hIMC, !fOpen);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
FIXME("We have to do something here\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY Imm32KShapeToggle(HIMC hIMC)
|
||||
{
|
||||
LPINPUTCONTEXT pIC;
|
||||
DWORD dwConversion, dwSentence;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
return FALSE;
|
||||
|
||||
dwConversion = (pIC->fdwConversion ^ IME_CMODE_FULLSHAPE);
|
||||
dwSentence = pIC->fdwSentence;
|
||||
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
||||
|
||||
if (pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE))
|
||||
ImmSetOpenStatus(hIMC, TRUE);
|
||||
else
|
||||
ImmSetOpenStatus(hIMC, FALSE);
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY Imm32KHanjaConvert(HIMC hIMC)
|
||||
{
|
||||
LPINPUTCONTEXT pIC;
|
||||
DWORD dwConversion, dwSentence;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (!pIC)
|
||||
return FALSE;
|
||||
|
||||
dwConversion = (pIC->fdwConversion ^ IME_CMODE_HANJACONVERT);
|
||||
dwSentence = pIC->fdwSentence;
|
||||
ImmUnlockIMC(hIMC);
|
||||
|
||||
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY Imm32KEnglish(HIMC hIMC)
|
||||
{
|
||||
LPINPUTCONTEXT pIC;
|
||||
DWORD dwConversion, dwSentence;
|
||||
BOOL fOpen;
|
||||
|
||||
pIC = ImmLockIMC(hIMC);
|
||||
if (pIC == NULL)
|
||||
return FALSE;
|
||||
|
||||
dwConversion = (pIC->fdwConversion ^ IME_CMODE_NATIVE);
|
||||
dwSentence = pIC->fdwSentence;
|
||||
ImmSetConversionStatus(hIMC, dwConversion, dwSentence);
|
||||
|
||||
fOpen = ((pIC->fdwConversion & (IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE)) != 0);
|
||||
ImmSetOpenStatus(hIMC, fOpen);
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL APIENTRY Imm32ProcessHotKey(HWND hWnd, HIMC hIMC, HKL hKL, DWORD dwHotKeyID)
|
||||
{
|
||||
PIMEDPI pImeDpi;
|
||||
BOOL ret;
|
||||
|
||||
if (hIMC && Imm32IsCrossThreadAccess(hIMC))
|
||||
return FALSE;
|
||||
|
||||
switch (dwHotKeyID)
|
||||
{
|
||||
case IME_CHOTKEY_IME_NONIME_TOGGLE:
|
||||
return Imm32ImeNonImeToggle(hIMC, hKL, hWnd, LANGID_CHINESE_SIMPLIFIED);
|
||||
|
||||
case IME_CHOTKEY_SHAPE_TOGGLE:
|
||||
return Imm32CShapeToggle(hIMC, hKL, hWnd);
|
||||
|
||||
case IME_CHOTKEY_SYMBOL_TOGGLE:
|
||||
return Imm32CSymbolToggle(hIMC, hKL, hWnd);
|
||||
|
||||
case IME_JHOTKEY_CLOSE_OPEN:
|
||||
return Imm32JCloseOpen(hIMC, hKL, hWnd);
|
||||
|
||||
case IME_KHOTKEY_SHAPE_TOGGLE:
|
||||
return Imm32KShapeToggle(hIMC);
|
||||
|
||||
case IME_KHOTKEY_HANJACONVERT:
|
||||
return Imm32KHanjaConvert(hIMC);
|
||||
|
||||
case IME_KHOTKEY_ENGLISH:
|
||||
return Imm32KEnglish(hIMC);
|
||||
|
||||
case IME_THOTKEY_IME_NONIME_TOGGLE:
|
||||
return Imm32ImeNonImeToggle(hIMC, hKL, hWnd, LANGID_CHINESE_TRADITIONAL);
|
||||
|
||||
case IME_THOTKEY_SHAPE_TOGGLE:
|
||||
return Imm32CShapeToggle(hIMC, hKL, hWnd);
|
||||
|
||||
case IME_THOTKEY_SYMBOL_TOGGLE:
|
||||
return Imm32CSymbolToggle(hIMC, hKL, hWnd);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (dwHotKeyID < IME_HOTKEY_PRIVATE_FIRST || IME_HOTKEY_PRIVATE_LAST < dwHotKeyID)
|
||||
return FALSE;
|
||||
|
||||
pImeDpi = ImmLockImeDpi(hKL);
|
||||
if (pImeDpi == NULL)
|
||||
return FALSE;
|
||||
|
||||
ret = (BOOL)pImeDpi->ImeEscape(hIMC, IME_ESC_PRIVATE_HOTKEY, &dwHotKeyID);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL APIENTRY
|
||||
ImmIsUIMessageAW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAnsi)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case WM_IME_STARTCOMPOSITION: case WM_IME_ENDCOMPOSITION:
|
||||
case WM_IME_COMPOSITION: case WM_IME_SETCONTEXT: case WM_IME_NOTIFY:
|
||||
case WM_IME_COMPOSITIONFULL: case WM_IME_SELECT: case WM_IME_SYSTEM:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!hWndIME)
|
||||
return TRUE;
|
||||
|
||||
if (bAnsi)
|
||||
SendMessageA(hWndIME, msg, wParam, lParam);
|
||||
else
|
||||
SendMessageW(hWndIME, msg, wParam, lParam);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmIsUIMessageA (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI ImmIsUIMessageA(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
TRACE("(%p, 0x%X, %p, %p)\n", hWndIME, msg, wParam, lParam);
|
||||
return ImmIsUIMessageAW(hWndIME, msg, wParam, lParam, TRUE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmIsUIMessageW (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI ImmIsUIMessageW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
TRACE("(%p, 0x%X, %p, %p)\n", hWndIME, msg, wParam, lParam);
|
||||
return ImmIsUIMessageAW(hWndIME, msg, wParam, lParam, FALSE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetHotKey(IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ImmGetHotKey(IN DWORD dwHotKey, OUT LPUINT lpuModifiers, OUT LPUINT lpuVKey,
|
||||
OUT LPHKL lphKL)
|
||||
{
|
||||
TRACE("(0x%lX, %p, %p, %p)\n", dwHotKey, lpuModifiers, lpuVKey, lphKL);
|
||||
if (lpuModifiers && lpuVKey)
|
||||
return NtUserGetImeHotKey(dwHotKey, lpuModifiers, lpuVKey, lphKL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmWINNLSGetIMEHotkey (IMM32.@)
|
||||
*/
|
||||
UINT WINAPI ImmWINNLSGetIMEHotkey(HWND hwndIme)
|
||||
{
|
||||
TRACE("(%p)\n", hwndIme);
|
||||
UNREFERENCED_PARAMETER(hwndIme);
|
||||
return 0; /* This is correct. This function of Windows just returns zero. */
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmSimulateHotKey (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI ImmSimulateHotKey(HWND hWnd, DWORD dwHotKeyID)
|
||||
{
|
||||
HIMC hIMC;
|
||||
DWORD dwThreadId;
|
||||
HKL hKL;
|
||||
BOOL ret;
|
||||
|
||||
TRACE("(%p, 0x%lX)\n", hWnd, dwHotKeyID);
|
||||
|
||||
hIMC = ImmGetContext(hWnd);
|
||||
dwThreadId = GetWindowThreadProcessId(hWnd, NULL);
|
||||
hKL = GetKeyboardLayout(dwThreadId);
|
||||
ret = Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID);
|
||||
ImmReleaseContext(hWnd, hIMC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetVirtualKey (IMM32.@)
|
||||
*/
|
||||
UINT WINAPI ImmGetVirtualKey(HWND hWnd)
|
||||
{
|
||||
HIMC hIMC;
|
||||
LPINPUTCONTEXTDX pIC;
|
||||
UINT ret = VK_PROCESSKEY;
|
||||
|
||||
TRACE("(%p)\n", hWnd);
|
||||
|
||||
hIMC = ImmGetContext(hWnd);
|
||||
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
||||
if (!pIC)
|
||||
return ret;
|
||||
|
||||
if (pIC->bNeedsTrans)
|
||||
ret = pIC->nVKey;
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmProcessKey(IMM32.@)
|
||||
* ( Undocumented, called from user32.dll )
|
||||
*/
|
||||
DWORD WINAPI
|
||||
ImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID)
|
||||
{
|
||||
DWORD ret = 0;
|
||||
HIMC hIMC;
|
||||
PIMEDPI pImeDpi;
|
||||
LPINPUTCONTEXTDX pIC;
|
||||
BYTE KeyState[256];
|
||||
UINT vk;
|
||||
BOOL bUseIme = TRUE, bSkipThisKey = FALSE, bLowWordOnly = FALSE;
|
||||
|
||||
TRACE("(%p, %p, 0x%X, %p, 0x%lX)\n", hWnd, hKL, vKey, lParam, dwHotKeyID);
|
||||
|
||||
hIMC = ImmGetContext(hWnd);
|
||||
pImeDpi = ImmLockImeDpi(hKL);
|
||||
if (pImeDpi)
|
||||
{
|
||||
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
||||
if (pIC)
|
||||
{
|
||||
if (LOBYTE(vKey) == VK_PACKET &&
|
||||
!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY))
|
||||
{
|
||||
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
||||
{
|
||||
bLowWordOnly = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
bUseIme = FALSE;
|
||||
if (pIC->fOpen)
|
||||
bSkipThisKey = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (bUseIme)
|
||||
{
|
||||
if (GetKeyboardState(KeyState))
|
||||
{
|
||||
vk = (bLowWordOnly ? LOWORD(vKey) : vKey);
|
||||
if (pImeDpi->ImeProcessKey(hIMC, vk, lParam, KeyState))
|
||||
{
|
||||
pIC->bNeedsTrans = TRUE;
|
||||
pIC->nVKey = vKey;
|
||||
ret |= IPHK_PROCESSBYIME;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bSkipThisKey)
|
||||
{
|
||||
ret |= IPHK_SKIPTHISKEY;
|
||||
}
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
}
|
||||
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
}
|
||||
|
||||
if (dwHotKeyID != INVALID_HOTKEY_ID)
|
||||
{
|
||||
if (Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID))
|
||||
{
|
||||
if (vKey != VK_KANJI || dwHotKeyID != IME_JHOTKEY_CLOSE_OPEN)
|
||||
ret |= IPHK_HOTKEY;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret & IPHK_PROCESSBYIME)
|
||||
{
|
||||
FIXME("TODO: We have to do something here.\n");
|
||||
}
|
||||
|
||||
ImmReleaseContext(hWnd, hIMC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGenerateMessage(IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI ImmGenerateMessage(HIMC hIMC)
|
||||
{
|
||||
PCLIENTIMC pClientImc;
|
||||
LPINPUTCONTEXT pIC;
|
||||
LPTRANSMSG pMsgs, pTrans = NULL, pItem;
|
||||
HWND hWnd;
|
||||
DWORD dwIndex, dwCount, cbTrans;
|
||||
HIMCC hMsgBuf = NULL;
|
||||
BOOL bAnsi;
|
||||
|
||||
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 IMM_NT3_SUPPORT
|
||||
if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* 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 = ImmNt3Trans(dwCount, pTrans, hIMC, bAnsi, wLang);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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 IMM_NT3_SUPPORT
|
||||
if (GetWin32ClientInfo()->dwExpWinVer < _WIN32_WINNT_NT4) /* 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 = ImmNt3Trans(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 IMM_NT3_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)
|
||||
{
|
||||
#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, 0x%X, %p, %p)\n", hwnd, msg, wParam, lKeyData);
|
||||
|
||||
/* filter the message */
|
||||
switch (msg)
|
||||
{
|
||||
case WM_KEYDOWN: case WM_KEYUP: case WM_SYSKEYDOWN: case WM_SYSKEYUP:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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
|
||||
}
|
205
dll/win32/imm32/nt3.c
Normal file
205
dll/win32/imm32/nt3.c
Normal file
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* PROJECT: ReactOS IMM32
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Implementing IMM32 NT3 compatibility
|
||||
* COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||
|
||||
#ifdef IMM_NT3_SUPPORT /* 3.x support */
|
||||
|
||||
DWORD APIENTRY
|
||||
ImmNt3JTransCompA(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
|
||||
const TRANSMSG *pSrc, LPTRANSMSG pDest)
|
||||
{
|
||||
// FIXME
|
||||
*pDest = *pSrc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
DWORD APIENTRY
|
||||
ImmNt3JTransCompW(LPINPUTCONTEXTDX pIC, LPCOMPOSITIONSTRING pCS,
|
||||
const TRANSMSG *pSrc, LPTRANSMSG pDest)
|
||||
{
|
||||
// FIXME
|
||||
*pDest = *pSrc;
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef LRESULT (WINAPI *FN_SendMessage)(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
DWORD APIENTRY
|
||||
ImmNt3JTrans(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 = ImmNt3JTransCompA(pIC, pCS, pEntry, pTrans);
|
||||
else
|
||||
dwNumber = ImmNt3JTransCompW(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
|
||||
ImmNt3KTrans(DWORD dwCount, LPTRANSMSG pEntries, LPINPUTCONTEXTDX pIC,
|
||||
LPCOMPOSITIONSTRING pCS, BOOL bAnsi)
|
||||
{
|
||||
return dwCount; // FIXME
|
||||
}
|
||||
|
||||
static DWORD APIENTRY
|
||||
ImmNt3Trans(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 = ImmNt3JTrans(dwCount, pEntries, pIC, pCS, bAnsi);
|
||||
else if (wLang == LANG_KOREAN)
|
||||
ret = ImmNt3KTrans(dwCount, pEntries, pIC, pCS, bAnsi);
|
||||
ImmUnlockIMCC(pIC->hCompStr);
|
||||
}
|
||||
|
||||
ImmUnlockIMC(hIMC);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* IMM_NT3_SUPPORT */
|
103
dll/win32/imm32/precomp.h
Normal file
103
dll/win32/imm32/precomp.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* PROJECT: ReactOS IMM32
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Implementing IMM32
|
||||
* COPYRIGHT: Copyright 1998 Patrik Stridvall
|
||||
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
|
||||
* Copyright 2017 James Tabor <james.tabor@reactos.org>
|
||||
* Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
|
||||
* Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
|
||||
* Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* PSDK/NDK Headers */
|
||||
#define WIN32_NO_STATUS
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <wingdi.h>
|
||||
#include <winuser.h>
|
||||
#include <winnls.h>
|
||||
#include <winreg.h>
|
||||
|
||||
#include <imm.h>
|
||||
#include <ddk/imm.h>
|
||||
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/umtypes.h>
|
||||
#include <ndk/pstypes.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
|
||||
/* Public Win32K Headers */
|
||||
#include "ntuser.h"
|
||||
#include "ntwin32.h"
|
||||
|
||||
/* Undocumented user definitions */
|
||||
#include <undocuser.h>
|
||||
#include <imm32_undoc.h>
|
||||
|
||||
#include <strsafe.h>
|
||||
|
||||
#include <wine/debug.h>
|
||||
#include <wine/list.h>
|
||||
|
||||
#define IMM_INIT_MAGIC 0x19650412
|
||||
#define IMM_INVALID_CANDFORM ULONG_MAX
|
||||
#define INVALID_HOTKEY_ID 0xFFFFFFFF
|
||||
#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)
|
||||
|
||||
#define REGKEY_KEYBOARD_LAYOUTS L"System\\CurrentControlSet\\Control\\Keyboard Layouts"
|
||||
#define REGKEY_IMM L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM"
|
||||
|
||||
#define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
|
||||
|
||||
extern HMODULE g_hImm32Inst;
|
||||
extern RTL_CRITICAL_SECTION g_csImeDpi;
|
||||
extern PIMEDPI g_pImeDpiList;
|
||||
extern PSERVERINFO g_psi;
|
||||
extern SHAREDINFO g_SharedInfo;
|
||||
extern BYTE g_bClientRegd;
|
||||
extern HANDLE g_hImm32Heap;
|
||||
|
||||
BOOL Imm32GetSystemLibraryPath(LPWSTR pszPath, DWORD cchPath, LPCWSTR pszFileName);
|
||||
VOID APIENTRY LogFontAnsiToWide(const LOGFONTA *plfA, LPLOGFONTW plfW);
|
||||
VOID APIENTRY LogFontWideToAnsi(const LOGFONTW *plfW, LPLOGFONTA plfA);
|
||||
PWND FASTCALL ValidateHwndNoErr(HWND hwnd);
|
||||
LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes);
|
||||
LPWSTR APIENTRY Imm32WideFromAnsi(LPCSTR pszA);
|
||||
LPSTR APIENTRY Imm32AnsiFromWide(LPCWSTR pszW);
|
||||
PIMEDPI APIENTRY ImmLockOrLoadImeDpi(HKL hKL);
|
||||
|
||||
static inline BOOL Imm32IsCrossThreadAccess(HIMC hIMC)
|
||||
{
|
||||
DWORD dwImeThreadId = NtUserQueryInputContext(hIMC, 1);
|
||||
DWORD dwThreadId = GetCurrentThreadId();
|
||||
return (dwImeThreadId != dwThreadId);
|
||||
}
|
||||
|
||||
static inline BOOL Imm32IsCrossProcessAccess(HWND hWnd)
|
||||
{
|
||||
return (NtUserQueryWindow(hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID) !=
|
||||
(DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess);
|
||||
}
|
||||
|
||||
DWORD APIENTRY
|
||||
CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen,
|
||||
UINT uCodePage);
|
||||
DWORD APIENTRY
|
||||
CandidateListAnsiToWide(const CANDIDATELIST *pAnsiCL, LPCANDIDATELIST pWideCL, DWORD dwBufLen,
|
||||
UINT uCodePage);
|
||||
|
||||
BOOL APIENTRY
|
||||
Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD_PTR dwValue,
|
||||
DWORD_PTR dwCommand, DWORD_PTR dwData);
|
||||
|
||||
DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphList);
|
520
dll/win32/imm32/regword.c
Normal file
520
dll/win32/imm32/regword.c
Normal file
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* PROJECT: ReactOS IMM32
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Implementing IMM32 registering/unregistering words
|
||||
* COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||
|
||||
typedef struct ENUM_WORD_A2W
|
||||
{
|
||||
REGISTERWORDENUMPROCW lpfnEnumProc;
|
||||
LPVOID lpData;
|
||||
UINT ret;
|
||||
} ENUM_WORD_A2W, *LPENUM_WORD_A2W;
|
||||
|
||||
typedef struct ENUM_WORD_W2A
|
||||
{
|
||||
REGISTERWORDENUMPROCA lpfnEnumProc;
|
||||
LPVOID lpData;
|
||||
UINT ret;
|
||||
} ENUM_WORD_W2A, *LPENUM_WORD_W2A;
|
||||
|
||||
/*
|
||||
* These functions absorb the difference between Ansi and Wide.
|
||||
*/
|
||||
static INT CALLBACK
|
||||
Imm32EnumWordProcA2W(LPCSTR pszReadingA, DWORD dwStyle, LPCSTR pszRegisterA, LPVOID lpData)
|
||||
{
|
||||
INT ret = 0;
|
||||
LPENUM_WORD_A2W lpEnumData = lpData;
|
||||
LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
|
||||
|
||||
if (pszReadingA)
|
||||
{
|
||||
pszReadingW = Imm32WideFromAnsi(pszReadingA);
|
||||
if (pszReadingW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (pszRegisterA)
|
||||
{
|
||||
pszRegisterW = Imm32WideFromAnsi(pszRegisterA);
|
||||
if (pszRegisterW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ret = lpEnumData->lpfnEnumProc(pszReadingW, dwStyle, pszRegisterW, lpEnumData->lpData);
|
||||
lpEnumData->ret = ret;
|
||||
|
||||
Quit:
|
||||
if (pszReadingW)
|
||||
HeapFree(g_hImm32Heap, 0, pszReadingW);
|
||||
if (pszRegisterW)
|
||||
HeapFree(g_hImm32Heap, 0, pszRegisterW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static INT CALLBACK
|
||||
Imm32EnumWordProcW2A(LPCWSTR pszReadingW, DWORD dwStyle, LPCWSTR pszRegisterW, LPVOID lpData)
|
||||
{
|
||||
INT ret = 0;
|
||||
LPENUM_WORD_W2A lpEnumData = lpData;
|
||||
LPSTR pszReadingA = NULL, pszRegisterA = NULL;
|
||||
|
||||
if (pszReadingW)
|
||||
{
|
||||
pszReadingA = Imm32AnsiFromWide(pszReadingW);
|
||||
if (pszReadingW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (pszRegisterW)
|
||||
{
|
||||
pszRegisterA = Imm32AnsiFromWide(pszRegisterW);
|
||||
if (pszRegisterA == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ret = lpEnumData->lpfnEnumProc(pszReadingA, dwStyle, pszRegisterA, lpEnumData->lpData);
|
||||
lpEnumData->ret = ret;
|
||||
|
||||
Quit:
|
||||
if (pszReadingA)
|
||||
HeapFree(g_hImm32Heap, 0, pszReadingA);
|
||||
if (pszRegisterA)
|
||||
HeapFree(g_hImm32Heap, 0, pszRegisterA);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmEnumRegisterWordA (IMM32.@)
|
||||
*/
|
||||
UINT WINAPI
|
||||
ImmEnumRegisterWordA(HKL hKL, REGISTERWORDENUMPROCA lpfnEnumProc,
|
||||
LPCSTR lpszReading, DWORD dwStyle,
|
||||
LPCSTR lpszRegister, LPVOID lpData)
|
||||
{
|
||||
UINT ret = 0;
|
||||
LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
|
||||
ENUM_WORD_W2A EnumDataW2A;
|
||||
PIMEDPI pImeDpi;
|
||||
|
||||
TRACE("(%p, %p, %s, 0x%lX, %s, %p)", hKL, lpfnEnumProc, debugstr_a(lpszReading),
|
||||
dwStyle, debugstr_a(lpszRegister), lpData);
|
||||
|
||||
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
||||
if (!pImeDpi)
|
||||
return 0;
|
||||
|
||||
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
||||
{
|
||||
ret = pImeDpi->ImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
|
||||
lpszRegister, lpData);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (lpszReading)
|
||||
{
|
||||
pszReadingW = Imm32WideFromAnsi(lpszReading);
|
||||
if (pszReadingW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (lpszRegister)
|
||||
{
|
||||
pszRegisterW = Imm32WideFromAnsi(lpszRegister);
|
||||
if (pszRegisterW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
EnumDataW2A.lpfnEnumProc = lpfnEnumProc;
|
||||
EnumDataW2A.lpData = lpData;
|
||||
EnumDataW2A.ret = 0;
|
||||
pImeDpi->ImeEnumRegisterWord(Imm32EnumWordProcW2A, pszReadingW, dwStyle,
|
||||
pszRegisterW, &EnumDataW2A);
|
||||
ret = EnumDataW2A.ret;
|
||||
|
||||
Quit:
|
||||
if (pszReadingW)
|
||||
HeapFree(g_hImm32Heap, 0, pszReadingW);
|
||||
if (pszRegisterW)
|
||||
HeapFree(g_hImm32Heap, 0, pszRegisterW);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmEnumRegisterWordW (IMM32.@)
|
||||
*/
|
||||
UINT WINAPI
|
||||
ImmEnumRegisterWordW(HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc,
|
||||
LPCWSTR lpszReading, DWORD dwStyle,
|
||||
LPCWSTR lpszRegister, LPVOID lpData)
|
||||
{
|
||||
UINT ret = 0;
|
||||
LPSTR pszReadingA = NULL, pszRegisterA = NULL;
|
||||
ENUM_WORD_A2W EnumDataA2W;
|
||||
PIMEDPI pImeDpi;
|
||||
|
||||
TRACE("(%p, %p, %s, 0x%lX, %s, %p)", hKL, lpfnEnumProc, debugstr_w(lpszReading),
|
||||
dwStyle, debugstr_w(lpszRegister), lpData);
|
||||
|
||||
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
||||
if (!pImeDpi)
|
||||
return 0;
|
||||
|
||||
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
||||
{
|
||||
ret = pImeDpi->ImeEnumRegisterWord(lpfnEnumProc, lpszReading, dwStyle,
|
||||
lpszRegister, lpData);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (lpszReading)
|
||||
{
|
||||
pszReadingA = Imm32AnsiFromWide(lpszReading);
|
||||
if (pszReadingA == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (lpszRegister)
|
||||
{
|
||||
pszRegisterA = Imm32AnsiFromWide(lpszRegister);
|
||||
if (pszRegisterA == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
EnumDataA2W.lpfnEnumProc = lpfnEnumProc;
|
||||
EnumDataA2W.lpData = lpData;
|
||||
EnumDataA2W.ret = 0;
|
||||
pImeDpi->ImeEnumRegisterWord(Imm32EnumWordProcA2W, pszReadingA, dwStyle,
|
||||
pszRegisterA, &EnumDataA2W);
|
||||
ret = EnumDataA2W.ret;
|
||||
|
||||
Quit:
|
||||
if (pszReadingA)
|
||||
HeapFree(g_hImm32Heap, 0, pszReadingA);
|
||||
if (pszRegisterA)
|
||||
HeapFree(g_hImm32Heap, 0, pszRegisterA);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetRegisterWordStyleA (IMM32.@)
|
||||
*/
|
||||
UINT WINAPI ImmGetRegisterWordStyleA(HKL hKL, UINT nItem, LPSTYLEBUFA lpStyleBuf)
|
||||
{
|
||||
UINT iItem, ret = 0;
|
||||
PIMEDPI pImeDpi;
|
||||
LPSTYLEBUFA pDestA;
|
||||
LPSTYLEBUFW pSrcW, pNewStylesW = NULL;
|
||||
size_t cchW;
|
||||
INT cchA;
|
||||
|
||||
TRACE("(%p, %u, %p)\n", hKL, nItem, lpStyleBuf);
|
||||
|
||||
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
||||
if (!pImeDpi)
|
||||
return 0;
|
||||
|
||||
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
||||
{
|
||||
ret = pImeDpi->ImeGetRegisterWordStyle(nItem, lpStyleBuf);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (nItem > 0)
|
||||
{
|
||||
pNewStylesW = Imm32HeapAlloc(0, nItem * sizeof(STYLEBUFW));
|
||||
if (!pNewStylesW)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ret = pImeDpi->ImeGetRegisterWordStyle(nItem, pNewStylesW);
|
||||
|
||||
if (nItem > 0)
|
||||
{
|
||||
/* lpStyleBuf <-- pNewStylesW */
|
||||
for (iItem = 0; iItem < ret; ++iItem)
|
||||
{
|
||||
pSrcW = &pNewStylesW[iItem];
|
||||
pDestA = &lpStyleBuf[iItem];
|
||||
pDestA->dwStyle = pSrcW->dwStyle;
|
||||
StringCchLengthW(pSrcW->szDescription, _countof(pSrcW->szDescription), &cchW);
|
||||
cchA = WideCharToMultiByte(CP_ACP, MB_PRECOMPOSED,
|
||||
pSrcW->szDescription, (INT)cchW,
|
||||
pDestA->szDescription, _countof(pDestA->szDescription),
|
||||
NULL, NULL);
|
||||
if (cchA > _countof(pDestA->szDescription) - 1)
|
||||
cchA = _countof(pDestA->szDescription) - 1;
|
||||
pDestA->szDescription[cchA] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Quit:
|
||||
if (pNewStylesW)
|
||||
HeapFree(g_hImm32Heap, 0, pNewStylesW);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetRegisterWordStyleW (IMM32.@)
|
||||
*/
|
||||
UINT WINAPI ImmGetRegisterWordStyleW(HKL hKL, UINT nItem, LPSTYLEBUFW lpStyleBuf)
|
||||
{
|
||||
UINT iItem, ret = 0;
|
||||
PIMEDPI pImeDpi;
|
||||
LPSTYLEBUFA pSrcA, pNewStylesA = NULL;
|
||||
LPSTYLEBUFW pDestW;
|
||||
size_t cchA;
|
||||
INT cchW;
|
||||
|
||||
TRACE("(%p, %u, %p)\n", hKL, nItem, lpStyleBuf);
|
||||
|
||||
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
||||
if (!pImeDpi)
|
||||
return 0;
|
||||
|
||||
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
||||
{
|
||||
ret = pImeDpi->ImeGetRegisterWordStyle(nItem, lpStyleBuf);
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (nItem > 0)
|
||||
{
|
||||
pNewStylesA = Imm32HeapAlloc(0, nItem * sizeof(STYLEBUFA));
|
||||
if (!pNewStylesA)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ret = pImeDpi->ImeGetRegisterWordStyle(nItem, pNewStylesA);
|
||||
|
||||
if (nItem > 0)
|
||||
{
|
||||
/* lpStyleBuf <-- pNewStylesA */
|
||||
for (iItem = 0; iItem < ret; ++iItem)
|
||||
{
|
||||
pSrcA = &pNewStylesA[iItem];
|
||||
pDestW = &lpStyleBuf[iItem];
|
||||
pDestW->dwStyle = pSrcA->dwStyle;
|
||||
StringCchLengthA(pSrcA->szDescription, _countof(pSrcA->szDescription), &cchA);
|
||||
cchW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
|
||||
pSrcA->szDescription, (INT)cchA,
|
||||
pDestW->szDescription, _countof(pDestW->szDescription));
|
||||
if (cchW > _countof(pDestW->szDescription) - 1)
|
||||
cchW = _countof(pDestW->szDescription) - 1;
|
||||
pDestW->szDescription[cchW] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Quit:
|
||||
if (pNewStylesA)
|
||||
HeapFree(g_hImm32Heap, 0, pNewStylesA);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmRegisterWordA (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ImmRegisterWordA(HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszRegister)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
PIMEDPI pImeDpi;
|
||||
LPWSTR pszReadingW = NULL, pszRegisterW = NULL;
|
||||
|
||||
TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_a(lpszReading), dwStyle,
|
||||
debugstr_a(lpszRegister));
|
||||
|
||||
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
||||
if (!pImeDpi)
|
||||
return FALSE;
|
||||
|
||||
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
||||
{
|
||||
ret = pImeDpi->ImeRegisterWord(lpszReading, dwStyle, lpszRegister);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (lpszReading)
|
||||
{
|
||||
pszReadingW = Imm32WideFromAnsi(lpszReading);
|
||||
if (pszReadingW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (lpszRegister)
|
||||
{
|
||||
pszRegisterW = Imm32WideFromAnsi(lpszRegister);
|
||||
if (pszRegisterW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ret = pImeDpi->ImeRegisterWord(pszReadingW, dwStyle, pszRegisterW);
|
||||
|
||||
Quit:
|
||||
if (pszReadingW)
|
||||
HeapFree(g_hImm32Heap, 0, pszReadingW);
|
||||
if (pszRegisterW)
|
||||
HeapFree(g_hImm32Heap, 0, pszRegisterW);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmRegisterWordW (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ImmRegisterWordW(HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszRegister)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
PIMEDPI pImeDpi;
|
||||
LPSTR pszReadingA = NULL, pszRegisterA = NULL;
|
||||
|
||||
TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_w(lpszReading), dwStyle,
|
||||
debugstr_w(lpszRegister));
|
||||
|
||||
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
||||
if (!pImeDpi)
|
||||
return FALSE;
|
||||
|
||||
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
||||
{
|
||||
ret = pImeDpi->ImeRegisterWord(lpszReading, dwStyle, lpszRegister);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (lpszReading)
|
||||
{
|
||||
pszReadingA = Imm32AnsiFromWide(lpszReading);
|
||||
if (!pszReadingA)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (lpszRegister)
|
||||
{
|
||||
pszRegisterA = Imm32AnsiFromWide(lpszRegister);
|
||||
if (!pszRegisterA)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ret = pImeDpi->ImeRegisterWord(pszReadingA, dwStyle, pszRegisterA);
|
||||
|
||||
Quit:
|
||||
if (pszReadingA)
|
||||
HeapFree(g_hImm32Heap, 0, pszReadingA);
|
||||
if (pszRegisterA)
|
||||
HeapFree(g_hImm32Heap, 0, pszRegisterA);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmUnregisterWordA (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ImmUnregisterWordA(HKL hKL, LPCSTR lpszReading, DWORD dwStyle, LPCSTR lpszUnregister)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
PIMEDPI pImeDpi;
|
||||
LPWSTR pszReadingW = NULL, pszUnregisterW = NULL;
|
||||
|
||||
TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_a(lpszReading), dwStyle,
|
||||
debugstr_a(lpszUnregister));
|
||||
|
||||
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
||||
if (pImeDpi == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))
|
||||
{
|
||||
ret = pImeDpi->ImeUnregisterWord(lpszReading, dwStyle, lpszUnregister);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (lpszReading)
|
||||
{
|
||||
pszReadingW = Imm32WideFromAnsi(lpszReading);
|
||||
if (pszReadingW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (lpszUnregister)
|
||||
{
|
||||
pszUnregisterW = Imm32WideFromAnsi(lpszUnregister);
|
||||
if (pszUnregisterW == NULL)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ret = pImeDpi->ImeUnregisterWord(pszReadingW, dwStyle, pszUnregisterW);
|
||||
|
||||
Quit:
|
||||
if (pszReadingW)
|
||||
HeapFree(g_hImm32Heap, 0, pszReadingW);
|
||||
if (pszUnregisterW)
|
||||
HeapFree(g_hImm32Heap, 0, pszUnregisterW);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmUnregisterWordW (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ImmUnregisterWordW(HKL hKL, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszUnregister)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
PIMEDPI pImeDpi;
|
||||
LPSTR pszReadingA = NULL, pszUnregisterA = NULL;
|
||||
|
||||
TRACE("(%p, %s, 0x%lX, %s)\n", hKL, debugstr_w(lpszReading), dwStyle,
|
||||
debugstr_w(lpszUnregister));
|
||||
|
||||
pImeDpi = ImmLockOrLoadImeDpi(hKL);
|
||||
if (!pImeDpi)
|
||||
return FALSE;
|
||||
|
||||
if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)
|
||||
{
|
||||
ret = pImeDpi->ImeUnregisterWord(lpszReading, dwStyle, lpszUnregister);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (lpszReading)
|
||||
{
|
||||
pszReadingA = Imm32AnsiFromWide(lpszReading);
|
||||
if (!pszReadingA)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
if (lpszUnregister)
|
||||
{
|
||||
pszUnregisterA = Imm32AnsiFromWide(lpszUnregister);
|
||||
if (!pszUnregisterA)
|
||||
goto Quit;
|
||||
}
|
||||
|
||||
ret = pImeDpi->ImeUnregisterWord(pszReadingA, dwStyle, pszUnregisterA);
|
||||
|
||||
Quit:
|
||||
if (pszReadingA)
|
||||
HeapFree(g_hImm32Heap, 0, pszReadingA);
|
||||
if (pszUnregisterA)
|
||||
HeapFree(g_hImm32Heap, 0, pszUnregisterA);
|
||||
ImmUnlockImeDpi(pImeDpi);
|
||||
return ret;
|
||||
}
|
276
dll/win32/imm32/utils.c
Normal file
276
dll/win32/imm32/utils.c
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* PROJECT: ReactOS IMM32
|
||||
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
||||
* PURPOSE: Implementing IMM32 helper functions
|
||||
* COPYRIGHT: Copyright 1998 Patrik Stridvall
|
||||
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
|
||||
* Copyright 2017 James Tabor <james.tabor@reactos.org>
|
||||
* Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
|
||||
* Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
|
||||
* Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||
|
||||
HANDLE g_hImm32Heap = NULL;
|
||||
|
||||
LPWSTR APIENTRY Imm32WideFromAnsi(LPCSTR pszA)
|
||||
{
|
||||
INT cch = lstrlenA(pszA);
|
||||
LPWSTR pszW = Imm32HeapAlloc(0, (cch + 1) * sizeof(WCHAR));
|
||||
if (pszW == NULL)
|
||||
return NULL;
|
||||
cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszA, cch, pszW, cch + 1);
|
||||
pszW[cch] = 0;
|
||||
return pszW;
|
||||
}
|
||||
|
||||
LPSTR APIENTRY Imm32AnsiFromWide(LPCWSTR pszW)
|
||||
{
|
||||
INT cchW = lstrlenW(pszW);
|
||||
INT cchA = (cchW + 1) * sizeof(WCHAR);
|
||||
LPSTR pszA = Imm32HeapAlloc(0, cchA);
|
||||
if (!pszA)
|
||||
return NULL;
|
||||
cchA = WideCharToMultiByte(CP_ACP, 0, pszW, cchW, pszA, cchA, NULL, NULL);
|
||||
pszA[cchA] = 0;
|
||||
return pszA;
|
||||
}
|
||||
|
||||
BOOL Imm32GetSystemLibraryPath(LPWSTR pszPath, DWORD cchPath, LPCWSTR pszFileName)
|
||||
{
|
||||
if (!pszFileName[0] || !GetSystemDirectoryW(pszPath, cchPath))
|
||||
return FALSE;
|
||||
StringCchCatW(pszPath, cchPath, L"\\");
|
||||
StringCchCatW(pszPath, cchPath, pszFileName);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID APIENTRY LogFontAnsiToWide(const LOGFONTA *plfA, LPLOGFONTW plfW)
|
||||
{
|
||||
size_t cch;
|
||||
RtlCopyMemory(plfW, plfA, offsetof(LOGFONTA, lfFaceName));
|
||||
StringCchLengthA(plfA->lfFaceName, _countof(plfA->lfFaceName), &cch);
|
||||
cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, plfA->lfFaceName, (INT)cch,
|
||||
plfW->lfFaceName, _countof(plfW->lfFaceName));
|
||||
if (cch > _countof(plfW->lfFaceName) - 1)
|
||||
cch = _countof(plfW->lfFaceName) - 1;
|
||||
plfW->lfFaceName[cch] = 0;
|
||||
}
|
||||
|
||||
VOID APIENTRY LogFontWideToAnsi(const LOGFONTW *plfW, LPLOGFONTA plfA)
|
||||
{
|
||||
size_t cch;
|
||||
RtlCopyMemory(plfA, plfW, offsetof(LOGFONTW, lfFaceName));
|
||||
StringCchLengthW(plfW->lfFaceName, _countof(plfW->lfFaceName), &cch);
|
||||
cch = WideCharToMultiByte(CP_ACP, 0, plfW->lfFaceName, (INT)cch,
|
||||
plfA->lfFaceName, _countof(plfA->lfFaceName), NULL, NULL);
|
||||
if (cch > _countof(plfA->lfFaceName) - 1)
|
||||
cch = _countof(plfA->lfFaceName) - 1;
|
||||
plfA->lfFaceName[cch] = 0;
|
||||
}
|
||||
|
||||
PWND FASTCALL ValidateHwndNoErr(HWND hwnd)
|
||||
{
|
||||
PCLIENTINFO ClientInfo = GetWin32ClientInfo();
|
||||
INT index;
|
||||
PUSER_HANDLE_TABLE ht;
|
||||
PUSER_HANDLE_ENTRY he;
|
||||
WORD generation;
|
||||
|
||||
/* See if the window is cached */
|
||||
if (hwnd == ClientInfo->CallbackWnd.hWnd)
|
||||
return ClientInfo->CallbackWnd.pWnd;
|
||||
|
||||
if (!NtUserValidateHandleSecure(hwnd))
|
||||
return NULL;
|
||||
|
||||
ht = g_SharedInfo.aheList; /* handle table */
|
||||
ASSERT(ht);
|
||||
/* ReactOS-Specific! */
|
||||
ASSERT(g_SharedInfo.ulSharedDelta != 0);
|
||||
he = (PUSER_HANDLE_ENTRY)((ULONG_PTR)ht->handles - g_SharedInfo.ulSharedDelta);
|
||||
|
||||
index = (LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1;
|
||||
if (index < 0 || index >= ht->nb_handles || he[index].type != TYPE_WINDOW)
|
||||
return NULL;
|
||||
|
||||
generation = HIWORD(hwnd);
|
||||
if (generation != he[index].generation && generation && generation != 0xFFFF)
|
||||
return NULL;
|
||||
|
||||
return (PWND)&he[index];
|
||||
}
|
||||
|
||||
LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes)
|
||||
{
|
||||
if (!g_hImm32Heap)
|
||||
{
|
||||
g_hImm32Heap = RtlGetProcessHeap();
|
||||
if (g_hImm32Heap == NULL)
|
||||
return NULL;
|
||||
}
|
||||
return HeapAlloc(g_hImm32Heap, dwFlags, dwBytes);
|
||||
}
|
||||
|
||||
BOOL APIENTRY
|
||||
Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD_PTR dwValue,
|
||||
DWORD_PTR dwCommand, DWORD_PTR dwData)
|
||||
{
|
||||
DWORD dwLayout;
|
||||
HKL hKL;
|
||||
PIMEDPI pImeDpi;
|
||||
|
||||
if (dwAction)
|
||||
{
|
||||
dwLayout = NtUserQueryInputContext(hIMC, 1);
|
||||
if (dwLayout)
|
||||
{
|
||||
/* find keyboard layout and lock it */
|
||||
hKL = GetKeyboardLayout(dwLayout);
|
||||
pImeDpi = ImmLockImeDpi(hKL);
|
||||
if (pImeDpi)
|
||||
{
|
||||
/* do notify */
|
||||
pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
|
||||
|
||||
ImmUnlockImeDpi(pImeDpi); /* unlock */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hwnd && dwCommand)
|
||||
SendMessageW(hwnd, WM_IME_NOTIFY, dwCommand, dwData);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphList)
|
||||
{
|
||||
#define INITIAL_COUNT 0x40
|
||||
#define MAX_RETRY 10
|
||||
NTSTATUS Status;
|
||||
DWORD dwCount = INITIAL_COUNT, cRetry = 0;
|
||||
HIMC *phNewList;
|
||||
|
||||
phNewList = Imm32HeapAlloc(0, dwCount * sizeof(HIMC));
|
||||
if (phNewList == NULL)
|
||||
return 0;
|
||||
|
||||
Status = NtUserBuildHimcList(dwThreadId, dwCount, phNewList, &dwCount);
|
||||
while (Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
HeapFree(g_hImm32Heap, 0, phNewList);
|
||||
if (cRetry++ >= MAX_RETRY)
|
||||
return 0;
|
||||
|
||||
phNewList = Imm32HeapAlloc(0, dwCount * sizeof(HIMC));
|
||||
if (phNewList == NULL)
|
||||
return 0;
|
||||
|
||||
Status = NtUserBuildHimcList(dwThreadId, dwCount, phNewList, &dwCount);
|
||||
}
|
||||
|
||||
if (NT_ERROR(Status) || !dwCount)
|
||||
{
|
||||
HeapFree(g_hImm32Heap, 0, phNewList);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pphList = phNewList;
|
||||
return dwCount;
|
||||
#undef INITIAL_COUNT
|
||||
#undef MAX_RETRY
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmCreateIMCC(IMM32.@)
|
||||
*/
|
||||
HIMCC WINAPI ImmCreateIMCC(DWORD size)
|
||||
{
|
||||
if (size < 4)
|
||||
size = 4;
|
||||
return LocalAlloc(LHND, size);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmDestroyIMCC(IMM32.@)
|
||||
*/
|
||||
HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
|
||||
{
|
||||
if (block)
|
||||
return LocalFree(block);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmLockIMCC(IMM32.@)
|
||||
*/
|
||||
LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
|
||||
{
|
||||
if (imcc)
|
||||
return LocalLock(imcc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmUnlockIMCC(IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
|
||||
{
|
||||
if (imcc)
|
||||
return LocalUnlock(imcc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetIMCCLockCount(IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
|
||||
{
|
||||
return LocalFlags(imcc) & LMEM_LOCKCOUNT;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmReSizeIMCC(IMM32.@)
|
||||
*/
|
||||
HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
|
||||
{
|
||||
if (!imcc)
|
||||
return NULL;
|
||||
return LocalReAlloc(imcc, size, LHND);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetIMCCSize(IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
|
||||
{
|
||||
if (imcc)
|
||||
return LocalSize(imcc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmGetIMCLockCount(IMM32.@)
|
||||
*/
|
||||
DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
|
||||
{
|
||||
DWORD ret;
|
||||
HIMC hClientImc;
|
||||
PCLIENTIMC pClientImc;
|
||||
|
||||
pClientImc = ImmLockClientImc(hIMC);
|
||||
if (pClientImc == NULL)
|
||||
return 0;
|
||||
|
||||
ret = 0;
|
||||
hClientImc = pClientImc->hImc;
|
||||
if (hClientImc)
|
||||
ret = (LocalFlags(hClientImc) & LMEM_LOCKCOUNT);
|
||||
|
||||
ImmUnlockClientImc(pClientImc);
|
||||
return ret;
|
||||
}
|
Loading…
Reference in a new issue