https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bfb7bd05a404d43985502…
commit bfb7bd05a404d43985502282ce9cccbcae0c832d
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Thu Oct 14 08:07:06 2021 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Thu Oct 14 08:07:06 2021 +0900
[IMM32] Re-implement ImmGetCompositionStringA/W (#4026)
- Re-implement ImmGetCompositionStringA and ImmGetCompositionStringW functions.
- Add Imm32CompStrAnsiToWide, Imm32CompStrWideToAnsi, Imm32CompAttrWideToAnsi,
Imm32CompAttrAnsiToWide, Imm32CompClauseAnsiToWide, and Imm32CompClauseWideToAnsi helper
functions.
CORE-11700
---
dll/win32/imm32/compstr.c | 403 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 390 insertions(+), 13 deletions(-)
diff --git a/dll/win32/imm32/compstr.c b/dll/win32/imm32/compstr.c
index 4ce157356e3..df0726c2fa2 100644
--- a/dll/win32/imm32/compstr.c
+++ b/dll/win32/imm32/compstr.c
@@ -2,38 +2,251 @@
* PROJECT: ReactOS IMM32
* LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Implementing composition strings of IMM32
- * COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ * COPYRIGHT: Copyright 1998 Patrik Stridvall
+ * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
+ * Copyright 2017 James Tabor <james.tabor(a)reactos.org>
+ * Copyright 2018 Amine Khaldi <amine.khaldi(a)reactos.org>
+ * Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013(a)yandex.ua>
+ * Copyright 2020-2021 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
*/
#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
+static inline LONG APIENTRY
+Imm32CompStrAnsiToWide(LPCSTR psz, DWORD cb, LPWSTR lpBuf, DWORD dwBufLen, UINT
uCodePage)
+{
+ DWORD ret = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, psz, cb / sizeof(CHAR),
+ lpBuf, dwBufLen / sizeof(WCHAR));
+ if ((ret + 1) * sizeof(WCHAR) <= dwBufLen)
+ lpBuf[ret] = 0;
+ return ret * sizeof(WCHAR);
+}
+
+static inline LONG APIENTRY
+Imm32CompStrWideToAnsi(LPCWSTR psz, DWORD cb, LPSTR lpBuf, DWORD dwBufLen, UINT
uCodePage)
+{
+ DWORD ret = WideCharToMultiByte(uCodePage, 0, psz, cb / sizeof(WCHAR),
+ lpBuf, dwBufLen / sizeof(CHAR), NULL, NULL);
+ if ((ret + 1) * sizeof(CHAR) <= dwBufLen)
+ lpBuf[ret] = 0;
+ return ret * sizeof(CHAR);
+}
+
+static INT APIENTRY
+Imm32CompAttrWideToAnsi(const BYTE *src, INT src_len, LPCWSTR text,
+ INT str_len, LPBYTE dst, INT dst_len, UINT uCodePage)
+{
+ INT rc;
+ INT i, j = 0, k = 0, len;
+
+ if (!src_len)
+ return 0;
+
+ rc = WideCharToMultiByte(uCodePage, 0, text, str_len, NULL, 0, NULL, NULL);
+
+ if (dst_len)
+ {
+ if (dst_len > rc)
+ dst_len = rc;
+
+ for (i = 0; i < str_len; ++i, ++k)
+ {
+ len = WideCharToMultiByte(uCodePage, 0, &text[i], 1, NULL, 0, NULL,
NULL);
+ for (; len > 0; --len)
+ {
+ dst[j++] = src[k];
+
+ if (dst_len <= j)
+ goto end;
+ }
+ }
+end:
+ rc = j;
+ }
+
+ return rc;
+}
+
+static INT APIENTRY
+Imm32CompAttrAnsiToWide(const BYTE *src, INT src_len, LPCSTR text,
+ INT str_len, LPBYTE dst, INT dst_len, UINT uCodePage)
+{
+ INT rc;
+ INT i, j = 0;
+
+ if (!src_len)
+ return 0;
+
+ rc = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, str_len, NULL, 0);
+
+ if (dst_len)
+ {
+ if (dst_len > rc)
+ dst_len = rc;
+
+ for (i = 0; i < str_len; ++i)
+ {
+ if (IsDBCSLeadByteEx(uCodePage, text[i]) && text[i + 1])
+ continue;
+
+ dst[j++] = src[i];
+
+ if (dst_len <= j)
+ break;
+ }
+
+ rc = j;
+ }
+
+ return rc;
+}
+
+static INT APIENTRY
+Imm32CompClauseAnsiToWide(const DWORD *source, INT slen, LPCSTR text,
+ LPDWORD target, INT tlen, UINT uCodePage)
+{
+ INT rc, i;
+
+ if (!slen)
+ return 0;
+
+ if (tlen)
+ {
+ if (tlen > slen)
+ tlen = slen;
+
+ tlen /= sizeof(DWORD);
+
+ for (i = 0; i < tlen; ++i)
+ {
+ target[i] = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, source[i],
NULL, 0);
+ }
+
+ rc = sizeof(DWORD) * i;
+ }
+ else
+ {
+ rc = slen;
+ }
+
+ return rc;
+}
+
+static INT APIENTRY
+Imm32CompClauseWideToAnsi(const DWORD *source, INT slen, LPCWSTR text,
+ LPDWORD target, INT tlen, UINT uCodePage)
+{
+ INT rc, i;
+
+ if (!slen)
+ return 0;
+
+ if (tlen)
+ {
+ if (tlen > slen)
+ tlen = slen;
+
+ tlen /= sizeof(DWORD);
+
+ for (i = 0; i < tlen; ++i)
+ {
+ target[i] = WideCharToMultiByte(uCodePage, 0, text, source[i], NULL, 0, NULL,
NULL);
+ }
+
+ rc = sizeof(DWORD) * i;
+ }
+ else
+ {
+ rc = slen;
+ }
+
+ return rc;
+}
+
+#define CS_StrA(pCS, Name) ((LPCSTR)(pCS) + (pCS)->dw##Name##Offset)
+#define CS_StrW(pCS, Name) ((LPCWSTR)CS_StrA(pCS, Name))
+#define CS_Attr(pCS, Name) ((const BYTE *)CS_StrA(pCS, Name))
+#define CS_Clause(pCS, Name) ((const DWORD *)CS_StrA(pCS, Name))
+#define CS_Size(pCS, Name) ((pCS)->dw##Name##Len)
+#define CS_SizeA(pCS, Name) (CS_Size(pCS, Name) * sizeof(CHAR))
+#define CS_SizeW(pCS, Name) (CS_Size(pCS, Name) * sizeof(WCHAR))
+
+#define CS_DoStr(pCS, Name, AorW) do { \
+ if (dwBufLen == 0) { \
+ dwBufLen = CS_Size##AorW((pCS), Name); \
+ } else { \
+ if (dwBufLen > CS_Size##AorW((pCS), Name)) \
+ dwBufLen = CS_Size##AorW((pCS), Name); \
+ RtlCopyMemory(lpBuf, CS_Str##AorW((pCS), Name), dwBufLen); \
+ } \
+} while (0)
+
+#define CS_DoStrA(pCS, Name) CS_DoStr(pCS, Name, A)
+#define CS_DoStrW(pCS, Name) CS_DoStr(pCS, Name, W)
+#define CS_DoAttr CS_DoStrA
+#define CS_DoClause CS_DoStrA
+
LONG APIENTRY
Imm32GetCompStrA(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex,
LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsiClient, UINT uCodePage)
{
- LONG ret = IMM_ERROR_GENERAL;
-
if (bAnsiClient)
{
switch (dwIndex)
{
case GCS_COMPREADSTR:
+ CS_DoStrA(pCS, CompReadStr);
+ break;
+
case GCS_COMPREADATTR:
+ CS_DoAttr(pCS, CompReadAttr);
+ break;
+
case GCS_COMPREADCLAUSE:
+ CS_DoClause(pCS, CompReadClause);
+ break;
+
case GCS_COMPSTR:
+ CS_DoStrA(pCS, CompStr);
+ break;
+
case GCS_COMPATTR:
+ CS_DoAttr(pCS, CompAttr);
+ break;
+
case GCS_COMPCLAUSE:
+ CS_DoClause(pCS, CompClause);
+ break;
+
case GCS_CURSORPOS:
+ dwBufLen = pCS->dwCursorPos;
+ break;
+
case GCS_DELTASTART:
+ dwBufLen = pCS->dwDeltaStart;
+ break;
+
case GCS_RESULTREADSTR:
+ CS_DoStrA(pCS, ResultReadStr);
+ break;
+
case GCS_RESULTREADCLAUSE:
+ CS_DoClause(pCS, ResultReadClause);
+ break;
+
case GCS_RESULTSTR:
+ CS_DoStrA(pCS, ResultStr);
+ break;
+
case GCS_RESULTCLAUSE:
+ CS_DoClause(pCS, ResultClause);
+ break;
+
default:
FIXME("TODO:\n");
- break;
+ return IMM_ERROR_GENERAL;
}
}
else /* !bAnsiClient */
@@ -41,51 +254,175 @@ Imm32GetCompStrA(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD
dwIndex,
switch (dwIndex)
{
case GCS_COMPREADSTR:
+ dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, CompReadStr),
+ CS_SizeW(pCS, CompReadStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPREADATTR:
+ dwBufLen = Imm32CompAttrWideToAnsi(CS_Attr(pCS, CompReadAttr),
+ CS_Size(pCS, CompReadAttr),
+ CS_StrW(pCS, CompStr),
+ CS_SizeW(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPREADCLAUSE:
+ dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, CompReadClause),
+ CS_Size(pCS, CompReadClause),
+ CS_StrW(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPSTR:
+ dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, CompStr),
+ CS_SizeW(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPATTR:
+ dwBufLen = Imm32CompAttrWideToAnsi(CS_Attr(pCS, CompAttr),
+ CS_Size(pCS, CompAttr),
+ CS_StrW(pCS, CompStr),
+ CS_SizeW(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPCLAUSE:
+ dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, CompClause),
+ CS_Size(pCS, CompClause),
+ CS_StrW(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_CURSORPOS:
+ dwBufLen = IchAnsiFromWide(pCS->dwCursorPos, CS_StrW(pCS, CompStr),
uCodePage);
+ break;
+
case GCS_DELTASTART:
+ dwBufLen = IchAnsiFromWide(pCS->dwDeltaStart, CS_StrW(pCS, CompStr),
uCodePage);
+ break;
+
case GCS_RESULTREADSTR:
+ dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, ResultReadStr),
+ CS_SizeW(pCS, ResultReadStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_RESULTREADCLAUSE:
+ dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, ResultReadClause),
+ CS_Size(pCS, ResultReadClause),
+ CS_StrW(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_RESULTSTR:
+ dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, ResultStr),
+ CS_SizeW(pCS, ResultStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_RESULTCLAUSE:
+ dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, ResultClause),
+ CS_Size(pCS, ResultClause),
+ CS_StrW(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
default:
FIXME("TODO:\n");
- break;
+ return IMM_ERROR_GENERAL;
}
}
- return ret;
+ return dwBufLen;
}
LONG APIENTRY
Imm32GetCompStrW(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex,
LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsiClient, UINT uCodePage)
{
- LONG ret = IMM_ERROR_GENERAL;
-
if (bAnsiClient)
{
switch (dwIndex)
{
case GCS_COMPREADSTR:
+ dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompReadStr),
+ CS_SizeA(pCS, CompReadStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPREADATTR:
+ dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompReadAttr),
+ CS_Size(pCS, CompReadAttr),
+ CS_StrA(pCS, CompStr), CS_SizeA(pCS,
CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPREADCLAUSE:
+ dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompReadClause),
+ CS_Size(pCS, CompReadClause),
+ CS_StrA(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPSTR:
+ dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompStr),
+ CS_SizeA(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPATTR:
+ dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompAttr),
+ CS_Size(pCS, CompAttr),
+ CS_StrA(pCS, CompStr), CS_SizeA(pCS,
CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_COMPCLAUSE:
+ dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompClause),
+ CS_Size(pCS, CompClause),
+ CS_StrA(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_CURSORPOS:
+ dwBufLen = IchWideFromAnsi(pCS->dwCursorPos, CS_StrA(pCS, CompStr),
uCodePage);
+ break;
+
case GCS_DELTASTART:
+ dwBufLen = IchWideFromAnsi(pCS->dwDeltaStart, CS_StrA(pCS, CompStr),
uCodePage);
+ break;
+
case GCS_RESULTREADSTR:
+ dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultReadStr),
+ CS_SizeA(pCS, ResultReadStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_RESULTREADCLAUSE:
+ dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultReadClause),
+ CS_Size(pCS, ResultReadClause),
+ CS_StrA(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_RESULTSTR:
+ dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultStr),
+ CS_SizeA(pCS, ResultStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
case GCS_RESULTCLAUSE:
+ dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultClause),
+ CS_Size(pCS, ResultClause),
+ CS_StrA(pCS, CompStr),
+ lpBuf, dwBufLen, uCodePage);
+ break;
+
default:
FIXME("TODO:\n");
- break;
+ return IMM_ERROR_GENERAL;
}
}
else /* !bAnsiClient */
@@ -93,24 +430,60 @@ Imm32GetCompStrW(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD
dwIndex,
switch (dwIndex)
{
case GCS_COMPREADSTR:
+ CS_DoStrW(pCS, CompReadStr);
+ break;
+
case GCS_COMPREADATTR:
+ CS_DoAttr(pCS, CompReadAttr);
+ break;
+
case GCS_COMPREADCLAUSE:
+ CS_DoClause(pCS, CompReadClause);
+ break;
+
case GCS_COMPSTR:
+ CS_DoStrW(pCS, CompStr);
+ break;
+
case GCS_COMPATTR:
+ CS_DoAttr(pCS, CompAttr);
+ break;
+
case GCS_COMPCLAUSE:
+ CS_DoClause(pCS, CompClause);
+ break;
+
case GCS_CURSORPOS:
+ dwBufLen = pCS->dwCursorPos;
+ break;
+
case GCS_DELTASTART:
+ dwBufLen = pCS->dwDeltaStart;
+ break;
+
case GCS_RESULTREADSTR:
+ CS_DoStrW(pCS, ResultReadStr);
+ break;
+
case GCS_RESULTREADCLAUSE:
+ CS_DoClause(pCS, ResultReadClause);
+ break;
+
case GCS_RESULTSTR:
+ CS_DoStrW(pCS, ResultStr);
+ break;
+
case GCS_RESULTCLAUSE:
+ CS_DoClause(pCS, ResultClause);
+ break;
+
default:
FIXME("TODO:\n");
- break;
+ return IMM_ERROR_GENERAL;
}
}
- return ret;
+ return dwBufLen;
}
BOOL APIENTRY
@@ -131,6 +504,7 @@ LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID
lpBuf, DWO
PCLIENTIMC pClientImc;
LPCOMPOSITIONSTRING pCS;
BOOL bAnsiClient;
+ UINT uCodePage;
TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
@@ -142,6 +516,7 @@ LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID
lpBuf, DWO
return 0;
bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
+ uCodePage = pClientImc->uCodePage;
ImmUnlockClientImc(pClientImc);
pIC = ImmLockIMC(hIMC);
@@ -155,7 +530,7 @@ LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID
lpBuf, DWO
return 0;
}
- ret = Imm32GetCompStrA(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, CP_ACP);
+ ret = Imm32GetCompStrA(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage);
ImmUnlockIMCC(pIC->hCompStr);
ImmUnlockIMC(hIMC);
return ret;
@@ -171,6 +546,7 @@ LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID
lpBuf, DWO
PCLIENTIMC pClientImc;
LPCOMPOSITIONSTRING pCS;
BOOL bAnsiClient;
+ UINT uCodePage;
TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
@@ -182,6 +558,7 @@ LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID
lpBuf, DWO
return 0;
bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
+ uCodePage = pClientImc->uCodePage;
ImmUnlockClientImc(pClientImc);
pIC = ImmLockIMC(hIMC);
@@ -195,7 +572,7 @@ LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID
lpBuf, DWO
return 0;
}
- ret = Imm32GetCompStrW(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, CP_ACP);
+ ret = Imm32GetCompStrW(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage);
ImmUnlockIMCC(pIC->hCompStr);
ImmUnlockIMC(hIMC);
return ret;