reactos/dll/win32/comctl32/string.c
2018-04-20 16:27:17 +02:00

914 lines
22 KiB
C

/*
* String manipulation functions
*
* Copyright 1998 Eric Kohl
* 1998 Juergen Schmied <j.schmied@metronet.de>
* 2000 Eric Kohl for CodeWeavers
* Copyright 2002 Jon Griffiths
*
* 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 "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <string.h>
#include <stdlib.h> /* atoi */
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "winnls.h"
#include "comctl32.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
/*************************************************************************
* COMCTL32_ChrCmpHelperA
*
* Internal helper for ChrCmpA/COMCTL32_ChrCmpIA.
*
* NOTES
* Both this function and its Unicode counterpart are very inefficient. To
* fix this, CompareString must be completely implemented and optimised
* first. Then the core character test can be taken out of that function and
* placed here, so that it need never be called at all. Until then, do not
* attempt to optimise this code unless you are willing to test that it
* still performs correctly.
*/
static BOOL COMCTL32_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
{
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(), dwFlags, str1, -1, str2, -1) - CSTR_EQUAL;
}
/*************************************************************************
* COMCTL32_ChrCmpA (internal)
*
* Internal helper function.
*/
static BOOL COMCTL32_ChrCmpA(WORD ch1, WORD ch2)
{
return COMCTL32_ChrCmpHelperA(ch1, ch2, 0);
}
/*************************************************************************
* COMCTL32_ChrCmpIA (internal)
*
* Compare two characters, ignoring case.
*
* PARAMS
* ch1 [I] First character to compare
* ch2 [I] Second character to compare
*
* RETURNS
* FALSE, if the characters are equal.
* Non-zero otherwise.
*/
static BOOL COMCTL32_ChrCmpIA(WORD ch1, WORD ch2)
{
TRACE("(%d,%d)\n", ch1, ch2);
return COMCTL32_ChrCmpHelperA(ch1, ch2, NORM_IGNORECASE);
}
/*************************************************************************
* COMCTL32_ChrCmpIW
*
* Internal helper function.
*/
static inline BOOL COMCTL32_ChrCmpIW(WCHAR ch1, WCHAR ch2)
{
return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, &ch1, 1, &ch2, 1) - CSTR_EQUAL;
}
/**************************************************************************
* Str_GetPtrA [COMCTL32.233]
*
* Copies a string into a destination buffer.
*
* PARAMS
* lpSrc [I] Source string
* lpDest [O] Destination buffer
* nMaxLen [I] Size of buffer in characters
*
* RETURNS
* The number of characters copied.
*/
INT WINAPI Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
{
INT len;
TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
if ((!lpDest || nMaxLen == 0) && lpSrc)
return (strlen(lpSrc) + 1);
if (nMaxLen == 0)
return 0;
if (lpSrc == NULL) {
lpDest[0] = '\0';
return 0;
}
len = strlen(lpSrc) + 1;
if (len >= nMaxLen)
len = nMaxLen;
RtlMoveMemory (lpDest, lpSrc, len - 1);
lpDest[len - 1] = '\0';
return len;
}
/**************************************************************************
* Str_SetPtrA [COMCTL32.234]
*
* Makes a copy of a string, allocating memory if necessary.
*
* PARAMS
* lppDest [O] Pointer to destination string
* lpSrc [I] Source string
*
* RETURNS
* Success: TRUE
* Failure: FALSE
*
* NOTES
* Set lpSrc to NULL to free the memory allocated by a previous call
* to this function.
*/
BOOL WINAPI Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
{
TRACE("(%p %p)\n", lppDest, lpSrc);
if (lpSrc) {
LPSTR ptr = ReAlloc (*lppDest, strlen (lpSrc) + 1);
if (!ptr)
return FALSE;
strcpy (ptr, lpSrc);
*lppDest = ptr;
}
else {
Free (*lppDest);
*lppDest = NULL;
}
return TRUE;
}
/**************************************************************************
* Str_GetPtrW [COMCTL32.235]
*
* See Str_GetPtrA.
*/
INT WINAPI Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
{
INT len;
TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
if (!lpDest && lpSrc)
return strlenW (lpSrc);
if (nMaxLen == 0)
return 0;
if (lpSrc == NULL) {
lpDest[0] = '\0';
return 0;
}
len = strlenW (lpSrc);
if (len >= nMaxLen)
len = nMaxLen - 1;
RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
lpDest[len] = '\0';
return len;
}
/**************************************************************************
* Str_SetPtrW [COMCTL32.236]
*
* See Str_SetPtrA.
*/
BOOL WINAPI Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
{
TRACE("(%p %s)\n", lppDest, debugstr_w(lpSrc));
if (lpSrc) {
INT len = strlenW (lpSrc) + 1;
LPWSTR ptr = ReAlloc (*lppDest, len * sizeof(WCHAR));
if (!ptr)
return FALSE;
strcpyW (ptr, lpSrc);
*lppDest = ptr;
}
else {
Free (*lppDest);
*lppDest = NULL;
}
return TRUE;
}
/**************************************************************************
* StrChrA [COMCTL32.350]
*
* Find a given character in a string.
*
* PARAMS
* lpszStr [I] String to search in.
* ch [I] Character to search for.
*
* RETURNS
* Success: A pointer to the first occurrence of ch in lpszStr, or NULL if
* not found.
* Failure: NULL, if any arguments are invalid.
*/
LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch)
{
TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch);
if (lpszStr)
{
while (*lpszStr)
{
if (!COMCTL32_ChrCmpA(*lpszStr, ch))
return (LPSTR)lpszStr;
lpszStr = CharNextA(lpszStr);
}
}
return NULL;
}
/**************************************************************************
* StrCmpNIA [COMCTL32.353]
*
* Compare two strings, up to a maximum length, ignoring case.
*
* PARAMS
* lpszStr [I] First string to compare
* lpszComp [I] Second string to compare
* iLen [I] Number of chars to compare
*
* RETURNS
* An integer less than, equal to or greater than 0, indicating that
* lpszStr is less than, the same, or greater than lpszComp.
*/
INT WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
{
TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
return CompareStringA(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL;
}
/*************************************************************************
* StrCmpNIW [COMCTL32.361]
*
* See StrCmpNIA.
*/
INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
{
TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen);
return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL;
}
/*************************************************************************
* COMCTL32_StrStrHelperA
*
* Internal implementation of StrStrA/StrStrIA
*/
static LPSTR COMCTL32_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch,
INT (WINAPI *pStrCmpFn)(LPCSTR,LPCSTR,INT))
{
size_t iLen;
LPCSTR end;
if (!lpszStr || !lpszSearch || !*lpszSearch)
return NULL;
iLen = strlen(lpszSearch);
end = lpszStr + strlen(lpszStr);
while (lpszStr + iLen <= end)
{
if (!pStrCmpFn(lpszStr, lpszSearch, iLen))
return (LPSTR)lpszStr;
lpszStr = CharNextA(lpszStr);
}
return NULL;
}
/**************************************************************************
* StrStrIA [COMCTL32.355]
*
* Find a substring within a string, ignoring case.
*
* PARAMS
* lpszStr [I] String to search in
* lpszSearch [I] String to look for
*
* RETURNS
* The start of lpszSearch within lpszStr, or NULL if not found.
*/
LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch)
{
TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
return COMCTL32_StrStrHelperA(lpszStr, lpszSearch, StrCmpNIA);
}
/**************************************************************************
* StrToIntA [COMCTL32.357]
*
* Read a signed integer from a string.
*
* PARAMS
* lpszStr [I] String to read integer from
*
* RETURNS
* The signed integer value represented by the string, or 0 if no integer is
* present.
*/
INT WINAPI StrToIntA (LPCSTR lpszStr)
{
return atoi(lpszStr);
}
/**************************************************************************
* StrStrIW [COMCTL32.363]
*
* See StrStrIA.
*/
LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
{
int iLen;
LPCWSTR end;
TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
if (!lpszStr || !lpszSearch || !*lpszSearch)
return NULL;
iLen = strlenW(lpszSearch);
end = lpszStr + strlenW(lpszStr);
while (lpszStr + iLen <= end)
{
if (!StrCmpNIW(lpszStr, lpszSearch, iLen))
return (LPWSTR)lpszStr;
lpszStr++;
}
return NULL;
}
/**************************************************************************
* StrToIntW [COMCTL32.365]
*
* See StrToIntA.
*/
INT WINAPI StrToIntW (LPCWSTR lpString)
{
return atoiW(lpString);
}
/*************************************************************************
* COMCTL32_StrSpnHelperA (internal)
*
* Internal implementation of StrSpnA/StrCSpnA/StrCSpnIA
*/
static int COMCTL32_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch,
LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD),
BOOL bInvert)
{
LPCSTR lpszRead = lpszStr;
if (lpszStr && *lpszStr && lpszMatch)
{
while (*lpszRead)
{
LPCSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead);
if (!bInvert && !lpszTest)
break;
if (bInvert && lpszTest)
break;
lpszRead = CharNextA(lpszRead);
};
}
return lpszRead - lpszStr;
}
/**************************************************************************
* StrCSpnA [COMCTL32.356]
*
* Find the length of the start of a string that does not contain certain
* characters.
*
* PARAMS
* lpszStr [I] String to search
* lpszMatch [I] Characters that cannot be in the substring
*
* RETURNS
* The length of the part of lpszStr containing only chars not in lpszMatch,
* or 0 if any parameter is invalid.
*/
int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
{
TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
return COMCTL32_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, TRUE);
}
/**************************************************************************
* StrChrW [COMCTL32.358]
*
* See StrChrA.
*/
LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
{
LPWSTR lpszRet = NULL;
TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch);
if (lpszStr)
lpszRet = strchrW(lpszStr, ch);
return lpszRet;
}
/**************************************************************************
* StrCmpNA [COMCTL32.352]
*
* Compare two strings, up to a maximum length.
*
* PARAMS
* lpszStr [I] First string to compare
* lpszComp [I] Second string to compare
* iLen [I] Number of chars to compare
*
* RETURNS
* An integer less than, equal to or greater than 0, indicating that
* lpszStr is less than, the same, or greater than lpszComp.
*/
INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
{
TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
return CompareStringA(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL;
}
/**************************************************************************
* StrCmpNW [COMCTL32.360]
*
* See StrCmpNA.
*/
INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
{
TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen);
return CompareStringW(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL;
}
/**************************************************************************
* StrRChrA [COMCTL32.351]
*
* Find the last occurrence of a character in string.
*
* PARAMS
* lpszStr [I] String to search in
* lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
* ch [I] Character to search for.
*
* RETURNS
* Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
* or NULL if not found.
* Failure: NULL, if any arguments are invalid.
*/
LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
{
LPCSTR lpszRet = NULL;
TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
if (lpszStr)
{
WORD ch2;
if (!lpszEnd)
lpszEnd = lpszStr + lstrlenA(lpszStr);
while (*lpszStr && lpszStr <= lpszEnd)
{
ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr;
if (!COMCTL32_ChrCmpA(ch, ch2))
lpszRet = lpszStr;
lpszStr = CharNextA(lpszStr);
}
}
return (LPSTR)lpszRet;
}
/**************************************************************************
* StrRChrW [COMCTL32.359]
*
* See StrRChrA.
*/
LPWSTR WINAPI StrRChrW(LPCWSTR str, LPCWSTR end, WORD ch)
{
WCHAR *ret = NULL;
if (!str) return NULL;
if (!end) end = str + strlenW(str);
while (str < end)
{
if (*str == ch) ret = (WCHAR *)str;
str++;
}
return ret;
}
/**************************************************************************
* StrStrA [COMCTL32.354]
*
* Find a substring within a string.
*
* PARAMS
* lpszStr [I] String to search in
* lpszSearch [I] String to look for
*
* RETURNS
* The start of lpszSearch within lpszStr, or NULL if not found.
*/
LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch)
{
TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
return COMCTL32_StrStrHelperA(lpszStr, lpszSearch, StrCmpNA);
}
/**************************************************************************
* StrStrW [COMCTL32.362]
*
* See StrStrA.
*/
LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
{
if (!lpszStr || !lpszSearch) return NULL;
return strstrW( lpszStr, lpszSearch );
}
/*************************************************************************
* StrChrIA [COMCTL32.366]
*
* Find a given character in a string, ignoring case.
*
* PARAMS
* lpszStr [I] String to search in.
* ch [I] Character to search for.
*
* RETURNS
* Success: A pointer to the first occurrence of ch in lpszStr, or NULL if
* not found.
* Failure: NULL, if any arguments are invalid.
*/
LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch)
{
TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch);
if (lpszStr)
{
while (*lpszStr)
{
if (!COMCTL32_ChrCmpIA(*lpszStr, ch))
return (LPSTR)lpszStr;
lpszStr = CharNextA(lpszStr);
}
}
return NULL;
}
/*************************************************************************
* StrChrIW [COMCTL32.367]
*
* See StrChrA.
*/
LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch)
{
TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch);
if (lpszStr)
{
ch = toupperW(ch);
while (*lpszStr)
{
if (toupperW(*lpszStr) == ch)
return (LPWSTR)lpszStr;
lpszStr++;
}
lpszStr = NULL;
}
return (LPWSTR)lpszStr;
}
/*************************************************************************
* StrRStrIA [COMCTL32.372]
*
* Find the last occurrence of a substring within a string.
*
* PARAMS
* lpszStr [I] String to search in
* lpszEnd [I] End of lpszStr
* lpszSearch [I] String to look for
*
* RETURNS
* The last occurrence lpszSearch within lpszStr, or NULL if not found.
*/
LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch)
{
LPSTR lpszRet = NULL;
WORD ch1, ch2;
INT iLen;
TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
if (!lpszStr || !lpszSearch || !*lpszSearch)
return NULL;
if (IsDBCSLeadByte(*lpszSearch))
ch1 = *lpszSearch << 8 | (UCHAR)lpszSearch[1];
else
ch1 = *lpszSearch;
iLen = lstrlenA(lpszSearch);
if (!lpszEnd)
lpszEnd = lpszStr + lstrlenA(lpszStr);
else /* reproduce the broken behaviour on Windows */
lpszEnd += min(iLen - 1, lstrlenA(lpszEnd));
while (lpszStr + iLen <= lpszEnd && *lpszStr)
{
ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | (UCHAR)lpszStr[1] : *lpszStr;
if (!COMCTL32_ChrCmpIA(ch1, ch2))
{
if (!StrCmpNIA(lpszStr, lpszSearch, iLen))
lpszRet = (LPSTR)lpszStr;
}
lpszStr = CharNextA(lpszStr);
}
return lpszRet;
}
/*************************************************************************
* StrRStrIW [COMCTL32.373]
*
* See StrRStrIA.
*/
LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch)
{
LPWSTR lpszRet = NULL;
INT iLen;
TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
if (!lpszStr || !lpszSearch || !*lpszSearch)
return NULL;
iLen = strlenW(lpszSearch);
if (!lpszEnd)
lpszEnd = lpszStr + strlenW(lpszStr);
else /* reproduce the broken behaviour on Windows */
lpszEnd += min(iLen - 1, lstrlenW(lpszEnd));
while (lpszStr + iLen <= lpszEnd && *lpszStr)
{
if (!COMCTL32_ChrCmpIW(*lpszSearch, *lpszStr))
{
if (!StrCmpNIW(lpszStr, lpszSearch, iLen))
lpszRet = (LPWSTR)lpszStr;
}
lpszStr++;
}
return lpszRet;
}
/*************************************************************************
* StrCSpnIA [COMCTL32.374]
*
* Find the length of the start of a string that does not contain certain
* characters, ignoring case.
*
* PARAMS
* lpszStr [I] String to search
* lpszMatch [I] Characters that cannot be in the substring
*
* RETURNS
* The length of the part of lpszStr containing only chars not in lpszMatch,
* or 0 if any parameter is invalid.
*/
int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch)
{
TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
return COMCTL32_StrSpnHelperA(lpszStr, lpszMatch, StrChrIA, TRUE);
}
/*************************************************************************
* StrCSpnIW [COMCTL32.375]
*
* See StrCSpnIA.
*/
int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
{
LPCWSTR lpszRead = lpszStr;
TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch));
if (lpszStr && *lpszStr && lpszMatch)
{
while (*lpszRead)
{
if (StrChrIW(lpszMatch, *lpszRead)) break;
lpszRead++;
}
}
return lpszRead - lpszStr;
}
/**************************************************************************
* StrRChrIA [COMCTL32.368]
*
* Find the last occurrence of a character in string, ignoring case.
*
* PARAMS
* lpszStr [I] String to search in
* lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
* ch [I] Character to search for.
*
* RETURNS
* Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
* or NULL if not found.
* Failure: NULL, if any arguments are invalid.
*/
LPSTR WINAPI StrRChrIA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
{
LPCSTR lpszRet = NULL;
TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
if (lpszStr)
{
WORD ch2;
if (!lpszEnd)
lpszEnd = lpszStr + lstrlenA(lpszStr);
while (*lpszStr && lpszStr <= lpszEnd)
{
ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr;
if (ch == ch2)
lpszRet = lpszStr;
lpszStr = CharNextA(lpszStr);
}
}
return (LPSTR)lpszRet;
}
/**************************************************************************
* StrRChrIW [COMCTL32.369]
*
* See StrRChrIA.
*/
LPWSTR WINAPI StrRChrIW(LPCWSTR str, LPCWSTR end, WORD ch)
{
WCHAR *ret = NULL;
if (!str) return NULL;
if (!end) end = str + strlenW(str);
while (str < end)
{
if (!COMCTL32_ChrCmpIW(*str, ch)) ret = (WCHAR *)str;
str++;
}
return ret;
}
/*************************************************************************
* StrCSpnW [COMCTL32.364]
*
* See StrCSpnA.
*/
int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
{
if (!lpszStr || !lpszMatch) return 0;
return strcspnW( lpszStr, lpszMatch );
}
/*************************************************************************
* IntlStrEqWorkerA [COMCTL32.376]
*
* Compare two strings.
*
* PARAMS
* bCase [I] Whether to compare case sensitively
* lpszStr [I] First string to compare
* lpszComp [I] Second string to compare
* iLen [I] Length to compare
*
* RETURNS
* TRUE If the strings are equal.
* FALSE Otherwise.
*/
BOOL WINAPI IntlStrEqWorkerA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp,
int iLen)
{
DWORD dwFlags;
int iRet;
TRACE("(%d,%s,%s,%d)\n", bCase,
debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
/* FIXME: This flag is undocumented and unknown by our CompareString.
*/
dwFlags = LOCALE_RETURN_GENITIVE_NAMES;
if (!bCase) dwFlags |= NORM_IGNORECASE;
iRet = CompareStringA(GetThreadLocale(),
dwFlags, lpszStr, iLen, lpszComp, iLen);
if (!iRet)
iRet = CompareStringA(2048, dwFlags, lpszStr, iLen, lpszComp, iLen);
return iRet == CSTR_EQUAL;
}
/*************************************************************************
* IntlStrEqWorkerW [COMCTL32.377]
*
* See IntlStrEqWorkerA.
*/
BOOL WINAPI IntlStrEqWorkerW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp,
int iLen)
{
DWORD dwFlags;
int iRet;
TRACE("(%d,%s,%s,%d)\n", bCase,
debugstr_w(lpszStr),debugstr_w(lpszComp), iLen);
/* FIXME: This flag is undocumented and unknown by our CompareString.
*/
dwFlags = LOCALE_RETURN_GENITIVE_NAMES;
if (!bCase) dwFlags |= NORM_IGNORECASE;
iRet = CompareStringW(GetThreadLocale(),
dwFlags, lpszStr, iLen, lpszComp, iLen);
if (!iRet)
iRet = CompareStringW(2048, dwFlags, lpszStr, iLen, lpszComp, iLen);
return iRet == CSTR_EQUAL;
}