Corel merge:
[wine] / dlls / crtdll / wcstring.c
1 /*
2  * CRTDLL wide-char functions
3  *
4  * Copyright 1999 Alexandre Julliard
5  *
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  */
10
11 #include "config.h"
12
13 #include <ctype.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #ifdef HAVE_WCTYPE_H
17 #include <wctype.h>
18 #endif
19
20 #include "windef.h"
21 #include "crtdll.h"
22 #include "debugtools.h"
23
24 DEFAULT_DEBUG_CHANNEL(crtdll);
25
26 /*********************************************************************
27  *           CRTDLL__wcsdup    (CRTDLL.320)
28  */
29 LPWSTR __cdecl CRTDLL__wcsdup( LPCWSTR str )
30 {
31     LPWSTR ret = NULL;
32     if (str)
33     {
34         int size = (CRTDLL_wcslen(str) + 1) * sizeof(WCHAR);
35         ret = CRTDLL_malloc( size );
36         if (ret) memcpy( ret, str, size );
37     }
38     return ret;
39 }
40
41
42 /*********************************************************************
43  *           CRTDLL__wcsicmp    (CRTDLL.321)
44  */
45 INT __cdecl CRTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
46 {
47     while (*str1 && (CRTDLL_towupper(*str1) == CRTDLL_towupper(*str2)))
48     {
49         str1++;
50         str2++;
51     }
52     return CRTDLL_towupper(*str1) - CRTDLL_towupper(*str2);
53 }
54
55
56 /*********************************************************************
57  *           CRTDLL__wcsicoll    (CRTDLL.322)
58  */
59 INT __cdecl CRTDLL__wcsicoll( LPCWSTR str1, LPCWSTR str2 )
60 {
61     /* FIXME: handle collates */
62     return CRTDLL__wcsicmp( str1, str2 );
63 }
64
65
66 /*********************************************************************
67  *           CRTDLL__wcslwr    (CRTDLL.323)
68  */
69 LPWSTR __cdecl CRTDLL__wcslwr( LPWSTR str )
70 {
71     LPWSTR ret = str;
72     for ( ; *str; str++) *str = CRTDLL_towlower(*str);
73     return ret;
74 }
75
76
77 /*********************************************************************
78  *           CRTDLL__wcsnicmp    (CRTDLL.324)
79  */
80 INT __cdecl CRTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
81 {
82     if (!n) return 0;
83     while ((--n > 0) && *str1 && (CRTDLL_towupper(*str1) == CRTDLL_towupper(*str2)))
84     {
85         str1++;
86         str2++;
87     }
88     return CRTDLL_towupper(*str1) - CRTDLL_towupper(*str2);
89 }
90
91
92 /*********************************************************************
93  *           CRTDLL__wcsnset    (CRTDLL.325)
94  */
95 LPWSTR __cdecl CRTDLL__wcsnset( LPWSTR str, WCHAR c, INT n )
96 {
97     LPWSTR ret = str;
98     while ((n-- > 0) && *str) *str++ = c;
99     return ret;
100 }
101
102
103 /*********************************************************************
104  *           CRTDLL__wcsrev    (CRTDLL.326)
105  */
106 LPWSTR __cdecl CRTDLL__wcsrev( LPWSTR str )
107 {
108     LPWSTR ret = str;
109     LPWSTR end = str + CRTDLL_wcslen(str) - 1;
110     while (end > str)
111     {
112         WCHAR t = *end;
113         *end--  = *str;
114         *str++  = t;
115     }
116     return ret;
117 }
118
119
120 /*********************************************************************
121  *           CRTDLL__wcsset    (CRTDLL.327)
122  */
123 LPWSTR __cdecl CRTDLL__wcsset( LPWSTR str, WCHAR c )
124 {
125     LPWSTR ret = str;
126     while (*str) *str++ = c;
127     return ret;
128 }
129
130
131 /*********************************************************************
132  *           CRTDLL__wcsupr    (CRTDLL.328)
133  */
134 LPWSTR __cdecl CRTDLL__wcsupr( LPWSTR str )
135 {
136     LPWSTR ret = str;
137     for ( ; *str; str++) *str = CRTDLL_towupper(*str);
138     return ret;
139 }
140
141
142 /*********************************************************************
143  *           CRTDLL_towlower    (CRTDLL.493)
144  */
145 WCHAR __cdecl CRTDLL_towlower( WCHAR ch )
146 {
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;
153 }
154
155
156 /*********************************************************************
157  *           CRTDLL_towupper    (CRTDLL.494)
158  */
159 WCHAR __cdecl CRTDLL_towupper( WCHAR ch )
160 {
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;
167 }
168
169
170 /***********************************************************************
171  *           CRTDLL_wcscat    (CRTDLL.503)
172  */
173 LPWSTR __cdecl CRTDLL_wcscat( LPWSTR dst, LPCWSTR src )
174 {
175     LPWSTR p = dst;
176     while (*p) p++;
177     while ((*p++ = *src++));
178     return dst;
179 }
180
181
182 /*********************************************************************
183  *           CRTDLL_wcschr    (CRTDLL.504)
184  */
185 LPWSTR __cdecl CRTDLL_wcschr( LPCWSTR str, WCHAR ch )
186 {
187     while (*str)
188     {
189         if (*str == ch) return (LPWSTR)str;
190         str++;
191     }
192     return NULL;
193 }
194
195
196 /*********************************************************************
197  *           CRTDLL_wcscmp    (CRTDLL.505)
198  */
199 INT __cdecl CRTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
200 {
201     while (*str1 && (*str1 == *str2)) { str1++; str2++; }
202     return (INT)(*str1 - *str2);
203 }
204
205
206 /*********************************************************************
207  *           CRTDLL_wcscoll    (CRTDLL.506)
208  */
209 DWORD __cdecl CRTDLL_wcscoll( LPCWSTR str1, LPCWSTR str2 )
210 {
211     /* FIXME: handle collates */
212     return CRTDLL_wcscmp( str1, str2 );
213 }
214
215
216 /***********************************************************************
217  *           CRTDLL_wcscpy    (CRTDLL.507)
218  */
219 LPWSTR __cdecl CRTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
220 {
221     LPWSTR p = dst;
222     while ((*p++ = *src++));
223     return dst;
224 }
225
226
227 /*********************************************************************
228  *           CRTDLL_wcscspn    (CRTDLL.508)
229  */
230 INT __cdecl CRTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
231 {
232     LPCWSTR start = str;
233     while (*str)
234     {
235         LPCWSTR p = reject;
236         while (*p && (*p != *str)) p++;
237         if (*p) break;
238         str++;
239     }
240     return str - start;
241 }
242
243
244 /***********************************************************************
245  *           CRTDLL_wcslen    (CRTDLL.510)
246  */
247 INT __cdecl CRTDLL_wcslen( LPCWSTR str )
248 {
249     LPCWSTR s = str;
250     while (*s) s++;
251     return s - str;
252 }
253
254
255 /*********************************************************************
256  *           CRTDLL_wcsncat    (CRTDLL.511)
257  */
258 LPWSTR __cdecl CRTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
259 {
260     LPWSTR ret = s1;
261     while (*s1) s1++;
262     while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
263     *s1 = 0;
264     return ret;
265 }
266
267
268 /*********************************************************************
269  *           CRTDLL_wcsncmp    (CRTDLL.512)
270  */
271 INT __cdecl CRTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
272 {
273     if (!n) return 0;
274     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
275     return (INT)(*str1 - *str2);
276 }
277
278
279 /*********************************************************************
280  *           CRTDLL_wcsncpy    (CRTDLL.513)
281  */
282 LPWSTR __cdecl CRTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
283 {
284     LPWSTR ret = s1;
285     while (n-- > 0) if (!(*s1++ = *s2++)) break;
286     while (n-- > 0) *s1++ = 0;
287     return ret;
288 }
289
290
291 /*********************************************************************
292  *           CRTDLL_wcspbrk    (CRTDLL.514)
293  */
294 LPWSTR __cdecl CRTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
295 {
296     LPCWSTR p;
297     while (*str)
298     {
299         for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
300         str++;
301     }
302     return NULL;
303 }
304
305
306 /*********************************************************************
307  *           CRTDLL_wcsrchr    (CRTDLL.515)
308  */
309 LPWSTR __cdecl CRTDLL_wcsrchr( LPWSTR str, WCHAR ch )
310 {
311     LPWSTR last = NULL;
312     while (*str)
313     {
314         if (*str == ch) last = str;
315         str++;
316     }
317     return last;
318 }
319
320
321 /*********************************************************************
322  *           CRTDLL_wcsspn    (CRTDLL.516)
323  */
324 INT __cdecl CRTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
325 {
326     LPCWSTR start = str;
327     while (*str)
328     {
329         LPCWSTR p = accept;
330         while (*p && (*p != *str)) p++;
331         if (!*p) break;
332         str++;
333     }
334     return str - start;
335 }
336
337
338 /*********************************************************************
339  *           CRTDLL_wcsstr    (CRTDLL.517)
340  */
341 LPWSTR __cdecl CRTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
342 {
343     while (*str)
344     {
345         LPCWSTR p1 = str, p2 = sub;
346         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
347         if (!*p2) return (LPWSTR)str;
348         str++;
349     }
350     return NULL;
351 }
352
353
354 /*********************************************************************
355  *           CRTDLL_wcstok    (CRTDLL.519)
356  */
357 LPWSTR __cdecl CRTDLL_wcstok( LPWSTR str, LPCWSTR delim )
358 {
359     static LPWSTR next = NULL;
360     LPWSTR ret;
361
362     if (!str)
363         if (!(str = next)) return NULL;
364
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;
372 }
373
374
375 /*********************************************************************
376  *           CRTDLL_wcstombs    (CRTDLL.521)
377  *
378  * FIXME: the reason I do not use wcstombs is that it seems to fail
379  *        for any latin-1 valid character. Not good.
380  */
381 INT __cdecl CRTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
382 {
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
392              */
393             *dst=*src;
394             ret = 1;
395         }
396         dst     += ret;
397         n       -= ret;
398         copied  += ret;
399         src++;
400     }
401     return copied;
402 }
403
404 /*********************************************************************
405  *           CRTDLL_wctomb    (CRTDLL.524)
406  */
407 INT __cdecl CRTDLL_wctomb( LPSTR dst, WCHAR ch )
408 {
409     return wctomb( dst, (wchar_t)ch );
410 }
411
412 /*********************************************************************
413  *           CRTDLL_iswalnum    (CRTDLL.405)
414  */
415 int CRTDLL_iswalnum( WCHAR wc )
416 {
417 #ifdef HAVE_WCTYPE_H
418 #undef iswalnum
419     return iswalnum(wc);
420 #else
421     return isalnum( LOBYTE(wc) );  /* FIXME */
422 #endif
423 }
424
425 /*********************************************************************
426  *           CRTDLL_iswalpha    (CRTDLL.406)
427  */
428 int CRTDLL_iswalpha( WCHAR wc )
429 {
430 #ifdef HAVE_WCTYPE_H
431 #undef iswalpha
432     return iswalpha(wc);
433 #else
434     return isalpha( LOBYTE(wc) );  /* FIXME */
435 #endif
436 }
437
438 /*********************************************************************
439  *           CRTDLL_iswcntrl    (CRTDLL.408)
440  */
441 int CRTDLL_iswcntrl( WCHAR wc )
442 {
443 #ifdef HAVE_WCTYPE_H
444 #undef iswcntrl
445     return iswcntrl(wc);
446 #else
447     return iscntrl( LOBYTE(wc) );  /* FIXME */
448 #endif
449 }
450
451 /*********************************************************************
452  *           CRTDLL_iswctype    (CRTDLL.409)
453  */
454 int CRTDLL_iswctype( WCHAR wc, WCHAR wct )
455 {
456 #ifdef HAVE_WCTYPE_H
457     wctype_t mask = 0;
458
459     if (wct & 0x0001)   mask |= _ISwupper;
460     if (wct & 0x0002)   mask |= _ISwlower;
461     if (wct & 0x0004)   mask |= _ISwdigit;
462     if (wct & 0x0008)   mask |= _ISwspace;
463     if (wct & 0x0010)   mask |= _ISwpunct;
464     if (wct & 0x0020)   mask |= _ISwcntrl;
465     if (wct & 0x0040)   mask |= _ISwblank;
466     if (wct & 0x0080)   mask |= _ISwxdigit;
467     if (wct & 0x0100)   mask |= _ISwalpha;
468     if (wct & 0x8000)
469         FIXME(": iswctype(%04hx,_LEADBYTE|...) requested\n",wc);
470
471 #undef iswctype
472     return iswctype(wc,mask);
473 #else
474     FIXME(":iswctype() not supported\n");
475     return 0;
476 #endif
477 }
478
479 /*********************************************************************
480  *           CRTDLL_iswdigit    (CRTDLL.410)
481  */
482 int CRTDLL_iswdigit( WCHAR wc )
483 {
484 #ifdef HAVE_WCTYPE_H
485 #undef iswdigit
486     return iswdigit(wc);
487 #else
488     return isdigit( LOBYTE(wc) );  /* FIXME */
489 #endif
490 }
491
492 /*********************************************************************
493  *           CRTDLL_iswgraph    (CRTDLL.411)
494  */
495 int CRTDLL_iswgraph( WCHAR wc )
496 {
497 #ifdef HAVE_WCTYPE_H
498 #undef iswgraph
499     return iswgraph(wc);
500 #else
501     return isgraph( LOBYTE(wc) );  /* FIXME */
502 #endif
503 }
504
505 /*********************************************************************
506  *           CRTDLL_iswlower    (CRTDLL.412)
507  */
508 int CRTDLL_iswlower( WCHAR wc )
509 {
510 #ifdef HAVE_WCTYPE_H
511 #undef iswlower
512     return iswlower(wc);
513 #else
514     return islower( LOBYTE(wc) );  /* FIXME */
515 #endif
516 }
517
518 /*********************************************************************
519  *           CRTDLL_iswprint    (CRTDLL.413)
520  */
521 int CRTDLL_iswprint( WCHAR wc )
522 {
523 #ifdef HAVE_WCTYPE_H
524 #undef iswprint
525     return iswprint(wc);
526 #else
527     return isprint( LOBYTE(wc) );  /* FIXME */
528 #endif
529 }
530
531 /*********************************************************************
532  *           CRTDLL_iswpunct    (CRTDLL.414)
533  */
534 int CRTDLL_iswpunct( WCHAR wc )
535 {
536 #ifdef HAVE_WCTYPE_H
537 #undef iswpunct
538     return iswpunct(wc);
539 #else
540     return ispunct( LOBYTE(wc) );  /* FIXME */
541 #endif
542 }
543
544 /*********************************************************************
545  *           CRTDLL_iswspace    (CRTDLL.415)
546  */
547 int CRTDLL_iswspace( WCHAR wc )
548 {
549 #ifdef HAVE_WCTYPE_H
550 #undef iswspace
551     return iswspace(wc);
552 #else
553     return isspace( LOBYTE(wc) );  /* FIXME */
554 #endif
555 }
556
557 /*********************************************************************
558  *           CRTDLL_iswupper    (CRTDLL.416)
559  */
560 int CRTDLL_iswupper( WCHAR wc )
561 {
562 #ifdef HAVE_WCTYPE_H
563 #undef iswupper
564     return iswupper(wc);
565 #else
566     return isupper( LOBYTE(wc) );  /* FIXME */
567 #endif
568 }
569
570 /*********************************************************************
571  *           CRTDLL_iswxdigit    (CRTDLL.417)
572  */
573 int CRTDLL_iswxdigit( WCHAR wc )
574 {
575 #ifdef HAVE_WCTYPE_H
576 #undef iswxdigit
577     return iswxdigit(wc);
578 #else
579     return isxdigit( LOBYTE(wc) );  /* FIXME */
580 #endif
581 }