Huw Davies : kernel32: Implement canonical composing.

Alexandre Julliard julliard at winehq.org
Mon Feb 11 16:12:10 CST 2019


Module: wine
Branch: master
Commit: 2d2e93519074997fabf7e1e285cb2048e29d8ecf
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=2d2e93519074997fabf7e1e285cb2048e29d8ecf

Author: Huw Davies <huw at codeweavers.com>
Date:   Fri Feb  8 10:41:27 2019 +0000

kernel32: Implement canonical composing.

Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernel32/locale.c       |  4 ++--
 dlls/kernel32/tests/locale.c | 44 ++++++++++++++++++++++----------------------
 include/wine/unicode.h       |  1 +
 libs/port/normalize.c        | 35 +++++++++++++++++++++++++++++++++++
 4 files changed, 60 insertions(+), 24 deletions(-)

diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c
index f2455bd..9f539dd 100644
--- a/dlls/kernel32/locale.c
+++ b/dlls/kernel32/locale.c
@@ -5407,8 +5407,8 @@ INT WINAPI NormalizeString(NORM_FORM form, const WCHAR *src, INT src_len, WCHAR
 
     if (compose)
     {
-        FIXME("Composing not yet implemented\n");
-        res = 0;
+        res = wine_compose_string( buf, res );
+        if (dst_len >= res) memcpy( dst, buf, res * sizeof(WCHAR) );
     }
 
 done:
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c
index d877c65..0c05311 100644
--- a/dlls/kernel32/tests/locale.c
+++ b/dlls/kernel32/tests/locale.c
@@ -5697,28 +5697,28 @@ static void test_NormalizeString(void)
     };
     static const struct test_data_normal test_arr[] =
     {
-        { part0_str1, { part0_str1, part0_nfd1, part0_str1, part0_nfd1 }, { 1, 0, 1, 0 } },
-        { part0_str2, { part0_nfc2, part0_str2, part0_nfc2, part0_str2 }, { 1, 0, 1, 0 } },
-        { part0_str3, { part0_nfc3, part0_str3, part0_nfc3, part0_str3 }, { 1, 0, 1, 0 } },
-        { part0_str4, { part0_nfc4, part0_str4, part0_nfc4, part0_str4 }, { 1, 0, 1, 0 } },
-        { part0_str5, { part0_nfc5, part0_nfc5, part0_nfc5, part0_nfc5 }, { 1, 0, 1, 0 } },
-        { part0_str6, { part0_nfc6, part0_nfc6, part0_nfc6, part0_nfc6 }, { 1, 0, 1, 0 } },
-        { part0_str8, { part0_str8, part0_nfd8, part0_str8, part0_nfd8 }, { 1, 0, 1, 0 } },
-        { part0_str9, { part0_nfc9, part0_nfd9, part0_nfc9, part0_nfd9 }, { 1, 0, 1, 0 } },
-        { part0_str10, { part0_str10, part0_nfd10, part0_str10, part0_nfd10 }, { 1, 0, 1, 0 } },
-        { part0_str11, { part0_str11, part0_nfd11, part0_str11, part0_nfd11 }, { 1, 0, 1, 0 } },
-        { part0_str12, { part0_nfc12, part0_nfd12, part0_nfc12, part0_nfd12 }, { 1, 0, 1, 0 } },
-        { part1_str1, { part1_str1, part1_str1, part1_nfkc1, part1_nfkc1 }, { 1, 0, 1, 0 } },
-        { part1_str2, { part1_str2, part1_str2, part1_nfkc2, part1_nfkc2 }, { 1, 0, 1, 0 } },
-        { part1_str3, { part1_str3, part1_nfd3, part1_str3, part1_nfd3 }, { 1, 0, 1, 0 } },
-        { part1_str4, { part1_str4, part1_str4, part1_nfkc4, part1_nfkc4 }, { 1, 0, 1, 0 } },
-        { part1_str5, { part1_str5, part1_nfd5, part1_str5, part1_nfd5 }, { 1, 0, 1, 0 } },
-        { part1_str6, { part1_str6, part1_nfd6, part1_str6, part1_nfd6 }, { 1, 0, 1, 0 } },
-        { part1_str7, { part1_str7, part1_str7, part1_nfkc7, part1_nfkc7 }, { 1, 0, 1, 0 } },
-        { part1_str8, { part1_str8, part1_nfd8, part1_str8, part1_nfd8 }, { 1, 0, 1, 0 } },
-        { part1_str9, { part1_str9, part1_str9, part1_nfkc9, part1_nfkc9 }, { 1, 0, 1, 0 } },
-        { part1_str10, { part1_str10, part1_str10, part1_nfkc10, part1_nfkc10 }, { 1, 0, 1, 0 } },
-        { part1_str11, { part1_nfc11, part1_nfd11, part1_nfc11, part1_nfd11 }, { 1, 0, 1, 0 } },
+        { part0_str1, { part0_str1, part0_nfd1, part0_str1, part0_nfd1 } },
+        { part0_str2, { part0_nfc2, part0_str2, part0_nfc2, part0_str2 } },
+        { part0_str3, { part0_nfc3, part0_str3, part0_nfc3, part0_str3 } },
+        { part0_str4, { part0_nfc4, part0_str4, part0_nfc4, part0_str4 } },
+        { part0_str5, { part0_nfc5, part0_nfc5, part0_nfc5, part0_nfc5 } },
+        { part0_str6, { part0_nfc6, part0_nfc6, part0_nfc6, part0_nfc6 } },
+        { part0_str8, { part0_str8, part0_nfd8, part0_str8, part0_nfd8 } },
+        { part0_str9, { part0_nfc9, part0_nfd9, part0_nfc9, part0_nfd9 } },
+        { part0_str10, { part0_str10, part0_nfd10, part0_str10, part0_nfd10 } },
+        { part0_str11, { part0_str11, part0_nfd11, part0_str11, part0_nfd11 } },
+        { part0_str12, { part0_nfc12, part0_nfd12, part0_nfc12, part0_nfd12 } },
+        { part1_str1, { part1_str1, part1_str1, part1_nfkc1, part1_nfkc1 } },
+        { part1_str2, { part1_str2, part1_str2, part1_nfkc2, part1_nfkc2 } },
+        { part1_str3, { part1_str3, part1_nfd3, part1_str3, part1_nfd3 } },
+        { part1_str4, { part1_str4, part1_str4, part1_nfkc4, part1_nfkc4 } },
+        { part1_str5, { part1_str5, part1_nfd5, part1_str5, part1_nfd5 } },
+        { part1_str6, { part1_str6, part1_nfd6, part1_str6, part1_nfd6 } },
+        { part1_str7, { part1_str7, part1_str7, part1_nfkc7, part1_nfkc7 } },
+        { part1_str8, { part1_str8, part1_nfd8, part1_str8, part1_nfd8 } },
+        { part1_str9, { part1_str9, part1_str9, part1_nfkc9, part1_nfkc9 } },
+        { part1_str10, { part1_str10, part1_str10, part1_nfkc10, part1_nfkc10 } },
+        { part1_str11, { part1_nfc11, part1_nfd11, part1_nfc11, part1_nfd11 } },
         { 0 }
     };
     const struct test_data_normal *ptest = test_arr;
diff --git a/include/wine/unicode.h b/include/wine/unicode.h
index 2c21cdf..a4b483a 100644
--- a/include/wine/unicode.h
+++ b/include/wine/unicode.h
@@ -101,6 +101,7 @@ extern int wine_compare_string( int flags, const WCHAR *str1, int len1, const WC
 extern int wine_get_sortkey( int flags, const WCHAR *src, int srclen, char *dst, int dstlen );
 extern int wine_fold_string( int flags, const WCHAR *src, int srclen , WCHAR *dst, int dstlen );
 
+extern unsigned int wine_compose_string( WCHAR *str, unsigned int len );
 extern unsigned int wine_decompose_string( int flags, const WCHAR *src, unsigned int srclen, WCHAR *dst, unsigned int dstlen );
 #define WINE_DECOMPOSE_COMPAT     1
 #define WINE_DECOMPOSE_REORDER    2
diff --git a/libs/port/normalize.c b/libs/port/normalize.c
index 8363eee..954a33c 100644
--- a/libs/port/normalize.c
+++ b/libs/port/normalize.c
@@ -20,6 +20,7 @@
 
 #include "wine/unicode.h"
 
+extern WCHAR wine_compose( const WCHAR *str ) DECLSPEC_HIDDEN;
 extern unsigned int wine_decompose( int flags, WCHAR ch, WCHAR *dst, unsigned int dstlen ) DECLSPEC_HIDDEN;
 extern const unsigned short combining_class_table[] DECLSPEC_HIDDEN;
 
@@ -104,3 +105,37 @@ unsigned int wine_decompose_string( int flags, const WCHAR *src, unsigned int sr
     if (flags & WINE_DECOMPOSE_REORDER) canonical_order_string( dst, dst_pos );
     return dst_pos;
 }
+
+static BOOL is_blocked( WCHAR *starter, WCHAR *ptr )
+{
+    if (ptr == starter + 1) return FALSE;
+    /* Because the string is already canonically ordered, the chars are blocked
+       only if the previous char's combining class is equal to the test char. */
+    if (get_combining_class( *(ptr - 1) ) == get_combining_class( *ptr )) return TRUE;
+    return FALSE;
+}
+
+unsigned int wine_compose_string( WCHAR *str, unsigned int len )
+{
+    unsigned int i, last_starter = len;
+    WCHAR pair[2], comp;
+
+    for (i = 0; i < len; i++)
+    {
+        pair[1] = str[i];
+        if (last_starter == len || is_blocked( str + last_starter, str + i ) || !(comp = wine_compose( pair )))
+        {
+            if (is_starter( str[i] ))
+            {
+                last_starter = i;
+                pair[0] = str[i];
+            }
+            continue;
+        }
+        str[last_starter] = pair[0] = comp;
+        len--;
+        memmove( str + i, str + i + 1, (len - i) * sizeof(WCHAR) );
+        i = last_starter;
+    }
+    return len;
+}




More information about the wine-cvs mailing list