Fixed compiler warnings.
[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
23
24 /*********************************************************************
25  *           CRTDLL__wcsdup    (CRTDLL.320)
26  */
27 LPWSTR __cdecl CRTDLL__wcsdup( LPCWSTR str )
28 {
29     LPWSTR ret = NULL;
30     if (str)
31     {
32         int size = (CRTDLL_wcslen(str) + 1) * sizeof(WCHAR);
33         ret = CRTDLL_malloc( size );
34         if (ret) memcpy( ret, str, size );
35     }
36     return ret;
37 }
38
39
40 /*********************************************************************
41  *           CRTDLL__wcsicmp    (CRTDLL.321)
42  */
43 INT __cdecl CRTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
44 {
45     while (*str1 && (CRTDLL_towupper(*str1) == CRTDLL_towupper(*str2)))
46     {
47         str1++;
48         str2++;
49     }
50     return CRTDLL_towupper(*str1) - CRTDLL_towupper(*str2);
51 }
52
53
54 /*********************************************************************
55  *           CRTDLL__wcsicoll    (CRTDLL.322)
56  */
57 INT __cdecl CRTDLL__wcsicoll( LPCWSTR str1, LPCWSTR str2 )
58 {
59     /* FIXME: handle collates */
60     return CRTDLL__wcsicmp( str1, str2 );
61 }
62
63
64 /*********************************************************************
65  *           CRTDLL__wcslwr    (CRTDLL.323)
66  */
67 LPWSTR __cdecl CRTDLL__wcslwr( LPWSTR str )
68 {
69     LPWSTR ret = str;
70     for ( ; *str; str++) *str = CRTDLL_towlower(*str);
71     return ret;
72 }
73
74
75 /*********************************************************************
76  *           CRTDLL__wcsnicmp    (CRTDLL.324)
77  */
78 INT __cdecl CRTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
79 {
80     if (!n) return 0;
81     while ((--n > 0) && *str1 && (CRTDLL_towupper(*str1) == CRTDLL_towupper(*str2)))
82     {
83         str1++;
84         str2++;
85     }
86     return CRTDLL_towupper(*str1) - CRTDLL_towupper(*str2);
87 }
88
89
90 /*********************************************************************
91  *           CRTDLL__wcsnset    (CRTDLL.325)
92  */
93 LPWSTR __cdecl CRTDLL__wcsnset( LPWSTR str, WCHAR c, INT n )
94 {
95     LPWSTR ret = str;
96     while ((n-- > 0) && *str) *str++ = c;
97     return ret;
98 }
99
100
101 /*********************************************************************
102  *           CRTDLL__wcsrev    (CRTDLL.326)
103  */
104 LPWSTR __cdecl CRTDLL__wcsrev( LPWSTR str )
105 {
106     LPWSTR ret = str;
107     LPWSTR end = str + CRTDLL_wcslen(str) - 1;
108     while (end > str)
109     {
110         WCHAR t = *end;
111         *end--  = *str;
112         *str++  = t;
113     }
114     return ret;
115 }
116
117
118 /*********************************************************************
119  *           CRTDLL__wcsset    (CRTDLL.327)
120  */
121 LPWSTR __cdecl CRTDLL__wcsset( LPWSTR str, WCHAR c )
122 {
123     LPWSTR ret = str;
124     while (*str) *str++ = c;
125     return ret;
126 }
127
128
129 /*********************************************************************
130  *           CRTDLL__wcsupr    (CRTDLL.328)
131  */
132 LPWSTR __cdecl CRTDLL__wcsupr( LPWSTR str )
133 {
134     LPWSTR ret = str;
135     for ( ; *str; str++) *str = CRTDLL_towupper(*str);
136     return ret;
137 }
138
139
140 /*********************************************************************
141  *           CRTDLL_towlower    (CRTDLL.493)
142  */
143 WCHAR __cdecl CRTDLL_towlower( WCHAR ch )
144 {
145 #ifdef HAVE_WCTYPE_H
146     ch = (WCHAR)towlower( (wchar_t)ch );
147 #else
148     if (!HIBYTE(ch)) ch = (WCHAR)tolower( LOBYTE(ch) );  /* FIXME */
149 #endif
150     return ch;
151 }
152
153
154 /*********************************************************************
155  *           CRTDLL_towupper    (CRTDLL.494)
156  */
157 WCHAR __cdecl CRTDLL_towupper( WCHAR ch )
158 {
159 #ifdef HAVE_WCTYPE_H
160     ch = (WCHAR)towupper( (wchar_t)ch );
161 #else
162     if (!HIBYTE(ch)) ch = (WCHAR)toupper( LOBYTE(ch) );  /* FIXME */
163 #endif
164     return ch;
165 }
166
167
168 /***********************************************************************
169  *           CRTDLL_wcscat    (CRTDLL.503)
170  */
171 LPWSTR __cdecl CRTDLL_wcscat( LPWSTR dst, LPCWSTR src )
172 {
173     LPWSTR p = dst;
174     while (*p) p++;
175     while ((*p++ = *src++));
176     return dst;
177 }
178
179
180 /*********************************************************************
181  *           CRTDLL_wcschr    (CRTDLL.504)
182  */
183 LPWSTR __cdecl CRTDLL_wcschr( LPCWSTR str, WCHAR ch )
184 {
185     while (*str)
186     {
187         if (*str == ch) return (LPWSTR)str;
188         str++;
189     }
190     return NULL;
191 }
192
193
194 /*********************************************************************
195  *           CRTDLL_wcscmp    (CRTDLL.505)
196  */
197 INT __cdecl CRTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
198 {
199     while (*str1 && (*str1 == *str2)) { str1++; str2++; }
200     return (INT)(*str1 - *str2);
201 }
202
203
204 /*********************************************************************
205  *           CRTDLL_wcscoll    (CRTDLL.506)
206  */
207 DWORD __cdecl CRTDLL_wcscoll( LPCWSTR str1, LPCWSTR str2 )
208 {
209     /* FIXME: handle collates */
210     return CRTDLL_wcscmp( str1, str2 );
211 }
212
213
214 /***********************************************************************
215  *           CRTDLL_wcscpy    (CRTDLL.507)
216  */
217 LPWSTR __cdecl CRTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
218 {
219     LPWSTR p = dst;
220     while ((*p++ = *src++));
221     return dst;
222 }
223
224
225 /*********************************************************************
226  *           CRTDLL_wcscspn    (CRTDLL.508)
227  */
228 INT __cdecl CRTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
229 {
230     LPCWSTR start = str;
231     while (*str)
232     {
233         LPCWSTR p = reject;
234         while (*p && (*p != *str)) p++;
235         if (*p) break;
236         str++;
237     }
238     return str - start;
239 }
240
241
242 /***********************************************************************
243  *           CRTDLL_wcslen    (CRTDLL.510)
244  */
245 INT __cdecl CRTDLL_wcslen( LPCWSTR str )
246 {
247     LPCWSTR s = str;
248     while (*s) s++;
249     return s - str;
250 }
251
252
253 /*********************************************************************
254  *           CRTDLL_wcsncat    (CRTDLL.511)
255  */
256 LPWSTR __cdecl CRTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
257 {
258     LPWSTR ret = s1;
259     while (*s1) s1++;
260     while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
261     *s1 = 0;
262     return ret;
263 }
264
265
266 /*********************************************************************
267  *           CRTDLL_wcsncmp    (CRTDLL.512)
268  */
269 INT __cdecl CRTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
270 {
271     if (!n) return 0;
272     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
273     return (INT)(*str1 - *str2);
274 }
275
276
277 /*********************************************************************
278  *           CRTDLL_wcsncpy    (CRTDLL.513)
279  */
280 LPWSTR __cdecl CRTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
281 {
282     LPWSTR ret = s1;
283     while (n-- > 0) if (!(*s1++ = *s2++)) break;
284     while (n-- > 0) *s1++ = 0;
285     return ret;
286 }
287
288
289 /*********************************************************************
290  *           CRTDLL_wcspbrk    (CRTDLL.514)
291  */
292 LPWSTR __cdecl CRTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
293 {
294     LPCWSTR p;
295     while (*str)
296     {
297         for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
298         str++;
299     }
300     return NULL;
301 }
302
303
304 /*********************************************************************
305  *           CRTDLL_wcsrchr    (CRTDLL.515)
306  */
307 LPWSTR __cdecl CRTDLL_wcsrchr( LPWSTR str, WCHAR ch )
308 {
309     LPWSTR last = NULL;
310     while (*str)
311     {
312         if (*str == ch) last = str;
313         str++;
314     }
315     return last;
316 }
317
318
319 /*********************************************************************
320  *           CRTDLL_wcsspn    (CRTDLL.516)
321  */
322 INT __cdecl CRTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
323 {
324     LPCWSTR start = str;
325     while (*str)
326     {
327         LPCWSTR p = accept;
328         while (*p && (*p != *str)) p++;
329         if (!*p) break;
330         str++;
331     }
332     return str - start;
333 }
334
335
336 /*********************************************************************
337  *           CRTDLL_wcsstr    (CRTDLL.517)
338  */
339 LPWSTR __cdecl CRTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
340 {
341     while (*str)
342     {
343         LPCWSTR p1 = str, p2 = sub;
344         while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; }
345         if (!*p2) return (LPWSTR)str;
346         str++;
347     }
348     return NULL;
349 }
350
351
352 /*********************************************************************
353  *           CRTDLL_wcstok    (CRTDLL.519)
354  */
355 LPWSTR __cdecl CRTDLL_wcstok( LPWSTR str, LPCWSTR delim )
356 {
357     static LPWSTR next = NULL;
358     LPWSTR ret;
359
360     if (!str)
361         if (!(str = next)) return NULL;
362
363     while (*str && CRTDLL_wcschr( delim, *str )) str++;
364     if (!*str) return NULL;
365     ret = str++;
366     while (*str && !CRTDLL_wcschr( delim, *str )) str++;
367     if (*str) *str++ = 0;
368     next = str;
369     return ret;
370 }
371
372
373 /*********************************************************************
374  *           CRTDLL_wcstombs    (CRTDLL.521)
375  *
376  * FIXME: the reason I do not use wcstombs is that it seems to fail
377  *        for any latin-1 valid character. Not good.
378  */
379 INT __cdecl CRTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
380 {
381     int copied=0;
382     while ((n>0) && *src) {
383         int ret;
384         /* FIXME: could potentially overflow if we ever have MB of 2 bytes*/
385         ret = wctomb(dst,(wchar_t)*src);
386         if (ret<0) {
387             /* FIXME: sadly, some versions of glibc do not like latin characters
388              * as UNICODE chars for some reason (like german umlauts). Just
389              * copy those anyway. MM 991106
390              */
391             *dst=*src;
392             ret = 1;
393         }
394         dst     += ret;
395         n       -= ret;
396         copied  += ret;
397         src++;
398     }
399     return copied;
400 }
401
402 /*********************************************************************
403  *           CRTDLL_wctomb    (CRTDLL.524)
404  */
405 INT __cdecl CRTDLL_wctomb( LPSTR dst, WCHAR ch )
406 {
407     return wctomb( dst, (wchar_t)ch );
408 }