1
0
mirror of https://github.com/UzixLS/KernelEx.git synced 2025-07-19 07:21:20 +03:00
Files
KernelEx/apilibs/kexbases/Kernel32/locale.c
2018-11-03 16:22:27 +03:00

446 lines
14 KiB
C
Executable File

/*
* Locale support
*
* Copyright 1995 Martin von Loewis
* Copyright 1998 David Lee Lambert
* Copyright 2000 Julio César Gázquez
* Copyright 2002 Alexandre Julliard for CodeWeavers
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "common.h"
#include "locale_unicode.h"
#ifdef _MSC_VER
#pragma warning(disable:4002)
#define TRACE() ((void)0)
#define TRACE_() ((void)0)
#define WARN() ((void)0)
#else
#define TRACE(...) do {} while(0)
#define TRACE_(x) TRACE
#define WARN(...) do {} while(0)
#endif
/******************************************************************************
* CompareStringW (KERNEL32.@)
*
* See CompareStringA.
*/
/* MAKE_EXPORT CompareStringW_new=CompareStringW */
INT WINAPI CompareStringW_new(LCID lcid, DWORD style,
LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
{
INT ret;
if (!str1 || !str2)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if( style & ~(NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS|
SORT_STRINGSORT|NORM_IGNOREKANATYPE|NORM_IGNOREWIDTH|LOCALE_USE_CP_ACP|0x10000000) )
{
SetLastError(ERROR_INVALID_FLAGS);
return 0;
}
/* this style is related to diacritics in Arabic, Japanese, and Hebrew */
if (style & 0x10000000)
WARN("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;
return CSTR_EQUAL;
}
/******************************************************************************
* GetStringTypeW (KERNEL32.@)
*
* See GetStringTypeA.
*/
/* MAKE_EXPORT GetStringTypeW_new=GetStringTypeW */
BOOL WINAPI GetStringTypeW_new( DWORD type, LPCWSTR src, INT count, LPWORD chartype )
{
if (count == -1) count = strlenW(src) + 1;
switch(type)
{
case CT_CTYPE1:
while (count--) *chartype++ = get_char_typeW( *src++ ) & 0xfff;
break;
case CT_CTYPE2:
while (count--) *chartype++ = get_char_typeW( *src++ ) >> 12;
break;
case CT_CTYPE3:
{
#if 0
WARN("CT_CTYPE3: semi-stub.\n");
while (count--)
{
int c = *src;
WORD type1, type3 = 0; /* C3_NOTAPPLICABLE */
type1 = get_char_typeW( *src++ ) & 0xfff;
/* try to construct type3 from type1 */
if(type1 & C1_SPACE) type3 |= C3_SYMBOL;
if(type1 & C1_ALPHA) type3 |= C3_ALPHA;
if ((c>=0x30A0)&&(c<=0x30FF)) type3 |= C3_KATAKANA;
if ((c>=0x3040)&&(c<=0x309F)) type3 |= C3_HIRAGANA;
if ((c>=0x4E00)&&(c<=0x9FAF)) type3 |= C3_IDEOGRAPH;
if ((c>=0x0600)&&(c<=0x06FF)) type3 |= C3_KASHIDA;
if ((c>=0x3000)&&(c<=0x303F)) type3 |= C3_SYMBOL;
if ((c>=0xFF00)&&(c<=0xFF60)) type3 |= C3_FULLWIDTH;
if ((c>=0xFF00)&&(c<=0xFF20)) type3 |= C3_SYMBOL;
if ((c>=0xFF3B)&&(c<=0xFF40)) type3 |= C3_SYMBOL;
if ((c>=0xFF5B)&&(c<=0xFF60)) type3 |= C3_SYMBOL;
if ((c>=0xFF21)&&(c<=0xFF3A)) type3 |= C3_ALPHA;
if ((c>=0xFF41)&&(c<=0xFF5A)) type3 |= C3_ALPHA;
if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_FULLWIDTH;
if ((c>=0xFFE0)&&(c<=0xFFE6)) type3 |= C3_SYMBOL;
if ((c>=0xFF61)&&(c<=0xFFDC)) type3 |= C3_HALFWIDTH;
if ((c>=0xFF61)&&(c<=0xFF64)) type3 |= C3_SYMBOL;
if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_KATAKANA;
if ((c>=0xFF65)&&(c<=0xFF9F)) type3 |= C3_ALPHA;
if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_HALFWIDTH;
if ((c>=0xFFE8)&&(c<=0xFFEE)) type3 |= C3_SYMBOL;
*chartype++ = type3;
}
break;
#else
//use implementation from SHLWAPI - ordinal 35
HMODULE hShlwapi = GetModuleHandle("SHLWAPI.DLL");
BOOL (WINAPI *GetStringType3ExW)(LPCWSTR, INT, LPWORD);
if (!hShlwapi)
hShlwapi = LoadLibrary("SHLWAPI.DLL");
if (!hShlwapi)
{
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
GetStringType3ExW = (BOOL (WINAPI*)(LPCWSTR, INT, LPWORD))
kexGetProcAddress(hShlwapi, (LPSTR) 35);
return GetStringType3ExW(src, count, chartype);
#endif
}
default:
SetLastError( ERROR_INVALID_PARAMETER );
return FALSE;
}
return TRUE;
}
/******************************************************************************
* GetStringTypeExW (KERNEL32.@)
*
* See GetStringTypeExA.
*/
/* MAKE_EXPORT GetStringTypeExW_new=GetStringTypeExW */
BOOL WINAPI GetStringTypeExW_new( LCID locale, DWORD type, LPCWSTR src, INT count, LPWORD chartype )
{
/* locale is ignored for Unicode */
return GetStringTypeW_new( type, src, count, chartype );
}
/*************************************************************************
* LCMapStringW (KERNEL32.@)
*
* See LCMapStringA.
*/
/* MAKE_EXPORT LCMapStringW_new=LCMapStringW */
INT WINAPI LCMapStringW_new(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;
lcid = ConvertDefaultLocale(lcid);
if (flags & LCMAP_SORTKEY)
{
INT ret;
if (src == dst)
{
SetLastError(ERROR_INVALID_FLAGS);
return 0;
}
if (srclen < 0) srclen = strlenW(src);
TRACE("(0x%04x,0x%08x,%s,%d,%p,%d)\n",
lcid, flags, debugstr_wn(src, srclen), srclen, dst, dstlen);
ret = wine_get_sortkey(flags, src, srclen, (BYTE *)dst, dstlen);
if (ret == 0)
SetLastError(ERROR_INSUFFICIENT_BUFFER);
else
ret++;
return ret;
}
/* 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%04x,0x%08x,%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--;
}
}
if (srclen)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return 0;
}
return dst_ptr - dst;
}
/*************************************************************************
* FoldStringW (KERNEL32.@)
*
* See FoldStringA.
*/
/* MAKE_EXPORT FoldStringW_new=FoldStringW */
INT WINAPI FoldStringW_new(DWORD dwFlags, LPCWSTR src, INT srclen,
LPWSTR dst, INT dstlen)
{
int ret;
switch (dwFlags & (MAP_COMPOSITE|MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES))
{
case 0:
if (dwFlags)
break;
/* Fall through for dwFlags == 0 */
case MAP_PRECOMPOSED|MAP_COMPOSITE:
case MAP_PRECOMPOSED|MAP_EXPAND_LIGATURES:
case MAP_COMPOSITE|MAP_EXPAND_LIGATURES:
SetLastError(ERROR_INVALID_FLAGS);
return 0;
}
if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
ret = wine_fold_string(dwFlags, src, srclen, dst, dstlen);
if (!ret)
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return ret;
}
/*************************************************************************
* FoldStringA (KERNEL32.@)
*
* Map characters in a string.
*
* PARAMS
* dwFlags [I] Flags controlling chars to map (MAP_ constants from "winnls.h")
* src [I] String to map
* srclen [I] Length of src, or -1 if src is NUL terminated
* dst [O] Destination for mapped string
* dstlen [I] Length of dst, or 0 to find the required length for the mapped string
*
* RETURNS
* Success: The length of the string written to dst, including the terminating NUL. If
* dstlen is 0, the value returned is the same, but nothing is written to dst,
* and dst may be NULL.
* Failure: 0. Use GetLastError() to determine the cause.
*/
/* MAKE_EXPORT FoldStringA_new=FoldStringA */
INT WINAPI FoldStringA_new(DWORD dwFlags, LPCSTR src, INT srclen,
LPSTR dst, INT dstlen)
{
INT ret = 0, srclenW = 0;
WCHAR *srcW = NULL, *dstW = NULL;
if (!src || !srclen || dstlen < 0 || (dstlen && !dst) || src == dst)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
srclenW = MultiByteToWideChar(CP_ACP, dwFlags & MAP_COMPOSITE ? MB_COMPOSITE : 0,
src, srclen, NULL, 0);
srcW = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, srclenW * sizeof(WCHAR));
if (!srcW)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto FoldStringA_exit;
}
MultiByteToWideChar(CP_ACP, dwFlags & MAP_COMPOSITE ? MB_COMPOSITE : 0,
src, srclen, srcW, srclenW);
dwFlags = (dwFlags & ~MAP_PRECOMPOSED) | MAP_FOLDCZONE;
ret = FoldStringW_new(dwFlags, srcW, srclenW, NULL, 0);
if (ret && dstlen)
{
dstW = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, ret * sizeof(WCHAR));
if (!dstW)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto FoldStringA_exit;
}
ret = FoldStringW_new(dwFlags, srcW, srclenW, dstW, ret);
if (!WideCharToMultiByte(CP_ACP, 0, dstW, ret, dst, dstlen, NULL, NULL))
{
ret = 0;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
}
}
HeapFree(GetProcessHeap(), 0, dstW);
FoldStringA_exit:
HeapFree(GetProcessHeap(), 0, srcW);
return ret;
}
/*************************************************************************
* lstrcmpW (KERNEL32.@)
*
* See lstrcmpA.
*/
/* MAKE_EXPORT lstrcmpW_new=lstrcmpW */
int WINAPI lstrcmpW_new(LPCWSTR str1, LPCWSTR str2)
{
int ret;
if ((str1 == NULL) && (str2 == NULL)) return 0;
if (str1 == NULL) return -1;
if (str2 == NULL) return 1;
ret = CompareStringW_new(GetThreadLocale(), 0, str1, -1, str2, -1);
if (ret) ret -= 2;
return ret;
}
/*************************************************************************
* lstrcmpiW (KERNEL32.@)
*
* See lstrcmpiA.
*/
/* MAKE_EXPORT lstrcmpiW_new=lstrcmpiW */
int WINAPI lstrcmpiW_new(LPCWSTR str1, LPCWSTR str2)
{
int ret;
if ((str1 == NULL) && (str2 == NULL)) return 0;
if (str1 == NULL) return -1;
if (str2 == NULL) return 1;
ret = CompareStringW_new(GetThreadLocale(), NORM_IGNORECASE, str1, -1, str2, -1);
if (ret) ret -= 2;
return ret;
}