Alexandre Julliard : kernelbase: Add NORM_IGNORENONSPACE support in LCMapStringEx().
Alexandre Julliard
julliard at winehq.org
Wed Jun 8 15:56:05 CDT 2022
Module: wine
Branch: master
Commit: 5dee0ed75502e0295d09e39d8a80d02954702212
URL: https://source.winehq.org/git/wine.git/?a=commit;h=5dee0ed75502e0295d09e39d8a80d02954702212
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Jun 8 14:57:20 2022 +0200
kernelbase: Add NORM_IGNORENONSPACE support in LCMapStringEx().
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=36720
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/kernel32/tests/locale.c | 17 ++++++++++++++
dlls/kernelbase/locale.c | 54 ++++++++++++++++++++++++++++++++++++++------
2 files changed, 64 insertions(+), 7 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index 9bd922dff98..9108942b8cc 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -2462,6 +2462,11 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
const static WCHAR cjk_compat_result[] = {
0x523b, 0x5246, 0x5272, 0x5277, 0x3515, 0x52c7, 0x52c9, 0x52e4, 0
};
+ const static WCHAR accents_text[] = {
+ 0x00e0, 0x00e7, ' ', 0x00e9, ',', 0x00ee, 0x00f1, '/', 0x00f6, 0x00fb, 0x00fd, '!', 0
+ };
+ const static WCHAR accents_result[] = L"ac e,in/ouy!";
+ const static WCHAR accents_result2[] = L"aceinouy";
int ret, ret2, i;
WCHAR buf[256], buf2[256];
char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
@@ -2703,6 +2708,12 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
lstrlenW(lower_case) + 1, ret);
ok(!lstrcmpW(buf, lower_case), "%s string comparison mismatch\n", func_name);
+ lstrcpyW(buf, fooW);
+ ret = func_ptr(NORM_IGNORENONSPACE, accents_text, -1, buf, ARRAY_SIZE(buf));
+ ok(ret == lstrlenW(buf) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
+ lstrlenW(buf) + 1, ret);
+ ok(!lstrcmpW(buf, accents_result), "%s string comparison mismatch %s\n", func_name, debugstr_w(buf));
+
/* test NORM_IGNORESYMBOLS */
lstrcpyW(buf, fooW);
ret = func_ptr(NORM_IGNORESYMBOLS, lower_case, -1, buf, ARRAY_SIZE(buf));
@@ -2717,6 +2728,12 @@ static void test_lcmapstring_unicode(lcmapstring_wrapper func_ptr, const char *f
lstrlenW(symbols_stripped) + 1, ret);
ok(!lstrcmpW(buf, symbols_stripped), "%s string comparison mismatch\n", func_name);
+ lstrcpyW(buf, fooW);
+ ret = func_ptr(NORM_IGNORESYMBOLS | NORM_IGNORENONSPACE, accents_text, -1, buf, ARRAY_SIZE(buf));
+ ok(ret == lstrlenW(buf) + 1, "%s func_ptr should return %d, ret = %d\n", func_name,
+ lstrlenW(buf) + 1, ret);
+ ok(!lstrcmpW(buf, accents_result2), "%s string comparison mismatch %s\n", func_name, debugstr_w(buf));
+
/* test small buffer */
lstrcpyW(buf, fooW);
ret = func_ptr(LCMAP_SORTKEY, lower_case, -1, buf, 2);
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c
index 6995209e30c..257d9f693ba 100644
--- a/dlls/kernelbase/locale.c
+++ b/dlls/kernelbase/locale.c
@@ -4023,6 +4023,52 @@ static int map_to_fullwidth( const USHORT *table, const WCHAR *src, int srclen,
return pos;
}
+
+static inline int nonspace_ignored( WCHAR ch )
+{
+ if (get_char_type( CT_CTYPE2, ch ) != C2_OTHERNEUTRAL) return FALSE;
+ return (get_char_type( CT_CTYPE3, ch ) & (C3_NONSPACING | C3_DIACRITIC));
+}
+
+/* remove ignored chars for NORM_IGNORENONSPACE/NORM_IGNORESYMBOLS */
+static int map_remove_ignored( DWORD flags, const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
+{
+ int pos;
+
+ for (pos = 0; srclen; src++, srclen--)
+ {
+ if (flags & NORM_IGNORESYMBOLS)
+ {
+ if (get_char_type( CT_CTYPE1, *src ) & C1_PUNCT) continue;
+ if (get_char_type( CT_CTYPE3, *src ) & C3_SYMBOL) continue;
+ }
+ if (flags & NORM_IGNORENONSPACE)
+ {
+ WCHAR buffer[8];
+ const WCHAR *decomp;
+ unsigned int i, j, len;
+
+ if ((decomp = get_decomposition( *src, &len )) && len > 1)
+ {
+ for (i = j = 0; i < len; i++)
+ if (!nonspace_ignored( decomp[i] )) buffer[j++] = decomp[i];
+
+ if (i > j) /* something was removed */
+ {
+ if (pos + j <= dstlen) memcpy( dst + pos, buffer, j * sizeof(WCHAR) );
+ pos += j;
+ continue;
+ }
+ }
+ else if (nonspace_ignored( *src )) continue;
+ }
+ if (pos < dstlen) dst[pos] = *src;
+ pos++;
+ }
+ return pos;
+}
+
+
/* map full-width characters to single or double half-width characters. */
static int map_to_halfwidth( const USHORT *table, const WCHAR *src, int srclen, WCHAR *dst, int dstlen )
{
@@ -4124,13 +4170,7 @@ static int lcmap_string( const struct sortguid *sortid, DWORD flags,
SetLastError( ERROR_INVALID_FLAGS );
return 0;
}
- for (ret = 0; srclen; src++, srclen--)
- {
- if ((flags & NORM_IGNORESYMBOLS) && (get_char_type( CT_CTYPE1, *src ) & (C1_PUNCT | C1_SPACE)))
- continue;
- if (ret < dstlen) dst[ret] = *src;
- ret++;
- }
+ ret = map_remove_ignored( flags, src, srclen, dst, dstlen );
break;
case 0:
if (case_table)
More information about the wine-cvs
mailing list