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

Last change on this file since 2100 was 2100, checked in by sandervl, 26 years ago

compile fixes

File size: 20.1 KB
Line 
1/* $Id: wsprintf.cpp,v 1.3 1999-12-17 17:24:52 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
32ODINDEBUGCHANNEL(USER32-WSPRINTF)
33
34
35/****************************************************************************
36 * Definitions & Structures *
37 ****************************************************************************/
38
39#define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */
40#define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */
41#define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */
42#define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */
43#define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */
44#define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */
45#define WPRINTF_WIDE 0x0040 /* Wide arg ('w' prefix) */
46
47typedef enum
48{
49 WPR_UNKNOWN,
50 WPR_CHAR,
51 WPR_WCHAR,
52 WPR_STRING,
53 WPR_WSTRING,
54 WPR_SIGNED,
55 WPR_UNSIGNED,
56 WPR_HEXA
57} WPRINTF_TYPE;
58
59typedef struct
60{
61 UINT flags;
62 UINT width;
63 UINT precision;
64 WPRINTF_TYPE type;
65} WPRINTF_FORMAT;
66
67typedef union {
68 WCHAR wchar_view;
69 CHAR char_view;
70 LPCSTR lpcstr_view;
71 LPCWSTR lpcwstr_view;
72 INT int_view;
73} WPRINTF_DATA;
74
75
76/****************************************************************************
77 * Module global variables *
78 ****************************************************************************/
79
80static const CHAR null_stringA[] = "(null)";
81static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
82
83
84/***********************************************************************
85 * WPRINTF_ParseFormatA
86 *
87 * Parse a format specification. A format specification has the form:
88 *
89 * [-][#][0][width][.precision]type
90 *
91 * Return value is the length of the format specification in characters.
92 */
93static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res )
94{
95 LPCSTR p = format;
96
97 res->flags = 0;
98 res->width = 0;
99 res->precision = 0;
100 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
101 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
102 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
103 while ((*p >= '0') && (*p <= '9')) /* width field */
104 {
105 res->width = res->width * 10 + *p - '0';
106 p++;
107 }
108 if (*p == '.') /* precision field */
109 {
110 p++;
111 while ((*p >= '0') && (*p <= '9'))
112 {
113 res->precision = res->precision * 10 + *p - '0';
114 p++;
115 }
116 }
117 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
118 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
119 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
120 switch(*p)
121 {
122 case 'c':
123 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
124 break;
125 case 'C':
126 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
127 break;
128 case 'd':
129 case 'i':
130 res->type = WPR_SIGNED;
131 break;
132 case 's':
133 res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE))
134 ? WPR_WSTRING : WPR_STRING;
135 break;
136 case 'S':
137 res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE))
138 ? WPR_STRING : WPR_WSTRING;
139 break;
140 case 'u':
141 res->type = WPR_UNSIGNED;
142 break;
143 case 'X':
144 res->flags |= WPRINTF_UPPER_HEX;
145 /* fall through */
146 case 'x':
147 res->type = WPR_HEXA;
148 break;
149 default: /* unknown format char */
150 res->type = WPR_UNKNOWN;
151 p--; /* print format as normal char */
152 break;
153 }
154 return (INT)(p - format) + 1;
155}
156
157
158/***********************************************************************
159 * WPRINTF_ParseFormatW
160 *
161 * Parse a format specification. A format specification has the form:
162 *
163 * [-][#][0][width][.precision]type
164 *
165 * Return value is the length of the format specification in characters.
166 */
167static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res )
168{
169 LPCWSTR p = format;
170
171 res->flags = 0;
172 res->width = 0;
173 res->precision = 0;
174 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
175 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
176 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
177 while ((*p >= '0') && (*p <= '9')) /* width field */
178 {
179 res->width = res->width * 10 + *p - '0';
180 p++;
181 }
182 if (*p == '.') /* precision field */
183 {
184 p++;
185 while ((*p >= '0') && (*p <= '9'))
186 {
187 res->precision = res->precision * 10 + *p - '0';
188 p++;
189 }
190 }
191 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
192 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
193 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
194 switch((CHAR)*p)
195 {
196 case 'c':
197 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
198 break;
199 case 'C':
200 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
201 break;
202 case 'd':
203 case 'i':
204 res->type = WPR_SIGNED;
205 break;
206 case 's':
207 res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
208 break;
209 case 'S':
210 res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
211 break;
212 case 'u':
213 res->type = WPR_UNSIGNED;
214 break;
215 case 'X':
216 res->flags |= WPRINTF_UPPER_HEX;
217 /* fall through */
218 case 'x':
219 res->type = WPR_HEXA;
220 break;
221 default:
222 res->type = WPR_UNKNOWN;
223 p--; /* print format as normal char */
224 break;
225 }
226 return (INT)(p - format) + 1;
227}
228
229
230/***********************************************************************
231 * WPRINTF_GetLen
232 */
233static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
234 LPSTR number, UINT maxlen )
235{
236 UINT len;
237
238 if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
239 if (format->width > maxlen) format->width = maxlen;
240 switch(format->type)
241 {
242 case WPR_CHAR:
243 case WPR_WCHAR:
244 return (format->precision = 1);
245 case WPR_STRING:
246 if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
247 for (len = 0; !format->precision || (len < format->precision); len++)
248 if (!*(arg->lpcstr_view + len)) break;
249 if (len > maxlen) len = maxlen;
250 return (format->precision = len);
251 case WPR_WSTRING:
252 if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
253 for (len = 0; !format->precision || (len < format->precision); len++)
254 if (!*(arg->lpcwstr_view + len)) break;
255 if (len > maxlen) len = maxlen;
256 return (format->precision = len);
257 case WPR_SIGNED:
258 len = sprintf( number, "%d", arg->int_view );
259 break;
260 case WPR_UNSIGNED:
261 len = sprintf( number, "%u", (UINT)arg->int_view );
262 break;
263 case WPR_HEXA:
264 len = sprintf( number,
265 (format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x",
266 (UINT)arg->int_view);
267 if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
268 break;
269 default:
270 return 0;
271 }
272 if (len > maxlen) len = maxlen;
273 if (format->precision < len) format->precision = len;
274 if (format->precision > maxlen) format->precision = maxlen;
275 if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
276 format->precision = format->width;
277 return len;
278}
279
280/***********************************************************************
281 * WPRINTF_ExtractVAPtr (Not a Windows API)
282 */
283static WPRINTF_DATA WPRINTF_ExtractVAPtr( WPRINTF_FORMAT *format, va_list* args )
284{
285 WPRINTF_DATA result;
286 switch(format->type)
287 {
288 case WPR_WCHAR:
289 result.wchar_view = va_arg( *args, WCHAR ); break;
290 case WPR_CHAR:
291 result.char_view = va_arg( *args, CHAR ); break;
292 case WPR_STRING:
293 result.lpcstr_view = va_arg( *args, LPCSTR); break;
294 case WPR_WSTRING:
295 result.lpcwstr_view = va_arg( *args, LPCWSTR); break;
296 case WPR_HEXA:
297 case WPR_SIGNED:
298 case WPR_UNSIGNED:
299 result.int_view = va_arg( *args, INT ); break;
300 default:
301 result.wchar_view = 0; break;
302 }
303 return result;
304}
305
306/***********************************************************************
307 * wvsnprintfA (Not a Windows API)
308 */
309INT WINAPI wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec,
310 va_list args )
311{
312 WPRINTF_FORMAT format;
313 LPSTR p = buffer;
314 UINT i, len;
315 CHAR number[20];
316 WPRINTF_DATA argData;
317
318 while (spec && *spec && (maxlen > 1))
319 {
320 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
321 spec++;
322 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
323 spec += WPRINTF_ParseFormatA( spec, &format );
324 argData = WPRINTF_ExtractVAPtr( &format, &args );
325 len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
326 if (!(format.flags & WPRINTF_LEFTALIGN))
327 for (i = format.precision; i < format.width; i++, maxlen--)
328 *p++ = ' ';
329 switch(format.type)
330 {
331 case WPR_WCHAR:
332 *p = argData.wchar_view;
333 if (*p != '\0') p++;
334 else if (format.width > 1) *p++ = ' ';
335 else len = 0;
336 break;
337 case WPR_CHAR:
338 *p = argData.char_view;
339 if (*p != '\0') p++;
340 else if (format.width > 1) *p++ = ' ';
341 else len = 0;
342 break;
343 case WPR_STRING:
344 memcpy( p, argData.lpcstr_view, len );
345 p += len;
346 break;
347 case WPR_WSTRING:
348 {
349 LPCWSTR ptr = argData.lpcwstr_view;
350 for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
351 }
352 break;
353 case WPR_HEXA:
354 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
355 {
356 *p++ = '0';
357 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
358 maxlen -= 2;
359 len -= 2;
360 format.precision -= 2;
361 format.width -= 2;
362 }
363 /* fall through */
364 case WPR_SIGNED:
365 case WPR_UNSIGNED:
366 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
367 memcpy( p, number, len );
368 p += len;
369 /* Go to the next arg */
370 break;
371 case WPR_UNKNOWN:
372 continue;
373 }
374 if (format.flags & WPRINTF_LEFTALIGN)
375 for (i = format.precision; i < format.width; i++, maxlen--)
376 *p++ = ' ';
377 maxlen -= len;
378 }
379 *p = 0;
380 TRACE("%s\n",buffer);
381 return (maxlen > 1) ? (INT)(p - buffer) : -1;
382}
383
384
385/***********************************************************************
386 * wvsnprintfW (Not a Windows API)
387 */
388INT WINAPI wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec,
389 va_list args )
390{
391 WPRINTF_FORMAT format;
392 LPWSTR p = buffer;
393 UINT i, len;
394 CHAR number[20];
395
396 while (spec && *spec && (maxlen > 1))
397 {
398 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
399 spec++;
400 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
401 spec += WPRINTF_ParseFormatW( spec, &format );
402 len = WPRINTF_GetLen( &format, (WPRINTF_DATA*)args, number, maxlen - 1 );
403 if (!(format.flags & WPRINTF_LEFTALIGN))
404 for (i = format.precision; i < format.width; i++, maxlen--)
405 *p++ = ' ';
406 switch(format.type)
407 {
408 case WPR_WCHAR:
409 *p = va_arg( args, WCHAR );
410 if (*p != '\0') p++;
411 else if (format.width > 1) *p++ = ' ';
412 else len = 0;
413 break;
414 case WPR_CHAR:
415 *p = (WCHAR)va_arg( args, CHAR );
416 if (*p != '\0') p++;
417 else if (format.width > 1) *p++ = ' ';
418 else len = 0;
419 break;
420 case WPR_STRING:
421 {
422 LPCSTR ptr = va_arg( args, LPCSTR );
423 for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++;
424 }
425 break;
426 case WPR_WSTRING:
427 if (len) memcpy( p, va_arg( args, LPCWSTR ), len * sizeof(WCHAR) );
428 p += len;
429 break;
430 case WPR_HEXA:
431 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
432 {
433 *p++ = '0';
434 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
435 maxlen -= 2;
436 len -= 2;
437 format.precision -= 2;
438 format.width -= 2;
439 }
440 /* fall through */
441 case WPR_SIGNED:
442 case WPR_UNSIGNED:
443 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
444 for (i = 0; i < len; i++) *p++ = (WCHAR)number[i];
445 (void)va_arg( args, INT ); /* Go to the next arg */
446 break;
447 case WPR_UNKNOWN:
448 continue;
449 }
450 if (format.flags & WPRINTF_LEFTALIGN)
451 for (i = format.precision; i < format.width; i++, maxlen--)
452 *p++ = ' ';
453 maxlen -= len;
454 }
455 *p = 0;
456 return (maxlen > 1) ? (INT)(p - buffer) : -1;
457}
458
459
460/***********************************************************************
461 * wvsprintfA (USER32.587)
462 */
463ODINFUNCTION3(INT, wvsprintfA,
464 LPSTR, buffer,
465 LPCSTR, spec,
466 va_list,args )
467{
468 return wvsnprintfA( buffer, 0xffffffff, spec, args );
469}
470
471
472/***********************************************************************
473 * wvsprintfW (USER32.588)
474 */
475ODINFUNCTION3(INT, wvsprintfW,
476 LPWSTR, buffer,
477 LPCWSTR, spec,
478 va_list, args )
479{
480 return wvsnprintfW( buffer, 0xffffffff, spec, args );
481}
482
483
484/***********************************************************************
485 * wsprintfA (USER32.585)
486 */
487INT WINAPIV wsprintfA( LPSTR buffer, LPCSTR spec, ... )
488{
489 va_list valist;
490 INT res;
491
492 TRACE("for %p got:\n",buffer);
493 va_start( valist, spec );
494 res = wvsnprintfA( buffer, 0xffffffff, spec, valist );
495 va_end( valist );
496 return res;
497}
498
499
500/***********************************************************************
501 * wsprintfW (USER32.586)
502 */
503INT WINAPIV wsprintfW( LPWSTR buffer, LPCWSTR spec, ... )
504{
505 va_list valist;
506 INT res;
507
508 TRACE("wsprintfW for %p\n",buffer);
509 va_start( valist, spec );
510 res = wvsnprintfW( buffer, 0xffffffff, spec, valist );
511 va_end( valist );
512 return res;
513}
514
515
516/***********************************************************************
517 * wsnprintfA (Not a Windows API)
518 */
519INT WINAPIV wsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, ... )
520{
521 va_list valist;
522 INT res;
523
524 va_start( valist, spec );
525 res = wvsnprintfA( buffer, maxlen, spec, valist );
526 va_end( valist );
527 return res;
528}
529
530
531/***********************************************************************
532 * wsnprintfW (Not a Windows API)
533 */
534INT WINAPIV wsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, ... )
535{
536 va_list valist;
537 INT res;
538
539 va_start( valist, spec );
540 res = wvsnprintfW( buffer, maxlen, spec, valist );
541 va_end( valist );
542 return res;
543}
544
545
546
547
548#if 0
549//@@@PH old ODIN implementation 1999/11/04
550/* String Manipulation Functions */
551
552int __cdecl wsprintfA(char *lpOut, LPCSTR lpFmt, ...)
553{
554 int rc;
555 va_list argptr;
556
557#ifdef DEBUG
558 WriteLog("USER32: wsprintfA\n");
559 WriteLog("USER32: %s\n", lpFmt);
560#endif
561 va_start(argptr, lpFmt);
562 rc = O32_wvsprintf(lpOut, (char *)lpFmt, argptr);
563 va_end(argptr);
564#ifdef DEBUG
565 WriteLog("USER32: %s\n", lpOut);
566#endif
567 return(rc);
568}
569//******************************************************************************
570//******************************************************************************
571int __cdecl wsprintfW(LPWSTR lpOut, LPCWSTR lpFmt, ...)
572{
573 int rc;
574 char *lpFmtA;
575 char szOut[512];
576 va_list argptr;
577
578 dprintf(("USER32: wsprintfW(%08xh,%08xh).\n",
579 lpOut,
580 lpFmt));
581
582 lpFmtA = UnicodeToAsciiString((LPWSTR)lpFmt);
583
584 /* @@@PH 98/07/13 transform "%s" to "%ls" does the unicode magic */
585 {
586 PCHAR pszTemp;
587 PCHAR pszTemp1;
588 ULONG ulStrings;
589 ULONG ulIndex; /* temporary string counter */
590
591 for (ulStrings = 0, /* determine number of placeholders */
592 pszTemp = lpFmtA;
593
594 (pszTemp != NULL) &&
595 (*pszTemp != 0);
596
597 ulStrings++)
598 {
599 pszTemp = strstr(pszTemp,
600 "%s");
601 if (pszTemp != NULL) /* skip 2 characters */
602 {
603 pszTemp++;
604 pszTemp++;
605 }
606 else
607 break; /* leave loop immediately */
608 }
609
610 if (ulStrings != 0) /* transformation required ? */
611 {
612 /* now reallocate lpFmt */
613 ulStrings += strlen(lpFmtA); /* calculate total string length */
614 pszTemp = lpFmtA; /* save string pointer */
615 pszTemp1 = lpFmtA; /* save string pointer */
616
617 /* @@@PH allocation has to be compatible to FreeAsciiString !!! */
618 lpFmtA = (char *)malloc(ulStrings + 1);
619 if (lpFmtA == NULL) /* check proper allocation */
620 return (0); /* raise error condition */
621
622 for (ulIndex = 0;
623 ulIndex <= ulStrings;
624 ulIndex++,
625 pszTemp++)
626 {
627 if ((pszTemp[0] == '%') &&
628 (pszTemp[1] == 's') )
629 {
630 /* replace %s by %ls */
631 lpFmtA[ulIndex++] = '%';
632 lpFmtA[ulIndex ] = 'l';
633 lpFmtA[ulIndex+1] = 's';
634 }
635 else
636 lpFmtA[ulIndex] = *pszTemp; /* just copy over the character */
637 }
638
639 lpFmtA[ulStrings] = 0; /* string termination */
640
641 FreeAsciiString(pszTemp1); /* the original string is obsolete */
642 }
643 }
644
645 dprintf(("USER32: wsprintfW (%s).\n",
646 lpFmt));
647
648 va_start(argptr,
649 lpFmt);
650
651 rc = O32_wvsprintf(szOut,
652 lpFmtA,
653 argptr);
654
655 AsciiToUnicode(szOut,
656 lpOut);
657
658 FreeAsciiString(lpFmtA);
659 return(rc);
660}
661//******************************************************************************
662//******************************************************************************
663int WIN32API wvsprintfA( LPSTR lpOutput, LPCSTR lpFormat, va_list arglist)
664{
665#ifdef DEBUG
666 WriteLog("USER32: wvsprintfA\n");
667#endif
668 return O32_wvsprintf(lpOutput,lpFormat,(LPCVOID*)arglist);
669}
670//******************************************************************************
671//******************************************************************************
672int WIN32API wvsprintfW(LPWSTR lpOutput, LPCWSTR lpFormat, va_list arglist)
673{
674 int rc;
675 char szOut[256];
676 char *lpFmtA;
677
678 lpFmtA = UnicodeToAsciiString((LPWSTR)lpFormat);
679#ifdef DEBUG
680 WriteLog("USER32: wvsprintfW, DOES NOT HANDLE UNICODE STRINGS!\n");
681 WriteLog("USER32: %s\n", lpFormat);
682#endif
683 rc = O32_wvsprintf(szOut, lpFmtA, (LPCVOID)arglist);
684
685 AsciiToUnicode(szOut, lpOutput);
686#ifdef DEBUG
687 WriteLog("USER32: %s\n", lpOutput);
688#endif
689 FreeAsciiString(lpFmtA);
690 return(rc);
691}
692#endif
693
Note: See TracBrowser for help on using the repository browser.