Alexandre Julliard : kernelbase: Add support for Kana extra weights in sortkeys.

Alexandre Julliard julliard at winehq.org
Mon May 30 15:34:56 CDT 2022


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon May 30 13:11:41 2022 +0200

kernelbase: Add support for Kana extra weights in sortkeys.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/kernelbase/locale.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 81 insertions(+), 3 deletions(-)

diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c
index d189cb004f0..179f0436578 100644
--- a/dlls/kernelbase/locale.c
+++ b/dlls/kernelbase/locale.c
@@ -3318,6 +3318,48 @@ static int get_compression_weights( UINT compression, const WCHAR *compr_tables[
     return 0;
 }
 
+/* append the extra weights for kana prolonged sound / repeat marks */
+static int append_extra_kana_weights( struct sortkey keys[4], const WCHAR *src, int pos, UINT except,
+                                      BYTE case_mask, union char_weights *weights )
+{
+    BYTE extra1 = 3, case_weight = weights->_case;
+
+    if (weights->primary <= 1)
+    {
+        while (pos > 0)
+        {
+            union char_weights prev = get_char_weights( src[--pos], except );
+            if (prev.script == SCRIPT_UNSORTABLE || prev.script == SCRIPT_NONSPACE_MARK) continue;
+            if (prev.script == SCRIPT_EXPANSION) return 0;
+            if (prev.script != SCRIPT_EASTASIA_SPECIAL)
+            {
+                *weights = prev;
+                return 1;
+            }
+            if (prev.primary <= 1) continue;
+
+            case_weight = prev._case & case_mask;
+            if (weights->primary == 1)  /* prolonged sound mark */
+            {
+                prev.primary &= 0x87;
+                case_weight &= ~CASE_FULLWIDTH;
+                case_weight |= weights->_case & CASE_FULLWIDTH;
+            }
+            extra1 = 4 + weights->primary;
+            weights->primary = prev.primary;
+            goto done;
+        }
+        return 0;
+    }
+done:
+    append_sortkey( &keys[0], 0xc4 | (case_weight & CASE_FULLSIZE) );
+    append_sortkey( &keys[1], extra1 );
+    append_sortkey( &keys[2], 0xc4 | (case_weight & CASE_KATAKANA) );
+    append_sortkey( &keys[3], 0xc4 | (case_weight & CASE_FULLWIDTH) );
+    weights->script = SCRIPT_KANA;
+    return 1;
+}
+
 
 #define HANGUL_SBASE  0xac00
 #define HANGUL_LCOUNT 19
@@ -3405,6 +3447,7 @@ struct sortkey_state
     struct sortkey         key_diacritic;
     struct sortkey         key_case;
     struct sortkey         key_special;
+    struct sortkey         key_extra[4];
     UINT                   primary_pos;
     BYTE                   buffer[3 * 128];
 };
@@ -3438,15 +3481,18 @@ static void init_sortkey_state( struct sortkey_state *s, DWORD flags, UINT srcle
     s->key_primary.max = srclen * 8;
     s->key_case.max = srclen * 3;
     s->key_special.max = srclen * 4;
+    s->key_extra[2].max = s->key_extra[3].max = srclen;
     if (!(flags & NORM_IGNORENONSPACE))
     {
         s->key_diacritic.max = srclen * 3;
+        s->key_extra[0].max = s->key_extra[1].max = srclen;
     }
 }
 
-static void remove_unneeded_weights( const struct sortguid *sortid, struct sortkey_state *s )
+static BOOL remove_unneeded_weights( const struct sortguid *sortid, struct sortkey_state *s )
 {
-    int i;
+    const BYTE ignore[4] = { 0xc4 | CASE_FULLSIZE, 0x03, 0xc4 | CASE_KATAKANA, 0xc4 | CASE_FULLWIDTH };
+    int i, j;
 
     if (sortid->flags & FLAG_REVERSEDIACRITICS) reverse_sortkey( &s->key_diacritic );
 
@@ -3455,6 +3501,15 @@ static void remove_unneeded_weights( const struct sortguid *sortid, struct sortk
 
     for (i = s->key_case.len; i > 0; i--) if (s->key_case.buf[i - 1] > 2) break;
     s->key_case.len = i;
+
+    if (!s->key_extra[2].len) return FALSE;
+
+    for (i = 0; i < 4; i++)
+    {
+        for (j = s->key_extra[i].len; j > 0; j--) if (s->key_extra[i].buf[j - 1] != ignore[i]) break;
+        s->key_extra[i].len = j;
+    }
+    return TRUE;
 }
 
 static void free_sortkey_state( struct sortkey_state *s )
@@ -3463,6 +3518,10 @@ static void free_sortkey_state( struct sortkey_state *s )
     RtlFreeHeap( GetProcessHeap(), 0, s->key_diacritic.new_buf );
     RtlFreeHeap( GetProcessHeap(), 0, s->key_case.new_buf );
     RtlFreeHeap( GetProcessHeap(), 0, s->key_special.new_buf );
+    RtlFreeHeap( GetProcessHeap(), 0, s->key_extra[0].new_buf );
+    RtlFreeHeap( GetProcessHeap(), 0, s->key_extra[1].new_buf );
+    RtlFreeHeap( GetProcessHeap(), 0, s->key_extra[2].new_buf );
+    RtlFreeHeap( GetProcessHeap(), 0, s->key_extra[3].new_buf );
 }
 
 static int append_weights( const struct sortguid *sortid, DWORD flags,
@@ -3502,6 +3561,17 @@ static int append_weights( const struct sortguid *sortid, DWORD flags,
                                   &s->key_case, weights, flags, is_compare );
         break;
 
+    case SCRIPT_EASTASIA_SPECIAL:
+        if (!append_extra_kana_weights( s->key_extra, src, pos, except, case_mask, &weights ))
+        {
+            append_sortkey( &s->key_primary, 0xff );
+            append_sortkey( &s->key_primary, 0xff );
+            break;
+        }
+        weights._case = 2;
+        append_normal_weights( sortid, &s->key_primary, &s->key_diacritic, &s->key_case, weights, flags );
+        break;
+
     case SCRIPT_JAMO_SPECIAL:
         ret += append_hangul_weights( &s->key_primary, src + pos, srclen - pos, except );
         append_sortkey( &s->key_diacritic, 2 );
@@ -3559,6 +3629,7 @@ static int get_sortkey( const struct sortguid *sortid, DWORD flags,
     struct sortkey_state s;
     BYTE primary_buf[256];
     int ret = 0, pos = 0;
+    BOOL have_extra;
     BYTE case_mask = 0x3f;
     UINT except = sortid->except;
     const WCHAR *compr_tables[8];
@@ -3574,12 +3645,19 @@ static int get_sortkey( const struct sortguid *sortid, DWORD flags,
     while (pos < srclen)
         pos += append_weights( sortid, flags, src, srclen, pos, case_mask, except, compr_tables, &s, FALSE );
 
-    remove_unneeded_weights( sortid, &s );
+    have_extra = remove_unneeded_weights( sortid, &s );
 
     ret = put_sortkey( dst, dstlen, ret, &s.key_primary, 0x01 );
     ret = put_sortkey( dst, dstlen, ret, &s.key_diacritic, 0x01 );
     ret = put_sortkey( dst, dstlen, ret, &s.key_case, 0x01 );
 
+    if (have_extra)
+    {
+        ret = put_sortkey( dst, dstlen, ret, &s.key_extra[0], 0xff );
+        ret = put_sortkey( dst, dstlen, ret, &s.key_extra[1], 0x02 );
+        ret = put_sortkey( dst, dstlen, ret, &s.key_extra[2], 0xff );
+        ret = put_sortkey( dst, dstlen, ret, &s.key_extra[3], 0xff );
+    }
     if (dstlen > ret) dst[ret] = 0x01;
     ret++;
 




More information about the wine-cvs mailing list