Module: wine Branch: master Commit: abc93d0809cfcccff28511327af3f9eccee65d33 URL: https://source.winehq.org/git/wine.git/?a=commit;h=abc93d0809cfcccff28511327...
Author: Alexandre Julliard julliard@winehq.org Date: Mon May 30 13:09:26 2022 +0200
kernelbase: Add support for Hangul composition in sortkeys.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/kernelbase/locale.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+)
diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 03b34bf99db..d189cb004f0 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -342,6 +342,16 @@ struct sort_expansion WCHAR exp[2]; };
+struct jamo_sort +{ + BYTE is_old; + BYTE leading; + BYTE vowel; + BYTE trailing; + BYTE weight; + BYTE pad[3]; +}; + struct sort_compression { UINT offset; @@ -412,6 +422,7 @@ static struct const struct sort_expansion *expansions; /* character expansions */ const struct sort_compression *compressions; /* character compression tables */ const WCHAR *compr_data; /* data for individual compressions */ + const struct jamo_sort *jamo; /* table for Jamo compositions */ } sort;
static CRITICAL_SECTION locale_section; @@ -478,7 +489,9 @@ static void load_sortdefault_nls(void)
const WORD *ctype; const UINT *table; + UINT i; SIZE_T size; + const struct sort_compression *last_compr;
NtGetNlsSectionPtr( 9, 0, NULL, (void **)&header, &size );
@@ -503,6 +516,12 @@ static void load_sortdefault_nls(void) sort.compressions = (struct sort_compression *)(table + 1); sort.compr_data = (WCHAR *)(sort.compressions + sort.compr_count);
+ last_compr = sort.compressions + sort.compr_count - 1; + table = (UINT *)(sort.compr_data + last_compr->offset); + for (i = 0; i < 7; i++) table += last_compr->len[i] * ((i + 5) / 2); + table += 1 + table[0] / 2; /* skip multiple weights */ + sort.jamo = (struct jamo_sort *)(table + 1); + locale_sorts = RtlAllocateHeap( GetProcessHeap(), HEAP_ZERO_MEMORY, locale_table->nb_lcnames * sizeof(*locale_sorts) ); } @@ -3299,6 +3318,75 @@ static int get_compression_weights( UINT compression, const WCHAR *compr_tables[ return 0; }
+ +#define HANGUL_SBASE 0xac00 +#define HANGUL_LCOUNT 19 +#define HANGUL_VCOUNT 21 +#define HANGUL_TCOUNT 28 + +static int append_hangul_weights( struct sortkey *key, const WCHAR *src, int srclen, UINT except ) +{ + int leading_idx = 0x115f - 0x1100; /* leading filler */ + int vowel_idx = 0x1160 - 0x1100; /* vowel filler */ + int trailing_idx = -1; + BYTE leading_off, vowel_off, trailing_off; + union char_weights weights; + WCHAR composed; + BYTE filler_mask = 0; + int pos = 0; + + /* leading */ + if (src[pos] >= 0x1100 && src[pos] <= 0x115f) leading_idx = src[pos++] - 0x1100; + else if (src[pos] >= 0xa960 && src[pos] <= 0xa97c) leading_idx = src[pos++] - (0xa960 - 0x100); + + /* vowel */ + if (srclen > pos) + { + if (src[pos] >= 0x1160 && src[pos] <= 0x11a7) vowel_idx = src[pos++] - 0x1100; + else if (src[pos] >= 0xd7b0 && src[pos] <= 0xd7c6) vowel_idx = src[pos++] - (0xd7b0 - 0x11d); + } + + /* trailing */ + if (srclen > pos) + { + if (src[pos] >= 0x11a8 && src[pos] <= 0x11ff) trailing_idx = src[pos++] - 0x1100; + else if (src[pos] >= 0xd7cb && src[pos] <= 0xd7fb) trailing_idx = src[pos++] - (0xd7cb - 0x134); + } + + if (!sort.jamo[leading_idx].is_old && !sort.jamo[vowel_idx].is_old && + (trailing_idx == -1 || !sort.jamo[trailing_idx].is_old)) + { + /* not old Hangul, only use leading char; vowel and trailing will be handled in the next pass */ + pos = 1; + vowel_idx = 0x1160 - 0x1100; + trailing_idx = -1; + } + + leading_off = max( sort.jamo[leading_idx].leading, sort.jamo[vowel_idx].leading ); + vowel_off = max( sort.jamo[leading_idx].vowel, sort.jamo[vowel_idx].vowel ); + trailing_off = max( sort.jamo[leading_idx].trailing, sort.jamo[vowel_idx].trailing ); + if (trailing_idx != -1) trailing_off = max( trailing_off, sort.jamo[trailing_idx].trailing ); + composed = HANGUL_SBASE + (leading_off * HANGUL_VCOUNT + vowel_off) * HANGUL_TCOUNT + trailing_off; + + if (leading_idx == 0x115f - 0x1100 || vowel_idx == 0x1160 - 0x1100) + { + filler_mask = 0x80; + composed--; + } + if (composed < HANGUL_SBASE) composed = 0x3260; + + weights = get_char_weights( composed, except ); + append_sortkey( key, weights.script ); + append_sortkey( key, weights.primary ); + append_sortkey( key, 0xff ); + append_sortkey( key, sort.jamo[leading_idx].weight | filler_mask ); + append_sortkey( key, 0xff ); + append_sortkey( key, sort.jamo[vowel_idx].weight ); + append_sortkey( key, 0xff ); + append_sortkey( key, trailing_idx != -1 ? sort.jamo[trailing_idx].weight : 2 ); + return pos - 1; +} + /* put one of the elements of a sortkey into the dst buffer */ static int put_sortkey( BYTE *dst, int dstlen, int pos, const struct sortkey *key, BYTE terminator ) { @@ -3414,6 +3502,12 @@ static int append_weights( const struct sortguid *sortid, DWORD flags, &s->key_case, weights, flags, is_compare ); break;
+ case SCRIPT_JAMO_SPECIAL: + ret += append_hangul_weights( &s->key_primary, src + pos, srclen - pos, except ); + append_sortkey( &s->key_diacritic, 2 ); + append_sortkey( &s->key_case, 2 ); + break; + case SCRIPT_EXTENSION_A: append_sortkey( &s->key_primary, 0xfd ); append_sortkey( &s->key_primary, 0xff );