00001
00002
00003
00004
00005
00006
00007 #ifdef __WIN32OS2__
00008 #include <odin.h>
00009 #include <odinwrap.h>
00010 #include <os2sel.h>
00011 #include <os2win.h>
00012
00013 #include <misc.h>
00014
00015 #define DBG_LOCALLOG DBG_wsprintf
00016 #include "dbglocal.h"
00017
00018 ODINDEBUGCHANNEL(USER32-WSPRINTF)
00019 #endif
00020
00021 #include <stdarg.h>
00022 #include <string.h>
00023 #include <stdio.h>
00024 #include "wine/winbase16.h"
00025 #include "windef.h"
00026 #include "wingdi.h"
00027 #include "winuser.h"
00028 #include "stackframe.h"
00029 #include "debugtools.h"
00030
00031 DEFAULT_DEBUG_CHANNEL(string);
00032
00033
00034 #define WPRINTF_LEFTALIGN 0x0001
00035 #define WPRINTF_PREFIX_HEX 0x0002
00036 #define WPRINTF_ZEROPAD 0x0004
00037 #define WPRINTF_LONG 0x0008
00038 #define WPRINTF_SHORT 0x0010
00039 #define WPRINTF_UPPER_HEX 0x0020
00040 #define WPRINTF_WIDE 0x0040
00041
00042 typedef enum
00043 {
00044 WPR_UNKNOWN,
00045 WPR_CHAR,
00046 WPR_WCHAR,
00047 WPR_STRING,
00048 WPR_WSTRING,
00049 WPR_SIGNED,
00050 WPR_UNSIGNED,
00051 WPR_HEXA
00052 } WPRINTF_TYPE;
00053
00054 typedef struct
00055 {
00056 UINT flags;
00057 UINT width;
00058 UINT precision;
00059 WPRINTF_TYPE type;
00060 } WPRINTF_FORMAT;
00061
00062 typedef union {
00063 WCHAR wchar_view;
00064 CHAR char_view;
00065 LPCSTR lpcstr_view;
00066 LPCWSTR lpcwstr_view;
00067 INT int_view;
00068 } WPRINTF_DATA;
00069
00070 static const CHAR null_stringA[] = "(null)";
00071 static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res )
00083 {
00084 LPCSTR p = format;
00085
00086 res->flags = 0;
00087 res->width = 0;
00088 res->precision = 0;
00089 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
00090 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
00091 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
00092 while ((*p >= '0') && (*p <= '9'))
00093 {
00094 res->width = res->width * 10 + *p - '0';
00095 p++;
00096 }
00097 if (*p == '.')
00098 {
00099 p++;
00100 while ((*p >= '0') && (*p <= '9'))
00101 {
00102 res->precision = res->precision * 10 + *p - '0';
00103 p++;
00104 }
00105 }
00106 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
00107 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
00108 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
00109 switch(*p)
00110 {
00111 case 'c':
00112 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
00113 break;
00114 case 'C':
00115 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
00116 break;
00117 case 'd':
00118 case 'i':
00119 res->type = WPR_SIGNED;
00120 break;
00121 case 's':
00122 res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
00123 break;
00124 case 'S':
00125 res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
00126 break;
00127 case 'u':
00128 res->type = WPR_UNSIGNED;
00129 break;
00130 case 'X':
00131 res->flags |= WPRINTF_UPPER_HEX;
00132
00133 case 'x':
00134 res->type = WPR_HEXA;
00135 break;
00136 default:
00137 res->type = WPR_UNKNOWN;
00138 p--;
00139 break;
00140 }
00141 return (INT)(p - format) + 1;
00142 }
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res )
00155 {
00156 LPCWSTR p = format;
00157
00158 res->flags = 0;
00159 res->width = 0;
00160 res->precision = 0;
00161 if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
00162 if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
00163 if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
00164 while ((*p >= '0') && (*p <= '9'))
00165 {
00166 res->width = res->width * 10 + *p - '0';
00167 p++;
00168 }
00169 if (*p == '.')
00170 {
00171 p++;
00172 while ((*p >= '0') && (*p <= '9'))
00173 {
00174 res->precision = res->precision * 10 + *p - '0';
00175 p++;
00176 }
00177 }
00178 if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
00179 else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
00180 else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
00181 switch((CHAR)*p)
00182 {
00183 case 'c':
00184 res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
00185 break;
00186 case 'C':
00187 res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
00188 break;
00189 case 'd':
00190 case 'i':
00191 res->type = WPR_SIGNED;
00192 break;
00193 case 's':
00194 res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
00195 break;
00196 case 'S':
00197 res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
00198 break;
00199 case 'u':
00200 res->type = WPR_UNSIGNED;
00201 break;
00202 case 'X':
00203 res->flags |= WPRINTF_UPPER_HEX;
00204
00205 case 'x':
00206 res->type = WPR_HEXA;
00207 break;
00208 default:
00209 res->type = WPR_UNKNOWN;
00210 p--;
00211 break;
00212 }
00213 return (INT)(p - format) + 1;
00214 }
00215
00216
00217
00218
00219
00220 static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
00221 LPSTR number, UINT maxlen )
00222 {
00223 UINT len;
00224
00225 if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
00226 if (format->width > maxlen) format->width = maxlen;
00227 switch(format->type)
00228 {
00229 case WPR_CHAR:
00230 case WPR_WCHAR:
00231 return (format->precision = 1);
00232 case WPR_STRING:
00233 if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
00234 for (len = 0; !format->precision || (len < format->precision); len++)
00235 if (!*(arg->lpcstr_view + len)) break;
00236 if (len > maxlen) len = maxlen;
00237 return (format->precision = len);
00238 case WPR_WSTRING:
00239 if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
00240 for (len = 0; !format->precision || (len < format->precision); len++)
00241 if (!*(arg->lpcwstr_view + len)) break;
00242 if (len > maxlen) len = maxlen;
00243 return (format->precision = len);
00244 case WPR_SIGNED:
00245 len = sprintf( number, "%d", arg->int_view );
00246 break;
00247 case WPR_UNSIGNED:
00248 len = sprintf( number, "%u", (UINT)arg->int_view );
00249 break;
00250 case WPR_HEXA:
00251 len = sprintf( number,
00252 (format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x",
00253 (UINT)arg->int_view);
00254 break;
00255 default:
00256 return 0;
00257 }
00258 if (len > maxlen) len = maxlen;
00259 if (format->precision < len) format->precision = len;
00260 if (format->precision > maxlen) format->precision = maxlen;
00261 if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
00262 format->precision = format->width;
00263 if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
00264 return len;
00265 }
00266
00267
00268 #ifndef __WIN32OS2__
00269
00270
00271
00272 static INT16 wvsnprintf16( LPSTR buffer, UINT16 maxlen, LPCSTR spec,
00273 LPCVOID args )
00274 {
00275 WPRINTF_FORMAT format;
00276 LPSTR p = buffer;
00277 UINT i, len;
00278 CHAR number[20];
00279 WPRINTF_DATA cur_arg;
00280 SEGPTR seg_str;
00281
00282 while (*spec && (maxlen > 1))
00283 {
00284 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
00285 spec++;
00286 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
00287 spec += WPRINTF_ParseFormatA( spec, &format );
00288 switch(format.type)
00289 {
00290 case WPR_WCHAR:
00291 case WPR_CHAR:
00292 cur_arg.char_view = VA_ARG16( args, CHAR );
00293 break;
00294 case WPR_WSTRING:
00295 case WPR_STRING:
00296 seg_str = VA_ARG16( args, SEGPTR );
00297 if (IsBadReadPtr16(seg_str, 1 )) cur_arg.lpcstr_view = "";
00298 else cur_arg.lpcstr_view = MapSL( seg_str );
00299 break;
00300 case WPR_SIGNED:
00301 if (!(format.flags & WPRINTF_LONG))
00302 {
00303 cur_arg.int_view = VA_ARG16( args, INT16 );
00304 break;
00305 }
00306
00307 case WPR_HEXA:
00308 case WPR_UNSIGNED:
00309 if (format.flags & WPRINTF_LONG)
00310 cur_arg.int_view = VA_ARG16( args, UINT );
00311 else
00312 cur_arg.int_view = VA_ARG16( args, UINT16 );
00313 break;
00314 case WPR_UNKNOWN:
00315 continue;
00316 }
00317 len = WPRINTF_GetLen( &format, &cur_arg, number, maxlen - 1 );
00318 if (!(format.flags & WPRINTF_LEFTALIGN))
00319 for (i = format.precision; i < format.width; i++, maxlen--)
00320 *p++ = ' ';
00321 switch(format.type)
00322 {
00323 case WPR_WCHAR:
00324 case WPR_CHAR:
00325 *p= cur_arg.char_view;
00326 if (*p != '\0') p++;
00327 else if (format.width > 1) *p++ = ' ';
00328 else len = 0;
00329 break;
00330 case WPR_WSTRING:
00331 case WPR_STRING:
00332 if (len) memcpy( p, cur_arg.lpcstr_view, len );
00333 p += len;
00334 break;
00335 case WPR_HEXA:
00336 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
00337 {
00338 *p++ = '0';
00339 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
00340 maxlen -= 2;
00341 len -= 2;
00342 }
00343
00344 case WPR_SIGNED:
00345 case WPR_UNSIGNED:
00346 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
00347 if (len) memcpy( p, number, len );
00348 p += len;
00349 break;
00350 case WPR_UNKNOWN:
00351 continue;
00352 }
00353 if (format.flags & WPRINTF_LEFTALIGN)
00354 for (i = format.precision; i < format.width; i++, maxlen--)
00355 *p++ = ' ';
00356 maxlen -= len;
00357 }
00358 *p = 0;
00359 return (maxlen > 1) ? (INT)(p - buffer) : -1;
00360 }
00361 #endif
00362
00363
00364
00365
00366
00367 INT WINAPI wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, va_list args )
00368 {
00369 WPRINTF_FORMAT format;
00370 LPSTR p = buffer;
00371 UINT i, len;
00372 CHAR number[20];
00373 WPRINTF_DATA argData;
00374
00375 TRACE("%p %u %s\n", buffer, maxlen, debugstr_a(spec));
00376
00377 while (*spec && (maxlen > 1))
00378 {
00379 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
00380 spec++;
00381 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
00382 spec += WPRINTF_ParseFormatA( spec, &format );
00383
00384 switch(format.type)
00385 {
00386 case WPR_WCHAR:
00387 argData.wchar_view = (WCHAR)va_arg( args, int );
00388 break;
00389 case WPR_CHAR:
00390 argData.char_view = (CHAR)va_arg( args, int );
00391 break;
00392 case WPR_STRING:
00393 argData.lpcstr_view = va_arg( args, LPCSTR );
00394 break;
00395 case WPR_WSTRING:
00396 argData.lpcwstr_view = va_arg( args, LPCWSTR );
00397 break;
00398 case WPR_HEXA:
00399 case WPR_SIGNED:
00400 case WPR_UNSIGNED:
00401 argData.int_view = va_arg( args, INT );
00402 break;
00403 default:
00404 argData.wchar_view = 0;
00405 break;
00406 }
00407
00408 len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
00409 if (!(format.flags & WPRINTF_LEFTALIGN))
00410 for (i = format.precision; i < format.width; i++, maxlen--)
00411 *p++ = ' ';
00412 switch(format.type)
00413 {
00414 case WPR_WCHAR:
00415 *p = argData.wchar_view;
00416 if (*p != '\0') p++;
00417 else if (format.width > 1) *p++ = ' ';
00418 else len = 0;
00419 break;
00420 case WPR_CHAR:
00421 *p = argData.char_view;
00422 if (*p != '\0') p++;
00423 else if (format.width > 1) *p++ = ' ';
00424 else len = 0;
00425 break;
00426 case WPR_STRING:
00427 memcpy( p, argData.lpcstr_view, len );
00428 p += len;
00429 break;
00430 case WPR_WSTRING:
00431 {
00432 LPCWSTR ptr = argData.lpcwstr_view;
00433 for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
00434 }
00435 break;
00436 case WPR_HEXA:
00437 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
00438 {
00439 *p++ = '0';
00440 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
00441 maxlen -= 2;
00442 len -= 2;
00443 }
00444
00445 case WPR_SIGNED:
00446 case WPR_UNSIGNED:
00447 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
00448 memcpy( p, number, len );
00449 p += len;
00450 break;
00451 case WPR_UNKNOWN:
00452 continue;
00453 }
00454 if (format.flags & WPRINTF_LEFTALIGN)
00455 for (i = format.precision; i < format.width; i++, maxlen--)
00456 *p++ = ' ';
00457 maxlen -= len;
00458 }
00459 *p = 0;
00460 TRACE("%s\n",debugstr_a(buffer));
00461 return (maxlen > 1) ? (INT)(p - buffer) : -1;
00462 }
00463
00464
00465
00466
00467
00468 INT WINAPI wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, va_list args )
00469 {
00470 WPRINTF_FORMAT format;
00471 LPWSTR p = buffer;
00472 UINT i, len;
00473 CHAR number[20];
00474 WPRINTF_DATA argData;
00475
00476 TRACE("%p %u %s\n", buffer, maxlen, debugstr_w(spec));
00477
00478 while (*spec && (maxlen > 1))
00479 {
00480 if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
00481 spec++;
00482 if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
00483 spec += WPRINTF_ParseFormatW( spec, &format );
00484
00485 switch(format.type)
00486 {
00487 case WPR_WCHAR:
00488 argData.wchar_view = (WCHAR)va_arg( args, int );
00489 break;
00490 case WPR_CHAR:
00491 argData.char_view = (CHAR)va_arg( args, int );
00492 break;
00493 case WPR_STRING:
00494 argData.lpcstr_view = va_arg( args, LPCSTR );
00495 break;
00496 case WPR_WSTRING:
00497 argData.lpcwstr_view = va_arg( args, LPCWSTR );
00498 break;
00499 case WPR_HEXA:
00500 case WPR_SIGNED:
00501 case WPR_UNSIGNED:
00502 argData.int_view = va_arg( args, INT );
00503 break;
00504 default:
00505 argData.wchar_view = 0;
00506 break;
00507 }
00508
00509 len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
00510 if (!(format.flags & WPRINTF_LEFTALIGN))
00511 for (i = format.precision; i < format.width; i++, maxlen--)
00512 *p++ = ' ';
00513 switch(format.type)
00514 {
00515 case WPR_WCHAR:
00516 *p = argData.wchar_view;
00517 if (*p != '\0') p++;
00518 else if (format.width > 1) *p++ = ' ';
00519 else len = 0;
00520 break;
00521 case WPR_CHAR:
00522 *p = argData.char_view;
00523 if (*p != '\0') p++;
00524 else if (format.width > 1) *p++ = ' ';
00525 else len = 0;
00526 break;
00527 case WPR_STRING:
00528 {
00529 LPCSTR ptr = argData.lpcstr_view;
00530 for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++;
00531 }
00532 break;
00533 case WPR_WSTRING:
00534 if (len) memcpy( p, argData.lpcwstr_view, len * sizeof(WCHAR) );
00535 p += len;
00536 break;
00537 case WPR_HEXA:
00538 if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
00539 {
00540 *p++ = '0';
00541 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
00542 maxlen -= 2;
00543 len -= 2;
00544 }
00545
00546 case WPR_SIGNED:
00547 case WPR_UNSIGNED:
00548 for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
00549 for (i = 0; i < len; i++) *p++ = (WCHAR)number[i];
00550 break;
00551 case WPR_UNKNOWN:
00552 continue;
00553 }
00554 if (format.flags & WPRINTF_LEFTALIGN)
00555 for (i = format.precision; i < format.width; i++, maxlen--)
00556 *p++ = ' ';
00557 maxlen -= len;
00558 }
00559 *p = 0;
00560 TRACE("%s\n",debugstr_w(buffer));
00561 return (maxlen > 1) ? (INT)(p - buffer) : -1;
00562 }
00563
00564
00565 #ifndef __WIN32OS2__
00566
00567
00568
00569 INT16 WINAPI wvsprintf16( LPSTR buffer, LPCSTR spec, LPCVOID args )
00570 {
00571 INT16 res;
00572
00573 TRACE("for %p got:\n",buffer);
00574 res = wvsnprintf16( buffer, 1024, spec, args );
00575 return ( res == -1 ) ? 1024 : res;
00576 }
00577 #endif
00578
00579
00580
00581
00582
00583 INT WINAPI wvsprintfA( LPSTR buffer, LPCSTR spec, va_list args )
00584 {
00585 INT res = wvsnprintfA( buffer, 1024, spec, args );
00586 return ( res == -1 ) ? 1024 : res;
00587 }
00588
00589
00590
00591
00592
00593 INT WINAPI wvsprintfW( LPWSTR buffer, LPCWSTR spec, va_list args )
00594 {
00595 INT res = wvsnprintfW( buffer, 1024, spec, args );
00596 return ( res == -1 ) ? 1024 : res;
00597 }
00598
00599 #ifndef __WIN32OS2__
00600
00601
00602
00603 INT16 WINAPIV wsprintf16(void)
00604 {
00605 VA_LIST16 valist;
00606 INT16 res;
00607 SEGPTR buffer, spec;
00608
00609 VA_START16( valist );
00610 buffer = VA_ARG16( valist, SEGPTR );
00611 spec = VA_ARG16( valist, SEGPTR );
00612 res = wvsnprintf16( MapSL(buffer), 1024, MapSL(spec), valist );
00613 VA_END16( valist );
00614 return ( res == -1 ) ? 1024 : res;
00615 }
00616 #endif
00617
00618
00619
00620
00621
00622 INT WINAPIV wsprintfA( LPSTR buffer, LPCSTR spec, ... )
00623 {
00624 va_list valist;
00625 INT res;
00626
00627 va_start( valist, spec );
00628 res = wvsnprintfA( buffer, 1024, spec, valist );
00629 va_end( valist );
00630 return ( res == -1 ) ? 1024 : res;
00631 }
00632
00633
00634
00635
00636
00637 INT WINAPIV wsprintfW( LPWSTR buffer, LPCWSTR spec, ... )
00638 {
00639 va_list valist;
00640 INT res;
00641
00642 va_start( valist, spec );
00643 res = wvsnprintfW( buffer, 1024, spec, valist );
00644 va_end( valist );
00645 return ( res == -1 ) ? 1024 : res;
00646 }
00647
00648
00649
00650
00651 INT WINAPIV wsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, ... )
00652 {
00653 va_list valist;
00654 INT res;
00655
00656 va_start( valist, spec );
00657 res = wvsnprintfA( buffer, maxlen, spec, valist );
00658 va_end( valist );
00659 return res;
00660 }
00661
00662
00663
00664
00665 INT WINAPIV wsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, ... )
00666 {
00667 va_list valist;
00668 INT res;
00669
00670 va_start( valist, spec );
00671 res = wvsnprintfW( buffer, maxlen, spec, valist );
00672 va_end( valist );
00673 return res;
00674 }