Updated.
[wine] / dlls / msvcrt / wcs.c
1 /*
2  * msvcrt.dll wide-char functions
3  *
4  * Copyright 1999 Alexandre Julliard
5  * Copyright 2000 Jon Griffiths
6  */
7 #include <limits.h>
8 #include <stdio.h>
9 #include "msvcrt.h"
10 #include "winnls.h"
11 #include "wine/unicode.h"
12
13 DEFAULT_DEBUG_CHANNEL(msvcrt);
14
15
16 /* INTERNAL: MSVCRT_malloc() based wstrndup */
17 LPWSTR MSVCRT__wstrndup(LPCWSTR buf, unsigned int size)
18 {
19   WCHAR* ret;
20   unsigned int len = strlenW(buf), max_len;
21
22   max_len = size <= len? size : len + 1;
23
24   ret = MSVCRT_malloc(max_len * sizeof (WCHAR));
25   if (ret)
26   {
27     memcpy(ret,buf,max_len * sizeof (WCHAR));
28     ret[max_len] = 0;
29   }
30   return ret;
31 }
32
33 /*********************************************************************
34  *              _wcsdup (MSVCRT.@)
35  */
36 LPWSTR __cdecl MSVCRT__wcsdup( LPCWSTR str )
37 {
38   LPWSTR ret = NULL;
39   if (str)
40   {
41     int size = (strlenW(str) + 1) * sizeof(WCHAR);
42     ret = MSVCRT_malloc( size );
43     if (ret) memcpy( ret, str, size );
44   }
45   return ret;
46 }
47
48 /*********************************************************************
49  *              _wcsicoll (MSVCRT.@)
50  */
51 INT __cdecl MSVCRT__wcsicoll( LPCWSTR str1, LPCWSTR str2 )
52 {
53   /* FIXME: handle collates */
54   return strcmpiW( str1, str2 );
55 }
56
57 /*********************************************************************
58  *              _wcsnset (MSVCRT.@)
59  */
60 LPWSTR __cdecl MSVCRT__wcsnset( LPWSTR str, WCHAR c, INT n )
61 {
62   LPWSTR ret = str;
63   while ((n-- > 0) && *str) *str++ = c;
64   return ret;
65 }
66
67 /*********************************************************************
68  *              _wcsrev (MSVCRT.@)
69  */
70 LPWSTR __cdecl MSVCRT__wcsrev( LPWSTR str )
71 {
72   LPWSTR ret = str;
73   LPWSTR end = str + strlenW(str) - 1;
74   while (end > str)
75   {
76     WCHAR t = *end;
77     *end--  = *str;
78     *str++  = t;
79   }
80   return ret;
81 }
82
83 /*********************************************************************
84  *              _wcsset (MSVCRT.@)
85  */
86 LPWSTR __cdecl MSVCRT__wcsset( LPWSTR str, WCHAR c )
87 {
88   LPWSTR ret = str;
89   while (*str) *str++ = c;
90   return ret;
91 }
92
93 /*********************************************************************
94  *              _vsnwprintf (MSVCRT.@)
95  */
96 int __cdecl MSVCRT__vsnwprintf(WCHAR *str, unsigned int len,
97                               const WCHAR *format, va_list valist)
98 {
99 /* If you fix a bug in this function, fix it in ntdll/wcstring.c also! */
100   unsigned int written = 0;
101   const WCHAR *iter = format;
102   char bufa[256], fmtbufa[64], *fmta;
103
104   TRACE("(%d,%s)\n",len,debugstr_w(format));
105
106   while (*iter)
107   {
108     while (*iter && *iter != (WCHAR)L'%')
109     {
110      if (written++ >= len)
111        return -1;
112      *str++ = *iter++;
113     }
114     if (*iter == (WCHAR)L'%')
115     {
116       fmta = fmtbufa;
117       *fmta++ = *iter++;
118       while (*iter == (WCHAR)L'0' ||
119              *iter == (WCHAR)L'+' ||
120              *iter == (WCHAR)L'-' ||
121              *iter == (WCHAR)L' ' ||
122              *iter == (WCHAR)L'0' ||
123              *iter == (WCHAR)L'*' ||
124              *iter == (WCHAR)L'#')
125       {
126         if (*iter == (WCHAR)L'*')
127         {
128           char *buffiter = bufa;
129           int fieldlen = va_arg(valist, int);
130           sprintf(buffiter, "%d", fieldlen);
131           while (*buffiter)
132             *fmta++ = *buffiter++;
133         }
134         else
135           *fmta++ = *iter;
136         iter++;
137       }
138
139       while (isdigit(*iter))
140         *fmta++ = *iter++;
141
142       if (*iter == (WCHAR)L'.')
143       {
144         *fmta++ = *iter++;
145         if (*iter == (WCHAR)L'*')
146         {
147           char *buffiter = bufa;
148           int fieldlen = va_arg(valist, int);
149           sprintf(buffiter, "%d", fieldlen);
150           while (*buffiter)
151             *fmta++ = *buffiter++;
152         }
153         else
154           while (isdigit(*iter))
155             *fmta++ = *iter++;
156       }
157       if (*iter == (WCHAR)L'h' ||
158           *iter == (WCHAR)L'l')
159       {
160           *fmta++ = *iter++;
161           *fmta++ = *iter++;
162       }
163
164       switch (*iter)
165       {
166       case (WCHAR)L's':
167         {
168           static const WCHAR none[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
169           const WCHAR *wstr = va_arg(valist, const WCHAR *);
170           const WCHAR *striter = wstr ? wstr : none;
171           while (*striter)
172           {
173             if (written++ >= len)
174               return -1;
175             *str++ = *striter++;
176           }
177           iter++;
178           break;
179         }
180
181       case (WCHAR)L'c':
182         if (written++ >= len)
183           return -1;
184         *str++ = (WCHAR)va_arg(valist, int);
185         iter++;
186         break;
187
188       default:
189         {
190           /* For non wc types, use system sprintf and append to wide char output */
191           /* FIXME: for unrecognised types, should ignore % when printing */
192           char *bufaiter = bufa;
193           if (*iter == (WCHAR)L'p')
194             sprintf(bufaiter, "%08lX", va_arg(valist, long));
195           else
196           {
197             *fmta++ = *iter;
198             *fmta = '\0';
199             sprintf(bufaiter, fmtbufa, va_arg(valist, void *));
200           }
201           while (*bufaiter)
202           {
203             if (written++ >= len)
204               return -1;
205             *str++ = *bufaiter++;
206           }
207           iter++;
208           break;
209         }
210       }
211     }
212   }
213   if (written >= len)
214     return -1;
215   *str++ = (WCHAR)L'\0';
216   return (int)written;
217 }
218
219 /*********************************************************************
220  *              vswprintf (MSVCRT.@)
221  */
222 int __cdecl MSVCRT_vswprintf( LPWSTR str, LPCWSTR format, va_list args )
223 {
224   return MSVCRT__vsnwprintf( str, INT_MAX, format, args );
225 }
226
227 /*********************************************************************
228  *              wcscoll (MSVCRT.@)
229  */
230 DWORD __cdecl MSVCRT_wcscoll( LPCWSTR str1, LPCWSTR str2 )
231 {
232   /* FIXME: handle collates */
233   return strcmpW( str1, str2 );
234 }
235
236 /*********************************************************************
237  *              wcspbrk (MSVCRT.@)
238  */
239 LPWSTR __cdecl MSVCRT_wcspbrk( LPCWSTR str, LPCWSTR accept )
240 {
241   LPCWSTR p;
242   while (*str)
243   {
244     for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
245       str++;
246   }
247   return NULL;
248 }
249
250 /*********************************************************************
251  *              wctomb (MSVCRT.@)
252  */
253 INT __cdecl MSVCRT_wctomb( char *dst, WCHAR ch )
254 {
255   return WideCharToMultiByte( CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL );
256 }
257
258 /*********************************************************************
259  *              iswalnum (MSVCRT.@)
260  */
261 INT __cdecl MSVCRT_iswalnum( WCHAR wc )
262 {
263   return get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT|C1_LOWER|C1_UPPER);
264 }
265
266 /*********************************************************************
267  *              iswalpha (MSVCRT.@)
268  */
269 INT __cdecl MSVCRT_iswalpha( WCHAR wc )
270 {
271   return get_char_typeW(wc) & (C1_ALPHA|C1_LOWER|C1_UPPER);
272 }
273
274 /*********************************************************************
275  *              iswcntrl (MSVCRT.@)
276  */
277 INT __cdecl MSVCRT_iswcntrl( WCHAR wc )
278 {
279   return get_char_typeW(wc) & C1_CNTRL;
280 }
281
282 /*********************************************************************
283  *              iswdigit (MSVCRT.@)
284  */
285 INT __cdecl MSVCRT_iswdigit( WCHAR wc )
286 {
287   return get_char_typeW(wc) & C1_DIGIT;
288 }
289
290 /*********************************************************************
291  *              iswgraph (MSVCRT.@)
292  */
293 INT __cdecl MSVCRT_iswgraph( WCHAR wc )
294 {
295   return get_char_typeW(wc) & (C1_ALPHA|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
296 }
297
298 /*********************************************************************
299  *              iswlower (MSVCRT.@)
300  */
301 INT __cdecl MSVCRT_iswlower( WCHAR wc )
302 {
303   return get_char_typeW(wc) & C1_LOWER;
304 }
305
306 /*********************************************************************
307  *              iswprint (MSVCRT.@)
308  */
309 INT __cdecl MSVCRT_iswprint( WCHAR wc )
310 {
311   return get_char_typeW(wc) & (C1_ALPHA|C1_BLANK|C1_PUNCT|C1_DIGIT|C1_LOWER|C1_UPPER);
312 }
313
314 /*********************************************************************
315  *              iswpunct (MSVCRT.@)
316  */
317 INT __cdecl MSVCRT_iswpunct( WCHAR wc )
318 {
319   return get_char_typeW(wc) & C1_PUNCT;
320 }
321
322 /*********************************************************************
323  *              iswspace (MSVCRT.@)
324  */
325 INT __cdecl MSVCRT_iswspace( WCHAR wc )
326 {
327   return get_char_typeW(wc) & C1_SPACE;
328 }
329
330 /*********************************************************************
331  *              iswupper (MSVCRT.@)
332  */
333 INT __cdecl MSVCRT_iswupper( WCHAR wc )
334 {
335   return get_char_typeW(wc) & C1_UPPER;
336 }
337
338 /*********************************************************************
339  *              iswxdigit (MSVCRT.@)
340  */
341 INT __cdecl MSVCRT_iswxdigit( WCHAR wc )
342 {
343   return get_char_typeW(wc) & C1_XDIGIT;
344 }
345
346 extern char *__cdecl _itoa( long , char *, int);
347 extern char *__cdecl _ultoa( long , char *, int);
348 extern char *__cdecl _ltoa( long , char *, int);
349
350 /*********************************************************************
351  *              _itow (MSVCRT.@)
352  */
353 WCHAR* __cdecl MSVCRT__itow(int value,WCHAR* out,int base)
354 {
355   char buf[64];
356   _itoa(value, buf, base);
357   MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128);
358   return out;
359 }
360
361 /*********************************************************************
362  *              _ltow (MSVCRT.@)
363  */
364 WCHAR* __cdecl MSVCRT__ltow(long value,WCHAR* out,int base)
365 {
366   char buf[128];
367   _ltoa(value, buf, base);
368   MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128);
369   return out;
370 }
371
372 /*********************************************************************
373  *              _ultow (MSVCRT.@)
374  */
375 WCHAR* __cdecl MSVCRT__ultow(unsigned long value,WCHAR* out,int base)
376 {
377   char buf[128];
378   _ultoa(value, buf, base);
379   MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, buf, -1, out, 128);
380   return out;
381 }
382