Use DrawFrameControl instead of bitmaps in certain cases.
[wine] / dlls / ntdll / wcstring.c
1 /*
2  * NTDLL wide-char functions
3  *
4  * Copyright 2000 Alexandre Julliard
5  * Copyright 2000 Jon Griffiths
6  */
7
8 #include "config.h"
9
10 #include <ctype.h>
11 #include <limits.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15
16 #include "ntddk.h"
17 #include "wine/unicode.h"
18 #include "debugtools.h"
19
20 DEFAULT_DEBUG_CHANNEL(ntdll);
21
22
23 /*********************************************************************
24  *           _wcsicmp    (NTDLL.@)
25  */
26 INT __cdecl NTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
27 {
28     return strcmpiW( str1, str2 );
29 }
30
31
32 /*********************************************************************
33  *           _wcslwr    (NTDLL.@)
34  */
35 LPWSTR __cdecl NTDLL__wcslwr( LPWSTR str )
36 {
37     return strlwrW( str );
38 }
39
40
41 /*********************************************************************
42  *           _wcsnicmp    (NTDLL.@)
43  */
44 INT __cdecl NTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
45 {
46     return strncmpiW( str1, str2, n );
47 }
48
49
50 /*********************************************************************
51  *           _wcsupr    (NTDLL.@)
52  */
53 LPWSTR __cdecl NTDLL__wcsupr( LPWSTR str )
54 {
55     return struprW( str );
56 }
57
58
59 /*********************************************************************
60  *           towlower    (NTDLL.@)
61  */
62 WCHAR __cdecl NTDLL_towlower( WCHAR ch )
63 {
64     return tolowerW(ch);
65 }
66
67
68 /*********************************************************************
69  *           towupper    (NTDLL.@)
70  */
71 WCHAR __cdecl NTDLL_towupper( WCHAR ch )
72 {
73     return toupperW(ch);
74 }
75
76
77 /***********************************************************************
78  *           wcscat    (NTDLL.@)
79  */
80 LPWSTR __cdecl NTDLL_wcscat( LPWSTR dst, LPCWSTR src )
81 {
82     return strcatW( dst, src );
83 }
84
85
86 /*********************************************************************
87  *           wcschr    (NTDLL.@)
88  */
89 LPWSTR __cdecl NTDLL_wcschr( LPCWSTR str, WCHAR ch )
90 {
91     return strchrW( str, ch );
92 }
93
94
95 /*********************************************************************
96  *           wcscmp    (NTDLL.@)
97  */
98 INT __cdecl NTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
99 {
100     return strcmpW( str1, str2 );
101 }
102
103
104 /***********************************************************************
105  *           wcscpy    (NTDLL.@)
106  */
107 LPWSTR __cdecl NTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
108 {
109     return strcpyW( dst, src );
110 }
111
112
113 /*********************************************************************
114  *           wcscspn    (NTDLL.@)
115  */
116 INT __cdecl NTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
117 {
118     LPCWSTR start = str;
119     while (*str)
120     {
121         LPCWSTR p = reject;
122         while (*p && (*p != *str)) p++;
123         if (*p) break;
124         str++;
125     }
126     return str - start;
127 }
128
129
130 /***********************************************************************
131  *           wcslen    (NTDLL.@)
132  */
133 INT __cdecl NTDLL_wcslen( LPCWSTR str )
134 {
135     return strlenW( str );
136 }
137
138
139 /*********************************************************************
140  *           wcsncat    (NTDLL.@)
141  */
142 LPWSTR __cdecl NTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
143 {
144     LPWSTR ret = s1;
145     while (*s1) s1++;
146     while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
147     *s1 = 0;
148     return ret;
149 }
150
151
152 /*********************************************************************
153  *           wcsncmp    (NTDLL.@)
154  */
155 INT __cdecl NTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
156 {
157     return strncmpW( str1, str2, n );
158 }
159
160
161 /*********************************************************************
162  *           wcsncpy    (NTDLL.@)
163  */
164 LPWSTR __cdecl NTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
165 {
166     return strncpyW( s1, s2, n );
167 }
168
169
170 /*********************************************************************
171  *           wcspbrk    (NTDLL.@)
172  */
173 LPWSTR __cdecl NTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
174 {
175     LPCWSTR p;
176     while (*str)
177     {
178         for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
179         str++;
180     }
181     return NULL;
182 }
183
184
185 /*********************************************************************
186  *           wcsrchr    (NTDLL.@)
187  */
188 LPWSTR __cdecl NTDLL_wcsrchr( LPWSTR str, WCHAR ch )
189 {
190     LPWSTR last = NULL;
191     while (*str)
192     {
193         if (*str == ch) last = str;
194         str++;
195     }
196     return last;
197 }
198
199
200 /*********************************************************************
201  *           wcsspn    (NTDLL.@)
202  */
203 INT __cdecl NTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
204 {
205     LPCWSTR start = str;
206     while (*str)
207     {
208         LPCWSTR p = accept;
209         while (*p && (*p != *str)) p++;
210         if (!*p) break;
211         str++;
212     }
213     return str - start;
214 }
215
216
217 /*********************************************************************
218  *           wcsstr    (NTDLL.@)
219  */
220 LPWSTR __cdecl NTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
221 {
222     return strstrW( str, sub );
223 }
224
225
226 /*********************************************************************
227  *           wcstok    (NTDLL.@)
228  */
229 LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim )
230 {
231     static LPWSTR next = NULL;
232     LPWSTR ret;
233
234     if (!str)
235         if (!(str = next)) return NULL;
236
237     while (*str && NTDLL_wcschr( delim, *str )) str++;
238     if (!*str) return NULL;
239     ret = str++;
240     while (*str && !NTDLL_wcschr( delim, *str )) str++;
241     if (*str) *str++ = 0;
242     next = str;
243     return ret;
244 }
245
246
247 /*********************************************************************
248  *           wcstombs    (NTDLL.@)
249  */
250 INT __cdecl NTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
251 {
252     DWORD len;
253
254     if (!dst)
255     {
256         RtlUnicodeToMultiByteSize( &len, src, strlenW(src)*sizeof(WCHAR) );
257         return len;
258     }
259     else
260     {
261         if (n <= 0) return 0;
262         RtlUnicodeToMultiByteN( dst, n, &len, src, strlenW(src)*sizeof(WCHAR) );
263         if (len < n) dst[len] = 0;
264     }
265     return len;
266 }
267
268
269 /*********************************************************************
270  *           mbstowcs    (NTDLL.@)
271  */
272 INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
273 {
274     DWORD len;
275
276     if (!dst)
277     {
278         RtlMultiByteToUnicodeSize( &len, src, strlen(src) );
279     }
280     else
281     {
282         if (n <= 0) return 0;
283         RtlMultiByteToUnicodeN( dst, n*sizeof(WCHAR), &len, src, strlen(src) );
284         if (len / sizeof(WCHAR) < n) dst[len / sizeof(WCHAR)] = 0;
285     }
286     return len / sizeof(WCHAR);
287 }
288
289
290 /*********************************************************************
291  *                  wcstol  (NTDLL.@)
292  * Like strtol, but for wide character strings.
293  */
294 INT __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base)
295 {
296     UNICODE_STRING uni;
297     ANSI_STRING ansi;
298     INT ret;
299     LPSTR endA;
300
301     RtlInitUnicodeString( &uni, s );
302     RtlUnicodeStringToAnsiString( &ansi, &uni, TRUE );
303     ret = strtol( ansi.Buffer, &endA, base );
304     if (end)
305     {
306         DWORD len;
307         RtlMultiByteToUnicodeSize( &len, ansi.Buffer, endA - ansi.Buffer );
308         *end = (LPWSTR)s + len/sizeof(WCHAR);
309     }
310     RtlFreeAnsiString( &ansi );
311     return ret;
312 }
313
314
315 /*********************************************************************
316  *                  wcstoul  (NTDLL.@)
317  * Like strtoul, but for wide character strings.
318  */
319 INT __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base)
320 {
321     UNICODE_STRING uni;
322     ANSI_STRING ansi;
323     INT ret;
324     LPSTR endA;
325
326     RtlInitUnicodeString( &uni, s );
327     RtlUnicodeStringToAnsiString( &ansi, &uni, TRUE );
328     ret = strtoul( ansi.Buffer, &endA, base );
329     if (end)
330     {
331         DWORD len;
332         RtlMultiByteToUnicodeSize( &len, ansi.Buffer, endA - ansi.Buffer );
333         *end = (LPWSTR)s + len/sizeof(WCHAR);
334     }
335     RtlFreeAnsiString( &ansi );
336     return ret;
337 }
338
339
340 /*********************************************************************
341  *           iswctype    (NTDLL.@)
342  */
343 INT __cdecl NTDLL_iswctype( WCHAR wc, WCHAR wct )
344 {
345     return (get_char_typeW(wc) & 0xfff) & wct;
346 }
347
348
349 /*********************************************************************
350  *           iswalpha    (NTDLL.@)
351  */
352 INT __cdecl NTDLL_iswalpha( WCHAR wc )
353 {
354     return get_char_typeW(wc) & C1_ALPHA;
355 }
356
357
358 /*********************************************************************
359  *           _ultow    (NTDLL.@)
360  * Like _ultoa, but for wide character strings.
361  */
362 LPWSTR __cdecl _ultow(ULONG value, LPWSTR string, INT radix)
363 {
364     WCHAR tmp[33];
365     LPWSTR tp = tmp;
366     LPWSTR sp;
367     LONG i;
368     ULONG v = value;
369
370     if (radix > 36 || radix <= 1)
371         return 0;
372
373     while (v || tp == tmp)
374     {
375         i = v % radix;
376         v = v / radix;
377         if (i < 10)
378             *tp++ = i + '0';
379         else
380             *tp++ = i + 'a' - 10;
381     }
382
383     sp = string;
384     while (tp > tmp)
385         *sp++ = *--tp;
386     *sp = 0;
387     return string;
388 }
389
390 /*********************************************************************
391  *           _wtol    (NTDLL.@)
392  * Like atol, but for wide character strings.
393  */
394 LONG __cdecl _wtol(LPWSTR string)
395 {
396     char buffer[30];
397     NTDLL_wcstombs( buffer, string, sizeof(buffer) );
398     return atol( buffer );
399 }
400
401 /*********************************************************************
402  *           _wtoi    (NTDLL.@)
403  */
404 INT __cdecl _wtoi(LPWSTR string)
405 {
406     return _wtol(string);
407 }
408
409 /* INTERNAL: Wide char snprintf
410  * If you fix a bug in this function, fix it in msvcrt/wcs.c also!
411  */
412 static int __cdecl NTDLL_vsnwprintf(WCHAR *str, unsigned int len,
413                                     const WCHAR *format, va_list valist)
414 {
415   unsigned int written = 0;
416   const WCHAR *iter = format;
417   char bufa[256], fmtbufa[64], *fmta;
418
419   TRACE("(%d,%s)\n",len,debugstr_w(format));
420
421   while (*iter)
422   {
423     while (*iter && *iter != (WCHAR)L'%')
424     {
425      if (written++ >= len)
426        return -1;
427      *str++ = *iter++;
428     }
429     if (*iter == (WCHAR)L'%')
430     {
431       fmta = fmtbufa;
432       *fmta++ = *iter++;
433       while (*iter == (WCHAR)L'0' ||
434              *iter == (WCHAR)L'+' ||
435              *iter == (WCHAR)L'-' ||
436              *iter == (WCHAR)L' ' ||
437              *iter == (WCHAR)L'0' ||
438              *iter == (WCHAR)L'*' ||
439              *iter == (WCHAR)L'#')
440       {
441         if (*iter == (WCHAR)L'*')
442         {
443           char *buffiter = bufa;
444           int fieldlen = va_arg(valist, int);
445           sprintf(buffiter, "%d", fieldlen);
446           while (*buffiter)
447             *fmta++ = *buffiter++;
448         }
449         else
450           *fmta++ = *iter;
451         iter++;
452       }
453
454       while (isdigit(*iter))
455         *fmta++ = *iter++;
456
457       if (*iter == (WCHAR)L'.')
458       {
459         *fmta++ = *iter++;
460         if (*iter == (WCHAR)L'*')
461         {
462           char *buffiter = bufa;
463           int fieldlen = va_arg(valist, int);
464           sprintf(buffiter, "%d", fieldlen);
465           while (*buffiter)
466             *fmta++ = *buffiter++;
467         }
468         else
469           while (isdigit(*iter))
470             *fmta++ = *iter++;
471       }
472       if (*iter == (WCHAR)L'h' ||
473           *iter == (WCHAR)L'l')
474       {
475           *fmta++ = *iter++;
476           *fmta++ = *iter++;
477       }
478
479       switch (*iter)
480       {
481       case (WCHAR)L's':
482         {
483           static const WCHAR none[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
484           const WCHAR *wstr = va_arg(valist, const WCHAR *);
485           const WCHAR *striter = wstr ? wstr : none;
486           while (*striter)
487           {
488             if (written++ >= len)
489               return -1;
490             *str++ = *striter++;
491           }
492           iter++;
493           break;
494         }
495
496       case (WCHAR)L'c':
497         if (written++ >= len)
498           return -1;
499         *str++ = (WCHAR)va_arg(valist, int);
500         iter++;
501         break;
502
503       default:
504         {
505           /* For non wc types, use system sprintf and append to wide char output */
506           /* FIXME: for unrecognised types, should ignore % when printing */
507           char *bufaiter = bufa;
508           if (*iter == (WCHAR)L'p')
509             sprintf(bufaiter, "%08lX", va_arg(valist, long));
510           else
511           {
512             *fmta++ = *iter;
513             *fmta = '\0';
514             if (*iter == (WCHAR)L'f')
515               sprintf(bufaiter, fmtbufa, va_arg(valist, double));
516             else
517               sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
518           }
519           while (*bufaiter)
520           {
521             if (written++ >= len)
522               return -1;
523             *str++ = *bufaiter++;
524           }
525           iter++;
526           break;
527         }
528       }
529     }
530   }
531   if (written >= len)
532     return -1;
533   *str++ = (WCHAR)L'\0';
534   return (int)written;
535 }
536
537
538 /***********************************************************************
539  *        _snwprintf (NTDLL.@)
540  */
541 int __cdecl _snwprintf(WCHAR *str, unsigned int len, const WCHAR *format, ...)
542 {
543   int retval;
544   va_list valist;
545   va_start(valist, format);
546   retval = NTDLL_vsnwprintf(str, len, format, valist);
547   va_end(valist);
548   return retval;
549 }
550
551
552 /***********************************************************************
553  *        swprintf (NTDLL.@)
554  */
555 int __cdecl NTDLL_swprintf(WCHAR *str, const WCHAR *format, ...)
556 {
557   int retval;
558   va_list valist;
559   va_start(valist, format);
560   retval = NTDLL_vsnwprintf(str, INT_MAX, format, valist);
561   va_end(valist);
562   return retval;
563 }