Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/string.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index 4991ba3fd1..8b3d94a9e6 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -58,52 +58,46 @@ DWORD WINAPI StrCmpNICW(const WCHAR *str, const WCHAR *cmp, DWORD len) return StrCmpNIW(str, cmp, len); }
-BOOL WINAPI IsCharBlankW(WCHAR wc) +static WORD get_char_type(char c) { - WORD type; + WORD type = 0; + GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &type); + return type; +}
- return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_BLANK); +BOOL WINAPI IsCharBlankW(WCHAR wc) +{ + return !!(get_char_typeW(wc) & C1_BLANK); }
BOOL WINAPI IsCharCntrlW(WCHAR wc) { - WORD type; - - return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_CNTRL); + return !!iscntrlW(wc); }
BOOL WINAPI IsCharDigitW(WCHAR wc) { - WORD type; - - return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_DIGIT); + return !!isdigitW(wc); }
BOOL WINAPI IsCharPunctW(WCHAR wc) { - WORD type; - - return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_PUNCT); + return !!ispunctW(wc); }
BOOL WINAPI IsCharSpaceA(CHAR c) { - WORD type; - return GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &type) && (type & C1_SPACE); + return !!(get_char_type(c) & C1_SPACE); }
BOOL WINAPI IsCharSpaceW(WCHAR wc) { - WORD type; - - return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_SPACE); + return !!isspaceW(wc); }
BOOL WINAPI IsCharXDigitW(WCHAR wc) { - WORD type; - - return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_XDIGIT); + return !!isxdigitW(wc); }
WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/kernelbase.spec | 44 +++---- dlls/kernelbase/string.c | 226 ++++++++++++++++++++++++++++++++ 2 files changed, 248 insertions(+), 22 deletions(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 8294c95282..6ff91518c3 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -109,20 +109,20 @@ @ stdcall CancelWaitableTimer(long) kernel32.CancelWaitableTimer # @ stub CeipIsOptedIn @ stdcall ChangeTimerQueueTimer(ptr ptr long long) kernel32.ChangeTimerQueueTimer -@ stdcall CharLowerA(str) user32.CharLowerA -@ stdcall CharLowerBuffA(str long) user32.CharLowerBuffA -@ stdcall CharLowerBuffW(wstr long) user32.CharLowerBuffW -@ stdcall CharLowerW(wstr) user32.CharLowerW -@ stdcall CharNextA(str) user32.CharNextA -@ stdcall CharNextExA(long str long) user32.CharNextExA -@ stdcall CharNextW(wstr) user32.CharNextW -@ stdcall CharPrevA(str str) user32.CharPrevA -@ stdcall CharPrevExA(long str str long) user32.CharPrevExA -@ stdcall CharPrevW(wstr wstr) user32.CharPrevW -@ stdcall CharUpperA(str) user32.CharUpperA -@ stdcall CharUpperBuffA(str long) user32.CharUpperBuffA -@ stdcall CharUpperBuffW(wstr long) user32.CharUpperBuffW -@ stdcall CharUpperW(wstr) user32.CharUpperW +@ stdcall CharLowerA(str) +@ stdcall CharLowerBuffA(str long) +@ stdcall CharLowerBuffW(wstr long) +@ stdcall CharLowerW(wstr) +@ stdcall CharNextA(str) +@ stdcall CharNextExA(long str long) +@ stdcall CharNextW(wstr) +@ stdcall CharPrevA(str str) +@ stdcall CharPrevExA(long str str long) +@ stdcall CharPrevW(wstr wstr) +@ stdcall CharUpperA(str) +@ stdcall CharUpperBuffA(str long) +@ stdcall CharUpperBuffW(wstr long) +@ stdcall CharUpperW(wstr) # @ stub CheckAllowDecryptedRemoteDestinationPolicy @ stub CheckGroupPolicyEnabled # @ stub CheckIfStateChangeNotificationExists @@ -839,20 +839,20 @@ # @ stub InternetTimeToSystemTimeW # @ stub InvalidateAppModelVersionCache @ stub InvalidateTzSpecificCache -@ stdcall IsCharAlphaA(long) user32.IsCharAlphaA -@ stdcall IsCharAlphaNumericA(long) user32.IsCharAlphaNumericA -@ stdcall IsCharAlphaNumericW(long) user32.IsCharAlphaNumericW -@ stdcall IsCharAlphaW(long) user32.IsCharAlphaW +@ stdcall IsCharAlphaA(long) +@ stdcall IsCharAlphaNumericA(long) +@ stdcall IsCharAlphaNumericW(long) +@ stdcall IsCharAlphaW(long) @ stdcall IsCharBlankW(long) @ stdcall IsCharCntrlW(long) @ stdcall IsCharDigitW(long) -@ stdcall IsCharLowerA(long) user32.IsCharLowerA -@ stdcall IsCharLowerW(long) user32.IsCharLowerW +@ stdcall IsCharLowerA(long) +@ stdcall IsCharLowerW(long) @ stdcall IsCharPunctW(long) @ stdcall IsCharSpaceA(long) @ stdcall IsCharSpaceW(long) -@ stdcall IsCharUpperA(long) user32.IsCharUpperA -@ stdcall IsCharUpperW(long) user32.IsCharUpperW +@ stdcall IsCharUpperA(long) +@ stdcall IsCharUpperW(long) @ stdcall IsCharXDigitW(long) @ stdcall IsDBCSLeadByte(long) kernel32.IsDBCSLeadByte @ stdcall IsDBCSLeadByteEx(long long) kernel32.IsDBCSLeadByteEx diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index 8b3d94a9e6..7e128765d8 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -24,6 +24,7 @@ #include "shlwapi.h"
#include "wine/debug.h" +#include "wine/exception.h" #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(string); @@ -100,6 +101,54 @@ BOOL WINAPI IsCharXDigitW(WCHAR wc) return !!isxdigitW(wc); }
+BOOL WINAPI IsCharAlphaA(CHAR x) +{ + WCHAR wch; + MultiByteToWideChar(CP_ACP, 0, &x, 1, &wch, 1); + return IsCharAlphaW(wch); +} + +BOOL WINAPI IsCharAlphaW(WCHAR ch) +{ + return !!(get_char_typeW(ch) & C1_ALPHA); +} + +BOOL WINAPI IsCharLowerA(CHAR x) +{ + WCHAR wch; + MultiByteToWideChar(CP_ACP, 0, &x, 1, &wch, 1); + return IsCharLowerW(wch); +} + +BOOL WINAPI IsCharLowerW(WCHAR ch) +{ + return !!islowerW(ch); +} + +BOOL WINAPI IsCharAlphaNumericA(CHAR x) +{ + WCHAR wch; + MultiByteToWideChar(CP_ACP, 0, &x, 1, &wch, 1); + return IsCharAlphaNumericW(wch); +} + +BOOL WINAPI IsCharAlphaNumericW(WCHAR ch) +{ + return !!(get_char_typeW(ch) & (C1_ALPHA | C1_DIGIT)); +} + +BOOL WINAPI IsCharUpperA(CHAR x) +{ + WCHAR wch; + MultiByteToWideChar(CP_ACP, 0, &x, 1, &wch, 1); + return IsCharUpperW(wch); +} + +BOOL WINAPI IsCharUpperW(WCHAR ch) +{ + return !!isupperW(ch); +} + WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch) { TRACE("%s, %#x\n", wine_dbgstr_w(str), ch); @@ -511,3 +560,180 @@ WCHAR * WINAPI StrCpyNXW(WCHAR *dst, const WCHAR *src, int len)
return dst; } + +LPSTR WINAPI CharLowerA(char *str) +{ + if (IS_INTRESOURCE(str)) + { + char ch = LOWORD(str); + CharLowerBuffA( &ch, 1 ); + return (LPSTR)(UINT_PTR)(BYTE)ch; + } + + __TRY + { + CharLowerBuffA( str, strlen(str) ); + } + __EXCEPT_PAGE_FAULT + { + SetLastError( ERROR_INVALID_PARAMETER ); + return NULL; + } + __ENDTRY + return str; +} + +DWORD WINAPI CharLowerBuffA(char *str, DWORD len) +{ + DWORD lenW; + WCHAR buffer[32]; + WCHAR *strW = buffer; + + if (!str) return 0; /* YES */ + + lenW = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0); + if (lenW > ARRAY_SIZE(buffer)) + { + strW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR)); + if (!strW) return 0; + } + MultiByteToWideChar(CP_ACP, 0, str, len, strW, lenW); + CharLowerBuffW(strW, lenW); + len = WideCharToMultiByte(CP_ACP, 0, strW, lenW, str, len, NULL, NULL); + if (strW != buffer) HeapFree(GetProcessHeap(), 0, strW); + return len; +} + +DWORD WINAPI CharLowerBuffW(WCHAR *str, DWORD len) +{ + if (!str) return 0; /* YES */ + return LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_LOWERCASE, str, len, str, len); +} + +LPWSTR WINAPI CharLowerW(WCHAR *str) +{ + if (!IS_INTRESOURCE(str)) + { + CharLowerBuffW(str, lstrlenW(str)); + return str; + } + else + { + WCHAR ch = LOWORD(str); + CharLowerBuffW(&ch, 1); + return (LPWSTR)(UINT_PTR)ch; + } +} + +LPSTR WINAPI CharNextA(const char *ptr) +{ + if (!*ptr) return (LPSTR)ptr; + if (IsDBCSLeadByte( ptr[0] ) && ptr[1]) return (LPSTR)(ptr + 2); + return (LPSTR)(ptr + 1); +} + +LPSTR WINAPI CharNextExA(WORD codepage, const char *ptr, DWORD flags) +{ + if (!*ptr) return (LPSTR)ptr; + if (IsDBCSLeadByteEx( codepage, ptr[0] ) && ptr[1]) return (LPSTR)(ptr + 2); + return (LPSTR)(ptr + 1); +} + +LPWSTR WINAPI CharNextW(const WCHAR *x) +{ + if (*x) x++; + + return (WCHAR *)x; +} + +LPSTR WINAPI CharPrevA(const char *start, const char *ptr) +{ + while (*start && (start < ptr)) + { + LPCSTR next = CharNextA(start); + if (next >= ptr) break; + start = next; + } + return (LPSTR)start; +} + +LPSTR WINAPI CharPrevExA(WORD codepage, const char *start, const char *ptr, DWORD flags) +{ + while (*start && (start < ptr)) + { + LPCSTR next = CharNextExA(codepage, start, flags); + if (next >= ptr) break; + start = next; + } + return (LPSTR)start; +} + +LPWSTR WINAPI CharPrevW(const WCHAR *start, const WCHAR *x) +{ + if (x > start) return (LPWSTR)(x - 1); + else return (LPWSTR)x; +} + +LPSTR WINAPI CharUpperA(LPSTR str) +{ + if (IS_INTRESOURCE(str)) + { + char ch = LOWORD(str); + CharUpperBuffA(&ch, 1); + return (LPSTR)(UINT_PTR)(BYTE)ch; + } + + __TRY + { + CharUpperBuffA(str, strlen(str)); + } + __EXCEPT_PAGE_FAULT + { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + __ENDTRY + return str; +} + +DWORD WINAPI CharUpperBuffA(LPSTR str, DWORD len) +{ + DWORD lenW; + WCHAR buffer[32]; + WCHAR *strW = buffer; + + if (!str) return 0; /* YES */ + + lenW = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0); + if (lenW > ARRAY_SIZE(buffer)) + { + strW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR)); + if (!strW) return 0; + } + MultiByteToWideChar(CP_ACP, 0, str, len, strW, lenW); + CharUpperBuffW(strW, lenW); + len = WideCharToMultiByte(CP_ACP, 0, strW, lenW, str, len, NULL, NULL); + if (strW != buffer) HeapFree(GetProcessHeap(), 0, strW); + return len; +} + +DWORD WINAPI CharUpperBuffW(WCHAR *str, DWORD len) +{ + if (!str) return 0; /* YES */ + return LCMapStringW(LOCALE_USER_DEFAULT, LCMAP_UPPERCASE, str, len, str, len); +} + +LPWSTR WINAPI CharUpperW(WCHAR *str) +{ + if (!IS_INTRESOURCE(str)) + { + CharUpperBuffW(str, lstrlenW(str)); + return str; + } + else + { + WCHAR ch = LOWORD(str); + CharUpperBuffW(&ch, 1); + return (LPWSTR)(UINT_PTR)ch; + } +}
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/kernelbase.spec | 4 +- dlls/kernelbase/string.c | 80 +++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 6ff91518c3..66bc105804 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -929,10 +929,10 @@ @ stdcall LoadLibraryW(wstr) kernel32.LoadLibraryW # @ stub LoadPackagedLibrary @ stdcall LoadResource(long long) kernel32.LoadResource -@ stdcall LoadStringA(long long ptr long) user32.LoadStringA +@ stdcall LoadStringA(long long ptr long) @ stub LoadStringBaseExW @ stub LoadStringByReference -@ stdcall LoadStringW(long long ptr long) user32.LoadStringW +@ stdcall LoadStringW(long long ptr long) @ stdcall LocalAlloc(long long) kernel32.LocalAlloc @ stdcall LocalFileTimeToFileTime(ptr ptr) kernel32.LocalFileTimeToFileTime @ stdcall LocalFree(long) kernel32.LocalFree diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index 7e128765d8..463f5af070 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -22,6 +22,7 @@ #include "winbase.h" #include "winnls.h" #include "shlwapi.h" +#include "winternl.h"
#include "wine/debug.h" #include "wine/exception.h" @@ -737,3 +738,82 @@ LPWSTR WINAPI CharUpperW(WCHAR *str) return (LPWSTR)(UINT_PTR)ch; } } + +INT WINAPI DECLSPEC_HOTPATCH LoadStringW(HINSTANCE instance, UINT resource_id, LPWSTR buffer, INT buflen) +{ + int string_num, i; + HGLOBAL hmem; + HRSRC hrsrc; + WCHAR *p; + + TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n", instance, resource_id, buffer, buflen); + + if (!buffer) + return 0; + + /* Use loword (incremented by 1) as resourceid */ + hrsrc = FindResourceW(instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1), (LPWSTR)RT_STRING); + if (!hrsrc) return 0; + hmem = LoadResource(instance, hrsrc); + if (!hmem) return 0; + + p = LockResource(hmem); + string_num = resource_id & 0x000f; + for (i = 0; i < string_num; i++) + p += *p + 1; + + TRACE("strlen = %d\n", (int)*p ); + + /*if buflen == 0, then return a read-only pointer to the resource itself in buffer + it is assumed that buffer is actually a (LPWSTR *) */ + if (buflen == 0) + { + *((LPWSTR *)buffer) = p + 1; + return *p; + } + + i = min(buflen - 1, *p); + if (i > 0) + { + memcpy(buffer, p + 1, i * sizeof (WCHAR)); + buffer[i] = 0; + } + else + { + if (buflen > 1) + { + buffer[0] = 0; + return 0; + } + } + + TRACE("returning %s\n", debugstr_w(buffer)); + return i; +} + +INT WINAPI DECLSPEC_HOTPATCH LoadStringA(HINSTANCE instance, UINT resource_id, LPSTR buffer, INT buflen) +{ + DWORD retval = 0; + HGLOBAL hmem; + HRSRC hrsrc; + + TRACE("instance = %p, id = %04x, buffer = %p, length = %d\n", instance, resource_id, buffer, buflen); + + if (!buflen) return -1; + + /* Use loword (incremented by 1) as resourceid */ + if ((hrsrc = FindResourceW(instance, MAKEINTRESOURCEW((LOWORD(resource_id) >> 4) + 1), (LPWSTR)RT_STRING )) && + (hmem = LoadResource(instance, hrsrc))) + { + const WCHAR *p = LockResource(hmem); + unsigned int id = resource_id & 0x000f; + + while (id--) p += *p + 1; + + if (buflen != 1) + RtlUnicodeToMultiByteN(buffer, buflen - 1, &retval, p + 1, *p * sizeof(WCHAR)); + } + buffer[retval] = 0; + TRACE("returning %s\n", debugstr_a(buffer)); + return retval; +}
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/kernelbase.spec | 24 +-- dlls/kernelbase/string.c | 302 ++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+), 12 deletions(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 66bc105804..8ca9e1bde4 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -130,7 +130,7 @@ # @ stub CheckTokenCapability @ stdcall CheckTokenMembership(long ptr ptr) advapi32.CheckTokenMembership # @ stub CheckTokenMembershipEx -@ stdcall ChrCmpIA(long long) shlwapi.ChrCmpIA +@ stdcall ChrCmpIA(long long) @ stdcall ChrCmpIW(long long) @ stdcall ClearCommBreak(long) kernel32.ClearCommBreak @ stdcall ClearCommError(long ptr ptr) kernel32.ClearCommError @@ -1532,9 +1532,9 @@ @ stdcall StrCatBuffA(str str long) shlwapi.StrCatBuffA @ stdcall StrCatBuffW(wstr wstr long) shlwapi.StrCatBuffW @ stdcall StrCatChainW(ptr long long wstr) shlwapi.StrCatChainW -@ stdcall StrChrA(str long) shlwapi.StrChrA +@ stdcall StrChrA(str long) # @ stub StrChrA_MB -@ stdcall StrChrIA(str long) shlwapi.StrChrIA +@ stdcall StrChrIA(str long) @ stdcall StrChrIW(wstr long) # @ stub StrChrNIW @ stdcall StrChrNW(wstr long long) @@ -1544,8 +1544,8 @@ @ stdcall StrCmpICA(str str) @ stdcall StrCmpICW(wstr wstr) @ stdcall StrCmpIW(wstr wstr) -@ stdcall StrCmpLogicalW(wstr wstr) shlwapi.StrCmpLogicalW -@ stdcall StrCmpNA(str str long) shlwapi.StrCmpNA +@ stdcall StrCmpLogicalW(wstr wstr) +@ stdcall StrCmpNA(str str long) @ stdcall StrCmpNCA(str ptr long) shlwapi.StrCmpNCA @ stdcall StrCmpNCW(wstr wstr long) shlwapi.StrCmpNCW @ stdcall StrCmpNIA(str str long) @@ -1559,9 +1559,9 @@ @ stdcall StrCpyNXW(ptr wstr long) @ stdcall StrDupA(str) @ stdcall StrDupW(wstr) -@ stdcall StrIsIntlEqualA(long str str long) shlwapi.StrIsIntlEqualA -@ stdcall StrIsIntlEqualW(long wstr wstr long) shlwapi.StrIsIntlEqualW -@ stdcall StrPBrkA(str str) shlwapi.StrPBrkA +@ stdcall StrIsIntlEqualA(long str str long) +@ stdcall StrIsIntlEqualW(long wstr wstr long) +@ stdcall StrPBrkA(str str) @ stdcall StrPBrkW(wstr wstr) @ stdcall StrRChrA(str str long) shlwapi.StrRChrA @ stdcall StrRChrIA(str str long) shlwapi.StrRChrIA @@ -1577,13 +1577,13 @@ @ stdcall StrStrNIW(wstr wstr long) @ stdcall StrStrNW(wstr wstr long) @ stdcall StrStrW(wstr wstr) -@ stdcall StrToInt64ExA(str long ptr) shlwapi.StrToInt64ExA +@ stdcall StrToInt64ExA(str long ptr) @ stdcall StrToInt64ExW(wstr long ptr) -@ stdcall StrToIntA(str) shlwapi.StrToIntA -@ stdcall StrToIntExA(str long ptr) shlwapi.StrToIntExA +@ stdcall StrToIntA(str) +@ stdcall StrToIntExA(str long ptr) @ stdcall StrToIntExW(wstr long ptr) @ stdcall StrToIntW(wstr) -@ stdcall StrTrimA(str str) shlwapi.StrTrimA +@ stdcall StrTrimA(str str) @ stdcall StrTrimW(wstr wstr) @ stdcall SubmitThreadpoolWork(ptr) kernel32.SubmitThreadpoolWork # @ stub SubscribeEdpEnabledStateChange diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index 463f5af070..d8d42deed6 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -30,6 +30,31 @@
WINE_DEFAULT_DEBUG_CHANNEL(string);
+static BOOL chrcmpa(WORD ch1, WORD ch2, DWORD flags) +{ + char str1[3], str2[3]; + + str1[0] = LOBYTE(ch1); + if (IsDBCSLeadByte(str1[0])) + { + str1[1] = HIBYTE(ch1); + str1[2] = '\0'; + } + else + str1[1] = '\0'; + + str2[0] = LOBYTE(ch2); + if (IsDBCSLeadByte(str2[0])) + { + str2[1] = HIBYTE(ch2); + str2[2] = '\0'; + } + else + str2[1] = '\0'; + + return CompareStringA(GetThreadLocale(), flags, str1, -1, str2, -1) - CSTR_EQUAL; +} + DWORD WINAPI StrCmpCA(const char *str, const char *cmp) { return lstrcmpA(str, cmp); @@ -150,6 +175,23 @@ BOOL WINAPI IsCharUpperW(WCHAR ch) return !!isupperW(ch); }
+char * WINAPI StrChrA(const char *str, WORD ch) +{ + TRACE("%s, %#x\n", wine_dbgstr_a(str), ch); + + if (!str) + return NULL; + + while (*str) + { + if (!chrcmpa(*str, ch, 0)) + return (char *)str; + str = CharNextA(str); + } + + return NULL; +} + WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch) { TRACE("%s, %#x\n", wine_dbgstr_w(str), ch); @@ -160,6 +202,23 @@ WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch) return strchrW(str, ch); }
+char * WINAPI StrChrIA(const char *str, WORD ch) +{ + TRACE("%s, %i\n", wine_dbgstr_a(str), ch); + + if (!str) + return NULL; + + while (*str) + { + if (!ChrCmpIA(*str, ch)) + return (char *)str; + str = CharNextA(str); + } + + return NULL; +} + WCHAR * WINAPI StrChrIW(const WCHAR *str, WCHAR ch) { TRACE("%s, %#x\n", wine_dbgstr_w(str), ch); @@ -238,6 +297,13 @@ WCHAR * WINAPI StrDupW(const WCHAR *str) return ret; }
+BOOL WINAPI ChrCmpIA(WORD ch1, WORD ch2) +{ + TRACE("%#x, %#x\n", ch1, ch2); + + return chrcmpa(ch1, ch2, NORM_IGNORECASE); +} + BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2) { return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, &ch1, 1, &ch2, 1) - CSTR_EQUAL; @@ -299,6 +365,12 @@ WCHAR * WINAPI StrStrNIW(const WCHAR *str, const WCHAR *search, UINT max_len) return NULL; }
+int WINAPI StrCmpNA(const char *str, const char *comp, int len) +{ + TRACE("%s, %s, %i\n", wine_dbgstr_a(str), wine_dbgstr_a(comp), len); + return CompareStringA(GetThreadLocale(), 0, str, len, comp, len) - CSTR_EQUAL; +} + int WINAPI StrCmpNW(const WCHAR *str, const WCHAR *comp, int len) { TRACE("%s, %s, %i\n", wine_dbgstr_w(str), wine_dbgstr_w(comp), len); @@ -400,12 +472,67 @@ WCHAR * WINAPI StrRChrIW(const WCHAR *str, const WCHAR *end, WORD ch) return ret; }
+char * WINAPI StrPBrkA(const char *str, const char *match) +{ + TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(match)); + + if (!str || !match || !*match) + return NULL; + + while (*str) + { + if (StrChrA(match, *str)) + return (char *)str; + str = CharNextA(str); + } + + return NULL; +} + WCHAR * WINAPI StrPBrkW(const WCHAR *str, const WCHAR *match) { if (!str || !match) return NULL; return strpbrkW(str, match); }
+BOOL WINAPI StrTrimA(char *str, const char *trim) +{ + unsigned int len; + BOOL ret = FALSE; + char *ptr = str; + + TRACE("%s, %s\n", debugstr_a(str), debugstr_a(trim)); + + if (!str || !*str) + return FALSE; + + while (*ptr && StrChrA(trim, *ptr)) + ptr = CharNextA(ptr); /* Skip leading matches */ + + len = strlen(ptr); + + if (ptr != str) + { + memmove(str, ptr, len + 1); + ret = TRUE; + } + + if (len > 0) + { + ptr = str + len; + while (StrChrA(trim, ptr[-1])) + ptr = CharPrevA(str, ptr); /* Skip trailing matches */ + + if (ptr != str + len) + { + *ptr = '\0'; + ret = TRUE; + } + } + + return ret; +} + BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim) { unsigned int len; @@ -444,6 +571,68 @@ BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim) return ret; }
+BOOL WINAPI StrToInt64ExA(const char *str, DWORD flags, LONGLONG *ret) +{ + BOOL negative = FALSE; + LONGLONG value = 0; + + TRACE("%s, %#x, %p\n", wine_dbgstr_a(str), flags, ret); + + if (!str || !ret) + return FALSE; + + if (flags > STIF_SUPPORT_HEX) + WARN("Unknown flags %#x\n", flags); + + /* Skip leading space, '+', '-' */ + while (isspace(*str)) + str = CharNextA(str); + + if (*str == '-') + { + negative = TRUE; + str++; + } + else if (*str == '+') + str++; + + if (flags & STIF_SUPPORT_HEX && *str == '0' && tolower(str[1]) == 'x') + { + /* Read hex number */ + str += 2; + + if (!isxdigit(*str)) + return FALSE; + + while (isxdigit(*str)) + { + value *= 16; + if (isdigit(*str)) + value += (*str - '0'); + else + value += 10 + (tolower(*str) - 'a'); + str++; + } + + *ret = value; + return TRUE; + } + + /* Read decimal number */ + if (!isdigit(*str)) + return FALSE; + + while (isdigit(*str)) + { + value *= 10; + value += (*str - '0'); + str++; + } + + *ret = negative ? -value : value; + return TRUE; +} + BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret) { BOOL negative = FALSE; @@ -506,6 +695,18 @@ BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret) return TRUE; }
+BOOL WINAPI StrToIntExA(const char *str, DWORD flags, INT *ret) +{ + LONGLONG value; + BOOL res; + + TRACE("%s, %#x, %p\n", wine_dbgstr_a(str), flags, ret); + + res = StrToInt64ExA(str, flags, &value); + if (res) *ret = value; + return res; +} + BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret) { LONGLONG value; @@ -518,6 +719,21 @@ BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret) return res; }
+int WINAPI StrToIntA(const char *str) +{ + int value = 0; + + TRACE("%s\n", wine_dbgstr_a(str)); + + if (!str) + return 0; + + if (*str == '-' || isdigit(*str)) + StrToIntExA(str, 0, &value); + + return value; +} + int WINAPI StrToIntW(const WCHAR *str) { int value = 0; @@ -817,3 +1033,89 @@ INT WINAPI DECLSPEC_HOTPATCH LoadStringA(HINSTANCE instance, UINT resource_id, L TRACE("returning %s\n", debugstr_a(buffer)); return retval; } + +int WINAPI StrCmpLogicalW(const WCHAR *str, const WCHAR *comp) +{ + TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(comp)); + + if (!str || !comp) + return 0; + + while (*str) + { + if (!*comp) + return 1; + else if (isdigitW(*str)) + { + int str_value, comp_value; + + if (!isdigitW(*comp)) + return -1; + + /* Compare the numbers */ + StrToIntExW(str, 0, &str_value); + StrToIntExW(comp, 0, &comp_value); + + if (str_value < comp_value) + return -1; + else if (str_value > comp_value) + return 1; + + /* Skip */ + while (isdigitW(*str)) + str++; + while (isdigitW(*comp)) + comp++; + } + else if (isdigitW(*comp)) + return 1; + else + { + int diff = ChrCmpIW(*str, *comp); + if (diff > 0) + return 1; + else if (diff < 0) + return -1; + + str++; + comp++; + } + } + + if (*comp) + return -1; + + return 0; +} + +BOOL WINAPI StrIsIntlEqualA(BOOL case_sensitive, const char *str, const char *cmp, int len) +{ + DWORD flags; + + TRACE("%d, %s, %s, %d\n", case_sensitive, wine_dbgstr_a(str), wine_dbgstr_a(cmp), len); + + /* FIXME: This flag is undocumented and unknown by our CompareString. + * We need a define for it. + */ + flags = 0x10000000; + if (!case_sensitive) + flags |= NORM_IGNORECASE; + + return (CompareStringA(GetThreadLocale(), flags, str, len, cmp, len) == CSTR_EQUAL); +} + +BOOL WINAPI StrIsIntlEqualW(BOOL case_sensitive, const WCHAR *str, const WCHAR *cmp, int len) +{ + DWORD flags; + + TRACE("%d, %s, %s, %d\n", case_sensitive, debugstr_w(str), debugstr_w(cmp), len); + + /* FIXME: This flag is undocumented and unknown by our CompareString. + * We need a define for it. + */ + flags = 0x10000000; + if (!case_sensitive) + flags |= NORM_IGNORECASE; + + return (CompareStringW(GetThreadLocale(), flags, str, len, cmp, len) == CSTR_EQUAL); +}
Nikolay Sivov nsivov@codeweavers.com writes:
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
dlls/kernelbase/string.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index 4991ba3fd1..8b3d94a9e6 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -58,52 +58,46 @@ DWORD WINAPI StrCmpNICW(const WCHAR *str, const WCHAR *cmp, DWORD len) return StrCmpNIW(str, cmp, len); }
-BOOL WINAPI IsCharBlankW(WCHAR wc) +static WORD get_char_type(char c) {
- WORD type;
- WORD type = 0;
- GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &type);
- return type;
+}
- return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_BLANK);
+BOOL WINAPI IsCharBlankW(WCHAR wc) +{
- return !!(get_char_typeW(wc) & C1_BLANK);
}
BOOL WINAPI IsCharCntrlW(WCHAR wc) {
- WORD type;
- return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_CNTRL);
- return !!iscntrlW(wc);
Actually I think it would be preferable to continue using Win32 API functions instead of wine/unicode.h ones. The ultimate goal being to store the character tables in a single place instead of having them accessed directly by multiple dlls.
On 5/16/19 9:28 PM, Alexandre Julliard wrote:
Nikolay Sivov nsivov@codeweavers.com writes:
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
dlls/kernelbase/string.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index 4991ba3fd1..8b3d94a9e6 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -58,52 +58,46 @@ DWORD WINAPI StrCmpNICW(const WCHAR *str, const WCHAR *cmp, DWORD len) return StrCmpNIW(str, cmp, len); }
-BOOL WINAPI IsCharBlankW(WCHAR wc) +static WORD get_char_type(char c) {
- WORD type;
- WORD type = 0;
- GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &type);
- return type;
+}
- return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_BLANK);
+BOOL WINAPI IsCharBlankW(WCHAR wc) +{
return !!(get_char_typeW(wc) & C1_BLANK); }
BOOL WINAPI IsCharCntrlW(WCHAR wc) {
- WORD type;
- return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_CNTRL);
- return !!iscntrlW(wc);
Actually I think it would be preferable to continue using Win32 API functions instead of wine/unicode.h ones. The ultimate goal being to store the character tables in a single place instead of having them accessed directly by multiple dlls.
Kernelbase.dll could be that single place in theory, because it exports GetStringTypeW(). I'm not planning to move kernel32 parts though, not right now.
I'll send another variant then.
Nikolay Sivov nsivov@codeweavers.com writes:
On 5/16/19 9:28 PM, Alexandre Julliard wrote:
Nikolay Sivov nsivov@codeweavers.com writes:
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
dlls/kernelbase/string.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-)
diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index 4991ba3fd1..8b3d94a9e6 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -58,52 +58,46 @@ DWORD WINAPI StrCmpNICW(const WCHAR *str, const WCHAR *cmp, DWORD len) return StrCmpNIW(str, cmp, len); } -BOOL WINAPI IsCharBlankW(WCHAR wc) +static WORD get_char_type(char c) {
- WORD type;
- WORD type = 0;
- GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &type);
- return type;
+}
- return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type &
C1_BLANK); +BOOL WINAPI IsCharBlankW(WCHAR wc) +{
- return !!(get_char_typeW(wc) & C1_BLANK); } BOOL WINAPI IsCharCntrlW(WCHAR wc) {
- WORD type;
- return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_CNTRL);
- return !!iscntrlW(wc);
Actually I think it would be preferable to continue using Win32 API functions instead of wine/unicode.h ones. The ultimate goal being to store the character tables in a single place instead of having them accessed directly by multiple dlls.
Kernelbase.dll could be that single place in theory, because it exports GetStringTypeW(). I'm not planning to move kernel32 parts though, not right now.
Yes, we may want to revisit this once kernel32 is implemented on top of kernelbase.