Yet another attempt at fixing CW_USEDEFAULT handling.
[wine.git] / dlls / crtdll / wcstring.c
blob0b677c9fdd236c3d019663b0bf130549c9256b47
1 /*
2 * CRTDLL wide-char functions
4 * Copyright 1999 Alexandre Julliard
6 * TODO:
7 * These functions are really necessary only if sizeof(WCHAR) != sizeof(wchar_t),
8 * otherwise we could use the libc functions directly.
9 */
11 #include "config.h"
13 #include <ctype.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #ifdef HAVE_WCTYPE_H
17 #include <wctype.h>
18 #endif
20 #include "windef.h"
21 #include "crtdll.h"
22 #include "debugtools.h"
24 DEFAULT_DEBUG_CHANNEL(crtdll);
26 /*********************************************************************
27 * CRTDLL__wcsdup (CRTDLL.320)
29 LPWSTR __cdecl CRTDLL__wcsdup( LPCWSTR str )
31 LPWSTR ret = NULL;
32 if (str)
34 int size = (CRTDLL_wcslen(str) + 1) * sizeof(WCHAR);
35 ret = CRTDLL_malloc( size );
36 if (ret) memcpy( ret, str, size );
38 return ret;
42 /*********************************************************************
43 * CRTDLL__wcsicmp (CRTDLL.321)
45 INT __cdecl CRTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
47 while (*str1 && (CRTDLL_towupper(*str1) == CRTDLL_towupper(*str2)))
49 str1++;
50 str2++;
52 return CRTDLL_towupper(*str1) - CRTDLL_towupper(*str2);
56 /*********************************************************************
57 * CRTDLL__wcsicoll (CRTDLL.322)
59 INT __cdecl CRTDLL__wcsicoll( LPCWSTR str1, LPCWSTR str2 )
61 /* FIXME: handle collates */
62 return CRTDLL__wcsicmp( str1, str2 );
66 /*********************************************************************
67 * CRTDLL__wcslwr (CRTDLL.323)
69 LPWSTR __cdecl CRTDLL__wcslwr( LPWSTR str )
71 LPWSTR ret = str;
72 for ( ; *str; str++) *str = CRTDLL_towlower(*str);
73 return ret;
77 /*********************************************************************
78 * CRTDLL__wcsnicmp (CRTDLL.324)
80 INT __cdecl CRTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
82 if (!n) return 0;
83 while ((--n > 0) && *str1 && (CRTDLL_towupper(*str1) == CRTDLL_towupper(*str2)))
85 str1++;
86 str2++;
88 return CRTDLL_towupper(*str1) - CRTDLL_towupper(*str2);
92 /*********************************************************************
93 * CRTDLL__wcsnset (CRTDLL.325)
95 LPWSTR __cdecl CRTDLL__wcsnset( LPWSTR str, WCHAR c, INT n )
97 LPWSTR ret = str;
98 while ((n-- > 0) && *str) *str++ = c;
99 return ret;
103 /*********************************************************************
104 * CRTDLL__wcsrev (CRTDLL.326)
106 LPWSTR __cdecl CRTDLL__wcsrev( LPWSTR str )
108 LPWSTR ret = str;
109 LPWSTR end = str + CRTDLL_wcslen(str) - 1;
110 while (end > str)
112 WCHAR t = *end;
113 *end-- = *str;
114 *str++ = t;
116 return ret;
120 /*********************************************************************
121 * CRTDLL__wcsset (CRTDLL.327)
123 LPWSTR __cdecl CRTDLL__wcsset( LPWSTR str, WCHAR c )
125 LPWSTR ret = str;
126 while (*str) *str++ = c;
127 return ret;
131 /*********************************************************************
132 * CRTDLL__wcsupr (CRTDLL.328)
134 LPWSTR __cdecl CRTDLL__wcsupr( LPWSTR str )
136 LPWSTR ret = str;
137 for ( ; *str; str++) *str = CRTDLL_towupper(*str);
138 return ret;
142 /*********************************************************************
143 * CRTDLL_towlower (CRTDLL.493)
145 WCHAR __cdecl CRTDLL_towlower( WCHAR ch )
147 #ifdef HAVE_WCTYPE_H
148 ch = (WCHAR)towlower( (wchar_t)ch );
149 #else
150 if (!HIBYTE(ch)) ch = (WCHAR)tolower( LOBYTE(ch) ); /* FIXME */
151 #endif
152 return ch;
156 /*********************************************************************
157 * CRTDLL_towupper (CRTDLL.494)
159 WCHAR __cdecl CRTDLL_towupper( WCHAR ch )
161 #ifdef HAVE_WCTYPE_H
162 ch = (WCHAR)towupper( (wchar_t)ch );
163 #else
164 if (!HIBYTE(ch)) ch = (WCHAR)toupper( LOBYTE(ch) ); /* FIXME */
165 #endif
166 return ch;
170 /***********************************************************************
171 * CRTDLL_wcscat (CRTDLL.503)
173 LPWSTR __cdecl CRTDLL_wcscat( LPWSTR dst, LPCWSTR src )
175 LPWSTR p = dst;
176 while (*p) p++;
177 while ((*p++ = *src++));
178 return dst;
182 /*********************************************************************
183 * CRTDLL_wcschr (CRTDLL.504)
185 LPWSTR __cdecl CRTDLL_wcschr( LPCWSTR str, WCHAR ch )
187 while (*str)
189 if (*str == ch) return (LPWSTR)str;
190 str++;
192 return NULL;
196 /*********************************************************************
197 * CRTDLL_wcscmp (CRTDLL.505)
199 INT __cdecl CRTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
201 while (*str1 && (*str1 == *str2)) { str1++; str2++; }
202 return (INT)(*str1 - *str2);
206 /*********************************************************************
207 * CRTDLL_wcscoll (CRTDLL.506)
209 DWORD __cdecl CRTDLL_wcscoll( LPCWSTR str1, LPCWSTR str2 )
211 /* FIXME: handle collates */
212 return CRTDLL_wcscmp( str1, str2 );
216 /***********************************************************************
217 * CRTDLL_wcscpy (CRTDLL.507)
219 LPWSTR __cdecl CRTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
221 LPWSTR p = dst;
222 while ((*p++ = *src++));
223 return dst;
227 /*********************************************************************
228 * CRTDLL_wcscspn (CRTDLL.508)
230 INT __cdecl CRTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
232 LPCWSTR start = str;
233 while (*str)
235 LPCWSTR p = reject;
236 while (*p && (*p != *str)) p++;
237 if (*p) break;
238 str++;
240 return str - start;
244 /***********************************************************************
245 * CRTDLL_wcslen (CRTDLL.510)
247 INT __cdecl CRTDLL_wcslen( LPCWSTR str )
249 LPCWSTR s = str;
250 while (*s) s++;
251 return s - str;
255 /*********************************************************************
256 * CRTDLL_wcsncat (CRTDLL.511)
258 LPWSTR __cdecl CRTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
260 LPWSTR ret = s1;
261 while (*s1) s1++;
262 while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
263 *s1 = 0;
264 return ret;
268 /*********************************************************************
269 * CRTDLL_wcsncmp (CRTDLL.512)
271 INT __cdecl CRTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
273 if (!n) return 0;
274 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
275 return (INT)(*str1 - *str2);
279 /*********************************************************************
280 * CRTDLL_wcsncpy (CRTDLL.513)
282 LPWSTR __cdecl CRTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
284 LPWSTR ret = s1;
285 while (n-- > 0) if (!(*s1++ = *s2++)) break;
286 while (n-- > 0) *s1++ = 0;
287 return ret;
291 /*********************************************************************
292 * CRTDLL_wcspbrk (CRTDLL.514)
294 LPWSTR __cdecl CRTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
296 LPCWSTR p;
297 while (*str)
299 for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
300 str++;
302 return NULL;
306 /*********************************************************************
307 * CRTDLL_wcsrchr (CRTDLL.515)
309 LPWSTR __cdecl CRTDLL_wcsrchr( LPWSTR str, WCHAR ch )
311 LPWSTR last = NULL;
312 while (*str)
314 if (*str == ch) last = str;
315 str++;
317 return last;
321 /*********************************************************************
322 * CRTDLL_wcsspn (CRTDLL.516)
324 INT __cdecl CRTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
326 LPCWSTR start = str;
327 while (*str)
329 LPCWSTR p = accept;
330 while (*p && (*p != *str)) p++;
331 if (!*p) break;
332 str++;
334 return str - start;
338 /*********************************************************************
339 * CRTDLL_wcsstr (CRTDLL.517)
341 LPWSTR __cdecl CRTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
343 while (*str)
345 LPCWSTR p1 = str, p2 = sub;
346 while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
347 if (!*p2) return (LPWSTR)str;
348 str++;
350 return NULL;
354 /*********************************************************************
355 * CRTDLL_wcstok (CRTDLL.519)
357 LPWSTR __cdecl CRTDLL_wcstok( LPWSTR str, LPCWSTR delim )
359 static LPWSTR next = NULL;
360 LPWSTR ret;
362 if (!str)
363 if (!(str = next)) return NULL;
365 while (*str && CRTDLL_wcschr( delim, *str )) str++;
366 if (!*str) return NULL;
367 ret = str++;
368 while (*str && !CRTDLL_wcschr( delim, *str )) str++;
369 if (*str) *str++ = 0;
370 next = str;
371 return ret;
375 /*********************************************************************
376 * CRTDLL_wcstombs (CRTDLL.521)
378 * FIXME: the reason I do not use wcstombs is that it seems to fail
379 * for any latin-1 valid character. Not good.
381 INT __cdecl CRTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
383 int copied=0;
384 while ((n>0) && *src) {
385 int ret;
386 /* FIXME: could potentially overflow if we ever have MB of 2 bytes*/
387 ret = wctomb(dst,(wchar_t)*src);
388 if (ret<0) {
389 /* FIXME: sadly, some versions of glibc do not like latin characters
390 * as UNICODE chars for some reason (like german umlauts). Just
391 * copy those anyway. MM 991106
393 *dst=*src;
394 ret = 1;
396 dst += ret;
397 n -= ret;
398 copied += ret;
399 src++;
401 return copied;
404 /*********************************************************************
405 * CRTDLL_wctomb (CRTDLL.524)
407 INT __cdecl CRTDLL_wctomb( LPSTR dst, WCHAR ch )
409 return wctomb( dst, (wchar_t)ch );
412 /*********************************************************************
413 * CRTDLL_iswalnum (CRTDLL.405)
415 INT __cdecl CRTDLL_iswalnum( WCHAR wc )
417 #ifdef HAVE_WCTYPE_H
418 #undef iswalnum
419 return iswalnum(wc);
420 #else
421 return isalnum( LOBYTE(wc) ); /* FIXME */
422 #endif
425 /*********************************************************************
426 * CRTDLL_iswalpha (CRTDLL.406)
428 INT __cdecl CRTDLL_iswalpha( WCHAR wc )
430 #ifdef HAVE_WCTYPE_H
431 #undef iswalpha
432 return iswalpha(wc);
433 #else
434 return isalpha( LOBYTE(wc) ); /* FIXME */
435 #endif
438 /*********************************************************************
439 * CRTDLL_iswcntrl (CRTDLL.408)
441 INT __cdecl CRTDLL_iswcntrl( WCHAR wc )
443 #ifdef HAVE_WCTYPE_H
444 #undef iswcntrl
445 return iswcntrl(wc);
446 #else
447 return iscntrl( LOBYTE(wc) ); /* FIXME */
448 #endif
451 /*********************************************************************
452 * CRTDLL_iswdigit (CRTDLL.410)
454 INT __cdecl CRTDLL_iswdigit( WCHAR wc )
456 #ifdef HAVE_WCTYPE_H
457 #undef iswdigit
458 return iswdigit(wc);
459 #else
460 return isdigit( LOBYTE(wc) ); /* FIXME */
461 #endif
464 /*********************************************************************
465 * CRTDLL_iswgraph (CRTDLL.411)
467 INT __cdecl CRTDLL_iswgraph( WCHAR wc )
469 #ifdef HAVE_WCTYPE_H
470 #undef iswgraph
471 return iswgraph(wc);
472 #else
473 return isgraph( LOBYTE(wc) ); /* FIXME */
474 #endif
477 /*********************************************************************
478 * CRTDLL_iswlower (CRTDLL.412)
480 INT __cdecl CRTDLL_iswlower( WCHAR wc )
482 #ifdef HAVE_WCTYPE_H
483 #undef iswlower
484 return iswlower(wc);
485 #else
486 return islower( LOBYTE(wc) ); /* FIXME */
487 #endif
490 /*********************************************************************
491 * CRTDLL_iswprint (CRTDLL.413)
493 INT __cdecl CRTDLL_iswprint( WCHAR wc )
495 #ifdef HAVE_WCTYPE_H
496 #undef iswprint
497 return iswprint(wc);
498 #else
499 return isprint( LOBYTE(wc) ); /* FIXME */
500 #endif
503 /*********************************************************************
504 * CRTDLL_iswpunct (CRTDLL.414)
506 INT __cdecl CRTDLL_iswpunct( WCHAR wc )
508 #ifdef HAVE_WCTYPE_H
509 #undef iswpunct
510 return iswpunct(wc);
511 #else
512 return ispunct( LOBYTE(wc) ); /* FIXME */
513 #endif
516 /*********************************************************************
517 * CRTDLL_iswspace (CRTDLL.415)
519 INT __cdecl CRTDLL_iswspace( WCHAR wc )
521 #ifdef HAVE_WCTYPE_H
522 #undef iswspace
523 return iswspace(wc);
524 #else
525 return isspace( LOBYTE(wc) ); /* FIXME */
526 #endif
529 /*********************************************************************
530 * CRTDLL_iswupper (CRTDLL.416)
532 INT __cdecl CRTDLL_iswupper( WCHAR wc )
534 #ifdef HAVE_WCTYPE_H
535 #undef iswupper
536 return iswupper(wc);
537 #else
538 return isupper( LOBYTE(wc) ); /* FIXME */
539 #endif
542 /*********************************************************************
543 * CRTDLL_iswxdigit (CRTDLL.417)
545 INT __cdecl CRTDLL_iswxdigit( WCHAR wc )
547 #ifdef HAVE_WCTYPE_H
548 #undef iswxdigit
549 return iswxdigit(wc);
550 #else
551 return isxdigit( LOBYTE(wc) ); /* FIXME */
552 #endif
555 /*********************************************************************
556 * CRTDLL_iswctype (CRTDLL.409)
558 INT __cdecl CRTDLL_iswctype( WCHAR wc, WCHAR wct )
560 INT res = 0;
562 if (wct & 0x0001) res |= CRTDLL_iswupper(wc);
563 if (wct & 0x0002) res |= CRTDLL_iswlower(wc);
564 if (wct & 0x0004) res |= CRTDLL_iswdigit(wc);
565 if (wct & 0x0008) res |= CRTDLL_iswspace(wc);
566 if (wct & 0x0010) res |= CRTDLL_iswpunct(wc);
567 if (wct & 0x0020) res |= CRTDLL_iswcntrl(wc);
568 if (wct & 0x0080) res |= CRTDLL_iswxdigit(wc);
569 if (wct & 0x0100) res |= CRTDLL_iswalpha(wc);
570 if (wct & 0x0040)
571 FIXME(": iswctype(%04hx,_BLANK|...) requested\n",wc);
572 if (wct & 0x8000)
573 FIXME(": iswctype(%04hx,_LEADBYTE|...) requested\n",wc);
574 return res;