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