Move CompareString implementation to libwine_unicode, add a bunch of
CompareString tests.
This commit is contained in:
parent
1bcbd54697
commit
33f9dcb1f9
|
@ -1971,6 +1971,12 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen,
|
|||
}
|
||||
}
|
||||
|
||||
if (srclen)
|
||||
{
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dst_ptr - dst;
|
||||
}
|
||||
|
||||
|
@ -1994,7 +2000,7 @@ INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen,
|
|||
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
|
||||
LPSTR dst, INT dstlen)
|
||||
{
|
||||
WCHAR bufW[128];
|
||||
WCHAR *bufW = NtCurrentTeb()->StaticUnicodeBuffer;
|
||||
LPWSTR srcW, dstW;
|
||||
INT ret = 0, srclenW, dstlenW;
|
||||
UINT locale_cp;
|
||||
|
@ -2007,7 +2013,7 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
|
|||
|
||||
locale_cp = get_lcid_codepage(lcid);
|
||||
|
||||
srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 128);
|
||||
srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 260);
|
||||
if (srclenW)
|
||||
srcW = bufW;
|
||||
else
|
||||
|
@ -2040,6 +2046,9 @@ INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
|
|||
}
|
||||
|
||||
dstlenW = LCMapStringW(lcid, flags, srcW, srclenW, NULL, 0);
|
||||
if (!dstlenW)
|
||||
goto map_string_exit;
|
||||
|
||||
dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
|
||||
if (!dstW)
|
||||
{
|
||||
|
@ -2172,7 +2181,7 @@ INT WINAPI FoldStringW(DWORD dwFlags, LPCWSTR src, INT srclen,
|
|||
INT WINAPI CompareStringW(LCID lcid, DWORD style,
|
||||
LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
|
||||
{
|
||||
INT ret, len;
|
||||
INT ret;
|
||||
|
||||
if (!str1 || !str2)
|
||||
{
|
||||
|
@ -2180,19 +2189,24 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (len1 < 0) len1 = lstrlenW(str1);
|
||||
if (len2 < 0) len2 = lstrlenW(str2);
|
||||
if( style & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|
|
||||
SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|0x10000000) )
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = (len1 < len2) ? len1 : len2;
|
||||
ret = (style & NORM_IGNORECASE) ? strncmpiW(str1, str2, len) :
|
||||
strncmpW(str1, str2, len);
|
||||
if (style & 0x10000000)
|
||||
FIXME("Ignoring unknown style 0x10000000\n");
|
||||
|
||||
if (len1 < 0) len1 = strlenW(str1);
|
||||
if (len2 < 0) len2 = strlenW(str2);
|
||||
|
||||
ret = wine_compare_string(style, str1, len1, str2, len2);
|
||||
|
||||
if (ret) /* need to translate result */
|
||||
return (ret < 0) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
|
||||
|
||||
if (len1 == len2) return CSTR_EQUAL;
|
||||
/* the longer one is lexically greater */
|
||||
return (len1 < len2) ? CSTR_LESS_THAN : CSTR_GREATER_THAN;
|
||||
return CSTR_EQUAL;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -2216,7 +2230,8 @@ INT WINAPI CompareStringW(LCID lcid, DWORD style,
|
|||
INT WINAPI CompareStringA(LCID lcid, DWORD style,
|
||||
LPCSTR str1, INT len1, LPCSTR str2, INT len2)
|
||||
{
|
||||
WCHAR buf1W[128], buf2W[128];
|
||||
WCHAR *buf1W = NtCurrentTeb()->StaticUnicodeBuffer;
|
||||
WCHAR *buf2W = buf1W + 130;
|
||||
LPWSTR str1W, str2W;
|
||||
INT len1W, len2W, ret;
|
||||
UINT locale_cp;
|
||||
|
@ -2226,13 +2241,12 @@ INT WINAPI CompareStringA(LCID lcid, DWORD style,
|
|||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len1 < 0) len1 = strlen(str1);
|
||||
if (len2 < 0) len2 = strlen(str2);
|
||||
|
||||
locale_cp = get_lcid_codepage(lcid);
|
||||
|
||||
len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 128);
|
||||
len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 130);
|
||||
if (len1W)
|
||||
str1W = buf1W;
|
||||
else
|
||||
|
@ -2246,7 +2260,7 @@ INT WINAPI CompareStringA(LCID lcid, DWORD style,
|
|||
}
|
||||
MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
|
||||
}
|
||||
len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 128);
|
||||
len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 130);
|
||||
if (len2W)
|
||||
str2W = buf2W;
|
||||
else
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
* even when the user has overridden their default i8n settings (e.g. in
|
||||
* the control panel i8n page), we will still get the expected results.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
@ -774,8 +777,151 @@ static void test_CompareStringA()
|
|||
ret = CompareStringA(lcid, NORM_IGNORECASE, "haha", -1, "hoho", 0);
|
||||
ok (ret== 3, "(haha/hoho) Expected 3, got %d\n", ret);
|
||||
|
||||
ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "SaLuT", -1);
|
||||
ok (ret== 2, "(Salut/SaLuT) Expected 2, got %d\n", ret);
|
||||
ret = CompareStringA(lcid, NORM_IGNORECASE, "Salut", 5, "saLuT", -1);
|
||||
ok (ret == 2, "(Salut/saLuT) Expected 2, got %d\n", ret);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0x10, "NULL", -1, "NULL", -1);
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
ok(!ret, "CompareStringA must fail with invalid flag\n");
|
||||
|
||||
ret = lstrcmpA("", "");
|
||||
ok (!ret, "lstrcmpA(\"\", \"\") should return 0, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"EndDialog",-1,"_Property",-1);
|
||||
ok( ret == 3, "EndDialog vs _Property ... expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0070",-1,"_IEWWBrowserComp",-1);
|
||||
ok( ret == 3, "osp_vba.sreg0070 vs _IEWWBrowserComp ... expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"r",-1,"\\",-1);
|
||||
ok( ret == 3, "r vs \\ ... expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT,0,"osp_vba.sreg0031", -1, "OriginalDatabase", -1 );
|
||||
ok( ret == 3, "osp_vba.sreg0031 vs OriginalDatabase ... expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aaa", -1 );
|
||||
ok( ret == 3, "AAA vs aaa expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "aab", -1 );
|
||||
ok( ret == 1, "AAA vs aab expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "AAA", -1, "Aab", -1 );
|
||||
ok( ret == 1, "AAA vs Aab expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "Aab", -1 );
|
||||
ok( ret == 1, ".AAA vs Aab expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, ".AAA", -1, "A.ab", -1 );
|
||||
ok( ret == 1, ".AAA vs A.ab expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "AB", -1 );
|
||||
ok( ret == 1, "aa vs AB expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aa", -1, "Aab", -1 );
|
||||
ok( ret == 1, "aa vs Aab expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "aB", -1, "Aab", -1 );
|
||||
ok( ret == 3, "aB vs Aab expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "Ba", -1, "bab", -1 );
|
||||
ok( ret == 1, "Ba vs bab expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "{100}{83}{71}{71}{71}", -1, "Global_DataAccess_JRO", -1 );
|
||||
ok( ret == 1, "{100}{83}{71}{71}{71} vs Global_DataAccess_JRO expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "a", -1, "{", -1 );
|
||||
ok( ret == 3, "a vs { expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "A", -1, "{", -1 );
|
||||
ok( ret == 3, "A vs { expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", 0, "4.0", -1 );
|
||||
ok(ret == 1, "3.5/0 vs 4.0/-1 expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.5", -1, "4.0", -1 );
|
||||
ok(ret == 1, "3.5 vs 4.0 expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "3.520.4403.2", -1, "4.0.2927.10", -1 );
|
||||
ok(ret == 1, "3.520.4403.2 vs 4.0.2927.10 expected 1, got %d", ret);
|
||||
|
||||
/* hyphen and apostrophe are treated differently depending on
|
||||
* whether SORT_STRINGSORT specified or not
|
||||
*/
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-o", -1, "/m", -1 );
|
||||
ok(ret == 3, "-o vs /m expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "-o", -1 );
|
||||
ok(ret == 1, "/m vs -o expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-o", -1, "/m", -1 );
|
||||
ok(ret == 1, "-o vs /m expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "-o", -1 );
|
||||
ok(ret == 3, "/m vs -o expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "/m", -1 );
|
||||
ok(ret == 3, "'o vs /m expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "'o", -1 );
|
||||
ok(ret == 1, "/m vs 'o expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "/m", -1 );
|
||||
ok(ret == 1, "'o vs /m expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "'o", -1 );
|
||||
ok(ret == 3, "/m vs 'o expected 3, got %d", ret);
|
||||
|
||||
#if 0 /* this requires collation table patch to make it MS compatible */
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'o", -1, "-o", -1 );
|
||||
ok(ret == 1, "'o vs -o expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'o", -1, "-o", -1 );
|
||||
ok(ret == 1, "'o vs -o expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "'", -1, "-", -1 );
|
||||
ok(ret == 1, "' vs - expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "'", -1, "-", -1 );
|
||||
ok(ret == 1, "' vs - expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "/m", -1 );
|
||||
ok(ret == 3, "`o vs /m expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "/m", -1, "`o", -1 );
|
||||
ok(ret == 1, "/m vs `o expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "/m", -1 );
|
||||
ok(ret == 3, "`o vs /m expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "/m", -1, "`o", -1 );
|
||||
ok(ret == 1, "/m vs `o expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "`o", -1, "-m", -1 );
|
||||
ok(ret == 1, "`o vs -m expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, 0, "-m", -1, "`o", -1 );
|
||||
ok(ret == 3, "-m vs `o expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "`o", -1, "-m", -1 );
|
||||
ok(ret == 3, "`o vs -m expected 3, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_SYSTEM_DEFAULT, SORT_STRINGSORT, "-m", -1, "`o", -1 );
|
||||
ok(ret == 1, "-m vs `o expected 1, got %d", ret);
|
||||
#endif
|
||||
|
||||
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ", 9);
|
||||
ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0 expected 2, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 7, "aLuZkUtZ\0A", 10);
|
||||
ok(ret == 1, "aLuZkUtZ vs aLuZkUtZ\\0A expected 1, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLuZkUtZ", 8, "aLuZkUtZ\0A", 10);
|
||||
ok(ret == 2, "aLuZkUtZ vs aLuZkUtZ\\0A expected 2, got %d", ret);
|
||||
|
||||
ret = CompareStringA(LOCALE_USER_DEFAULT, 0, "aLu\0ZkUtZ", 8, "aLu\0ZkUtZ\0A", 10);
|
||||
ok(ret == 2, "aLu\\0ZkUtZ vs aLu\\0ZkUtZ\\0A expected 2, got %d", ret);
|
||||
}
|
||||
|
||||
void test_LCMapStringA(void)
|
||||
|
@ -834,6 +980,13 @@ void test_LCMapStringA(void)
|
|||
ret, GetLastError(), lstrlenA(lower_case) + 1);
|
||||
ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
|
||||
|
||||
/* test buffer overflow */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||
lower_case, -1, buf, 4);
|
||||
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
"should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
|
||||
|
||||
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
|
||||
lstrcpyA(buf, lower_case);
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||
|
@ -924,6 +1077,13 @@ void test_LCMapStringA(void)
|
|||
ok(ret == lstrlenA(symbols_stripped) + 1, "LCMapStringA should return %d, ret = %d\n",
|
||||
lstrlenA(symbols_stripped) + 1, ret);
|
||||
ok(!lstrcmpA(buf, symbols_stripped), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
|
||||
|
||||
/* test srclen = 0 */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
|
||||
ok(!ret, "LCMapStringA should fail with srclen = 0");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
}
|
||||
|
||||
void test_LCMapStringW(void)
|
||||
|
@ -988,6 +1148,13 @@ void test_LCMapStringW(void)
|
|||
ret, GetLastError(), lstrlenW(lower_case) + 1);
|
||||
ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
|
||||
|
||||
/* test buffer overflow */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||
lower_case, -1, buf, 4);
|
||||
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
|
||||
"should return 0 and ERROR_INSUFFICIENT_BUFFER, got %d\n", ret);
|
||||
|
||||
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
|
||||
lstrcpyW(buf, lower_case);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||
|
@ -1069,9 +1236,143 @@ void test_LCMapStringW(void)
|
|||
ok(ret == lstrlenW(symbols_stripped) + 1, "LCMapStringW should return %d, ret = %d\n",
|
||||
lstrlenW(symbols_stripped) + 1, ret);
|
||||
ok(!lstrcmpW(buf, symbols_stripped), "string comparison mismatch\n");
|
||||
|
||||
/* test srclen = 0 */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, 0, upper_case, 0, buf, sizeof(buf));
|
||||
ok(!ret, "LCMapStringW should fail with srclen = 0");
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
}
|
||||
|
||||
void test_FoldStringA(void)
|
||||
#if 0 /* this requires collation table patch to make it MS compatible */
|
||||
const char *strings_sorted[] =
|
||||
{
|
||||
"'",
|
||||
"-",
|
||||
"!",
|
||||
"\"",
|
||||
".",
|
||||
":",
|
||||
"\\",
|
||||
"_",
|
||||
"`",
|
||||
"{",
|
||||
"}",
|
||||
"+",
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"a",
|
||||
"A",
|
||||
"b",
|
||||
"B",
|
||||
"c",
|
||||
"C"
|
||||
};
|
||||
|
||||
const char *strings[] =
|
||||
{
|
||||
"C",
|
||||
"\"",
|
||||
"9",
|
||||
"'",
|
||||
"}",
|
||||
"-",
|
||||
"7",
|
||||
"+",
|
||||
"`",
|
||||
"1",
|
||||
"a",
|
||||
"5",
|
||||
"\\",
|
||||
"8",
|
||||
"B",
|
||||
"3",
|
||||
"_",
|
||||
"6",
|
||||
"{",
|
||||
"2",
|
||||
"c",
|
||||
"4",
|
||||
"!",
|
||||
"0",
|
||||
"A",
|
||||
":",
|
||||
"b",
|
||||
"."
|
||||
};
|
||||
|
||||
static int compare_string1(const void *e1, const void *e2)
|
||||
{
|
||||
const char *s1 = *(const char **)e1;
|
||||
const char *s2 = *(const char **)e2;
|
||||
|
||||
return lstrcmpA(s1, s2);
|
||||
}
|
||||
|
||||
static int compare_string2(const void *e1, const void *e2)
|
||||
{
|
||||
const char *s1 = *(const char **)e1;
|
||||
const char *s2 = *(const char **)e2;
|
||||
|
||||
return CompareStringA(0, 0, s1, -1, s2, -1) - 2;
|
||||
}
|
||||
|
||||
static int compare_string3(const void *e1, const void *e2)
|
||||
{
|
||||
const char *s1 = *(const char **)e1;
|
||||
const char *s2 = *(const char **)e2;
|
||||
char key1[256], key2[256];
|
||||
|
||||
LCMapStringA(0, LCMAP_SORTKEY, s1, -1, key1, sizeof(key1));
|
||||
LCMapStringA(0, LCMAP_SORTKEY, s2, -1, key2, sizeof(key2));
|
||||
return strcmp(key1, key2);
|
||||
}
|
||||
|
||||
static void test_sorting(void)
|
||||
{
|
||||
char buf[256];
|
||||
char **str_buf = (char **)buf;
|
||||
int i;
|
||||
|
||||
assert(sizeof(buf) >= sizeof(strings));
|
||||
|
||||
/* 1. sort using lstrcmpA */
|
||||
memcpy(buf, strings, sizeof(strings));
|
||||
qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string1);
|
||||
for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
|
||||
{
|
||||
ok(!strcmp(strings_sorted[i], str_buf[i]),
|
||||
"qsort using lstrcmpA failed for element %d\n", i);
|
||||
}
|
||||
/* 2. sort using CompareStringA */
|
||||
memcpy(buf, strings, sizeof(strings));
|
||||
qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string2);
|
||||
for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
|
||||
{
|
||||
ok(!strcmp(strings_sorted[i], str_buf[i]),
|
||||
"qsort using CompareStringA failed for element %d\n", i);
|
||||
}
|
||||
/* 3. sort using sort keys */
|
||||
memcpy(buf, strings, sizeof(strings));
|
||||
qsort(buf, sizeof(strings)/sizeof(strings[0]), sizeof(strings[0]), compare_string3);
|
||||
for (i = 0; i < sizeof(strings)/sizeof(strings[0]); i++)
|
||||
{
|
||||
ok(!strcmp(strings_sorted[i], str_buf[i]),
|
||||
"qsort using sort keys failed for element %d\n", i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void test_FoldStringA(void)
|
||||
{
|
||||
int ret, i;
|
||||
char src[256], dst[256];
|
||||
|
@ -1118,6 +1419,13 @@ void test_FoldStringA(void)
|
|||
if (!pFoldStringA)
|
||||
return; /* FoldString is present in NT v3.1+, but not 95/98/Me */
|
||||
|
||||
/* these tests are locale specific */
|
||||
if (GetACP() != 1252)
|
||||
{
|
||||
trace("Skipping FoldStringA tests for a not Latin 1 locale\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* MAP_FOLDDIGITS */
|
||||
SetLastError(0);
|
||||
ret = pFoldStringA(MAP_FOLDDIGITS, digits_src, -1, dst, 256);
|
||||
|
@ -1212,7 +1520,7 @@ void test_FoldStringA(void)
|
|||
}
|
||||
}
|
||||
|
||||
void test_FoldStringW(void)
|
||||
static void test_FoldStringW(void)
|
||||
{
|
||||
int ret;
|
||||
size_t i, j;
|
||||
|
@ -1596,8 +1904,8 @@ static BOOL CALLBACK langgrp_procA(LGRPID lgrpid, LPSTR lpszNum, LPSTR lpszName,
|
|||
"Enumerated grp %ld not valid (flags %ld)\n", lgrpid, dwFlags);
|
||||
|
||||
/* If lParam is one, we are calling with flags defaulted from 0 */
|
||||
ok(!lParam || dwFlags == LGRPID_INSTALLED,
|
||||
"Expected dwFlags == LGRPID_INSTALLED, got %ld\n", dwFlags);
|
||||
ok(!lParam || (dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED),
|
||||
"Expected dwFlags == LGRPID_INSTALLED || dwFlags == LGRPID_SUPPORTED, got %ld\n", dwFlags);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1710,4 +2018,7 @@ START_TEST(locale)
|
|||
test_EnumSystemLanguageGroupsA();
|
||||
test_EnumLanguageGroupLocalesA();
|
||||
test_SetLocaleInfoA();
|
||||
#if 0 /* this requires collation table patch to make it MS compatible */
|
||||
test_sorting();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ static BOOL WINAPI SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
|
|||
char str1[3], str2[3];
|
||||
|
||||
str1[0] = LOBYTE(ch1);
|
||||
if (IsDBCSLeadByte(ch1))
|
||||
if (IsDBCSLeadByte(str1[0]))
|
||||
{
|
||||
str1[1] = HIBYTE(ch1);
|
||||
str1[2] = '\0';
|
||||
|
@ -73,7 +73,7 @@ static BOOL WINAPI SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
|
|||
str1[1] = '\0';
|
||||
|
||||
str2[0] = LOBYTE(ch2);
|
||||
if (IsDBCSLeadByte(ch2))
|
||||
if (IsDBCSLeadByte(str2[0]))
|
||||
{
|
||||
str2[1] = HIBYTE(ch2);
|
||||
str2[2] = '\0';
|
||||
|
|
|
@ -156,33 +156,37 @@ static const StrFromTimeIntervalResult StrFromTimeInterval_results[] = {
|
|||
static void test_StrChrA(void)
|
||||
{
|
||||
char string[129];
|
||||
int count;
|
||||
WORD count;
|
||||
|
||||
ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!");
|
||||
/* this test crashes on win2k SP4 */
|
||||
/*ok(!StrChrA(NULL,'\0'), "found a character in a NULL string!");*/
|
||||
|
||||
for (count = 32; count < 128; count++)
|
||||
string[count] = count;
|
||||
string[count] = (char)count;
|
||||
string[128] = '\0';
|
||||
|
||||
for (count = 32; count < 128; count++)
|
||||
{
|
||||
LPSTR result = StrChrA(string+32, count);
|
||||
ok(result - string == count, "found char %d in wrong place", count);
|
||||
ok(result - string == count,
|
||||
"found char '%c' in wrong place: got %d, expected %d\n",
|
||||
count, result - string, count);
|
||||
}
|
||||
|
||||
for (count = 32; count < 128; count++)
|
||||
{
|
||||
LPSTR result = StrChrA(string+count+1, count);
|
||||
ok(!result, "found char not in the string");
|
||||
ok(!result, "found char '%c' not in the string\n", count);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_StrChrW(void)
|
||||
{
|
||||
WCHAR string[16385];
|
||||
int count;
|
||||
WORD count;
|
||||
|
||||
ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!");
|
||||
/* this test crashes on win2k SP4 */
|
||||
/*ok(!StrChrW(NULL,'\0'), "found a character in a NULL string!");*/
|
||||
|
||||
for (count = 32; count < 16384; count++)
|
||||
string[count] = count;
|
||||
|
@ -204,12 +208,13 @@ static void test_StrChrW(void)
|
|||
static void test_StrChrIA(void)
|
||||
{
|
||||
char string[129];
|
||||
int count;
|
||||
WORD count;
|
||||
|
||||
ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");
|
||||
/* this test crashes on win2k SP4 */
|
||||
/*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");*/
|
||||
|
||||
for (count = 32; count < 128; count++)
|
||||
string[count] = count;
|
||||
string[count] = (char)count;
|
||||
string[128] = '\0';
|
||||
|
||||
for (count = 'A'; count <= 'X'; count++)
|
||||
|
@ -230,9 +235,10 @@ static void test_StrChrIA(void)
|
|||
static void test_StrChrIW(void)
|
||||
{
|
||||
WCHAR string[129];
|
||||
int count;
|
||||
WORD count;
|
||||
|
||||
ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");
|
||||
/* this test crashes on win2k SP4 */
|
||||
/*ok(!StrChrIA(NULL,'\0'), "found a character in a NULL string!");*/
|
||||
|
||||
for (count = 32; count < 128; count++)
|
||||
string[count] = count;
|
||||
|
@ -256,12 +262,13 @@ static void test_StrChrIW(void)
|
|||
static void test_StrRChrA(void)
|
||||
{
|
||||
char string[129];
|
||||
int count;
|
||||
WORD count;
|
||||
|
||||
ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!");
|
||||
/* this test crashes on win2k SP4 */
|
||||
/*ok(!StrRChrA(NULL, NULL,'\0'), "found a character in a NULL string!");*/
|
||||
|
||||
for (count = 32; count < 128; count++)
|
||||
string[count] = count;
|
||||
string[count] = (char)count;
|
||||
string[128] = '\0';
|
||||
|
||||
for (count = 32; count < 128; count++)
|
||||
|
@ -285,31 +292,34 @@ static void test_StrRChrA(void)
|
|||
|
||||
static void test_StrRChrW(void)
|
||||
{
|
||||
WCHAR string[16385];
|
||||
int count;
|
||||
WCHAR string[129];
|
||||
WORD count;
|
||||
|
||||
ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!");
|
||||
/* this test crashes on win2k SP4 */
|
||||
/*ok(!StrRChrW(NULL, NULL,'\0'), "found a character in a NULL string!");*/
|
||||
|
||||
for (count = 32; count < 16384; count++)
|
||||
for (count = 32; count < 128; count++)
|
||||
string[count] = count;
|
||||
string[16384] = '\0';
|
||||
string[128] = '\0';
|
||||
|
||||
for (count = 32; count < 16384; count++)
|
||||
for (count = 32; count < 128; count++)
|
||||
{
|
||||
LPWSTR result = StrRChrW(string+32, NULL, count);
|
||||
ok(result - string == count, "found char %d in wrong place", count);
|
||||
ok(result - string == count,
|
||||
"found char %d in wrong place: got %d, expected %d\n",
|
||||
count, result - string, count);
|
||||
}
|
||||
|
||||
for (count = 32; count < 16384; count++)
|
||||
for (count = 32; count < 128; count++)
|
||||
{
|
||||
LPWSTR result = StrRChrW(string+count+1, NULL, count);
|
||||
ok(!result, "found char not in the string");
|
||||
ok(!result, "found char %d not in the string\n", count);
|
||||
}
|
||||
|
||||
for (count = 32; count < 16384; count++)
|
||||
for (count = 32; count < 128; count++)
|
||||
{
|
||||
LPWSTR result = StrRChrW(string+count+1, string + 127, count);
|
||||
ok(!result, "found char not in the string");
|
||||
ok(!result, "found char %d not in the string\n", count);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -455,6 +465,8 @@ static void test_StrDupA()
|
|||
|
||||
static void test_StrFormatByteSize64A(void)
|
||||
{
|
||||
/* this test fails on locales which do not use '.' as a decimal separator */
|
||||
#if 0
|
||||
char szBuff[256];
|
||||
const StrFormatSizeResult* result = StrFormatSize_results;
|
||||
|
||||
|
@ -462,10 +474,13 @@ static void test_StrFormatByteSize64A(void)
|
|||
{
|
||||
StrFormatByteSize64A(result->value, szBuff, 256);
|
||||
|
||||
ok(!strcmp(result->byte_size_64, szBuff), "Formatted %lld wrong", result->value);
|
||||
ok(!strcmp(result->byte_size_64, szBuff),
|
||||
"Formatted %lx%08lx wrong: got %s, expected %s\n",
|
||||
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->byte_size_64);
|
||||
|
||||
result++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_StrFormatKBSizeW(void)
|
||||
|
@ -480,8 +495,9 @@ static void test_StrFormatKBSizeW(void)
|
|||
{
|
||||
StrFormatKBSizeW(result->value, szBuffW, 256);
|
||||
WideCharToMultiByte(0,0,szBuffW,-1,szBuff,sizeof(szBuff)/sizeof(WCHAR),0,0);
|
||||
ok(!strcmp(result->kb_size, szBuff), "Formatted %lld wrong",
|
||||
result->value);
|
||||
ok(!strcmp(result->kb_size, szBuff),
|
||||
"Formatted %lx%08lx wrong: got %s, expected %s\n",
|
||||
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
|
||||
result++;
|
||||
}
|
||||
#endif
|
||||
|
@ -489,6 +505,7 @@ static void test_StrFormatKBSizeW(void)
|
|||
|
||||
static void test_StrFormatKBSizeA(void)
|
||||
{
|
||||
/* this test fails on locales which do not use '.' as a decimal separator */
|
||||
#if 0
|
||||
char szBuff[256];
|
||||
const StrFormatSizeResult* result = StrFormatSize_results;
|
||||
|
@ -497,8 +514,9 @@ static void test_StrFormatKBSizeA(void)
|
|||
{
|
||||
StrFormatKBSizeA(result->value, szBuff, 256);
|
||||
|
||||
ok(!strcmp(result->kb_size, szBuff), "Formatted %lld wrong",
|
||||
result->value);
|
||||
ok(!strcmp(result->kb_size, szBuff),
|
||||
"Formatted %lx%08lx wrong: got %s, expected %s\n",
|
||||
(LONG)(result->value >> 32), (LONG)result->value, szBuff, result->kb_size);
|
||||
result++;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -74,6 +74,7 @@ extern int wine_cp_wcstombs( const union cptable *table, int flags,
|
|||
extern int wine_utf8_wcstombs( const WCHAR *src, int srclen, char *dst, int dstlen );
|
||||
extern int wine_utf8_mbstowcs( int flags, const char *src, int srclen, WCHAR *dst, int dstlen );
|
||||
|
||||
extern int wine_compare_string( int flags, const WCHAR *str1, int len1, const WCHAR *str2, int len2 );
|
||||
extern int wine_get_sortkey( int flags, const WCHAR *src, int srclen, char *dst, int dstlen );
|
||||
extern int wine_fold_string( int flags, const WCHAR *src, int srclen , WCHAR *dst, int dstlen );
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "wine/unicode.h"
|
||||
|
||||
extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
|
||||
extern const unsigned int collation_table[];
|
||||
|
||||
/*
|
||||
* flags - normalization NORM_* flags
|
||||
|
@ -28,7 +29,6 @@ extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
|
|||
*/
|
||||
int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dstlen)
|
||||
{
|
||||
extern const unsigned int collation_table[];
|
||||
WCHAR dummy[4]; /* no decomposition is larger than 4 chars */
|
||||
int key_len[4];
|
||||
char *key_ptr[4];
|
||||
|
@ -38,7 +38,8 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
|||
key_len[0] = key_len[1] = key_len[2] = key_len[3] = 0;
|
||||
for (; srclen; srclen--, src++)
|
||||
{
|
||||
int decomposed_len = get_decomposition(*src, dummy, 4);
|
||||
int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/
|
||||
dummy[0] = *src;
|
||||
if (decomposed_len)
|
||||
{
|
||||
int i;
|
||||
|
@ -62,18 +63,18 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
|||
if (ce >> 16) key_len[0] += 2;
|
||||
if ((ce >> 8) & 0xff) key_len[1]++;
|
||||
if ((ce >> 4) & 0x0f) key_len[2]++;
|
||||
/*if (ce & 1)
|
||||
if (ce & 1)
|
||||
{
|
||||
if (wch >> 8) key_len[3]++;
|
||||
key_len[3]++;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
/*else
|
||||
else
|
||||
{
|
||||
key_len[0] += 2;
|
||||
if (wch >> 8) key_len[0]++;
|
||||
if (wch & 0xff) key_len[0]++;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +96,8 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
|||
|
||||
for (; srclen; srclen--, src++)
|
||||
{
|
||||
int decomposed_len = get_decomposition(*src, dummy, 4);
|
||||
int decomposed_len = 1;/*get_decomposition(*src, dummy, 4);*/
|
||||
dummy[0] = *src;
|
||||
if (decomposed_len)
|
||||
{
|
||||
int i;
|
||||
|
@ -127,19 +129,19 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
|||
/* make key 2 start from 2 */
|
||||
if ((key = (ce >> 4) & 0x0f)) *key_ptr[2]++ = key + 1;
|
||||
/* key 3 is always a character code */
|
||||
/*if (ce & 1)
|
||||
if (ce & 1)
|
||||
{
|
||||
if (wch >> 8) *key_ptr[3]++ = wch >> 8;
|
||||
if (wch & 0xff) *key_ptr[3]++ = wch & 0xff;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
/*else
|
||||
else
|
||||
{
|
||||
*key_ptr[0]++ = 0xff;
|
||||
*key_ptr[0]++ = 0xfe;
|
||||
if (wch >> 8) *key_ptr[0]++ = wch >> 8;
|
||||
if (wch & 0xff) *key_ptr[0]++ = wch & 0xff;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,3 +154,198 @@ int wine_get_sortkey(int flags, const WCHAR *src, int srclen, char *dst, int dst
|
|||
|
||||
return key_ptr[3] - dst;
|
||||
}
|
||||
|
||||
static inline int compare_unicode_weights(int flags, const WCHAR *str1, int len1,
|
||||
const WCHAR *str2, int len2)
|
||||
{
|
||||
unsigned int ce1, ce2;
|
||||
int ret;
|
||||
|
||||
/* 32-bit collation element table format:
|
||||
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||
* case weight - high 4 bit of low 8 bit.
|
||||
*/
|
||||
while (len1 > 0 && len2 > 0)
|
||||
{
|
||||
if (flags & NORM_IGNORESYMBOLS)
|
||||
{
|
||||
int skip = 0;
|
||||
/* FIXME: not tested */
|
||||
if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
|
||||
{
|
||||
str1++;
|
||||
len1--;
|
||||
skip = 1;
|
||||
}
|
||||
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
|
||||
{
|
||||
str2++;
|
||||
len2--;
|
||||
skip = 1;
|
||||
}
|
||||
if (skip) continue;
|
||||
}
|
||||
|
||||
/* hyphen and apostrophe are treated differently depending on
|
||||
* whether SORT_STRINGSORT specified or not
|
||||
*/
|
||||
if (!(flags & SORT_STRINGSORT))
|
||||
{
|
||||
if (*str1 == '-' || *str1 == '\'')
|
||||
{
|
||||
if (*str2 != '-' && *str2 != '\'')
|
||||
{
|
||||
str1++;
|
||||
len1--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (*str2 == '-' || *str2 == '\'')
|
||||
{
|
||||
str2++;
|
||||
len2--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||
|
||||
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||
ret = (ce1 >> 16) - (ce2 >> 16);
|
||||
else
|
||||
ret = *str1 - *str2;
|
||||
|
||||
if (ret) return ret;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
len1--;
|
||||
len2--;
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
static inline int compare_diacritic_weights(int flags, const WCHAR *str1, int len1,
|
||||
const WCHAR *str2, int len2)
|
||||
{
|
||||
unsigned int ce1, ce2;
|
||||
int ret;
|
||||
|
||||
/* 32-bit collation element table format:
|
||||
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||
* case weight - high 4 bit of low 8 bit.
|
||||
*/
|
||||
while (len1 > 0 && len2 > 0)
|
||||
{
|
||||
if (flags & NORM_IGNORESYMBOLS)
|
||||
{
|
||||
int skip = 0;
|
||||
/* FIXME: not tested */
|
||||
if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
|
||||
{
|
||||
str1++;
|
||||
len1--;
|
||||
skip = 1;
|
||||
}
|
||||
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
|
||||
{
|
||||
str2++;
|
||||
len2--;
|
||||
skip = 1;
|
||||
}
|
||||
if (skip) continue;
|
||||
}
|
||||
|
||||
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||
|
||||
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||
ret = ((ce1 >> 8) & 0xff) - ((ce2 >> 8) & 0xff);
|
||||
else
|
||||
ret = *str1 - *str2;
|
||||
|
||||
if (ret) return ret;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
len1--;
|
||||
len2--;
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
static inline int compare_case_weights(int flags, const WCHAR *str1, int len1,
|
||||
const WCHAR *str2, int len2)
|
||||
{
|
||||
unsigned int ce1, ce2;
|
||||
int ret;
|
||||
|
||||
/* 32-bit collation element table format:
|
||||
* unicode weight - high 16 bit, diacritic weight - high 8 bit of low 16 bit,
|
||||
* case weight - high 4 bit of low 8 bit.
|
||||
*/
|
||||
while (len1 > 0 && len2 > 0)
|
||||
{
|
||||
if (flags & NORM_IGNORESYMBOLS)
|
||||
{
|
||||
int skip = 0;
|
||||
/* FIXME: not tested */
|
||||
if (get_char_typeW(*str1) & (C1_PUNCT | C1_SPACE))
|
||||
{
|
||||
str1++;
|
||||
len1--;
|
||||
skip = 1;
|
||||
}
|
||||
if (get_char_typeW(*str2) & (C1_PUNCT | C1_SPACE))
|
||||
{
|
||||
str2++;
|
||||
len2--;
|
||||
skip = 1;
|
||||
}
|
||||
if (skip) continue;
|
||||
}
|
||||
|
||||
ce1 = collation_table[collation_table[*str1 >> 8] + (*str1 & 0xff)];
|
||||
ce2 = collation_table[collation_table[*str2 >> 8] + (*str2 & 0xff)];
|
||||
|
||||
if (ce1 != (unsigned int)-1 && ce2 != (unsigned int)-1)
|
||||
ret = ((ce1 >> 4) & 0x0f) - ((ce2 >> 4) & 0x0f);
|
||||
else
|
||||
ret = *str1 - *str2;
|
||||
|
||||
if (ret) return ret;
|
||||
|
||||
str1++;
|
||||
str2++;
|
||||
len1--;
|
||||
len2--;
|
||||
}
|
||||
return len1 - len2;
|
||||
}
|
||||
|
||||
static inline int real_length(const WCHAR *str, int len)
|
||||
{
|
||||
int real_len = 0;
|
||||
while (len-- && *str++) real_len++;
|
||||
return real_len;
|
||||
}
|
||||
|
||||
int wine_compare_string(int flags, const WCHAR *str1, int len1,
|
||||
const WCHAR *str2, int len2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
len1 = real_length(str1, len1);
|
||||
len2 = real_length(str2, len2);
|
||||
|
||||
ret = compare_unicode_weights(flags, str1, len1, str2, len2);
|
||||
if (!ret)
|
||||
{
|
||||
if (!(flags & NORM_IGNORENONSPACE))
|
||||
ret = compare_diacritic_weights(flags, str1, len1, str2, len2);
|
||||
if (!ret && !(flags & NORM_IGNORECASE))
|
||||
ret = compare_case_weights(flags, str1, len1, str2, len2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ int strcmpiW( const WCHAR *str1, const WCHAR *str2 )
|
|||
{
|
||||
for (;;)
|
||||
{
|
||||
int ret = toupperW(*str1) - toupperW(*str2);
|
||||
int ret = tolowerW(*str1) - tolowerW(*str2);
|
||||
if (ret || !*str1) return ret;
|
||||
str1++;
|
||||
str2++;
|
||||
|
@ -38,7 +38,7 @@ int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n )
|
|||
{
|
||||
int ret = 0;
|
||||
for ( ; n > 0; n--, str1++, str2++)
|
||||
if ((ret = toupperW(*str1) - toupperW(*str2)) || !*str1) break;
|
||||
if ((ret = tolowerW(*str1) - tolowerW(*str2)) || !*str1) break;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ EXPORTS
|
|||
vsprintfW
|
||||
wine_casemap_lower
|
||||
wine_casemap_upper
|
||||
wine_compare_string
|
||||
wine_cp_enum_table
|
||||
wine_cp_get_table
|
||||
wine_cp_mbstowcs
|
||||
|
|
Loading…
Reference in New Issue