--- dlls/kernel32/tests/locale.c | 3 +++ dlls/kernelbase/locale.c | 45 +++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/dlls/kernel32/tests/locale.c b/dlls/kernel32/tests/locale.c index 01ba3c0cb6..6437f043f7 100644 --- a/dlls/kernel32/tests/locale.c +++ b/dlls/kernel32/tests/locale.c @@ -3216,6 +3216,9 @@ static const struct sorting_test_entry unicode_sorting_tests[] = /* 86 */ { L"en-US", NORM_IGNORENONSPACE, L"\x31a2", L"\x3110", CSTR_EQUAL }, /* NORM_IGNORENONSPACE */ /* 87 */ { L"en-US", NORM_IGNORENONSPACE, L"\x1342", L"\x133a", CSTR_EQUAL }, /* NORM_IGNORENONSPACE */ /* 88 */ { L"en-US", NORM_IGNORENONSPACE, L"\x16a4", L"\x16a5", CSTR_EQUAL }, /* NORM_IGNORENONSPACE */ + /* 89 */ { L"en-US", 0, L"\x00c6", L"\x0041\x0045", CSTR_EQUAL }, /* Expansion */ + /* 90 */ { L"en-US", 0, L"\x0f5c", L"\x0f5b\x0fb7", CSTR_EQUAL }, /* Expansion */ + /* 91 */ { L"en-US", 0, L"\x05f0", L"\x05d5\x05d5", CSTR_EQUAL }, /* Expansion */ };
static void test_unicode_sorting(void) diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 789e90cbf5..a02d1bf855 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -2471,6 +2471,13 @@ typedef struct _character_info BYTE weight_case; } character_info;
+typedef struct _character_info_expansion +{ + int character; + int character_result1; + int character_result2; +} character_info_expansion; + typedef struct _weight_main_info { BYTE script_member; @@ -2571,6 +2578,8 @@ typedef struct _sortkey_data static BOOL get_char(sortkey_data* data, character_info* info, WCHAR ch) { DWORD value = sort.keys[ch]; + if ((WORD)value == 0x200) /* Expansion */ + return FALSE;
info->weight_case = value >> 24; info->weight_diacritic = (value >> 16) & 0xff; @@ -2579,6 +2588,28 @@ static BOOL get_char(sortkey_data* data, character_info* info, WCHAR ch) return info->script_member != 0; }
+static BOOL get_expansion(character_info_expansion* info, WCHAR ch) +{ + DWORD pos_info = sort.keys[ch]; + int count = (WORD)pos_info; + int pos = pos_info >> 16; + const DWORD* ptr; + const WCHAR* p; + int count_expansion; + if (count != 0x200) + return FALSE; + ptr = (const DWORD *)(sort.guids + sort.guid_count); + count_expansion = *ptr++; + if (pos >= count_expansion) + return FALSE; + p = (const WCHAR *)(ptr + pos); + info->character = ch; + info->character_result1 = p[0]; + info->character_result2 = p[1]; + return TRUE; +} + + static void sortkey_data_init(sortkey_data* data, int flags, const WCHAR* locale, BOOL is_compare_string) { data->flags = flags; @@ -2642,14 +2673,21 @@ static void diacritic_weights_add(sortkey_data* data, const character_info* info
/* Main sortkey logic */
-static void sortkey_handle_default_character(sortkey_data* data, WCHAR c) +static BOOL sortkey_handle_default_character(sortkey_data* data, WCHAR c) { weight_main_info weightmain; character_info info; + character_info_expansion expansion;
if (!get_char(data, &info, c)) { - return; + if (get_expansion(&expansion, c)) + { + sortkey_handle_default_character(data, (WCHAR)expansion.character_result1); + sortkey_handle_default_character(data, (WCHAR)expansion.character_result2); + return TRUE; + } + return FALSE; }
weightmain = create_weight_main(info.script_member, info.weight_primary); @@ -2661,6 +2699,7 @@ static void sortkey_handle_default_character(sortkey_data* data, WCHAR c) main_weights_add(data, &weightmain);
case_weights_add(data, info.weight_case); + return TRUE; }
static void sortkey_handle_japanese_character(sortkey_data* data, weight_main_info* weightmain, const character_info* info, const character_info* info_other) @@ -2701,7 +2740,7 @@ static BOOL sortkey_handle_character(sortkey_data* data, WCHAR c, const WCHAR* s
if (!get_char(data, &info, c)) { - return FALSE; + return sortkey_handle_default_character(data, c); }
switch (info.script_member) -- 2.26.0