kernelbase: Use linguistic case table for LCMAP_LINGUISTIC_CASING.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
7ad740cd29
commit
b780e5f5b1
|
@ -6471,7 +6471,6 @@ static void test_SpecialCasing(void)
|
|||
WCHAR ch;
|
||||
WCHAR exp; /* 0 if self */
|
||||
WCHAR exp_ling; /* 0 if exp */
|
||||
BOOL todo;
|
||||
} tests[] = {
|
||||
{deDEW, LCMAP_UPPERCASE, 0x00DF}, /* LATIN SMALL LETTER SHARP S */
|
||||
|
||||
|
@ -6580,29 +6579,29 @@ static void test_SpecialCasing(void)
|
|||
|
||||
{enUSW, LCMAP_UPPERCASE, 'i', 'I'}, /* LATIN SMALL LETTER I */
|
||||
{ltLTW, LCMAP_UPPERCASE, 'i', 'I'}, /* LATIN SMALL LETTER I */
|
||||
{trTRW, LCMAP_UPPERCASE, 'i', 'I', 0x0130, TRUE}, /* LATIN SMALL LETTER I */
|
||||
{TRTRW, LCMAP_UPPERCASE, 'i', 'I', 0x0130, TRUE}, /* LATIN SMALL LETTER I */
|
||||
{azCyrlazW, LCMAP_UPPERCASE, 'i', 'I', 0x0130, TRUE}, /* LATIN SMALL LETTER I */
|
||||
{azLatnazW, LCMAP_UPPERCASE, 'i', 'I', 0x0130, TRUE}, /* LATIN SMALL LETTER I */
|
||||
{trTRW, LCMAP_UPPERCASE, 'i', 'I', 0x0130}, /* LATIN SMALL LETTER I */
|
||||
{TRTRW, LCMAP_UPPERCASE, 'i', 'I', 0x0130}, /* LATIN SMALL LETTER I */
|
||||
{azCyrlazW, LCMAP_UPPERCASE, 'i', 'I', 0x0130}, /* LATIN SMALL LETTER I */
|
||||
{azLatnazW, LCMAP_UPPERCASE, 'i', 'I', 0x0130}, /* LATIN SMALL LETTER I */
|
||||
|
||||
{enUSW, LCMAP_LOWERCASE, 'I', 'i'}, /* LATIN CAPITAL LETTER I */
|
||||
{ltLTW, LCMAP_LOWERCASE, 'I', 'i'}, /* LATIN CAPITAL LETTER I */
|
||||
{trTRW, LCMAP_LOWERCASE, 'I', 'i', 0x0131, TRUE}, /* LATIN CAPITAL LETTER I */
|
||||
{TRTRW, LCMAP_LOWERCASE, 'I', 'i', 0x0131, TRUE}, /* LATIN CAPITAL LETTER I */
|
||||
{azCyrlazW, LCMAP_LOWERCASE, 'I', 'i', 0x0131, TRUE}, /* LATIN CAPITAL LETTER I */
|
||||
{azLatnazW, LCMAP_LOWERCASE, 'I', 'i', 0x0131, TRUE}, /* LATIN CAPITAL LETTER I */
|
||||
{trTRW, LCMAP_LOWERCASE, 'I', 'i', 0x0131}, /* LATIN CAPITAL LETTER I */
|
||||
{TRTRW, LCMAP_LOWERCASE, 'I', 'i', 0x0131}, /* LATIN CAPITAL LETTER I */
|
||||
{azCyrlazW, LCMAP_LOWERCASE, 'I', 'i', 0x0131}, /* LATIN CAPITAL LETTER I */
|
||||
{azLatnazW, LCMAP_LOWERCASE, 'I', 'i', 0x0131}, /* LATIN CAPITAL LETTER I */
|
||||
|
||||
{enUSW, LCMAP_LOWERCASE, 0x0130,0,'i', TRUE}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{trTRW, LCMAP_LOWERCASE, 0x0130,0,'i', TRUE}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{TRTRW, LCMAP_LOWERCASE, 0x0130,0,'i', TRUE}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{azCyrlazW, LCMAP_LOWERCASE, 0x0130,0,'i', TRUE}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{azLatnazW, LCMAP_LOWERCASE, 0x0130,0,'i', TRUE}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{enUSW, LCMAP_LOWERCASE, 0x0130,0,'i'}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{trTRW, LCMAP_LOWERCASE, 0x0130,0,'i'}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{TRTRW, LCMAP_LOWERCASE, 0x0130,0,'i'}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{azCyrlazW, LCMAP_LOWERCASE, 0x0130,0,'i'}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{azLatnazW, LCMAP_LOWERCASE, 0x0130,0,'i'}, /* LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
|
||||
{enUSW, LCMAP_UPPERCASE, 0x0131,0,'I', TRUE}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{trTRW, LCMAP_UPPERCASE, 0x0131,0,'I', TRUE}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{TRTRW, LCMAP_UPPERCASE, 0x0131,0,'I', TRUE}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{azCyrlazW, LCMAP_UPPERCASE, 0x0131,0,'I', TRUE}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{azLatnazW, LCMAP_UPPERCASE, 0x0131,0,'I', TRUE}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{enUSW, LCMAP_UPPERCASE, 0x0131,0,'I'}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{trTRW, LCMAP_UPPERCASE, 0x0131,0,'I'}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{TRTRW, LCMAP_UPPERCASE, 0x0131,0,'I'}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{azCyrlazW, LCMAP_UPPERCASE, 0x0131,0,'I'}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
{azLatnazW, LCMAP_UPPERCASE, 0x0131,0,'I'}, /* LATIN SMALL LETTER DOTLESS I */
|
||||
};
|
||||
|
||||
if (!pLCMapStringEx)
|
||||
|
@ -6628,7 +6627,6 @@ static void test_SpecialCasing(void)
|
|||
ok(ret == 1, "expected 1, got %d for %04x for %s\n", ret, tests[i].ch,
|
||||
wine_dbgstr_w(tests[i].lang));
|
||||
exp = tests[i].exp_ling ? tests[i].exp_ling : exp;
|
||||
todo_wine_if(tests[i].todo)
|
||||
ok(buffer[0] == exp || broken(buffer[0] != exp),
|
||||
"expected %04x, got %04x for %04x for %s\n",
|
||||
exp, buffer[0], tests[i].ch, wine_dbgstr_w(tests[i].lang));
|
||||
|
|
|
@ -576,12 +576,34 @@ static unsigned int nb_codepages;
|
|||
|
||||
static struct norm_table *norm_info;
|
||||
|
||||
struct sortguid
|
||||
{
|
||||
GUID id; /* sort GUID */
|
||||
DWORD flags; /* flags */
|
||||
DWORD compr; /* offset to compression table */
|
||||
DWORD except; /* exception table offset in sortkey table */
|
||||
DWORD ling_except; /* exception table offset for linguistic casing */
|
||||
DWORD casemap; /* linguistic casemap table offset */
|
||||
};
|
||||
|
||||
#define FLAG_HAS_3_BYTE_WEIGHTS 0x01
|
||||
#define FLAG_REVERSEDIACRITICS 0x10
|
||||
#define FLAG_DOUBLECOMPRESSION 0x20
|
||||
#define FLAG_INVERSECASING 0x40
|
||||
|
||||
static const struct sortguid *current_locale_sort;
|
||||
|
||||
static const GUID default_sort_guid = { 0x00000001, 0x57ee, 0x1e5c, { 0x00, 0xb4, 0xd0, 0x00, 0x0b, 0xb1, 0xe1, 0x1e }};
|
||||
|
||||
static struct
|
||||
{
|
||||
DWORD *keys; /* sortkey table, indexed by char */
|
||||
USHORT *casemap; /* casemap table, in l_intl.nls format */
|
||||
WORD *ctypes; /* CT_CTYPE1,2,3 values */
|
||||
BYTE *ctype_idx; /* index to map char to ctypes array entry */
|
||||
DWORD *keys; /* sortkey table, indexed by char */
|
||||
USHORT *casemap; /* casemap table, in l_intl.nls format */
|
||||
WORD *ctypes; /* CT_CTYPE1,2,3 values */
|
||||
BYTE *ctype_idx; /* index to map char to ctypes array entry */
|
||||
DWORD version; /* NLS version */
|
||||
DWORD guid_count; /* number of sort GUIDs */
|
||||
struct sortguid *guids; /* table of sort GUIDs */
|
||||
} sort;
|
||||
|
||||
static CRITICAL_SECTION locale_section;
|
||||
|
@ -594,18 +616,82 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
|
|||
static CRITICAL_SECTION locale_section = { &critsect_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* init_sortkeys
|
||||
*/
|
||||
static void init_sortkeys( DWORD *ptr )
|
||||
{
|
||||
WORD *ctype;
|
||||
DWORD *table;
|
||||
|
||||
sort.keys = (DWORD *)((char *)ptr + ptr[0]);
|
||||
sort.casemap = (USHORT *)((char *)ptr + ptr[1]);
|
||||
ctype = (WORD *)((char *)ptr + ptr[2]);
|
||||
sort.ctypes = ctype + 2;
|
||||
sort.keys = (DWORD *)((char *)ptr + ptr[0]);
|
||||
sort.casemap = (USHORT *)((char *)ptr + ptr[1]);
|
||||
|
||||
ctype = (WORD *)((char *)ptr + ptr[2]);
|
||||
sort.ctypes = ctype + 2;
|
||||
sort.ctype_idx = (BYTE *)ctype + ctype[1] + 2;
|
||||
|
||||
table = (DWORD *)((char *)ptr + ptr[3]);
|
||||
sort.version = table[0];
|
||||
sort.guid_count = table[1];
|
||||
sort.guids = (struct sortguid *)(table + 2);
|
||||
}
|
||||
|
||||
|
||||
static const struct sortguid *find_sortguid( const GUID *guid )
|
||||
{
|
||||
int pos, ret, min = 0, max = sort.guid_count - 1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
pos = (min + max) / 2;
|
||||
ret = memcmp( guid, &sort.guids[pos].id, sizeof(*guid) );
|
||||
if (!ret) return &sort.guids[pos];
|
||||
if (ret > 0) min = pos + 1;
|
||||
else max = pos - 1;
|
||||
}
|
||||
ERR( "no sort found for %s\n", debugstr_guid( guid ));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static const struct sortguid *get_language_sort( const WCHAR *locale )
|
||||
{
|
||||
WCHAR *p, *end, buffer[LOCALE_NAME_MAX_LENGTH], guidstr[39];
|
||||
const struct sortguid *ret;
|
||||
UNICODE_STRING str;
|
||||
GUID guid;
|
||||
HKEY key;
|
||||
DWORD size, type;
|
||||
|
||||
if (locale == LOCALE_NAME_USER_DEFAULT)
|
||||
{
|
||||
if (current_locale_sort) return current_locale_sort;
|
||||
GetUserDefaultLocaleName( buffer, ARRAY_SIZE( buffer ));
|
||||
}
|
||||
else lstrcpynW( buffer, locale, LOCALE_NAME_MAX_LENGTH );
|
||||
|
||||
if (buffer[0] && !RegOpenKeyExW( nls_key, L"Sorting\\Ids", 0, KEY_READ, &key ))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
size = sizeof(guidstr);
|
||||
if (!RegQueryValueExW( key, buffer, NULL, &type, (BYTE *)guidstr, &size ) && type == REG_SZ)
|
||||
{
|
||||
RtlInitUnicodeString( &str, guidstr );
|
||||
if (!RtlGUIDFromString( &str, &guid ))
|
||||
{
|
||||
ret = find_sortguid( &guid );
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
for (p = end = buffer; *p; p++) if (*p == '-' || *p == '_') end = p;
|
||||
if (end == buffer) break;
|
||||
*end = 0;
|
||||
}
|
||||
}
|
||||
ret = find_sortguid( &default_sort_guid );
|
||||
done:
|
||||
RegCloseKey( key );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -648,6 +734,8 @@ void init_locale(void)
|
|||
RtlInitNlsTables( ansi_ptr, oem_ptr, sort.casemap, &nls_info );
|
||||
RtlResetRtlTranslations( &nls_info );
|
||||
|
||||
current_locale_sort = get_language_sort( LOCALE_NAME_USER_DEFAULT );
|
||||
|
||||
RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\Nls",
|
||||
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &nls_key, NULL );
|
||||
RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
|
||||
|
@ -4737,6 +4825,7 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co
|
|||
WCHAR *dst, int dstlen, NLSVERSIONINFO *version,
|
||||
void *reserved, LPARAM handle )
|
||||
{
|
||||
const struct sortguid *sortid;
|
||||
LPWSTR dst_ptr;
|
||||
INT len;
|
||||
|
||||
|
@ -4767,6 +4856,13 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co
|
|||
|
||||
if (!dstlen) dst = NULL;
|
||||
|
||||
if (!(sortid = get_language_sort( locale )))
|
||||
{
|
||||
FIXME( "unknown locale %s\n", debugstr_w(locale) );
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & LCMAP_SORTKEY)
|
||||
{
|
||||
INT ret;
|
||||
|
@ -4910,7 +5006,8 @@ INT WINAPI DECLSPEC_HOTPATCH LCMapStringEx( const WCHAR *locale, DWORD flags, co
|
|||
|
||||
if (flags & (LCMAP_UPPERCASE | LCMAP_LOWERCASE))
|
||||
{
|
||||
USHORT *table = (flags & LCMAP_LOWERCASE) ? nls_info.LowerCaseTable : nls_info.UpperCaseTable;
|
||||
const USHORT *table = sort.casemap + (flags & LCMAP_LINGUISTIC_CASING ? sortid->casemap : 0);
|
||||
table = table + 2 + (flags & LCMAP_LOWERCASE ? table[1] : 0);
|
||||
for (len = dstlen, dst_ptr = dst; srclen && len; src++, srclen--, len--)
|
||||
*dst_ptr++ = casemap( table, *src );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue