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

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

EB's fixes + removal of GetIconInfo hack

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