Implement LCMapString using unicode collation tables.
Move CompareString and LCMapString to dlls/kernel/locale.c.
This commit is contained in:
parent
4cb212063b
commit
85d4281616
|
@ -16344,8 +16344,6 @@ esac
|
|||
|
||||
ac_config_commands="$ac_config_commands objects"
|
||||
|
||||
ac_config_commands="$ac_config_commands ole"
|
||||
|
||||
ac_config_commands="$ac_config_commands programs/regapi/tests"
|
||||
|
||||
ac_config_commands="$ac_config_commands programs/regedit/tests"
|
||||
|
@ -17118,7 +17116,6 @@ do
|
|||
"misc" ) CONFIG_COMMANDS="$CONFIG_COMMANDS misc" ;;
|
||||
"msdos" ) CONFIG_COMMANDS="$CONFIG_COMMANDS msdos" ;;
|
||||
"objects" ) CONFIG_COMMANDS="$CONFIG_COMMANDS objects" ;;
|
||||
"ole" ) CONFIG_COMMANDS="$CONFIG_COMMANDS ole" ;;
|
||||
"programs/regapi/tests" ) CONFIG_COMMANDS="$CONFIG_COMMANDS programs/regapi/tests" ;;
|
||||
"programs/regedit/tests" ) CONFIG_COMMANDS="$CONFIG_COMMANDS programs/regedit/tests" ;;
|
||||
"relay32" ) CONFIG_COMMANDS="$CONFIG_COMMANDS relay32" ;;
|
||||
|
@ -17857,8 +17854,6 @@ echo "$as_me: creating misc" >&6;} && mkdir "misc") ;;
|
|||
echo "$as_me: creating msdos" >&6;} && mkdir "msdos") ;;
|
||||
objects ) test -d "objects" || ({ echo "$as_me:$LINENO: creating objects" >&5
|
||||
echo "$as_me: creating objects" >&6;} && mkdir "objects") ;;
|
||||
ole ) test -d "ole" || ({ echo "$as_me:$LINENO: creating ole" >&5
|
||||
echo "$as_me: creating ole" >&6;} && mkdir "ole") ;;
|
||||
programs/regapi/tests ) test -d "programs/regapi/tests" || ({ echo "$as_me:$LINENO: creating programs/regapi/tests" >&5
|
||||
echo "$as_me: creating programs/regapi/tests" >&6;} && mkdir "programs/regapi/tests") ;;
|
||||
programs/regedit/tests ) test -d "programs/regedit/tests" || ({ echo "$as_me:$LINENO: creating programs/regedit/tests" >&5
|
||||
|
|
|
@ -1351,7 +1351,6 @@ WINE_CONFIG_EXTRA_DIR(memory)
|
|||
WINE_CONFIG_EXTRA_DIR(misc)
|
||||
WINE_CONFIG_EXTRA_DIR(msdos)
|
||||
WINE_CONFIG_EXTRA_DIR(objects)
|
||||
WINE_CONFIG_EXTRA_DIR(ole)
|
||||
WINE_CONFIG_EXTRA_DIR(programs/regapi/tests)
|
||||
WINE_CONFIG_EXTRA_DIR(programs/regedit/tests)
|
||||
WINE_CONFIG_EXTRA_DIR(relay32)
|
||||
|
|
|
@ -20,7 +20,6 @@ SPEC_SRCS16 = \
|
|||
windebug.spec
|
||||
|
||||
C_SRCS = \
|
||||
$(TOPOBJDIR)/ole/ole2nls.c \
|
||||
atom.c \
|
||||
change.c \
|
||||
comm.c \
|
||||
|
@ -65,7 +64,7 @@ MC_SRCS = \
|
|||
messages/winerr_enu.mc
|
||||
|
||||
SUBDIRS = tests
|
||||
EXTRASUBDIRS = messages nls $(TOPOBJDIR)/ole
|
||||
EXTRASUBDIRS = messages nls
|
||||
|
||||
@MAKE_DLL_RULES@
|
||||
|
||||
|
|
|
@ -535,7 +535,7 @@ static INT get_registry_locale_info( LPCWSTR value, LPWSTR buffer, INT len )
|
|||
* GetLocaleInfoA (KERNEL32.@)
|
||||
*
|
||||
* NOTES
|
||||
* LANG_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
|
||||
* LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
|
||||
*
|
||||
* MS online documentation states that the string returned is NULL terminated
|
||||
* except for LOCALE_FONTSIGNATURE which "will return a non-NULL
|
||||
|
@ -593,7 +593,7 @@ INT WINAPI GetLocaleInfoA( LCID lcid, LCTYPE lctype, LPSTR buffer, INT len )
|
|||
* GetLocaleInfoW (KERNEL32.@)
|
||||
*
|
||||
* NOTES
|
||||
* LANG_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
|
||||
* LOCALE_NEUTRAL is equal to LOCALE_SYSTEM_DEFAULT
|
||||
*
|
||||
* MS online documentation states that the string returned is NULL terminated
|
||||
* except for LOCALE_FONTSIGNATURE which "will return a non-NULL
|
||||
|
@ -617,8 +617,8 @@ INT WINAPI GetLocaleInfoW( LCID lcid, LCTYPE lctype, LPWSTR buffer, INT len )
|
|||
}
|
||||
if (!len) buffer = NULL;
|
||||
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LANG_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LANG_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LOCALE_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LOCALE_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
|
||||
lcflags = lctype & LOCALE_LOCALEINFOFLAGSMASK;
|
||||
lctype &= ~LOCALE_LOCALEINFOFLAGSMASK;
|
||||
|
@ -705,8 +705,8 @@ BOOL WINAPI SetLocaleInfoA(LCID lcid, LCTYPE lctype, LPCSTR data)
|
|||
DWORD len;
|
||||
BOOL ret;
|
||||
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LANG_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LANG_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LOCALE_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LOCALE_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
|
||||
if (!(lctype & LOCALE_USE_CP_ACP)) codepage = get_lcid_codepage( lcid );
|
||||
len = MultiByteToWideChar( codepage, 0, data, -1, NULL, 0 );
|
||||
|
@ -733,8 +733,8 @@ BOOL WINAPI SetLocaleInfoW( LCID lcid, LCTYPE lctype, LPCWSTR data )
|
|||
NTSTATUS status;
|
||||
HKEY hkey;
|
||||
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LANG_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LANG_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LOCALE_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LOCALE_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
|
||||
if (!(value = get_locale_value_name( lctype )))
|
||||
{
|
||||
|
@ -780,8 +780,8 @@ LCID WINAPI GetThreadLocale(void)
|
|||
*/
|
||||
BOOL WINAPI SetThreadLocale( LCID lcid ) /* [in] Locale identifier */
|
||||
{
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LANG_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LANG_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LOCALE_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LOCALE_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
|
||||
NtCurrentTeb()->CurrentLocale = lcid;
|
||||
NtCurrentTeb()->code_page = get_lcid_codepage( lcid );
|
||||
|
@ -994,6 +994,319 @@ BOOL WINAPI GetStringTypeExA( LCID locale, DWORD type, LPCSTR src, INT count, LP
|
|||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* LCMapStringW (KERNEL32.@)
|
||||
*/
|
||||
INT WINAPI LCMapStringW(LCID lcid, DWORD flags, LPCWSTR src, INT srclen,
|
||||
LPWSTR dst, INT dstlen)
|
||||
{
|
||||
LPWSTR dst_ptr;
|
||||
|
||||
if (!src || !srclen || dstlen < 0)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* mutually exclusive flags */
|
||||
if ((flags & (LCMAP_LOWERCASE | LCMAP_UPPERCASE)) == (LCMAP_LOWERCASE | LCMAP_UPPERCASE) ||
|
||||
(flags & (LCMAP_HIRAGANA | LCMAP_KATAKANA)) == (LCMAP_HIRAGANA | LCMAP_KATAKANA) ||
|
||||
(flags & (LCMAP_HALFWIDTH | LCMAP_FULLWIDTH)) == (LCMAP_HALFWIDTH | LCMAP_FULLWIDTH) ||
|
||||
(flags & (LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE)) == (LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dstlen) dst = NULL;
|
||||
|
||||
if (lcid == LOCALE_NEUTRAL || lcid == LOCALE_SYSTEM_DEFAULT) lcid = GetSystemDefaultLCID();
|
||||
else if (lcid == LOCALE_USER_DEFAULT) lcid = GetUserDefaultLCID();
|
||||
|
||||
if (flags & LCMAP_SORTKEY)
|
||||
{
|
||||
if (src == dst)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (srclen < 0) srclen = strlenW(src);
|
||||
|
||||
TRACE("(0x%04lx,0x%08lx,%s,%d,%p,%d)\n",
|
||||
lcid, flags, debugstr_wn(src, srclen), srclen, dst, dstlen);
|
||||
|
||||
return wine_get_sortkey(flags, src, srclen, (char *)dst, dstlen);
|
||||
}
|
||||
|
||||
/* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
|
||||
if (flags & SORT_STRINGSORT)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (srclen < 0) srclen = strlenW(src) + 1;
|
||||
|
||||
TRACE("(0x%04lx,0x%08lx,%s,%d,%p,%d)\n",
|
||||
lcid, flags, debugstr_wn(src, srclen), srclen, dst, dstlen);
|
||||
|
||||
if (!dst) /* return required string length */
|
||||
{
|
||||
INT len;
|
||||
|
||||
for (len = 0; srclen; src++, srclen--)
|
||||
{
|
||||
WCHAR wch = *src;
|
||||
/* tests show that win2k just ignores NORM_IGNORENONSPACE,
|
||||
* and skips white space and punctuation characters for
|
||||
* NORM_IGNORESYMBOLS.
|
||||
*/
|
||||
if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
|
||||
continue;
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
if (flags & LCMAP_UPPERCASE)
|
||||
{
|
||||
for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
|
||||
{
|
||||
WCHAR wch = *src;
|
||||
if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
|
||||
continue;
|
||||
*dst_ptr++ = toupperW(wch);
|
||||
dstlen--;
|
||||
}
|
||||
}
|
||||
else if (flags & LCMAP_LOWERCASE)
|
||||
{
|
||||
for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
|
||||
{
|
||||
WCHAR wch = *src;
|
||||
if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
|
||||
continue;
|
||||
*dst_ptr++ = tolowerW(wch);
|
||||
dstlen--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src == dst)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
return 0;
|
||||
}
|
||||
for (dst_ptr = dst; srclen && dstlen; src++, srclen--)
|
||||
{
|
||||
WCHAR wch = *src;
|
||||
if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
|
||||
continue;
|
||||
*dst_ptr++ = wch;
|
||||
dstlen--;
|
||||
}
|
||||
}
|
||||
|
||||
return dst_ptr - dst;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* LCMapStringA (KERNEL32.@)
|
||||
*/
|
||||
INT WINAPI LCMapStringA(LCID lcid, DWORD flags, LPCSTR src, INT srclen,
|
||||
LPSTR dst, INT dstlen)
|
||||
{
|
||||
WCHAR bufW[128];
|
||||
LPWSTR srcW, dstW;
|
||||
INT ret = 0, srclenW, dstlenW;
|
||||
UINT locale_cp;
|
||||
|
||||
if (!src || !srclen || dstlen < 0)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
(WCHAR *)&locale_cp, (sizeof(locale_cp)/sizeof(WCHAR)));
|
||||
|
||||
srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, bufW, 128);
|
||||
if (srclenW)
|
||||
srcW = bufW;
|
||||
else
|
||||
{
|
||||
srclenW = MultiByteToWideChar(locale_cp, 0, src, srclen, NULL, 0);
|
||||
srcW = HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
|
||||
if (!srcW)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
MultiByteToWideChar(locale_cp, 0, src, srclen, srcW, srclenW);
|
||||
}
|
||||
|
||||
if (flags & LCMAP_SORTKEY)
|
||||
{
|
||||
if (src == dst)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
goto map_string_exit;
|
||||
}
|
||||
ret = wine_get_sortkey(flags, srcW, srclenW, dst, dstlen);
|
||||
}
|
||||
|
||||
if (flags & SORT_STRINGSORT)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FLAGS);
|
||||
goto map_string_exit;
|
||||
}
|
||||
|
||||
dstlenW = LCMapStringW(lcid, flags, srcW, srclenW, NULL, 0);
|
||||
dstW = HeapAlloc(GetProcessHeap(), 0, dstlenW * sizeof(WCHAR));
|
||||
if (!dstW)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
goto map_string_exit;
|
||||
}
|
||||
|
||||
LCMapStringW(lcid, flags, srcW, srclenW, dstW, dstlenW);
|
||||
ret = WideCharToMultiByte(locale_cp, 0, dstW, dstlenW, dst, dstlen, NULL, NULL);
|
||||
HeapFree(GetProcessHeap(), 0, dstW);
|
||||
|
||||
map_string_exit:
|
||||
if (srcW != bufW) HeapFree(GetProcessHeap(), 0, srcW);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CompareStringW (KERNEL32.@)
|
||||
*/
|
||||
INT WINAPI CompareStringW(LCID lcid, DWORD style,
|
||||
LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
|
||||
{
|
||||
INT ret, len;
|
||||
|
||||
if (!str1 || !str2)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (len1 < 0) len1 = lstrlenW(str1);
|
||||
if (len2 < 0) len2 = lstrlenW(str2);
|
||||
|
||||
len = (len1 < len2) ? len1 : len2;
|
||||
ret = (style & NORM_IGNORECASE) ? strncmpiW(str1, str2, len) :
|
||||
strncmpW(str1, str2, len);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* CompareStringA (KERNEL32.@)
|
||||
*/
|
||||
INT WINAPI CompareStringA(LCID lcid, DWORD style,
|
||||
LPCSTR str1, INT len1, LPCSTR str2, INT len2)
|
||||
{
|
||||
WCHAR buf1W[128], buf2W[128];
|
||||
LPWSTR str1W, str2W;
|
||||
INT len1W, len2W, ret;
|
||||
UINT locale_cp;
|
||||
|
||||
if (!str1 || !str2)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
|
||||
(WCHAR *)&locale_cp, (sizeof(locale_cp)/sizeof(WCHAR)));
|
||||
|
||||
len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, buf1W, 128);
|
||||
if (len1W)
|
||||
str1W = buf1W;
|
||||
else
|
||||
{
|
||||
len1W = MultiByteToWideChar(locale_cp, 0, str1, len1, NULL, 0);
|
||||
str1W = HeapAlloc(GetProcessHeap(), 0, len1W * sizeof(WCHAR));
|
||||
if (!str1W)
|
||||
{
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
MultiByteToWideChar(locale_cp, 0, str1, len1, str1W, len1W);
|
||||
}
|
||||
len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, buf2W, 128);
|
||||
if (len2W)
|
||||
str2W = buf2W;
|
||||
else
|
||||
{
|
||||
len2W = MultiByteToWideChar(locale_cp, 0, str2, len2, NULL, 0);
|
||||
str2W = HeapAlloc(GetProcessHeap(), 0, len2W * sizeof(WCHAR));
|
||||
if (!str2W)
|
||||
{
|
||||
if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
|
||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||
return 0;
|
||||
}
|
||||
MultiByteToWideChar(locale_cp, 0, str2, len2, str2W, len2W);
|
||||
}
|
||||
|
||||
ret = CompareStringW(lcid, style, str1W, len1W, str2W, len2W);
|
||||
|
||||
if (str1W != buf1W) HeapFree(GetProcessHeap(), 0, str1W);
|
||||
if (str2W != buf2W) HeapFree(GetProcessHeap(), 0, str2W);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* lstrcmp (KERNEL32.@)
|
||||
* lstrcmpA (KERNEL32.@)
|
||||
*/
|
||||
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
|
||||
{
|
||||
int ret = CompareStringA(GetThreadLocale(), 0, str1, -1, str2, -1);
|
||||
if (ret) ret -= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* lstrcmpi (KERNEL32.@)
|
||||
* lstrcmpiA (KERNEL32.@)
|
||||
*/
|
||||
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
|
||||
{
|
||||
int ret = CompareStringA(GetThreadLocale(), NORM_IGNORECASE, str1, -1, str2, -1);
|
||||
if (ret) ret -= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* lstrcmpW (KERNEL32.@)
|
||||
*/
|
||||
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
|
||||
{
|
||||
int ret = CompareStringW(GetThreadLocale(), 0, str1, -1, str2, -1);
|
||||
if (ret) ret -= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* lstrcmpiW (KERNEL32.@)
|
||||
*/
|
||||
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
|
||||
{
|
||||
int ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str1, -1, str2, -1);
|
||||
if (ret) ret -= 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* LOCALE_Init
|
||||
*/
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Test run on win2K (French)
|
||||
*
|
||||
* Copyright (c) 2002 YASAR Mehmet
|
||||
* Copyright 2003 Dmitry Timoshkov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -696,30 +697,282 @@ char buffer1[BUFFER_SIZE], buffer2[BUFFER_SIZE];
|
|||
|
||||
strcpy(buffer1, "Salut"); strcpy(buffer2, "Salute");
|
||||
ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
|
||||
ok (ret== 1, "CompareStringA (st1=%s str2=%s) expected result=1", buffer1, buffer2);
|
||||
ok(ret == 1, "CompareStringA (st1=%s str2=%s) expected result=1, got %d", buffer1, buffer2, ret);
|
||||
|
||||
strcpy(buffer1, "Salut"); strcpy(buffer2, "saLuT");
|
||||
ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
|
||||
ok (ret== 2, "CompareStringA (st1=%s str2=%s) expected result=2", buffer1, buffer2);
|
||||
ok(ret == 2, "CompareStringA (st1=%s str2=%s) expected result=2, got %d", buffer1, buffer2, ret);
|
||||
|
||||
strcpy(buffer1, "Salut"); strcpy(buffer2, "hola");
|
||||
ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
|
||||
ok (ret== 3, "CompareStringA (st1=%s str2=%s) expected result=3", buffer1, buffer2);
|
||||
ok(ret == 3, "CompareStringA (st1=%s str2=%s) expected result=3, got %d", buffer1, buffer2, ret);
|
||||
|
||||
strcpy(buffer1, "héhé"); strcpy(buffer2, "hèhè");
|
||||
strcpy(buffer1, "haha"); strcpy(buffer2, "hoho");
|
||||
ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
|
||||
ok (ret== 1, "CompareStringA (st1=%s str2=%s) expected result=1", buffer1, buffer2);
|
||||
ok (ret == 1, "CompareStringA (st1=%s str2=%s) expected result=1, got %d", buffer1, buffer2, ret);
|
||||
|
||||
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT );
|
||||
|
||||
strcpy(buffer1, "héhé"); strcpy(buffer2, "hèhè");
|
||||
strcpy(buffer1, "haha"); strcpy(buffer2, "hoho");
|
||||
ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, -1);
|
||||
ok (ret== 1, "CompareStringA (st1=%s str2=%s) expected result=1", buffer1, buffer2);
|
||||
ok (ret == 1, "CompareStringA (st1=%s str2=%s) expected result=1, got %d", buffer1, buffer2, ret);
|
||||
|
||||
ret = CompareStringA(lcid, NORM_IGNORECASE, buffer1, -1, buffer2, 0);
|
||||
ok (ret== 3, "CompareStringA (st1=%s str2=%s) expected result=3", buffer1, buffer2);
|
||||
ok (ret == 3, "CompareStringA (st1=%s str2=%s) expected result=3, got %d", buffer1, buffer2, ret);
|
||||
}
|
||||
|
||||
void test_LCMapStringA(void)
|
||||
{
|
||||
int ret, ret2;
|
||||
char buf[256], buf2[256];
|
||||
static const char upper_case[] = "\tJUST! A, TEST; STRING 1/*+-.\r\n";
|
||||
static const char lower_case[] = "\tjust! a, test; string 1/*+-.\r\n";
|
||||
static const char symbols_stripped[] = "justateststring1";
|
||||
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
|
||||
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
|
||||
/* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
|
||||
ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
|
||||
|
||||
/* test LCMAP_LOWERCASE */
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(ret == lstrlenA(upper_case) + 1,
|
||||
"ret %d, error %ld, expected value %d\n",
|
||||
ret, GetLastError(), lstrlenA(upper_case) + 1);
|
||||
ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
|
||||
|
||||
/* test LCMAP_UPPERCASE */
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||
lower_case, -1, buf, sizeof(buf));
|
||||
ok(ret == lstrlenA(lower_case) + 1,
|
||||
"ret %d, error %ld, expected value %d\n",
|
||||
ret, GetLastError(), lstrlenA(lower_case) + 1);
|
||||
ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
|
||||
|
||||
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
|
||||
lstrcpyA(buf, lower_case);
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||
buf, -1, buf, sizeof(buf));
|
||||
if (!ret) /* Win9x */
|
||||
trace("Ignoring LCMapStringA(LCMAP_UPPERCASE, buf, buf) error on Win9x\n");
|
||||
else
|
||||
{
|
||||
ok(ret == lstrlenA(lower_case) + 1,
|
||||
"ret %d, error %ld, expected value %d\n",
|
||||
ret, GetLastError(), lstrlenA(lower_case) + 1);
|
||||
ok(!lstrcmpA(buf, upper_case), "LCMapStringA should return %s, but not %s\n", upper_case, buf);
|
||||
}
|
||||
lstrcpyA(buf, upper_case);
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
|
||||
buf, -1, buf, sizeof(buf));
|
||||
if (!ret) /* Win9x */
|
||||
trace("Ignoring LCMapStringA(LCMAP_LOWERCASE, buf, buf) error on Win9x\n");
|
||||
else
|
||||
{
|
||||
ok(ret == lstrlenA(upper_case) + 1,
|
||||
"ret %d, error %ld, expected value %d\n",
|
||||
ret, GetLastError(), lstrlenA(lower_case) + 1);
|
||||
ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
|
||||
}
|
||||
|
||||
/* otherwise src == dst should fail */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
|
||||
buf, 10, buf, sizeof(buf));
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
|
||||
|
||||
/* test whether '\0' is always appended */
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(ret, "LCMapStringA must succeed\n");
|
||||
ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
|
||||
upper_case, lstrlenA(upper_case), buf2, sizeof(buf2));
|
||||
ok(ret, "LCMapStringA must succeed\n");
|
||||
ok(ret == ret2, "lengths of sort keys must be equal\n");
|
||||
ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
|
||||
|
||||
/* test LCMAP_SORTKEY | NORM_IGNORECASE */
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(ret, "LCMapStringA must succeed\n");
|
||||
ret2 = LCMapStringA(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
|
||||
lower_case, -1, buf2, sizeof(buf2));
|
||||
ok(ret2, "LCMapStringA must succeed\n");
|
||||
ok(ret == ret2, "lengths of sort keys must be equal\n");
|
||||
ok(!lstrcmpA(buf, buf2), "sort keys must be equal\n");
|
||||
|
||||
/* test NORM_IGNORENONSPACE */
|
||||
lstrcpyA(buf, "foo");
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
|
||||
lower_case, -1, buf, sizeof(buf));
|
||||
ok(ret == lstrlenA(lower_case) + 1, "LCMapStringA should return %d, ret = %d\n",
|
||||
lstrlenA(lower_case) + 1, ret);
|
||||
ok(!lstrcmpA(buf, lower_case), "LCMapStringA should return %s, but not %s\n", lower_case, buf);
|
||||
|
||||
/* test NORM_IGNORESYMBOLS */
|
||||
lstrcpyA(buf, "foo");
|
||||
ret = LCMapStringA(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
|
||||
lower_case, -1, buf, sizeof(buf));
|
||||
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);
|
||||
}
|
||||
|
||||
void test_LCMapStringW(void)
|
||||
{
|
||||
int ret, ret2;
|
||||
WCHAR buf[256], buf2[256];
|
||||
char *p_buf = (char *)buf, *p_buf2 = (char *)buf2;
|
||||
static const WCHAR upper_case[] = {'\t','J','U','S','T','!',' ','A',',',' ','T','E','S','T',';',' ','S','T','R','I','N','G',' ','1','/','*','+','-','.','\r','\n',0};
|
||||
static const WCHAR lower_case[] = {'\t','j','u','s','t','!',' ','a',',',' ','t','e','s','t',';',' ','s','t','r','i','n','g',' ','1','/','*','+','-','.','\r','\n',0};
|
||||
static const WCHAR symbols_stripped[] = {'j','u','s','t','a','t','e','s','t','s','t','r','i','n','g','1',0};
|
||||
static const WCHAR fooW[] = {'f','o','o',0};
|
||||
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | LCMAP_UPPERCASE,
|
||||
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
|
||||
{
|
||||
trace("Skipping LCMapStringW tests on Win9x\n");
|
||||
return;
|
||||
}
|
||||
ok(!ret, "LCMAP_LOWERCASE and LCMAP_UPPERCASE are mutually exclusive\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HIRAGANA | LCMAP_KATAKANA,
|
||||
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(!ret, "LCMAP_HIRAGANA and LCMAP_KATAKANA are mutually exclusive\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_HALFWIDTH | LCMAP_FULLWIDTH,
|
||||
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(!ret, "LCMAP_HALFWIDTH | LCMAP_FULLWIDTH are mutually exclusive\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_TRADITIONAL_CHINESE | LCMAP_SIMPLIFIED_CHINESE,
|
||||
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(!ret, "LCMAP_TRADITIONAL_CHINESE and LCMAP_SIMPLIFIED_CHINESE are mutually exclusive\n");
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
|
||||
/* SORT_STRINGSORT must be used exclusively with LCMAP_SORTKEY */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE | SORT_STRINGSORT,
|
||||
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS, "expected ERROR_INVALID_FLAGS, got %ld\n", GetLastError());
|
||||
ok(!ret, "SORT_STRINGSORT without LCMAP_SORTKEY must fail\n");
|
||||
|
||||
/* test LCMAP_LOWERCASE */
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
|
||||
upper_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(ret == lstrlenW(upper_case) + 1,
|
||||
"ret %d, error %ld, expected value %d\n",
|
||||
ret, GetLastError(), lstrlenW(upper_case) + 1);
|
||||
ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
|
||||
|
||||
/* test LCMAP_UPPERCASE */
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||
lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(ret == lstrlenW(lower_case) + 1,
|
||||
"ret %d, error %ld, expected value %d\n",
|
||||
ret, GetLastError(), lstrlenW(lower_case) + 1);
|
||||
ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
|
||||
|
||||
/* LCMAP_UPPERCASE or LCMAP_LOWERCASE should accept src == dst */
|
||||
lstrcpyW(buf, lower_case);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE,
|
||||
buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(ret == lstrlenW(lower_case) + 1,
|
||||
"ret %d, error %ld, expected value %d\n",
|
||||
ret, GetLastError(), lstrlenW(lower_case) + 1);
|
||||
ok(!lstrcmpW(buf, upper_case), "string compare mismatch\n");
|
||||
|
||||
lstrcpyW(buf, upper_case);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE,
|
||||
buf, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(ret == lstrlenW(upper_case) + 1,
|
||||
"ret %d, error %ld, expected value %d\n",
|
||||
ret, GetLastError(), lstrlenW(lower_case) + 1);
|
||||
ok(!lstrcmpW(buf, lower_case), "string compare mismatch\n");
|
||||
|
||||
/* otherwise src == dst should fail */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | LCMAP_UPPERCASE,
|
||||
buf, 10, buf, sizeof(buf));
|
||||
ok(GetLastError() == ERROR_INVALID_FLAGS /* NT */ ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER /* Win9x */,
|
||||
"unexpected error code %ld\n", GetLastError());
|
||||
ok(!ret, "src == dst without LCMAP_UPPERCASE or LCMAP_LOWERCASE must fail\n");
|
||||
|
||||
/* test whether '\0' is always appended */
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(ret, "LCMapStringW must succeed\n");
|
||||
ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
|
||||
upper_case, lstrlenW(upper_case), buf2, sizeof(buf2));
|
||||
ok(ret, "LCMapStringW must succeed\n");
|
||||
ok(ret == ret2, "lengths of sort keys must be equal\n");
|
||||
ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
|
||||
|
||||
/* test LCMAP_SORTKEY | NORM_IGNORECASE */
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY | NORM_IGNORECASE,
|
||||
upper_case, -1, buf, sizeof(buf));
|
||||
ok(ret, "LCMapStringW must succeed\n");
|
||||
ret2 = LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_SORTKEY,
|
||||
lower_case, -1, buf2, sizeof(buf2));
|
||||
ok(ret2, "LCMapStringW must succeed\n");
|
||||
ok(ret == ret2, "lengths of sort keys must be equal\n");
|
||||
ok(!lstrcmpA(p_buf, p_buf2), "sort keys must be equal\n");
|
||||
|
||||
/* test NORM_IGNORENONSPACE */
|
||||
lstrcpyW(buf, fooW);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORENONSPACE,
|
||||
lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
ok(ret == lstrlenW(lower_case) + 1, "LCMapStringW should return %d, ret = %d\n",
|
||||
lstrlenW(lower_case) + 1, ret);
|
||||
ok(!lstrcmpW(buf, lower_case), "string comparison mismatch\n");
|
||||
|
||||
/* test NORM_IGNORESYMBOLS */
|
||||
lstrcpyW(buf, fooW);
|
||||
ret = LCMapStringW(LOCALE_USER_DEFAULT, NORM_IGNORESYMBOLS,
|
||||
lower_case, -1, buf, sizeof(buf)/sizeof(WCHAR));
|
||||
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");
|
||||
}
|
||||
|
||||
START_TEST(locale)
|
||||
{
|
||||
|
@ -733,4 +986,7 @@ START_TEST(locale)
|
|||
TestGetNumberFormat();
|
||||
TestGetCurrencyFormat();
|
||||
TestCompareStringA();
|
||||
|
||||
test_LCMapStringW();
|
||||
test_LCMapStringA();
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ static inline void release( void *ptr )
|
|||
/* put an ASCII string into the debug buffer */
|
||||
inline static char *put_string_a( const char *src, int n )
|
||||
{
|
||||
static const char hex[16] = "0123456789abcdef";
|
||||
char *dst, *res;
|
||||
|
||||
if (n == -1) n = strlen(src);
|
||||
|
@ -123,9 +124,9 @@ inline static char *put_string_a( const char *src, int n )
|
|||
else
|
||||
{
|
||||
*dst++ = '\\';
|
||||
*dst++ = '0' + ((c >> 6) & 7);
|
||||
*dst++ = '0' + ((c >> 3) & 7);
|
||||
*dst++ = '0' + ((c >> 0) & 7);
|
||||
*dst++ = 'x';
|
||||
*dst++ = hex[(c >> 4) & 0x0f];
|
||||
*dst++ = hex[c & 0x0f];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#ifndef __WINE_UNICODE_H
|
||||
#define __WINE_UNICODE_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winnls.h"
|
||||
|
||||
|
@ -71,6 +73,8 @@ 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_get_sortkey( int flags, const WCHAR *src, int srclen, char *dst, int dstlen );
|
||||
|
||||
extern int strcmpiW( const WCHAR *str1, const WCHAR *str2 );
|
||||
extern int strncmpiW( const WCHAR *str1, const WCHAR *str2, int n );
|
||||
extern WCHAR *strstrW( const WCHAR *str, const WCHAR *sub );
|
||||
|
|
|
@ -196,6 +196,10 @@ extern "C" {
|
|||
#define LCMAP_HALFWIDTH 0x00400000 /* map double byte to single byte */
|
||||
#define LCMAP_FULLWIDTH 0x00800000 /* map single byte to double byte */
|
||||
|
||||
#define LCMAP_LINGUISTIC_CASING 0x01000000 /* use linguistic rules for casing */
|
||||
#define LCMAP_SIMPLIFIED_CHINESE 0x02000000 /* map traditional chinese to simplified chinese */
|
||||
#define LCMAP_TRADITIONAL_CHINESE 0x04000000 /* map simplified chinese to traditional chinese */
|
||||
|
||||
/* Date Flags for GetDateFormat. */
|
||||
|
||||
#define DATE_SHORTDATE 0x00000001 /* use short date picture */
|
||||
|
|
|
@ -70,9 +70,11 @@ CODEPAGES = \
|
|||
|
||||
C_SRCS = \
|
||||
casemap.c \
|
||||
collation.c \
|
||||
compose.c \
|
||||
cptable.c \
|
||||
mbtowc.c \
|
||||
sortkey.c \
|
||||
string.c \
|
||||
utf8.c \
|
||||
wctomb.c \
|
||||
|
|
|
@ -20,11 +20,10 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "winnls.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
/* get the decomposition of a Unicode char */
|
||||
static int get_decomposition( WCHAR src, WCHAR *dst, unsigned int dstlen )
|
||||
int get_decomposition( WCHAR src, WCHAR *dst, unsigned int dstlen )
|
||||
{
|
||||
extern const WCHAR unicode_decompose_table[];
|
||||
const WCHAR *ptr = unicode_decompose_table;
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Unicode sort key generation
|
||||
*
|
||||
* Copyright 2003 Dmitry Timoshkov
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "wine/unicode.h"
|
||||
|
||||
extern int get_decomposition(WCHAR src, WCHAR *dst, unsigned int dstlen);
|
||||
|
||||
/*
|
||||
* flags - normalization NORM_* flags
|
||||
*
|
||||
* FIXME: 'variable' flag not handled
|
||||
*/
|
||||
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];
|
||||
const WCHAR *src_save = src;
|
||||
int srclen_save = srclen;
|
||||
|
||||
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);
|
||||
if (decomposed_len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < decomposed_len; i++)
|
||||
{
|
||||
WCHAR wch = dummy[i];
|
||||
unsigned int ce;
|
||||
|
||||
/* tests show that win2k just ignores NORM_IGNORENONSPACE,
|
||||
* and skips white space and punctuation characters for
|
||||
* NORM_IGNORESYMBOLS.
|
||||
*/
|
||||
if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
|
||||
continue;
|
||||
|
||||
if (flags & NORM_IGNORECASE) wch = tolowerW(wch);
|
||||
|
||||
ce = collation_table[collation_table[wch >> 8] + (wch & 0xff)];
|
||||
if (ce != (unsigned int)-1)
|
||||
{
|
||||
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 (wch >> 8) key_len[3]++;
|
||||
key_len[3]++;
|
||||
}*/
|
||||
}
|
||||
/*else
|
||||
{
|
||||
key_len[0] += 2;
|
||||
if (wch >> 8) key_len[0]++;
|
||||
if (wch & 0xff) key_len[0]++;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dstlen) /* compute length */
|
||||
/* 4 * '\1' + 1 * '\0' + key length */
|
||||
return key_len[0] + key_len[1] + key_len[2] + key_len[3] + 4 + 1;
|
||||
|
||||
if (dstlen < key_len[0] + key_len[1] + key_len[2] + key_len[3] + 4 + 1)
|
||||
return 0; /* overflow */
|
||||
|
||||
src = src_save;
|
||||
srclen = srclen_save;
|
||||
|
||||
key_ptr[0] = dst;
|
||||
key_ptr[1] = key_ptr[0] + key_len[0] + 1;
|
||||
key_ptr[2] = key_ptr[1] + key_len[1] + 1;
|
||||
key_ptr[3] = key_ptr[2] + key_len[2] + 1;
|
||||
|
||||
for (; srclen; srclen--, src++)
|
||||
{
|
||||
int decomposed_len = get_decomposition(*src, dummy, 4);
|
||||
if (decomposed_len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < decomposed_len; i++)
|
||||
{
|
||||
WCHAR wch = dummy[i];
|
||||
unsigned int ce;
|
||||
|
||||
/* tests show that win2k just ignores NORM_IGNORENONSPACE,
|
||||
* and skips white space and punctuation characters for
|
||||
* NORM_IGNORESYMBOLS.
|
||||
*/
|
||||
if ((flags & NORM_IGNORESYMBOLS) && (get_char_typeW(wch) & (C1_PUNCT | C1_SPACE)))
|
||||
continue;
|
||||
|
||||
if (flags & NORM_IGNORECASE) wch = tolowerW(wch);
|
||||
|
||||
ce = collation_table[collation_table[wch >> 8] + (wch & 0xff)];
|
||||
if (ce != (unsigned int)-1)
|
||||
{
|
||||
WCHAR key;
|
||||
if ((key = ce >> 16))
|
||||
{
|
||||
*key_ptr[0]++ = key >> 8;
|
||||
*key_ptr[0]++ = key & 0xff;
|
||||
}
|
||||
/* make key 1 start from 2 */
|
||||
if ((key = (ce >> 8) & 0xff)) *key_ptr[1]++ = key + 1;
|
||||
/* 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 (wch >> 8) *key_ptr[3]++ = wch >> 8;
|
||||
if (wch & 0xff) *key_ptr[3]++ = wch & 0xff;
|
||||
}*/
|
||||
}
|
||||
/*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;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*key_ptr[0] = '\1';
|
||||
*key_ptr[1] = '\1';
|
||||
*key_ptr[2] = '\1';
|
||||
*key_ptr[3]++ = '\1';
|
||||
*key_ptr[3] = 0;
|
||||
|
||||
return key_ptr[3] - dst;
|
||||
}
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "winnls.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
/* number of following bytes in sequence based on first byte value (for bytes above 0x7f) */
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "winnls.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
/* search for a character in the unicode_compose_table; helper for compose() */
|
||||
|
|
|
@ -16,6 +16,7 @@ EXPORTS
|
|||
wine_cp_get_table
|
||||
wine_cp_mbstowcs
|
||||
wine_cp_wcstombs
|
||||
wine_get_sortkey
|
||||
wine_utf8_mbstowcs
|
||||
wine_utf8_wcstombs
|
||||
wine_wctype_table
|
||||
|
|
1218
ole/ole2nls.c
1218
ole/ole2nls.c
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue