Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 1 | /* |
| 2 | * msvcrt.dll wide-char functions |
| 3 | * |
| 4 | * Copyright 1999 Alexandre Julliard |
| 5 | * Copyright 2000 Jon Griffiths |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU Lesser General Public |
| 9 | * License as published by the Free Software Foundation; either |
| 10 | * version 2.1 of the License, or (at your option) any later version. |
| 11 | * |
| 12 | * This library is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 | * Lesser General Public License for more details. |
| 16 | * |
| 17 | * You should have received a copy of the GNU Lesser General Public |
| 18 | * License along with this library; if not, write to the Free Software |
| 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 20 | */ |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 21 | #include <limits.h> |
| 22 | #include <stdio.h> |
Dave Belanger | 9a05e1f | 2004-04-08 19:48:19 +0000 | [diff] [blame] | 23 | #include <math.h> |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 24 | #include <assert.h> |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 25 | #include "msvcrt.h" |
| 26 | #include "winnls.h" |
| 27 | #include "wine/unicode.h" |
Alexandre Julliard | bd1689e | 2002-01-22 00:57:16 +0000 | [diff] [blame] | 28 | #include "wine/debug.h" |
| 29 | |
| 30 | WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 31 | |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 32 | |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 33 | /* INTERNAL: MSVCRT_malloc() based wstrndup */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 34 | MSVCRT_wchar_t* msvcrt_wstrndup(const MSVCRT_wchar_t *buf, unsigned int size) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 35 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 36 | MSVCRT_wchar_t* ret; |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 37 | unsigned int len = strlenW(buf), max_len; |
| 38 | |
| 39 | max_len = size <= len? size : len + 1; |
| 40 | |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 41 | ret = MSVCRT_malloc(max_len * sizeof (MSVCRT_wchar_t)); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 42 | if (ret) |
| 43 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 44 | memcpy(ret,buf,max_len * sizeof (MSVCRT_wchar_t)); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 45 | ret[max_len] = 0; |
| 46 | } |
| 47 | return ret; |
| 48 | } |
| 49 | |
| 50 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 51 | * _wcsdup (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 52 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 53 | MSVCRT_wchar_t* _wcsdup( const MSVCRT_wchar_t* str ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 54 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 55 | MSVCRT_wchar_t* ret = NULL; |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 56 | if (str) |
| 57 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 58 | int size = (strlenW(str) + 1) * sizeof(MSVCRT_wchar_t); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 59 | ret = MSVCRT_malloc( size ); |
| 60 | if (ret) memcpy( ret, str, size ); |
| 61 | } |
| 62 | return ret; |
| 63 | } |
| 64 | |
| 65 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 66 | * _wcsicoll (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 67 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 68 | INT _wcsicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 69 | { |
| 70 | /* FIXME: handle collates */ |
| 71 | return strcmpiW( str1, str2 ); |
| 72 | } |
| 73 | |
| 74 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 75 | * _wcsnset (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 76 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 77 | MSVCRT_wchar_t* _wcsnset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c, MSVCRT_size_t n ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 78 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 79 | MSVCRT_wchar_t* ret = str; |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 80 | while ((n-- > 0) && *str) *str++ = c; |
| 81 | return ret; |
| 82 | } |
| 83 | |
| 84 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 85 | * _wcsrev (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 86 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 87 | MSVCRT_wchar_t* _wcsrev( MSVCRT_wchar_t* str ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 88 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 89 | MSVCRT_wchar_t* ret = str; |
| 90 | MSVCRT_wchar_t* end = str + strlenW(str) - 1; |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 91 | while (end > str) |
| 92 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 93 | MSVCRT_wchar_t t = *end; |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 94 | *end-- = *str; |
| 95 | *str++ = t; |
| 96 | } |
| 97 | return ret; |
| 98 | } |
| 99 | |
| 100 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 101 | * _wcsset (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 102 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 103 | MSVCRT_wchar_t* _wcsset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 104 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 105 | MSVCRT_wchar_t* ret = str; |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 106 | while (*str) *str++ = c; |
| 107 | return ret; |
| 108 | } |
| 109 | |
| 110 | /********************************************************************* |
Jon Griffiths | d051a95 | 2003-09-23 22:50:30 +0000 | [diff] [blame] | 111 | * wcstod (MSVCRT.@) |
| 112 | */ |
| 113 | double MSVCRT_wcstod(const MSVCRT_wchar_t* lpszStr, MSVCRT_wchar_t** end) |
| 114 | { |
| 115 | const MSVCRT_wchar_t* str = lpszStr; |
| 116 | int negative = 0; |
| 117 | double ret = 0, divisor = 10.0; |
| 118 | |
| 119 | TRACE("(%s,%p) semi-stub\n", debugstr_w(lpszStr), end); |
| 120 | |
| 121 | /* FIXME: |
| 122 | * - Should set errno on failure |
| 123 | * - Should fail on overflow |
| 124 | * - Need to check which input formats are allowed |
| 125 | */ |
| 126 | while (isspaceW(*str)) |
| 127 | str++; |
| 128 | |
| 129 | if (*str == '-') |
| 130 | { |
| 131 | negative = 1; |
| 132 | str++; |
| 133 | } |
| 134 | |
| 135 | while (isdigitW(*str)) |
| 136 | { |
| 137 | ret = ret * 10.0 + (*str - '0'); |
| 138 | str++; |
| 139 | } |
| 140 | if (*str == '.') |
| 141 | str++; |
| 142 | while (isdigitW(*str)) |
| 143 | { |
| 144 | ret = ret + (*str - '0') / divisor; |
| 145 | divisor *= 10; |
| 146 | str++; |
| 147 | } |
| 148 | |
Dave Belanger | 9a05e1f | 2004-04-08 19:48:19 +0000 | [diff] [blame] | 149 | if (*str == 'E' || *str == 'e' || *str == 'D' || *str == 'd') |
| 150 | { |
| 151 | int negativeExponent = 0; |
| 152 | int exponent = 0; |
| 153 | if (*(++str) == '-') |
| 154 | { |
| 155 | negativeExponent = 1; |
| 156 | str++; |
| 157 | } |
| 158 | while (isdigitW(*str)) |
| 159 | { |
| 160 | exponent = exponent * 10 + (*str - '0'); |
| 161 | str++; |
| 162 | } |
| 163 | if (exponent != 0) |
| 164 | { |
| 165 | if (negativeExponent) |
| 166 | ret = ret / pow(10.0, exponent); |
| 167 | else |
| 168 | ret = ret * pow(10.0, exponent); |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | if (negative) |
| 173 | ret = -ret; |
| 174 | |
Jon Griffiths | d051a95 | 2003-09-23 22:50:30 +0000 | [diff] [blame] | 175 | if (end) |
| 176 | *end = (MSVCRT_wchar_t*)str; |
| 177 | |
| 178 | TRACE("returning %g\n", ret); |
| 179 | return ret; |
| 180 | } |
| 181 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 182 | |
| 183 | typedef struct pf_output_t |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 184 | { |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 185 | int used; |
| 186 | int len; |
| 187 | BOOL unicode; |
| 188 | union { |
| 189 | LPWSTR W; |
| 190 | LPSTR A; |
| 191 | } buf; |
| 192 | } pf_output; |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 193 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 194 | typedef struct pf_flags_t |
| 195 | { |
| 196 | char Sign, LeftAlign, Alternate, PadZero; |
Mike McCormack | 990e537 | 2005-10-27 10:20:08 +0000 | [diff] [blame] | 197 | int FieldLength, Precision; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 198 | char IntegerLength, IntegerDouble; |
| 199 | char WideString; |
| 200 | char Format; |
| 201 | } pf_flags; |
| 202 | |
| 203 | /* |
| 204 | * writes a string of characters to the output |
| 205 | * returns -1 if the string doesn't fit in the output buffer |
| 206 | * return the length of the string if all characters were written |
| 207 | */ |
| 208 | static inline int pf_output_stringW( pf_output *out, LPCWSTR str, int len ) |
| 209 | { |
| 210 | int space = out->len - out->used; |
| 211 | |
| 212 | if( len < 0 ) |
| 213 | len = strlenW( str ); |
| 214 | if( out->unicode ) |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 215 | { |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 216 | LPWSTR p = out->buf.W + out->used; |
| 217 | |
| 218 | if( space >= len ) |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 219 | { |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 220 | memcpy( p, str, len*sizeof(WCHAR) ); |
| 221 | out->used += len; |
| 222 | return len; |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 223 | } |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 224 | if( space > 0 ) |
| 225 | memcpy( p, str, space*sizeof(WCHAR) ); |
| 226 | out->used += len; |
| 227 | } |
| 228 | else |
| 229 | { |
| 230 | int n = WideCharToMultiByte( CP_ACP, 0, str, len, NULL, 0, NULL, NULL ); |
| 231 | LPSTR p = out->buf.A + out->used; |
| 232 | |
| 233 | if( space >= n ) |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 234 | { |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 235 | WideCharToMultiByte( CP_ACP, 0, str, len, p, n, NULL, NULL ); |
| 236 | out->used += n; |
| 237 | return len; |
| 238 | } |
| 239 | if( space > 0 ) |
| 240 | WideCharToMultiByte( CP_ACP, 0, str, len, p, space, NULL, NULL ); |
| 241 | out->used += n; |
| 242 | } |
| 243 | return -1; |
| 244 | } |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 245 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 246 | static inline int pf_output_stringA( pf_output *out, LPCSTR str, int len ) |
| 247 | { |
| 248 | int space = out->len - out->used; |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 249 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 250 | if( len < 0 ) |
| 251 | len = strlen( str ); |
| 252 | if( !out->unicode ) |
| 253 | { |
| 254 | LPSTR p = out->buf.A + out->used; |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 255 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 256 | if( space >= len ) |
| 257 | { |
| 258 | memcpy( p, str, len ); |
| 259 | out->used += len; |
| 260 | return len; |
| 261 | } |
| 262 | if( space > 0 ) |
| 263 | memcpy( p, str, space ); |
| 264 | out->used += len; |
| 265 | } |
| 266 | else |
| 267 | { |
| 268 | int n = MultiByteToWideChar( CP_ACP, 0, str, len, NULL, 0 ); |
| 269 | LPWSTR p = out->buf.W + out->used; |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 270 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 271 | if( space >= n ) |
| 272 | { |
| 273 | MultiByteToWideChar( CP_ACP, 0, str, len, p, n ); |
| 274 | out->used += n; |
| 275 | return len; |
| 276 | } |
| 277 | if( space > 0 ) |
| 278 | MultiByteToWideChar( CP_ACP, 0, str, len, p, space ); |
| 279 | out->used += n; |
| 280 | } |
| 281 | return -1; |
| 282 | } |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 283 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 284 | static inline int pf_fill( pf_output *out, int len, pf_flags *flags, char left ) |
| 285 | { |
| 286 | int i, r = 0; |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 287 | |
Jesse Allen | 419d493 | 2005-12-26 13:01:38 +0100 | [diff] [blame] | 288 | if( flags->Sign && !( flags->Format == 'd' || flags->Format == 'i' ) ) |
| 289 | flags->Sign = 0; |
| 290 | |
| 291 | if( left && flags->Sign ) |
| 292 | { |
| 293 | flags->FieldLength--; |
| 294 | if( flags->PadZero ) |
| 295 | r = pf_output_stringA( out, &flags->Sign, 1 ); |
| 296 | } |
| 297 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 298 | if( ( !left && flags->LeftAlign ) || |
Jesse Allen | 39b725b | 2005-12-20 11:49:05 +0100 | [diff] [blame] | 299 | ( left && !flags->LeftAlign )) |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 300 | { |
| 301 | for( i=0; (i<(flags->FieldLength-len)) && (r>=0); i++ ) |
| 302 | { |
Jesse Allen | 39b725b | 2005-12-20 11:49:05 +0100 | [diff] [blame] | 303 | if( left && flags->PadZero ) |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 304 | r = pf_output_stringA( out, "0", 1 ); |
| 305 | else |
| 306 | r = pf_output_stringA( out, " ", 1 ); |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 307 | } |
| 308 | } |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 309 | |
Jesse Allen | 419d493 | 2005-12-26 13:01:38 +0100 | [diff] [blame] | 310 | if( left && flags->Sign && !flags->PadZero ) |
| 311 | r = pf_output_stringA( out, &flags->Sign, 1 ); |
| 312 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 313 | return r; |
| 314 | } |
| 315 | |
| 316 | static inline int pf_output_format_W( pf_output *out, LPCWSTR str, |
| 317 | int len, pf_flags *flags ) |
| 318 | { |
| 319 | int r = 0; |
| 320 | |
| 321 | if( len < 0 ) |
| 322 | len = strlenW( str ); |
| 323 | |
Mike McCormack | 990e537 | 2005-10-27 10:20:08 +0000 | [diff] [blame] | 324 | if (flags->Precision >= 0 && flags->Precision < len) |
| 325 | len = flags->Precision; |
Uwe Bonnes | 0fb9ef6 | 2005-02-25 19:16:46 +0000 | [diff] [blame] | 326 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 327 | r = pf_fill( out, len, flags, 1 ); |
| 328 | |
| 329 | if( r>=0 ) |
| 330 | r = pf_output_stringW( out, str, len ); |
| 331 | |
| 332 | if( r>=0 ) |
| 333 | r = pf_fill( out, len, flags, 0 ); |
| 334 | |
| 335 | return r; |
| 336 | } |
| 337 | |
| 338 | static inline int pf_output_format_A( pf_output *out, LPCSTR str, |
| 339 | int len, pf_flags *flags ) |
| 340 | { |
| 341 | int r = 0; |
| 342 | |
| 343 | if( len < 0 ) |
| 344 | len = strlen( str ); |
| 345 | |
Mike McCormack | 990e537 | 2005-10-27 10:20:08 +0000 | [diff] [blame] | 346 | if (flags->Precision >= 0 && flags->Precision < len) |
| 347 | len = flags->Precision; |
Uwe Bonnes | 0fb9ef6 | 2005-02-25 19:16:46 +0000 | [diff] [blame] | 348 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 349 | r = pf_fill( out, len, flags, 1 ); |
| 350 | |
| 351 | if( r>=0 ) |
| 352 | r = pf_output_stringA( out, str, len ); |
| 353 | |
| 354 | if( r>=0 ) |
| 355 | r = pf_fill( out, len, flags, 0 ); |
| 356 | |
| 357 | return r; |
| 358 | } |
| 359 | |
Jesse Allen | 419d493 | 2005-12-26 13:01:38 +0100 | [diff] [blame] | 360 | static inline BOOL pf_is_integer_format( char fmt ) |
| 361 | { |
| 362 | static const char float_fmts[] = "diouxX"; |
| 363 | if (!fmt) |
| 364 | return FALSE; |
| 365 | return strchr( float_fmts, fmt ) ? TRUE : FALSE; |
| 366 | } |
| 367 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 368 | static inline BOOL pf_is_double_format( char fmt ) |
| 369 | { |
Jesse Allen | 5c63116 | 2005-12-19 21:26:46 +0100 | [diff] [blame] | 370 | static const char float_fmts[] = "aeEfgG"; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 371 | if (!fmt) |
| 372 | return FALSE; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 373 | return strchr( float_fmts, fmt ) ? TRUE : FALSE; |
| 374 | } |
| 375 | |
| 376 | static inline BOOL pf_is_valid_format( char fmt ) |
| 377 | { |
Jesse Allen | 5c63116 | 2005-12-19 21:26:46 +0100 | [diff] [blame] | 378 | static const char float_fmts[] = "acCdeEfgGinouxX"; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 379 | if (!fmt) |
| 380 | return FALSE; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 381 | return strchr( float_fmts, fmt ) ? TRUE : FALSE; |
| 382 | } |
| 383 | |
| 384 | static void pf_rebuild_format_string( char *p, pf_flags *flags ) |
| 385 | { |
| 386 | *p++ = '%'; |
| 387 | if( flags->Sign ) |
| 388 | *p++ = flags->Sign; |
| 389 | if( flags->LeftAlign ) |
| 390 | *p++ = flags->LeftAlign; |
| 391 | if( flags->Alternate ) |
| 392 | *p++ = flags->Alternate; |
| 393 | if( flags->PadZero ) |
| 394 | *p++ = flags->PadZero; |
| 395 | if( flags->FieldLength ) |
| 396 | { |
| 397 | sprintf(p, "%d", flags->FieldLength); |
| 398 | p += strlen(p); |
| 399 | } |
Mike McCormack | 990e537 | 2005-10-27 10:20:08 +0000 | [diff] [blame] | 400 | if( flags->Precision >= 0 ) |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 401 | { |
| 402 | sprintf(p, ".%d", flags->Precision); |
| 403 | p += strlen(p); |
| 404 | } |
| 405 | *p++ = flags->Format; |
| 406 | *p++ = 0; |
| 407 | } |
| 408 | |
Jesse Allen | 419d493 | 2005-12-26 13:01:38 +0100 | [diff] [blame] | 409 | /* pf_integer_conv: prints x to buf, including alternate formats, |
| 410 | but not the sign */ |
| 411 | static void pf_integer_conv( char *buf, pf_flags *flags, LONGLONG x ) |
| 412 | { |
| 413 | unsigned int base; |
| 414 | char *digits; |
| 415 | |
| 416 | int i, j, k; |
| 417 | char tmp[40]; |
| 418 | |
| 419 | base = 10; |
| 420 | if( flags->Format == 'o' ) |
| 421 | base = 8; |
| 422 | else if( flags->Format == 'x' || flags->Format == 'X' ) |
| 423 | base = 16; |
| 424 | |
| 425 | if( flags->Format == 'X' ) |
| 426 | digits = "0123456789ABCDEFX"; |
| 427 | else |
| 428 | digits = "0123456789abcdefx"; |
| 429 | |
| 430 | if( x < 0 && ( flags->Format == 'd' || flags->Format == 'i' ) ) |
| 431 | { |
| 432 | x = -x; |
| 433 | flags->Sign = '-'; |
| 434 | } |
| 435 | |
| 436 | /* Do conversion (backwards) */ |
| 437 | i = 0; |
| 438 | if( x == 0 && flags->Precision ) |
| 439 | tmp[i++] = '0'; |
| 440 | else |
| 441 | while( x != 0 ) |
| 442 | { |
| 443 | j = (ULONGLONG) x % base; |
| 444 | x = (ULONGLONG) x / base; |
| 445 | tmp[i++] = digits[j]; |
| 446 | } |
| 447 | k = flags->Precision - i; |
| 448 | while( k-- > 0 ) |
| 449 | tmp[i++] = '0'; |
| 450 | if( flags->Alternate ) |
| 451 | { |
| 452 | if( base == 16 ) |
| 453 | { |
| 454 | tmp[i++] = digits[16]; |
| 455 | tmp[i++] = '0'; |
| 456 | } |
| 457 | else if( base == 8 && tmp[i-1] != '0' ) |
| 458 | tmp[i++] = '0'; |
| 459 | } |
| 460 | |
| 461 | /* Reverse for buf */ |
| 462 | j = 0; |
| 463 | while( i-- > 0 ) |
| 464 | buf[j++] = tmp[i]; |
| 465 | buf[j] = '\0'; |
| 466 | |
| 467 | /* Adjust precision so pf_fill won't truncate the number later */ |
| 468 | flags->Precision = strlen( buf ); |
| 469 | |
| 470 | return; |
| 471 | } |
| 472 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 473 | /********************************************************************* |
| 474 | * pf_vsnprintf (INTERNAL) |
| 475 | * |
| 476 | * implements both A and W vsnprintf functions |
| 477 | */ |
| 478 | static int pf_vsnprintf( pf_output *out, const WCHAR *format, va_list valist ) |
| 479 | { |
| 480 | int r; |
| 481 | LPCWSTR q, p = format; |
| 482 | pf_flags flags; |
| 483 | |
Rein Klazes | b6d331d | 2005-04-14 11:32:53 +0000 | [diff] [blame] | 484 | TRACE("format is %s\n",debugstr_w(format)); |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 485 | while (*p) |
| 486 | { |
| 487 | q = strchrW( p, '%' ); |
| 488 | |
| 489 | /* there's no % characters left, output the rest of the string */ |
| 490 | if( !q ) |
| 491 | { |
| 492 | r = pf_output_stringW(out, p, -1); |
| 493 | if( r<0 ) |
| 494 | return r; |
| 495 | p += r; |
| 496 | continue; |
| 497 | } |
| 498 | |
| 499 | /* there's characters before the %, output them */ |
| 500 | if( q != p ) |
| 501 | { |
| 502 | r = pf_output_stringW(out, p, q - p); |
| 503 | if( r<0 ) |
| 504 | return r; |
| 505 | p = q; |
| 506 | } |
| 507 | |
| 508 | /* we must be at a % now, skip over it */ |
| 509 | assert( *p == '%' ); |
| 510 | p++; |
| 511 | |
| 512 | /* output a single % character */ |
| 513 | if( *p == '%' ) |
| 514 | { |
| f438056 | 2005-05-10 08:27:38 +0000 | [diff] [blame] | 515 | r = pf_output_stringW(out, p++, 1); |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 516 | if( r<0 ) |
| 517 | return r; |
| 518 | continue; |
| 519 | } |
| 520 | |
| 521 | /* parse the flags */ |
| 522 | memset( &flags, 0, sizeof flags ); |
| 523 | while (*p) |
| 524 | { |
| 525 | if( *p == '+' || *p == ' ' ) |
Jesse Allen | 180326b | 2005-12-21 20:07:03 +0100 | [diff] [blame] | 526 | { |
| 527 | if ( flags.Sign != '+' ) |
| 528 | flags.Sign = *p; |
| 529 | } |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 530 | else if( *p == '-' ) |
| 531 | flags.LeftAlign = *p; |
| 532 | else if( *p == '0' ) |
| 533 | flags.PadZero = *p; |
| 534 | else if( *p == '#' ) |
| 535 | flags.Alternate = *p; |
| 536 | else |
| 537 | break; |
| 538 | p++; |
| 539 | } |
| 540 | |
| 541 | /* deal with the field width specifier */ |
| 542 | flags.FieldLength = 0; |
Rein Klazes | b6d331d | 2005-04-14 11:32:53 +0000 | [diff] [blame] | 543 | if( *p == '*' ) |
| 544 | { |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 545 | flags.FieldLength = va_arg( valist, int ); |
Rein Klazes | b6d331d | 2005-04-14 11:32:53 +0000 | [diff] [blame] | 546 | p++; |
| 547 | } |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 548 | else while( isdigit(*p) ) |
| 549 | { |
| 550 | flags.FieldLength *= 10; |
| 551 | flags.FieldLength += *p++ - '0'; |
| 552 | } |
| 553 | |
| 554 | /* deal with precision */ |
Mike McCormack | 990e537 | 2005-10-27 10:20:08 +0000 | [diff] [blame] | 555 | flags.Precision = -1; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 556 | if( *p == '.' ) |
| 557 | { |
Mike McCormack | 990e537 | 2005-10-27 10:20:08 +0000 | [diff] [blame] | 558 | flags.Precision = 0; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 559 | p++; |
| 560 | if( *p == '*' ) |
Uwe Bonnes | 0fb9ef6 | 2005-02-25 19:16:46 +0000 | [diff] [blame] | 561 | { |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 562 | flags.Precision = va_arg( valist, int ); |
Uwe Bonnes | 0fb9ef6 | 2005-02-25 19:16:46 +0000 | [diff] [blame] | 563 | p++; |
| 564 | } |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 565 | else while( isdigit(*p) ) |
| 566 | { |
| 567 | flags.Precision *= 10; |
| 568 | flags.Precision += *p++ - '0'; |
| 569 | } |
| 570 | } |
| 571 | |
| 572 | /* deal with integer width modifier */ |
| 573 | while( *p ) |
| 574 | { |
| 575 | if( *p == 'h' || *p == 'l' || *p == 'L' ) |
| 576 | { |
Jesse Allen | ee058ed | 2005-12-26 13:00:35 +0100 | [diff] [blame] | 577 | flags.IntegerLength = *p; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 578 | p++; |
| 579 | } |
Jesse Allen | 6c70942 | 2005-12-26 13:00:01 +0100 | [diff] [blame] | 580 | else if( *p == 'I' ) |
| 581 | { |
| 582 | if( *(p+1) == '6' && *(p+2) == '4' ) |
| 583 | { |
| 584 | flags.IntegerDouble++; |
| 585 | p += 3; |
| 586 | } |
| 587 | else if( *(p+1) == '3' && *(p+2) == '2' ) |
| 588 | p += 3; |
| 589 | else if( isdigit(*(p+1)) || *(p+1) == 0 ) |
| 590 | break; |
| 591 | else |
| 592 | p++; |
| 593 | } |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 594 | else if( *p == 'w' ) |
| 595 | flags.WideString = *p++; |
Mike McCormack | 5b43275 | 2005-03-04 10:47:27 +0000 | [diff] [blame] | 596 | else if( *p == 'F' ) |
| 597 | p++; /* ignore */ |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 598 | else |
| 599 | break; |
| 600 | } |
| 601 | |
| 602 | flags.Format = *p; |
| 603 | r = 0; |
| 604 | |
| 605 | /* output a unicode string */ |
Mike McCormack | 5def7dd | 2005-03-05 10:46:46 +0000 | [diff] [blame] | 606 | if( ( flags.Format == 's' && (flags.WideString || flags.IntegerLength == 'l' )) || |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 607 | ( !out->unicode && flags.Format == 'S' ) || |
| 608 | ( out->unicode && flags.Format == 's' ) ) |
| 609 | { |
| 610 | LPCWSTR str = va_arg( valist, const WCHAR * ); |
| 611 | |
| 612 | if( str ) |
| 613 | r = pf_output_format_W( out, str, -1, &flags ); |
| 614 | else |
| 615 | r = pf_output_format_A( out, "(null)", -1, &flags ); |
| 616 | } |
| 617 | |
| 618 | /* output a ASCII string */ |
| 619 | else if( ( flags.Format == 's' && flags.IntegerLength == 'h' ) || |
| 620 | ( out->unicode && flags.Format == 'S' ) || |
| 621 | ( !out->unicode && flags.Format == 's' ) ) |
| 622 | { |
| 623 | LPCSTR str = va_arg( valist, const CHAR * ); |
| 624 | |
| 625 | if( str ) |
| 626 | r = pf_output_format_A( out, str, -1, &flags ); |
| 627 | else |
| 628 | r = pf_output_format_A( out, "(null)", -1, &flags ); |
| 629 | } |
| 630 | |
| 631 | /* output a single wide character */ |
| 632 | else if( ( flags.Format == 'c' && flags.IntegerLength == 'w' ) || |
| 633 | ( out->unicode && flags.Format == 'c' ) || |
| 634 | ( !out->unicode && flags.Format == 'C' ) ) |
| 635 | { |
| 636 | WCHAR ch = va_arg( valist, int ); |
| 637 | |
| 638 | r = pf_output_format_W( out, &ch, 1, &flags ); |
| 639 | } |
| 640 | |
| 641 | /* output a single ascii character */ |
| 642 | else if( ( flags.Format == 'c' && flags.IntegerLength == 'h' ) || |
| 643 | ( out->unicode && flags.Format == 'C' ) || |
| 644 | ( !out->unicode && flags.Format == 'c' ) ) |
| 645 | { |
| 646 | CHAR ch = va_arg( valist, int ); |
| 647 | |
| 648 | r = pf_output_format_A( out, &ch, 1, &flags ); |
| 649 | } |
| 650 | |
| 651 | /* output a pointer */ |
| 652 | else if( flags.Format == 'p' ) |
| 653 | { |
Marcus Meissner | 222d74a | 2005-07-03 11:19:29 +0000 | [diff] [blame] | 654 | char pointer[11]; |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 655 | |
| 656 | flags.PadZero = 0; |
| 657 | if( flags.Alternate ) |
| 658 | sprintf(pointer, "0X%08lX", va_arg(valist, long)); |
| 659 | else |
| 660 | sprintf(pointer, "%08lX", va_arg(valist, long)); |
| 661 | r = pf_output_format_A( out, pointer, -1, &flags ); |
| 662 | } |
| 663 | |
| 664 | /* deal with %n */ |
| 665 | else if( flags.Format == 'n' ) |
| 666 | { |
| 667 | int *x = va_arg(valist, int *); |
| 668 | *x = out->used; |
| 669 | } |
| 670 | |
Jesse Allen | 419d493 | 2005-12-26 13:01:38 +0100 | [diff] [blame] | 671 | /* deal with 64-bit integers */ |
| 672 | else if( pf_is_integer_format( flags.Format ) && flags.IntegerDouble ) |
| 673 | { |
| 674 | char number[40], *x = number; |
| 675 | |
| 676 | if( flags.FieldLength >= sizeof number ) |
| 677 | x = HeapAlloc( GetProcessHeap(), 0, flags.FieldLength+1 ); |
| 678 | |
| 679 | pf_integer_conv( x, &flags, va_arg(valist, LONGLONG) ); |
| 680 | |
| 681 | r = pf_output_format_A( out, x, -1, &flags ); |
| 682 | if( x != number ) |
| 683 | HeapFree( GetProcessHeap(), 0, number ); |
| 684 | } |
| 685 | |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 686 | /* deal with integers and floats using libc's printf */ |
| 687 | else if( pf_is_valid_format( flags.Format ) ) |
| 688 | { |
| 689 | char fmt[20], number[40], *x = number; |
| 690 | |
| 691 | if( flags.FieldLength >= sizeof number ) |
| 692 | x = HeapAlloc( GetProcessHeap(), 0, flags.FieldLength+1 ); |
| 693 | |
| 694 | pf_rebuild_format_string( fmt, &flags ); |
| 695 | |
| 696 | if( pf_is_double_format( flags.Format ) ) |
Mike McCormack | cbe3fb6 | 2005-10-28 09:40:16 +0000 | [diff] [blame] | 697 | sprintf( x, fmt, va_arg(valist, double) ); |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 698 | else |
Mike McCormack | cbe3fb6 | 2005-10-28 09:40:16 +0000 | [diff] [blame] | 699 | sprintf( x, fmt, va_arg(valist, int) ); |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 700 | |
Mike McCormack | cbe3fb6 | 2005-10-28 09:40:16 +0000 | [diff] [blame] | 701 | r = pf_output_stringA( out, x, -1 ); |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 702 | if( x != number ) |
| 703 | HeapFree( GetProcessHeap(), 0, number ); |
| 704 | } |
| 705 | else |
| 706 | continue; |
| 707 | |
| 708 | if( r<0 ) |
| 709 | return r; |
| 710 | p++; |
| 711 | } |
| 712 | |
| 713 | /* check we reached the end, and null terminate the string */ |
| 714 | assert( *p == 0 ); |
Alexandre Julliard | ee603ce | 2006-01-14 17:30:02 +0100 | [diff] [blame] | 715 | pf_output_stringW( out, p, 1 ); |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 716 | |
| 717 | return out->used - 1; |
| 718 | } |
| 719 | |
| 720 | /********************************************************************* |
| 721 | * _vsnprintf (MSVCRT.@) |
| 722 | */ |
| 723 | int MSVCRT_vsnprintf( char *str, unsigned int len, |
| 724 | const char *format, va_list valist ) |
| 725 | { |
| 726 | DWORD sz; |
| 727 | LPWSTR formatW = NULL; |
| 728 | pf_output out; |
| 729 | int r; |
| 730 | |
| 731 | out.unicode = FALSE; |
| 732 | out.buf.A = str; |
| 733 | out.used = 0; |
| 734 | out.len = len; |
| 735 | |
| 736 | if( format ) |
| 737 | { |
| 738 | sz = MultiByteToWideChar( CP_ACP, 0, format, -1, NULL, 0 ); |
| 739 | formatW = HeapAlloc( GetProcessHeap(), 0, sz*sizeof(WCHAR) ); |
| 740 | MultiByteToWideChar( CP_ACP, 0, format, -1, formatW, sz ); |
| 741 | } |
| 742 | |
| 743 | r = pf_vsnprintf( &out, formatW, valist ); |
| 744 | |
| 745 | HeapFree( GetProcessHeap(), 0, formatW ); |
| 746 | |
| 747 | return r; |
| 748 | } |
| 749 | |
| 750 | /********************************************************************* |
Alexandre Julliard | ee603ce | 2006-01-14 17:30:02 +0100 | [diff] [blame] | 751 | * _snprintf (MSVCRT.@) |
| 752 | */ |
| 753 | int MSVCRT__snprintf(char *str, unsigned int len, const char *format, ...) |
| 754 | { |
| 755 | int retval; |
| 756 | va_list valist; |
| 757 | va_start(valist, format); |
| 758 | retval = MSVCRT_vsnprintf(str, len, format, valist); |
| 759 | va_end(valist); |
| 760 | return retval; |
| 761 | } |
| 762 | |
| 763 | /********************************************************************* |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 764 | * _vsnwsprintf (MSVCRT.@) |
| 765 | */ |
| 766 | int MSVCRT_vsnwprintf( MSVCRT_wchar_t *str, unsigned int len, |
Alexandre Julliard | a17b2c1 | 2006-01-24 12:21:58 +0100 | [diff] [blame] | 767 | const MSVCRT_wchar_t *format, va_list valist ) |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 768 | { |
| 769 | pf_output out; |
| 770 | |
| 771 | out.unicode = TRUE; |
| 772 | out.buf.W = str; |
| 773 | out.used = 0; |
| 774 | out.len = len; |
| 775 | |
| 776 | return pf_vsnprintf( &out, format, valist ); |
| 777 | } |
| 778 | |
| 779 | /********************************************************************* |
Alexandre Julliard | ee603ce | 2006-01-14 17:30:02 +0100 | [diff] [blame] | 780 | * _snwprintf (MSVCRT.@) |
| 781 | */ |
| 782 | int MSVCRT__snwprintf( MSVCRT_wchar_t *str, unsigned int len, const MSVCRT_wchar_t *format, ...) |
| 783 | { |
| 784 | int retval; |
| 785 | va_list valist; |
| 786 | va_start(valist, format); |
| 787 | retval = MSVCRT_vsnwprintf(str, len, format, valist); |
| 788 | va_end(valist); |
| 789 | return retval; |
| 790 | } |
| 791 | |
| 792 | /********************************************************************* |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 793 | * sprintf (MSVCRT.@) |
| 794 | */ |
| 795 | int MSVCRT_sprintf( char *str, const char *format, ... ) |
| 796 | { |
| 797 | va_list ap; |
| 798 | int r; |
| 799 | |
| 800 | va_start( ap, format ); |
| 801 | r = MSVCRT_vsnprintf( str, INT_MAX, format, ap ); |
| 802 | va_end( ap ); |
| 803 | return r; |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 804 | } |
| 805 | |
| 806 | /********************************************************************* |
| 807 | * swprintf (MSVCRT.@) |
| 808 | */ |
| 809 | int MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... ) |
| 810 | { |
| 811 | va_list ap; |
| 812 | int r; |
| 813 | |
| 814 | va_start( ap, format ); |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 815 | r = MSVCRT_vsnwprintf( str, INT_MAX, format, ap ); |
Mike McCormack | db0d0bb | 2004-06-02 00:35:09 +0000 | [diff] [blame] | 816 | va_end( ap ); |
| 817 | return r; |
| 818 | } |
| 819 | |
Jon Griffiths | d051a95 | 2003-09-23 22:50:30 +0000 | [diff] [blame] | 820 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 821 | * vswprintf (MSVCRT.@) |
| 822 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 823 | int MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, va_list args ) |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 824 | { |
Mike McCormack | 2cc5f1e | 2005-02-14 20:53:42 +0000 | [diff] [blame] | 825 | return MSVCRT_vsnwprintf( str, INT_MAX, format, args ); |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 826 | } |
| 827 | |
| 828 | /********************************************************************* |
| 829 | * wcscoll (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 830 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 831 | int MSVCRT_wcscoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 832 | { |
| 833 | /* FIXME: handle collates */ |
| 834 | return strcmpW( str1, str2 ); |
| 835 | } |
| 836 | |
| 837 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 838 | * wcspbrk (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 839 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 840 | MSVCRT_wchar_t* MSVCRT_wcspbrk( const MSVCRT_wchar_t* str, const MSVCRT_wchar_t* accept ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 841 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 842 | const MSVCRT_wchar_t* p; |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 843 | while (*str) |
| 844 | { |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 845 | for (p = accept; *p; p++) if (*p == *str) return (MSVCRT_wchar_t*)str; |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 846 | str++; |
| 847 | } |
| 848 | return NULL; |
| 849 | } |
| 850 | |
| 851 | /********************************************************************* |
Alexandre Julliard | 2ec3b96 | 2006-01-14 17:24:49 +0100 | [diff] [blame] | 852 | * wcstok (MSVCRT.@) |
| 853 | */ |
| 854 | MSVCRT_wchar_t *MSVCRT_wcstok( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim ) |
| 855 | { |
| 856 | thread_data_t *data = msvcrt_get_thread_data(); |
| 857 | MSVCRT_wchar_t *ret; |
| 858 | |
| 859 | if (!str) |
| 860 | if (!(str = data->wcstok_next)) return NULL; |
| 861 | |
| 862 | while (*str && strchrW( delim, *str )) str++; |
| 863 | if (!*str) return NULL; |
| 864 | ret = str++; |
| 865 | while (*str && !strchrW( delim, *str )) str++; |
| 866 | if (*str) *str++ = 0; |
| 867 | data->wcstok_next = str; |
| 868 | return ret; |
| 869 | } |
| 870 | |
| 871 | |
| 872 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 873 | * wctomb (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 874 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 875 | INT MSVCRT_wctomb( char *dst, MSVCRT_wchar_t ch ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 876 | { |
| 877 | return WideCharToMultiByte( CP_ACP, 0, &ch, 1, dst, 6, NULL, NULL ); |
| 878 | } |
| 879 | |
| 880 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 881 | * iswalnum (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 882 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 883 | INT MSVCRT_iswalnum( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 884 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 885 | return isalnumW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 886 | } |
| 887 | |
| 888 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 889 | * iswalpha (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 890 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 891 | INT MSVCRT_iswalpha( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 892 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 893 | return isalphaW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 894 | } |
| 895 | |
| 896 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 897 | * iswcntrl (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 898 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 899 | INT MSVCRT_iswcntrl( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 900 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 901 | return iscntrlW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 902 | } |
| 903 | |
| 904 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 905 | * iswdigit (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 906 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 907 | INT MSVCRT_iswdigit( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 908 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 909 | return isdigitW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 910 | } |
| 911 | |
| 912 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 913 | * iswgraph (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 914 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 915 | INT MSVCRT_iswgraph( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 916 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 917 | return isgraphW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 918 | } |
| 919 | |
| 920 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 921 | * iswlower (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 922 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 923 | INT MSVCRT_iswlower( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 924 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 925 | return islowerW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 926 | } |
| 927 | |
| 928 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 929 | * iswprint (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 930 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 931 | INT MSVCRT_iswprint( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 932 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 933 | return isprintW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 934 | } |
| 935 | |
| 936 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 937 | * iswpunct (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 938 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 939 | INT MSVCRT_iswpunct( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 940 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 941 | return ispunctW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 942 | } |
| 943 | |
| 944 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 945 | * iswspace (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 946 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 947 | INT MSVCRT_iswspace( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 948 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 949 | return isspaceW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 950 | } |
| 951 | |
| 952 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 953 | * iswupper (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 954 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 955 | INT MSVCRT_iswupper( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 956 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 957 | return isupperW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 958 | } |
| 959 | |
| 960 | /********************************************************************* |
Jon Griffiths | 34c786b | 2001-01-22 02:21:54 +0000 | [diff] [blame] | 961 | * iswxdigit (MSVCRT.@) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 962 | */ |
Alexandre Julliard | 5f31b32 | 2002-12-19 04:21:30 +0000 | [diff] [blame] | 963 | INT MSVCRT_iswxdigit( MSVCRT_wchar_t wc ) |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 964 | { |
Alexandre Julliard | 22c2ac7 | 2001-11-08 19:16:34 +0000 | [diff] [blame] | 965 | return isxdigitW( wc ); |
Jon Griffiths | 1db20bf | 2001-01-10 23:59:25 +0000 | [diff] [blame] | 966 | } |