source: trunk/src/user32/wsprintf.cpp@ 3209

Last change on this file since 3209 was 3209, checked in by sandervl, 25 years ago

replaced writelog calls

File size: 16.0 KB
Line 
1/* $Id: wsprintf.cpp,v 1.7 2000-03-23 23:06:54 sandervl Exp $ */
2
3/*
4 * Win32 misc user32 API functions for OS/2
5 * wsprintf functions
6 *
7 * Copyright 1996 Alexandre Julliard
8 * Copyright 1999 Patrick Haller
9 *
10 * Project Odin Software License can be found in LICENSE.TXT
11 */
12
13
14/****************************************************************************
15 * Includes *
16 ****************************************************************************/
17
18#include <odin.h>
19#include <odinwrap.h>
20#include <os2sel.h>
21#include <os2win.h>
22
23#include <stdarg.h>
24#include <string.h>
25#include "stackframe.h"
26#include "module.h"
27#include "global.h"
28#include "debugtools.h"
29
30#include <misc.h>
31
32#define DBG_LOCALLOG DBG_wsprintf
33#include "dbglocal.h"
34
35ODINDEBUGCHANNEL(USER32-WSPRINTF)
36
37
38/****************************************************************************
39 * Definitions & Structures *
40 ****************************************************************************/
41
42#define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */
43#define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */
44#define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */
45#define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */
46#define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */
47#define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */
48#define WPRINTF_WIDE 0x0040 /* Wide arg ('w' prefix) */
49
50typedef enum
51{
52 WPR_UNKNOWN,
53 WPR_CHAR,
54 WPR_WCHAR,
55 WPR_STRING,
56 WPR_WSTRING,
57 WPR_SIGNED,
58 WPR_UNSIGNED,
59 WPR_HEXA
60} WPRINTF_TYPE;
61
62typedef struct
63{
64 UINT flags;
65 UINT width;
66 UINT precision;
67 WPRINTF_TYPE type;
68} WPRINTF_FORMAT;
69
70typedef union {
71 WCHAR wchar_view;
72 CHAR char_view;
73 LPCSTR lpcstr_view;
74 LPCWSTR lpcwstr_view;
75 INT int_view;
76} WPRINTF_DATA;
77
78
79/****************************************************************************
80 * Module global variables *
81 ****************************************************************************/
82
83static const CHAR null_stringA[] = "(null)";
84static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
85
86
87/***********************************************************************
88 * WPRINTF_ParseFormatA
89 *
90 * Parse a format specification. A format specification has the form:
91 *
92 * [-][#][0][width][.precision]type
93 *
94 * Return value is the length of the format specification in characters.
95 */
96static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res )
97{
98 LPCSTR p = format;
99
100 res->flags = 0;
101 res->width = 0;
102 res->precision = 0;
103 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
104 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
105 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
106 while ((*p >= '0') && (*p <= '9')) /* width field */
107 {
108 res->width = res->width * 10 + *p - '0';
109 p++;
110 }
111 if (*p == '.') /* precision field */
112 {
113 p++;
114 while ((*p >= '0') && (*p <= '9'))
115 {
116 res->precision = res->precision * 10 + *p - '0';
117 p++;
118 }
119 }
120 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
121 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
122 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
123 switch(*p)
124 {
125 case 'c':
126 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
127 break;
128 case 'C':
129 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
130 break;
131 case 'd':
132 case 'i':
133 res->type = WPR_SIGNED;
134 break;
135 case 's':
136 res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE))
137 ? WPR_WSTRING : WPR_STRING;
138 break;
139 case 'S':
140 res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE))
141 ? WPR_STRING : WPR_WSTRING;
142 break;
143 case 'u':
144 res->type = WPR_UNSIGNED;
145 break;
146 case 'X':
147 res->flags |= WPRINTF_UPPER_HEX;
148 /* fall through */
149 case 'x':
150 res->type = WPR_HEXA;
151 break;
152 default: /* unknown format char */
153 res->type = WPR_UNKNOWN;
154 p--; /* print format as normal char */
155 break;
156 }
157 return (INT)(p - format) + 1;
158}
159
160
161/***********************************************************************
162 * WPRINTF_ParseFormatW
163 *
164 * Parse a format specification. A format specification has the form:
165 *
166 * [-][#][0][width][.precision]type
167 *
168 * Return value is the length of the format specification in characters.
169 */
170static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res )
171{
172 LPCWSTR p = format;
173
174 res->flags = 0;
175 res->width = 0;
176 res->precision = 0;
177 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
178 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
179 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
180 while ((*p >= '0') && (*p <= '9')) /* width field */
181 {
182 res->width = res->width * 10 + *p - '0';
183 p++;
184 }
185 if (*p == '.') /* precision field */
186 {
187 p++;
188 while ((*p >= '0') && (*p <= '9'))
189 {
190 res->precision = res->precision * 10 + *p - '0';
191 p++;
192 }
193 }
194 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
195 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
196 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
197 switch((CHAR)*p)
198 {
199 case 'c':
200 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
201 break;
202 case 'C':
203 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
204 break;
205 case 'd':
206 case 'i':
207 res->type = WPR_SIGNED;
208 break;
209 case 's':
210 res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
211 break;
212 case 'S':
213 res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
214 break;
215 case 'u':
216 res->type = WPR_UNSIGNED;
217 break;
218 case 'X':
219 res->flags |= WPRINTF_UPPER_HEX;
220 /* fall through */
221 case 'x':
222 res->type = WPR_HEXA;
223 break;
224 default:
225 res->type = WPR_UNKNOWN;
226 p--; /* print format as normal char */
227 break;
228 }
229 return (INT)(p - format) + 1;
230}
231
232
233/***********************************************************************
234 * WPRINTF_GetLen
235 */
236static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
237 LPSTR number, UINT maxlen )
238{
239 UINT len;
240
241 if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
242 if (format->width > maxlen) format->width = maxlen;
243 switch(format->type)
244 {
245 case WPR_CHAR:
246 case WPR_WCHAR:
247 return (format->precision = 1);
248 case WPR_STRING:
249 if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
250 for (len = 0; !format->precision || (len < format->precision); len++)
251 if (!*(arg->lpcstr_view + len)) break;
252 if (len > maxlen) len = maxlen;
253 return (format->precision = len);
254 case WPR_WSTRING:
255 if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
256 for (len = 0; !format->precision || (len < format->precision); len++)
257 if (!*(arg->lpcwstr_view + len)) break;
258 if (len > maxlen) len = maxlen;
259 return (format->precision = len);
260 case WPR_SIGNED:
261 len = sprintf( number, "%d", arg->int_view );
262 break;
263 case WPR_UNSIGNED:
264 len = sprintf( number, "%u", (UINT)arg->int_view );
265 break;
266 case WPR_HEXA:
267 len = sprintf( number,
268 (format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x",
269 (UINT)arg->int_view);
270 if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
271 break;
272 default:
273 return 0;
274 }
275 if (len > maxlen) len = maxlen;
276 if (format->precision < len) format->precision = len;
277 if (format->precision > maxlen) format->precision = maxlen;
278 if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
279 format->precision = format->width;
280 return len;
281}
282
283/***********************************************************************
284 * WPRINTF_ExtractVAPtr (Not a Windows API)
285 */
286static WPRINTF_DATA WPRINTF_ExtractVAPtr( WPRINTF_FORMAT *format, va_list* args )
287{
288 WPRINTF_DATA result;
289 switch(format->type)
290 {
291 case WPR_WCHAR:
292 result.wchar_view = va_arg( *args, WCHAR ); break;
293 case WPR_CHAR:
294 result.char_view = va_arg( *args, CHAR ); break;
295 case WPR_STRING:
296 result.lpcstr_view = va_arg( *args, LPCSTR); break;
297 case WPR_WSTRING:
298 result.lpcwstr_view = va_arg( *args, LPCWSTR); break;
299 case WPR_HEXA:
300 case WPR_SIGNED:
301 case WPR_UNSIGNED:
302 result.int_view = va_arg( *args, INT ); break;
303 default:
304 result.wchar_view = 0; break;
305 }
306 return result;
307}
308
309/***********************************************************************
310 * wvsnprintfA (Not a Windows API)
311 */
312INT WINAPI wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec,
313 va_list args )
314{
315 WPRINTF_FORMAT format;
316 LPSTR p = buffer;
317 UINT i, len;
318 CHAR number[20];
319 WPRINTF_DATA argData;
320
321 while (spec && *spec && (maxlen > 1))
322 {
323 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
324 spec++;
325 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
326 spec += WPRINTF_ParseFormatA( spec, &format );
327 argData = WPRINTF_ExtractVAPtr( &format, &args );
328 len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
329 if (!(format.flags & WPRINTF_LEFTALIGN))
330 for (i = format.precision; i < format.width; i++, maxlen--)
331 *p++ = ' ';
332 switch(format.type)
333 {
334 case WPR_WCHAR:
335 *p = argData.wchar_view;
336 if (*p != '\0') p++;
337 else if (format.width > 1) *p++ = ' ';
338 else len = 0;
339 break;
340 case WPR_CHAR:
341 *p = argData.char_view;
342 if (*p != '\0') p++;
343 else if (format.width > 1) *p++ = ' ';
344 else len = 0;
345 break;
346 case WPR_STRING:
347 memcpy( p, argData.lpcstr_view, len );
348 p += len;
349 break;
350 case WPR_WSTRING:
351 {
352 LPCWSTR ptr = argData.lpcwstr_view;
353 for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
354 }
355 break;
356 case WPR_HEXA:
357 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
358 {
359 *p++ = '0';
360 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
361 maxlen -= 2;
362 len -= 2;
363 format.precision -= 2;
364 format.width -= 2;
365 }
366 /* fall through */
367 case WPR_SIGNED:
368 case WPR_UNSIGNED:
369 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
370 memcpy( p, number, len );
371 p += len;
372 /* Go to the next arg */
373 break;
374 case WPR_UNKNOWN:
375 continue;
376 }
377 if (format.flags & WPRINTF_LEFTALIGN)
378 for (i = format.precision; i < format.width; i++, maxlen--)
379 *p++ = ' ';
380 maxlen -= len;
381 }
382 *p = 0;
383 TRACE("%s\n",buffer);
384 return (maxlen > 1) ? (INT)(p - buffer) : -1;
385}
386
387
388/***********************************************************************
389 * wvsnprintfW (Not a Windows API)
390 */
391INT WINAPI wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec,
392 va_list args )
393{
394 WPRINTF_FORMAT format;
395 LPWSTR p = buffer;
396 UINT i, len;
397 CHAR number[20];
398
399 while (spec && *spec && (maxlen > 1))
400 {
401 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
402 spec++;
403 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
404 spec += WPRINTF_ParseFormatW( spec, &format );
405 len = WPRINTF_GetLen( &format, (WPRINTF_DATA*)args, number, maxlen - 1 );
406 if (!(format.flags & WPRINTF_LEFTALIGN))
407 for (i = format.precision; i < format.width; i++, maxlen--)
408 *p++ = ' ';
409 switch(format.type)
410 {
411 case WPR_WCHAR:
412 *p = va_arg( args, WCHAR );
413 if (*p != '\0') p++;
414 else if (format.width > 1) *p++ = ' ';
415 else len = 0;
416 break;
417 case WPR_CHAR:
418 *p = (WCHAR)va_arg( args, CHAR );
419 if (*p != '\0') p++;
420 else if (format.width > 1) *p++ = ' ';
421 else len = 0;
422 break;
423 case WPR_STRING:
424 {
425 LPCSTR ptr = va_arg( args, LPCSTR );
426 for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++;
427 }
428 break;
429 case WPR_WSTRING:
430 if (len) memcpy( p, va_arg( args, LPCWSTR ), len * sizeof(WCHAR) );
431 p += len;
432 break;
433 case WPR_HEXA:
434 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
435 {
436 *p++ = '0';
437 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
438 maxlen -= 2;
439 len -= 2;
440 format.precision -= 2;
441 format.width -= 2;
442 }
443 /* fall through */
444 case WPR_SIGNED:
445 case WPR_UNSIGNED:
446 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
447 for (i = 0; i < len; i++) *p++ = (WCHAR)number[i];
448 (void)va_arg( args, INT ); /* Go to the next arg */
449 break;
450 case WPR_UNKNOWN:
451 continue;
452 }
453 if (format.flags & WPRINTF_LEFTALIGN)
454 for (i = format.precision; i < format.width; i++, maxlen--)
455 *p++ = ' ';
456 maxlen -= len;
457 }
458 *p = 0;
459 return (maxlen > 1) ? (INT)(p - buffer) : -1;
460}
461
462
463/***********************************************************************
464 * wvsprintfA (USER32.587)
465 */
466ODINFUNCTION3(INT, wvsprintfA,
467 LPSTR, buffer,
468 LPCSTR, spec,
469 va_list,args )
470{
471 return wvsnprintfA( buffer, 0xffffffff, spec, args );
472}
473
474
475/***********************************************************************
476 * wvsprintfW (USER32.588)
477 */
478ODINFUNCTION3(INT, wvsprintfW,
479 LPWSTR, buffer,
480 LPCWSTR, spec,
481 va_list, args )
482{
483 return wvsnprintfW( buffer, 0xffffffff, spec, args );
484}
485
486
487/***********************************************************************
488 * wsprintfA (USER32.585)
489 */
490INT WINAPIV wsprintfA( LPSTR buffer, LPCSTR spec, ... )
491{
492 va_list valist;
493 INT res;
494
495 TRACE("for %p got:\n",buffer);
496 va_start( valist, spec );
497 res = wvsnprintfA( buffer, 0xffffffff, spec, valist );
498 va_end( valist );
499 return res;
500}
501
502
503/***********************************************************************
504 * wsprintfW (USER32.586)
505 */
506INT WINAPIV wsprintfW( LPWSTR buffer, LPCWSTR spec, ... )
507{
508 va_list valist;
509 INT res;
510
511 TRACE("wsprintfW for %p\n",buffer);
512 va_start( valist, spec );
513 res = wvsnprintfW( buffer, 0xffffffff, spec, valist );
514 va_end( valist );
515 return res;
516}
517
518
519/***********************************************************************
520 * wsnprintfA (Not a Windows API)
521 */
522INT WINAPIV wsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, ... )
523{
524 va_list valist;
525 INT res;
526
527 va_start( valist, spec );
528 res = wvsnprintfA( buffer, maxlen, spec, valist );
529 va_end( valist );
530 return res;
531}
532
533
534/***********************************************************************
535 * wsnprintfW (Not a Windows API)
536 */
537INT WINAPIV wsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, ... )
538{
539 va_list valist;
540 INT res;
541
542 va_start( valist, spec );
543 res = wvsnprintfW( buffer, maxlen, spec, valist );
544 va_end( valist );
545 return res;
546}
547
548
549
550
551
Note: See TracBrowser for help on using the repository browser.