wgl: Move wglGetCurrentDC to gdi32.
[wine/dibdrv.git] / dlls / comctl32 / string.c
blob82bfa5edc56ac1e4f843c88f3f0d36268ac63938
1 /*
2 * String manipulation functions
4 * Copyright 1998 Eric Kohl
5 * 1998 Juergen Schmied <j.schmied@metronet.de>
6 * 2000 Eric Kohl for CodeWeavers
7 * Copyright 2002 Jon Griffiths
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wine/port.h"
28 #include <stdarg.h>
29 #include <string.h>
30 #include <stdlib.h> /* atoi */
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winuser.h"
35 #include "winnls.h"
37 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
43 /*************************************************************************
44 * COMCTL32_ChrCmpHelperA
46 * Internal helper for ChrCmpA/COMCTL32_ChrCmpIA.
48 * NOTES
49 * Both this function and its Unicode counterpart are very inneficient. To
50 * fix this, CompareString must be completely implemented and optimised
51 * first. Then the core character test can be taken out of that function and
52 * placed here, so that it need never be called at all. Until then, do not
53 * attempt to optimise this code unless you are willing to test that it
54 * still performs correctly.
56 static BOOL COMCTL32_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags)
58 char str1[3], str2[3];
60 str1[0] = LOBYTE(ch1);
61 if (IsDBCSLeadByte(str1[0]))
63 str1[1] = HIBYTE(ch1);
64 str1[2] = '\0';
66 else
67 str1[1] = '\0';
69 str2[0] = LOBYTE(ch2);
70 if (IsDBCSLeadByte(str2[0]))
72 str2[1] = HIBYTE(ch2);
73 str2[2] = '\0';
75 else
76 str2[1] = '\0';
78 return CompareStringA(GetThreadLocale(), dwFlags, str1, -1, str2, -1) - 2;
81 /*************************************************************************
82 * COMCTL32_ChrCmpHelperW
84 * Internal helper for COMCTL32_ChrCmpW/ChrCmpIW.
86 static BOOL COMCTL32_ChrCmpHelperW(WCHAR ch1, WCHAR ch2, DWORD dwFlags)
88 WCHAR str1[2], str2[2];
90 str1[0] = ch1;
91 str1[1] = '\0';
92 str2[0] = ch2;
93 str2[1] = '\0';
94 return CompareStringW(GetThreadLocale(), dwFlags, str1, 2, str2, 2) - 2;
97 /*************************************************************************
98 * COMCTL32_ChrCmpA (internal)
100 * Internal helper function.
102 static BOOL COMCTL32_ChrCmpA(WORD ch1, WORD ch2)
104 return COMCTL32_ChrCmpHelperA(ch1, ch2, 0);
107 /*************************************************************************
108 * COMCTL32_ChrCmpIA (internal)
110 * Compare two characters, ignoring case.
112 * PARAMS
113 * ch1 [I] First character to compare
114 * ch2 [I] Second character to compare
116 * RETURNS
117 * FALSE, if the characters are equal.
118 * Non-zero otherwise.
120 static BOOL COMCTL32_ChrCmpIA(WORD ch1, WORD ch2)
122 TRACE("(%d,%d)\n", ch1, ch2);
124 return COMCTL32_ChrCmpHelperA(ch1, ch2, NORM_IGNORECASE);
127 /*************************************************************************
128 * COMCTL32_ChrCmpW
130 * Internal helper function.
132 static BOOL COMCTL32_ChrCmpW(WCHAR ch1, WCHAR ch2)
134 return COMCTL32_ChrCmpHelperW(ch1, ch2, 0);
137 /*************************************************************************
138 * COMCTL32_ChrCmpIW
140 * Internal helper function.
142 static BOOL COMCTL32_ChrCmpIW(WCHAR ch1, WCHAR ch2)
144 return COMCTL32_ChrCmpHelperW(ch1, ch2, NORM_IGNORECASE);
147 /**************************************************************************
148 * StrChrA [COMCTL32.350]
150 * Find a given character in a string.
152 * PARAMS
153 * lpszStr [I] String to search in.
154 * ch [I] Character to search for.
156 * RETURNS
157 * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if
158 * not found.
159 * Failure: NULL, if any arguments are invalid.
161 LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch)
163 TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch);
165 if (lpszStr)
167 while (*lpszStr)
169 if (!COMCTL32_ChrCmpA(*lpszStr, ch))
170 return (LPSTR)lpszStr;
171 lpszStr = CharNextA(lpszStr);
174 return NULL;
177 /**************************************************************************
178 * StrCmpNIA [COMCTL32.353]
180 * Compare two strings, up to a maximum length, ignoring case.
182 * PARAMS
183 * lpszStr [I] First string to compare
184 * lpszComp [I] Second string to compare
185 * iLen [I] Maximum number of chars to compare.
187 * RETURNS
188 * An integer less than, equal to or greater than 0, indicating that
189 * lpszStr is less than, the same, or greater than lpszComp.
191 INT WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
193 INT iRet;
195 TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
197 iRet = CompareStringA(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen);
198 return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
201 /*************************************************************************
202 * StrCmpNIW [COMCTL32.361]
204 * See StrCmpNIA.
206 INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
208 INT iRet;
210 TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen);
212 iRet = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen);
213 return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
216 /*************************************************************************
217 * COMCTL32_StrStrHelperA
219 * Internal implementation of StrStrA/StrStrIA
221 static LPSTR COMCTL32_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch,
222 INT (WINAPI *pStrCmpFn)(LPCSTR,LPCSTR,INT))
224 size_t iLen;
226 if (!lpszStr || !lpszSearch || !*lpszSearch)
227 return NULL;
229 iLen = strlen(lpszSearch);
231 while (*lpszStr)
233 if (!pStrCmpFn(lpszStr, lpszSearch, iLen))
234 return (LPSTR)lpszStr;
235 lpszStr = CharNextA(lpszStr);
237 return NULL;
240 /*************************************************************************
241 * COMCTL32_StrStrHelperW
243 * Internal implementation of StrStrW/StrStrIW
245 static LPWSTR COMCTL32_StrStrHelperW(LPCWSTR lpszStr, LPCWSTR lpszSearch,
246 INT (WINAPI *pStrCmpFn)(LPCWSTR,LPCWSTR,INT))
248 int iLen;
250 if (!lpszStr || !lpszSearch || !*lpszSearch)
251 return NULL;
253 iLen = strlenW(lpszSearch);
255 while (*lpszStr)
257 if (!pStrCmpFn(lpszStr, lpszSearch, iLen))
258 return (LPWSTR)lpszStr;
259 lpszStr = CharNextW(lpszStr);
261 return NULL;
264 /**************************************************************************
265 * StrStrIA [COMCTL32.355]
267 * Find a substring within a string, ignoring case.
269 * PARAMS
270 * lpszStr [I] String to search in
271 * lpszSearch [I] String to look for
273 * RETURNS
274 * The start of lpszSearch within lpszStr, or NULL if not found.
276 LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch)
278 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
280 return COMCTL32_StrStrHelperA(lpszStr, lpszSearch, StrCmpNIA);
283 /**************************************************************************
284 * StrToIntA [COMCTL32.357]
286 * Read a signed integer from a string.
288 * PARAMS
289 * lpszStr [I] String to read integer from
291 * RETURNS
292 * The signed integer value represented by the string, or 0 if no integer is
293 * present.
295 INT WINAPI StrToIntA (LPSTR lpszStr)
297 return atoi(lpszStr);
300 /**************************************************************************
301 * StrStrIW [COMCTL32.363]
303 * See StrStrIA.
305 LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
307 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
309 return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, StrCmpNIW);
312 /**************************************************************************
313 * StrToIntW [COMCTL32.365]
315 * See StrToIntA.
317 INT WINAPI StrToIntW (LPWSTR lpString)
319 return atoiW(lpString);
322 /*************************************************************************
323 * COMCTL32_StrSpnHelperA (internal)
325 * Internal implementation of StrSpnA/StrCSpnA/StrCSpnIA
327 static int COMCTL32_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch,
328 LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD),
329 BOOL bInvert)
331 LPCSTR lpszRead = lpszStr;
332 if (lpszStr && *lpszStr && lpszMatch)
334 while (*lpszRead)
336 LPCSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead);
338 if (!bInvert && !lpszTest)
339 break;
340 if (bInvert && lpszTest)
341 break;
342 lpszRead = CharNextA(lpszRead);
345 return lpszRead - lpszStr;
348 /**************************************************************************
349 * StrCSpnA [COMCTL32.356]
351 * Find the length of the start of a string that does not contain certain
352 * characters.
354 * PARAMS
355 * lpszStr [I] String to search
356 * lpszMatch [I] Characters that cannot be in the substring
358 * RETURNS
359 * The length of the part of lpszStr containing only chars not in lpszMatch,
360 * or 0 if any parameter is invalid.
362 int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch)
364 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
366 return COMCTL32_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, TRUE);
369 /**************************************************************************
370 * StrChrW [COMCTL32.358]
372 * See StrChrA.
374 LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch)
376 LPWSTR lpszRet = NULL;
378 TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch);
380 if (lpszStr)
381 lpszRet = strchrW(lpszStr, ch);
382 return lpszRet;
385 /**************************************************************************
386 * StrCmpNA [COMCTL32.352]
388 * Compare two strings, up to a maximum length.
390 * PARAMS
391 * lpszStr [I] First string to compare
392 * lpszComp [I] Second string to compare
393 * iLen [I] Maximum number of chars to compare.
395 * RETURNS
396 * An integer less than, equal to or greater than 0, indicating that
397 * lpszStr is less than, the same, or greater than lpszComp.
399 INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen)
401 INT iRet;
403 TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
405 iRet = CompareStringA(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen);
406 return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
409 /**************************************************************************
410 * StrCmpNW [COMCTL32.360]
412 * See StrCmpNA.
414 INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
416 INT iRet;
418 TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen);
420 iRet = CompareStringW(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen);
421 return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
424 /**************************************************************************
425 * StrRChrA [COMCTL32.351]
427 * Find the last occurrence of a character in string.
429 * PARAMS
430 * lpszStr [I] String to search in
431 * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
432 * ch [I] Character to search for.
434 * RETURNS
435 * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
436 * or NULL if not found.
437 * Failure: NULL, if any arguments are invalid.
439 LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
441 LPCSTR lpszRet = NULL;
443 TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
445 if (lpszStr)
447 WORD ch2;
449 if (!lpszEnd)
450 lpszEnd = lpszStr + lstrlenA(lpszStr);
452 while (*lpszStr && lpszStr <= lpszEnd)
454 ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr;
456 if (!COMCTL32_ChrCmpA(ch, ch2))
457 lpszRet = lpszStr;
458 lpszStr = CharNextA(lpszStr);
461 return (LPSTR)lpszRet;
465 /**************************************************************************
466 * StrRChrW [COMCTL32.359]
468 * See StrRChrA.
470 LPWSTR WINAPI StrRChrW(LPCWSTR lpszStr, LPCWSTR lpszEnd, WORD ch)
472 LPCWSTR lpszRet = NULL;
474 TRACE("(%s,%s,%x)\n", debugstr_w(lpszStr), debugstr_w(lpszEnd), ch);
476 if (lpszStr)
478 if (!lpszEnd)
479 lpszEnd = lpszStr + strlenW(lpszStr);
481 while (*lpszStr && lpszStr <= lpszEnd)
483 if (!COMCTL32_ChrCmpW(ch, *lpszStr))
484 lpszRet = lpszStr;
485 lpszStr = CharNextW(lpszStr);
488 return (LPWSTR)lpszRet;
491 /**************************************************************************
492 * StrStrA [COMCTL32.354]
494 * Find a substring within a string.
496 * PARAMS
497 * lpszStr [I] String to search in
498 * lpszSearch [I] String to look for
500 * RETURNS
501 * The start of lpszSearch within lpszStr, or NULL if not found.
503 LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch)
505 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
507 return COMCTL32_StrStrHelperA(lpszStr, lpszSearch, StrCmpNA);
510 /**************************************************************************
511 * StrStrW [COMCTL32.362]
513 * See StrStrA.
515 LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
517 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
519 return COMCTL32_StrStrHelperW(lpszStr, lpszSearch, StrCmpNW);
522 /*************************************************************************
523 * StrChrIA [COMCTL32.366]
525 * Find a given character in a string, ignoring case.
527 * PARAMS
528 * lpszStr [I] String to search in.
529 * ch [I] Character to search for.
531 * RETURNS
532 * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if
533 * not found.
534 * Failure: NULL, if any arguments are invalid.
536 LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch)
538 TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch);
540 if (lpszStr)
542 while (*lpszStr)
544 if (!COMCTL32_ChrCmpIA(*lpszStr, ch))
545 return (LPSTR)lpszStr;
546 lpszStr = CharNextA(lpszStr);
549 return NULL;
552 /*************************************************************************
553 * StrChrIW [COMCTL32.367]
555 * See StrChrA.
557 LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch)
559 TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch);
561 if (lpszStr)
563 ch = toupperW(ch);
564 while (*lpszStr)
566 if (toupperW(*lpszStr) == ch)
567 return (LPWSTR)lpszStr;
568 lpszStr = CharNextW(lpszStr);
570 lpszStr = NULL;
572 return (LPWSTR)lpszStr;
575 /*************************************************************************
576 * StrRStrIA [COMCTL32.372]
578 * Find the last occurrence of a substring within a string.
580 * PARAMS
581 * lpszStr [I] String to search in
582 * lpszEnd [I] End of lpszStr
583 * lpszSearch [I] String to look for
585 * RETURNS
586 * The last occurrence lpszSearch within lpszStr, or NULL if not found.
588 LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch)
590 LPSTR lpszRet = NULL;
591 WORD ch1, ch2;
592 INT iLen;
594 TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch));
596 if (!lpszStr || !lpszSearch || !*lpszSearch)
597 return NULL;
599 if (!lpszEnd)
600 lpszEnd = lpszStr + lstrlenA(lpszStr);
602 if (IsDBCSLeadByte(*lpszSearch))
603 ch1 = *lpszSearch << 8 | lpszSearch[1];
604 else
605 ch1 = *lpszSearch;
606 iLen = lstrlenA(lpszSearch);
608 while (lpszStr <= lpszEnd && *lpszStr)
610 ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr;
611 if (!COMCTL32_ChrCmpIA(ch1, ch2))
613 if (!StrCmpNIA(lpszStr, lpszSearch, iLen))
614 lpszRet = (LPSTR)lpszStr;
616 lpszStr = CharNextA(lpszStr);
618 return lpszRet;
621 /*************************************************************************
622 * StrRStrIW [COMCTL32.373]
624 * See StrRStrIA.
626 LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch)
628 LPWSTR lpszRet = NULL;
629 INT iLen;
631 TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
633 if (!lpszStr || !lpszSearch || !*lpszSearch)
634 return NULL;
636 if (!lpszEnd)
637 lpszEnd = lpszStr + strlenW(lpszStr);
639 iLen = strlenW(lpszSearch);
641 while (lpszStr <= lpszEnd && *lpszStr)
643 if (!COMCTL32_ChrCmpIW(*lpszSearch, *lpszStr))
645 if (!StrCmpNIW(lpszStr, lpszSearch, iLen))
646 lpszRet = (LPWSTR)lpszStr;
648 lpszStr = CharNextW(lpszStr);
650 return lpszRet;
653 /*************************************************************************
654 * COMCTL32_StrSpnHelperW
656 * Internal implementation of StrSpnW/StrCSpnW/StrCSpnIW
658 static int COMCTL32_StrSpnHelperW(LPCWSTR lpszStr, LPCWSTR lpszMatch,
659 LPWSTR (WINAPI *pStrChrFn)(LPCWSTR,WCHAR),
660 BOOL bInvert)
662 LPCWSTR lpszRead = lpszStr;
663 if (lpszStr && *lpszStr && lpszMatch)
665 while (*lpszRead)
667 LPCWSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead);
669 if (!bInvert && !lpszTest)
670 break;
671 if (bInvert && lpszTest)
672 break;
673 lpszRead = CharNextW(lpszRead);
676 return lpszRead - lpszStr;
679 /*************************************************************************
680 * StrCSpnIA [COMCTL32.374]
682 * Find the length of the start of a string that does not contain certain
683 * characters, ignoring case.
685 * PARAMS
686 * lpszStr [I] String to search
687 * lpszMatch [I] Characters that cannot be in the substring
689 * RETURNS
690 * The length of the part of lpszStr containing only chars not in lpszMatch,
691 * or 0 if any parameter is invalid.
693 int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch)
695 TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch));
697 return COMCTL32_StrSpnHelperA(lpszStr, lpszMatch, StrChrIA, TRUE);
700 /*************************************************************************
701 * StrCSpnIW [COMCTL32.375]
703 * See StrCSpnIA.
705 int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
707 TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch));
709 return COMCTL32_StrSpnHelperW(lpszStr, lpszMatch, StrChrIW, TRUE);
712 /**************************************************************************
713 * StrRChrIA [COMCTL32.368]
715 * Find the last occurrence of a character in string, ignoring case.
717 * PARAMS
718 * lpszStr [I] String to search in
719 * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr
720 * ch [I] Character to search for.
722 * RETURNS
723 * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd,
724 * or NULL if not found.
725 * Failure: NULL, if any arguments are invalid.
727 LPSTR WINAPI StrRChrIA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch)
729 LPCSTR lpszRet = NULL;
731 TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch);
733 if (lpszStr)
735 WORD ch2;
737 if (!lpszEnd)
738 lpszEnd = lpszStr + lstrlenA(lpszStr);
740 while (*lpszStr && lpszStr <= lpszEnd)
742 ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr;
744 if (ch == ch2)
745 lpszRet = lpszStr;
746 lpszStr = CharNextA(lpszStr);
749 return (LPSTR)lpszRet;
752 /**************************************************************************
753 * StrRChrIW [COMCTL32.369]
755 * See StrRChrIA.
757 LPWSTR WINAPI StrRChrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, WORD ch)
759 LPCWSTR lpszRet = NULL;
761 TRACE("(%s,%s,%x)\n", debugstr_w(lpszStr), debugstr_w(lpszEnd), ch);
763 if (lpszStr)
765 if (!lpszEnd)
766 lpszEnd = lpszStr + strlenW(lpszStr);
768 while (*lpszStr && lpszStr <= lpszEnd)
770 if (ch == *lpszStr)
771 lpszRet = lpszStr;
772 lpszStr = CharNextW(lpszStr);
775 return (LPWSTR)lpszRet;
778 /*************************************************************************
779 * StrCSpnW [COMCTL32.364]
781 * See StrCSpnA.
783 int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch)
785 TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch));
787 return COMCTL32_StrSpnHelperW(lpszStr, lpszMatch, StrChrW, TRUE);
790 /*************************************************************************
791 * IntlStrEqWorkerA [COMCTL32.376]
793 * Compare two strings.
795 * PARAMS
796 * bCase [I] Whether to compare case sensitively
797 * lpszStr [I] First string to compare
798 * lpszComp [I] Second string to compare
799 * iLen [I] Length to compare
801 * RETURNS
802 * TRUE If the strings are equal.
803 * FALSE Otherwise.
805 BOOL WINAPI IntlStrEqWorkerA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp,
806 int iLen)
808 DWORD dwFlags = LOCALE_USE_CP_ACP;
809 int iRet;
811 TRACE("(%d,%s,%s,%d)\n", bCase,
812 debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
814 /* FIXME: These flags are undocumented and unknown by our CompareString.
815 * We need defines for them.
817 dwFlags |= bCase ? 0x10000000 : 0x10000001;
819 iRet = CompareStringA(GetThreadLocale(),
820 dwFlags, lpszStr, iLen, lpszComp, iLen);
822 if (!iRet)
823 iRet = CompareStringA(2048, dwFlags, lpszStr, iLen, lpszComp, iLen);
825 return iRet == 2 ? TRUE : FALSE;
828 /*************************************************************************
829 * IntlStrEqWorkerW [COMCTL32.377]
831 * See IntlStrEqWorkerA.
833 BOOL WINAPI IntlStrEqWorkerW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp,
834 int iLen)
836 DWORD dwFlags;
837 int iRet;
839 TRACE("(%d,%s,%s,%d)\n", bCase,
840 debugstr_w(lpszStr),debugstr_w(lpszComp), iLen);
842 /* FIXME: These flags are undocumented and unknown by our CompareString.
843 * We need defines for them.
845 dwFlags = bCase ? 0x10000000 : 0x10000001;
847 iRet = CompareStringW(GetThreadLocale(),
848 dwFlags, lpszStr, iLen, lpszComp, iLen);
850 if (!iRet)
851 iRet = CompareStringW(2048, dwFlags, lpszStr, iLen, lpszComp, iLen);
853 return iRet == 2 ? TRUE : FALSE;