Module: wine Branch: master Commit: 5dee0ed75502e0295d09e39d8a80d02954702212 URL: https://source.winehq.org/git/wine.git/?a=commit;h=5dee0ed75502e0295d09e39d8...
Author: Alexandre Julliard julliard@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@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)