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