Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910/* * 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 <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/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 lstrlenW (lpSrc);
if (nMaxLen == 0) return 0;
if (lpSrc == NULL) { lpDest[0] = '\0'; return 0; }
len = lstrlenW (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 = lstrlenW (lpSrc) + 1; LPWSTR ptr = ReAlloc (*lppDest, len * sizeof(WCHAR)); if (!ptr) return FALSE; lstrcpyW (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 = lstrlenW(lpszSearch); end = lpszStr + lstrlenW(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 wcstol(lpString, NULL, 10);}
/************************************************************************* * 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 = wcschr(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 + lstrlenW(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 wcsstr( 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 = towupper(ch); while (*lpszStr) { if (towupper(*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 = lstrlenW(lpszSearch);
if (!lpszEnd) lpszEnd = lpszStr + lstrlenW(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 + lstrlenW(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 wcscspn( 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;}