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