diff --git a/reactos/lib/user32/misc/sprintf.c b/reactos/lib/user32/misc/sprintf.c index dce05814632..8c3c9437b70 100644 --- a/reactos/lib/user32/misc/sprintf.c +++ b/reactos/lib/user32/misc/sprintf.c @@ -1,13 +1,34 @@ -/* $Id: sprintf.c,v 1.7 2003/07/10 21:04:31 chorns Exp $ - * - * user32.dll - * +/* * wsprintf functions * * Copyright 1996 Alexandre Julliard * - * 1999-05-01 (Emanuele Aliberti) - * Adapted from Wine to ReactOS + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * NOTE: + * This code is duplicated in shlwapi. If you change something here make sure + * to change it in shlwapi too. + */ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS User32 + * PURPOSE: [w]sprintf functions + * FILE: lib/user32/sprintf.c + * PROGRAMER: Steven Edwards + * REVISION HISTORY: 2003/07/13 Merged from wine user/wsprintf.c + * NOTES: Adapted from Wine */ #include @@ -25,923 +46,480 @@ typedef enum { - WPR_UNKNOWN, - WPR_CHAR, - WPR_WCHAR, - WPR_STRING, - WPR_WSTRING, - WPR_SIGNED, - WPR_UNSIGNED, - WPR_HEXA - + WPR_UNKNOWN, + WPR_CHAR, + WPR_WCHAR, + WPR_STRING, + WPR_WSTRING, + WPR_SIGNED, + WPR_UNSIGNED, + WPR_HEXA } WPRINTF_TYPE; - typedef struct { - UINT flags; - UINT width; - UINT precision; - WPRINTF_TYPE type; - + UINT flags; + UINT width; + UINT precision; + WPRINTF_TYPE type; } WPRINTF_FORMAT; +typedef union { + WCHAR wchar_view; + CHAR char_view; + LPCSTR lpcstr_view; + LPCWSTR lpcwstr_view; + INT int_view; +} WPRINTF_DATA; -static const LPSTR null_stringA = "(null)"; -static const LPWSTR null_stringW = L"(null)"; - - -/* === COMMON === */ - +static const CHAR null_stringA[] = "(null)"; +static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 }; /*********************************************************************** - * NAME PRIVATE - * WPRINTF_GetLen + * WPRINTF_ParseFormatA * - * DESCRIPTION - * ? + * Parse a format specification. A format specification has the form: * - * ARGUMENTS - * format - * ? - * arg - * ? - * number - * ? - * maxlen - * ? + * [-][#][0][width][.precision]type * - * RETURN VALUE - * ? + * Return value is the length of the format specification in characters. */ -static -UINT -WPRINTF_GetLen( - WPRINTF_FORMAT *format, - LPCVOID arg, - LPSTR number, - UINT maxlen - ) +static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res ) { - UINT len; + LPCSTR p = format; - if (format->flags & WPRINTF_LEFTALIGN) - { - format->flags &= ~WPRINTF_ZEROPAD; - } - if (format->width > maxlen) - { - format->width = maxlen; - } - switch(format->type) - { - case WPR_CHAR: - case WPR_WCHAR: - return (format->precision = 1); - - case WPR_STRING: - if (!*(LPCSTR *)arg) - { - *(LPCSTR *)arg = null_stringA; - } - for ( len = 0; - (!format->precision || (len < format->precision)); - len++ - ) - { - if (!*(*(LPCSTR *)arg + len)) - { - break; - } - } - if (len > maxlen) - { - len = maxlen; - } - return (format->precision = len); - - case WPR_WSTRING: - if (!*(LPCWSTR *)arg) - { - *(LPCWSTR *)arg = null_stringW; - } - for ( len = 0; - (!format->precision || (len < format->precision)); - len++ - ) - { - if (!*(*(LPCWSTR *)arg + len)) - break; - } - if (len > maxlen) - { - len = maxlen; - } - return (format->precision = len); - - case WPR_SIGNED: - len = sprintf( - number, - "%d", - *(INT *) arg - ); - break; - - case WPR_UNSIGNED: - len = sprintf( - number, - "%u", - *(UINT *) arg - ); - break; - - case WPR_HEXA: - len = sprintf( - number, - ((format->flags & WPRINTF_UPPER_HEX) - ? "%X" - : "%x"), - *(UINT *) arg - ); - if (format->flags & WPRINTF_PREFIX_HEX) - { - len += 2; - } - break; - - default: - return 0; - } - if (len > maxlen) - { - len = maxlen; - } - if (format->precision < len) - { - format->precision = len; - } - if (format->precision > maxlen) - { - format->precision = maxlen; - } - if ( (format->flags & WPRINTF_ZEROPAD) - && (format->width > format->precision) - ) - { - format->precision = format->width; - } - return len; -} - - -/* === ANSI VERSION === */ - - -/*********************************************************************** - * NAME PRIVATE - * WPRINTF_ParseFormatA - * - * DESCRIPTION - * Parse a format specification. A format specification has the - * form: - * - * [-][#][0][width][.precision]type - * - * ARGUMENTS - * format - * ? - * res - * ? - * - * RETURN VALUE - * The length of the format specification in characters. - */ -static -INT -WPRINTF_ParseFormatA( - LPCSTR format, - WPRINTF_FORMAT *res - ) -{ - LPCSTR p = format; - - res->flags = 0; - res->width = 0; - res->precision = 0; - if (*p == '-') - { - res->flags |= WPRINTF_LEFTALIGN; - p++; - } - if (*p == '#') - { - res->flags |= WPRINTF_PREFIX_HEX; - p++; - } - if (*p == '0') - { - res->flags |= WPRINTF_ZEROPAD; - p++; - } - while ((*p >= '0') && (*p <= '9')) /* width field */ - { - res->width = - (res->width * 10) - + (*p - '0'); - p++; - } - if (*p == '.') /* precision field */ - { - p++; - while ((*p >= '0') && (*p <= '9')) - { - res->precision = - (res->precision * 10) - + (*p - '0'); - p++; - } - } - if (*p == 'l') - { - res->flags |= WPRINTF_LONG; - p++; - } - else if (*p == 'h') - { - res->flags |= WPRINTF_SHORT; - p++; - } - else if (*p == 'w') - { - res->flags |= WPRINTF_WIDE; - p++; - } - - switch (*p) - { - case 'c': - res->type = - (res->flags & WPRINTF_LONG) - ? WPR_WCHAR - : WPR_CHAR; - break; - - case 'C': - res->type = - (res->flags & WPRINTF_SHORT) - ? WPR_CHAR - : WPR_WCHAR; - break; - - case 'd': - case 'i': - res->type = WPR_SIGNED; - break; - - case 's': - res->type = - (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) - ? WPR_WSTRING - : WPR_STRING; - break; - - case 'S': - res->type = - (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) - ? WPR_STRING - : WPR_WSTRING; - break; - - case 'u': - res->type = WPR_UNSIGNED; - break; - - case 'X': - res->flags |= WPRINTF_UPPER_HEX; - /* fall through */ - - case 'x': - res->type = WPR_HEXA; - break; - - default: /* unknown format char */ - res->type = WPR_UNKNOWN; - p--; /* print format as normal char */ - break; - - } /* switch */ - - return (INT) (p - format) + 1; + res->flags = 0; + res->width = 0; + res->precision = 0; + if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; } + if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } + if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; } + while ((*p >= '0') && (*p <= '9')) /* width field */ + { + res->width = res->width * 10 + *p - '0'; + p++; + } + if (*p == '.') /* precision field */ + { + p++; + while ((*p >= '0') && (*p <= '9')) + { + res->precision = res->precision * 10 + *p - '0'; + p++; + } + } + if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; } + else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; } + else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; } + switch(*p) + { + case 'c': + res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR; + break; + case 'C': + res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR; + break; + case 'd': + case 'i': + res->type = WPR_SIGNED; + break; + case 's': + res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING; + break; + case 'S': + res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING; + break; + case 'u': + res->type = WPR_UNSIGNED; + break; + case 'X': + res->flags |= WPRINTF_UPPER_HEX; + /* fall through */ + case 'x': + res->type = WPR_HEXA; + break; + default: /* unknown format char */ + res->type = WPR_UNKNOWN; + p--; /* print format as normal char */ + break; + } + return (INT)(p - format) + 1; } /*********************************************************************** - * NAME PRIVATE - * wvsnprintfA (Not a Windows API) + * WPRINTF_ParseFormatW + * + * Parse a format specification. A format specification has the form: + * + * [-][#][0][width][.precision]type + * + * Return value is the length of the format specification in characters. */ -INT -STDCALL -wvsnprintfA( - LPSTR buffer, - UINT maxlen, - LPCSTR spec, - va_list args - ) +static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res ) { - WPRINTF_FORMAT format; - LPSTR p = buffer; - UINT i; - UINT len; - CHAR number [20]; + LPCWSTR p = format; - while (*spec && (maxlen > 1)) - { - if (*spec != '%') - { - *p++ = *spec++; - maxlen--; - continue; - } - spec++; - if (*spec == '%') - { - *p++ = *spec++; - maxlen--; - continue; - } - spec += WPRINTF_ParseFormatA( - spec, - & format - ); - len = WPRINTF_GetLen( - & format, - args, - number, - (maxlen - 1) - ); - if (!(format.flags & WPRINTF_LEFTALIGN)) - { - for ( i = format.precision; - (i < format.width); - i++, maxlen-- - ) - { - *p++ = ' '; - } - } - switch (format.type) - { - case WPR_WCHAR: - if ((*p = (CHAR) (WCHAR) va_arg( args, int))) - { - p++; - } - else if (format.width > 1) - { - *p++ = ' '; - } - else - { - len = 0; - } - break; - - case WPR_CHAR: - if ((*p = (CHAR) va_arg( args, int ))) - { - p++; - } - else if (format.width > 1) - { - *p++ = ' '; - } - else - { - len = 0; - } - break; - - case WPR_STRING: - memcpy( - p, - va_arg( args, LPCSTR ), - len - ); - p += len; - break; - - case WPR_WSTRING: - { - LPCWSTR ptr = va_arg( args, LPCWSTR ); - - for ( i = 0; - (i < len); - i++ - ) - { - *p++ = (CHAR) *ptr++; - } - } - break; - - case WPR_HEXA: - if ( (format.flags & WPRINTF_PREFIX_HEX) - && (maxlen > 3) - ) - { - *p++ = '0'; - *p++ = (format.flags & WPRINTF_UPPER_HEX) - ? 'X' - : 'x'; - maxlen -= 2; - len -= 2; - format.precision -= 2; - format.width -= 2; - } - /* fall through */ - - case WPR_SIGNED: - case WPR_UNSIGNED: - for ( i = len; - (i < format.precision); - i++, maxlen-- - ) - { - *p++ = '0'; - } - memcpy( - p, - number, - len - ); - p += len; - (void) va_arg( args, INT ); /* Go to the next arg */ - break; - - case WPR_UNKNOWN: - continue; - } /* switch */ - - if (format.flags & WPRINTF_LEFTALIGN) - { - for ( i = format.precision; - (i < format.width); - i++, maxlen-- - ) - { - *p++ = ' '; - } - } - maxlen -= len; - } /* while */ - - *p = '\0'; - return (maxlen > 1) - ? (INT) (p - buffer) - : -1; + res->flags = 0; + res->width = 0; + res->precision = 0; + if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; } + if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } + if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; } + while ((*p >= '0') && (*p <= '9')) /* width field */ + { + res->width = res->width * 10 + *p - '0'; + p++; + } + if (*p == '.') /* precision field */ + { + p++; + while ((*p >= '0') && (*p <= '9')) + { + res->precision = res->precision * 10 + *p - '0'; + p++; + } + } + if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; } + else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; } + else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; } + switch((CHAR)*p) + { + case 'c': + res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR; + break; + case 'C': + res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR; + break; + case 'd': + case 'i': + res->type = WPR_SIGNED; + break; + case 's': + res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING; + break; + case 'S': + res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING; + break; + case 'u': + res->type = WPR_UNSIGNED; + break; + case 'X': + res->flags |= WPRINTF_UPPER_HEX; + /* fall through */ + case 'x': + res->type = WPR_HEXA; + break; + default: + res->type = WPR_UNKNOWN; + p--; /* print format as normal char */ + break; + } + return (INT)(p - format) + 1; } /*********************************************************************** - * NAME PUBLIC - * wsprintfA (USER32.585) - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * + * WPRINTF_GetLen + */ +static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg, + LPSTR number, UINT maxlen ) +{ + UINT len; + + if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD; + if (format->width > maxlen) format->width = maxlen; + switch(format->type) + { + case WPR_CHAR: + case WPR_WCHAR: + return (format->precision = 1); + case WPR_STRING: + if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA; + for (len = 0; !format->precision || (len < format->precision); len++) + if (!*(arg->lpcstr_view + len)) break; + if (len > maxlen) len = maxlen; + return (format->precision = len); + case WPR_WSTRING: + if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW; + for (len = 0; !format->precision || (len < format->precision); len++) + if (!*(arg->lpcwstr_view + len)) break; + if (len > maxlen) len = maxlen; + return (format->precision = len); + case WPR_SIGNED: + len = sprintf( number, "%d", arg->int_view ); + break; + case WPR_UNSIGNED: + len = sprintf( number, "%u", (UINT)arg->int_view ); + break; + case WPR_HEXA: + len = sprintf( number, + (format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x", + (UINT)arg->int_view); + break; + default: + return 0; + } + if (len > maxlen) len = maxlen; + if (format->precision < len) format->precision = len; + if (format->precision > maxlen) format->precision = maxlen; + if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision)) + format->precision = format->width; + if (format->flags & WPRINTF_PREFIX_HEX) len += 2; + return len; +} + +/*********************************************************************** + * wvsnprintfA (internal) + */ +static INT wvsnprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, va_list args ) +{ + WPRINTF_FORMAT format; + LPSTR p = buffer; + UINT i, len, sign; + CHAR number[20]; + WPRINTF_DATA argData; + + //TRACE("%p %u %s\n", buffer, maxlen, debugstr_a(spec)); + + while (*spec && (maxlen > 1)) + { + if (*spec != '%') { *p++ = *spec++; maxlen--; continue; } + spec++; + if (*spec == '%') { *p++ = *spec++; maxlen--; continue; } + spec += WPRINTF_ParseFormatA( spec, &format ); + + switch(format.type) + { + case WPR_WCHAR: + argData.wchar_view = (WCHAR)va_arg( args, int ); + break; + case WPR_CHAR: + argData.char_view = (CHAR)va_arg( args, int ); + break; + case WPR_STRING: + argData.lpcstr_view = va_arg( args, LPCSTR ); + break; + case WPR_WSTRING: + argData.lpcwstr_view = va_arg( args, LPCWSTR ); + break; + case WPR_HEXA: + case WPR_SIGNED: + case WPR_UNSIGNED: + argData.int_view = va_arg( args, INT ); + break; + default: + argData.wchar_view = 0; + break; + } + + len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 ); + sign = 0; + if (!(format.flags & WPRINTF_LEFTALIGN)) + for (i = format.precision; i < format.width; i++, maxlen--) + *p++ = ' '; + switch(format.type) + { + case WPR_WCHAR: + *p++ = argData.wchar_view; + break; + case WPR_CHAR: + *p++ = argData.char_view; + break; + case WPR_STRING: + memcpy( p, argData.lpcstr_view, len ); + p += len; + break; + case WPR_WSTRING: + { + LPCWSTR ptr = argData.lpcwstr_view; + for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++; + } + break; + case WPR_HEXA: + if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3)) + { + *p++ = '0'; + *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x'; + maxlen -= 2; + len -= 2; + } + /* fall through */ + case WPR_SIGNED: + /* Transfer the sign now, just in case it will be zero-padded*/ + if (number[0] == '-') + { + *p++ = '-'; + sign = 1; + } + /* fall through */ + case WPR_UNSIGNED: + for (i = len; i < format.precision; i++, maxlen--) *p++ = '0'; + memcpy( p, number + sign, len - sign ); + p += len - sign; + break; + case WPR_UNKNOWN: + continue; + } + if (format.flags & WPRINTF_LEFTALIGN) + for (i = format.precision; i < format.width; i++, maxlen--) + *p++ = ' '; + maxlen -= len; + } + *p = 0; + //TRACE("%s\n",debugstr_a(buffer)); + return (maxlen > 1) ? (INT)(p - buffer) : -1; +} + + +/*********************************************************************** + * wvsnprintfW (internal) + */ +static INT wvsnprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, va_list args ) +{ + WPRINTF_FORMAT format; + LPWSTR p = buffer; + UINT i, len, sign; + CHAR number[20]; + WPRINTF_DATA argData; + + //TRACE("%p %u %s\n", buffer, maxlen, debugstr_w(spec)); + + while (*spec && (maxlen > 1)) + { + if (*spec != '%') { *p++ = *spec++; maxlen--; continue; } + spec++; + if (*spec == '%') { *p++ = *spec++; maxlen--; continue; } + spec += WPRINTF_ParseFormatW( spec, &format ); + + switch(format.type) + { + case WPR_WCHAR: + argData.wchar_view = (WCHAR)va_arg( args, int ); + break; + case WPR_CHAR: + argData.char_view = (CHAR)va_arg( args, int ); + break; + case WPR_STRING: + argData.lpcstr_view = va_arg( args, LPCSTR ); + break; + case WPR_WSTRING: + argData.lpcwstr_view = va_arg( args, LPCWSTR ); + break; + case WPR_HEXA: + case WPR_SIGNED: + case WPR_UNSIGNED: + argData.int_view = va_arg( args, INT ); + break; + default: + argData.wchar_view = 0; + break; + } + + len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 ); + sign = 0; + if (!(format.flags & WPRINTF_LEFTALIGN)) + for (i = format.precision; i < format.width; i++, maxlen--) + *p++ = ' '; + switch(format.type) + { + case WPR_WCHAR: + *p++ = argData.wchar_view; + break; + case WPR_CHAR: + *p++ = argData.char_view; + break; + case WPR_STRING: + { + LPCSTR ptr = argData.lpcstr_view; + for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++; + } + break; + case WPR_WSTRING: + if (len) memcpy( p, argData.lpcwstr_view, len * sizeof(WCHAR) ); + p += len; + break; + case WPR_HEXA: + if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3)) + { + *p++ = '0'; + *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x'; + maxlen -= 2; + len -= 2; + } + /* fall through */ + case WPR_SIGNED: + /* Transfer the sign now, just in case it will be zero-padded*/ + if (number[0] == '-') + { + *p++ = '-'; + sign = 1; + } + /* fall through */ + case WPR_UNSIGNED: + for (i = len; i < format.precision; i++, maxlen--) *p++ = '0'; + for (i = sign; i < len; i++) *p++ = (WCHAR)number[i]; + break; + case WPR_UNKNOWN: + continue; + } + if (format.flags & WPRINTF_LEFTALIGN) + for (i = format.precision; i < format.width; i++, maxlen--) + *p++ = ' '; + maxlen -= len; + } + *p = 0; + //TRACE("%s\n",debugstr_w(buffer)); + return (maxlen > 1) ? (INT)(p - buffer) : -1; +} + +/*********************************************************************** + * wvsprintfA (USER32.@) * @implemented */ -INT -CDECL -wsprintfA( - LPSTR buffer, - LPCSTR spec, - ... - ) +INT STDCALL wvsprintfA( LPSTR buffer, LPCSTR spec, va_list args ) { - va_list valist; - INT res; - - va_start( valist, spec ); - res = wvsnprintfA( - buffer, - 0xffffffff, - spec, - valist - ); - va_end( valist ); - return res; + INT res = wvsnprintfA( buffer, 1024, spec, args ); + return ( res == -1 ) ? 1024 : res; } /*********************************************************************** - * NAME PUBLIC - * wvsprintfA (USER32.587) - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * + * wvsprintfW (USER32.@) * @implemented */ -INT -STDCALL -wvsprintfA( - LPSTR buffer, - LPCSTR spec, - va_list args - ) +INT STDCALL wvsprintfW( LPWSTR buffer, LPCWSTR spec, va_list args ) { - return wvsnprintfA( - buffer, - 0xffffffff, - spec, - args - ); + INT res = wvsnprintfW( buffer, 1024, spec, args ); + return ( res == -1 ) ? 1024 : res; } - -/* === UNICODE VERSION === */ - - /*********************************************************************** - * NAME PRIVATE - * WPRINTF_ParseFormatW - * - * DESCRIPTION - * Parse a format specification. A format specification has - * the form: - * - * [-][#][0][width][.precision]type - * - * ARGUMENTS - * format - * ? - * res - * ? - * - * RETURN VALUE - * The length of the format specification in characters. - */ -static -INT -WPRINTF_ParseFormatW( - LPCWSTR format, - WPRINTF_FORMAT *res - ) -{ - LPCWSTR p = format; - - res->flags = 0; - res->width = 0; - res->precision = 0; - if (*p == L'-') - { - res->flags |= WPRINTF_LEFTALIGN; - p++; - } - if (*p == L'#') - { - res->flags |= WPRINTF_PREFIX_HEX; - p++; - } - if (*p == L'0') - { - res->flags |= WPRINTF_ZEROPAD; - p++; - } - - while ((*p >= L'0') && (*p <= L'9')) /* width field */ - { - res->width = - (res->width * 10) - + (*p - L'0'); - p++; - } - - if (*p == L'.') /* precision field */ - { - p++; - while ((*p >= L'0') && (*p <= L'9')) - { - res->precision = - (res->precision * 10) - + (*p - '0'); - p++; - } - } - if (*p == L'l') - { - res->flags |= WPRINTF_LONG; - p++; - } - else if (*p == L'h') - { - res->flags |= WPRINTF_SHORT; - p++; - } - else if (*p == L'w') - { - res->flags |= WPRINTF_WIDE; - p++; - } - - switch ((CHAR)*p) - { - case L'c': - res->type = - (res->flags & WPRINTF_SHORT) - ? WPR_CHAR - : WPR_WCHAR; - break; - - case L'C': - res->type = - (res->flags & WPRINTF_LONG) - ? WPR_WCHAR - : WPR_CHAR; - break; - - case L'd': - case L'i': - res->type = WPR_SIGNED; - break; - - case L's': - res->type = - ((res->flags & WPRINTF_SHORT) - && !(res->flags & WPRINTF_WIDE) - ) - ? WPR_STRING - : WPR_WSTRING; - break; - - case L'S': - res->type = - (res->flags & (WPRINTF_LONG | WPRINTF_WIDE)) - ? WPR_WSTRING - : WPR_STRING; - break; - - case L'u': - res->type = WPR_UNSIGNED; - break; - - case L'X': - res->flags |= WPRINTF_UPPER_HEX; - /* fall through */ - - case L'x': - res->type = WPR_HEXA; - break; - - default: - res->type = WPR_UNKNOWN; - p--; /* print format as normal char */ - break; - } /* switch */ - - return (INT) (p - format) + 1; -} - - -/*********************************************************************** - * NAME PRIVATE - * wvsnprintfW (Not a Windows API) - */ -INT -wvsnprintfW( - LPWSTR buffer, - UINT maxlen, - LPCWSTR spec, - va_list args - ) -{ - WPRINTF_FORMAT format; - LPWSTR p = buffer; - UINT i; - UINT len; - CHAR number [20]; - - while (*spec && (maxlen > 1)) - { - if (*spec != L'%') - { - *p++ = *spec++; - maxlen--; - continue; - } - spec++; - if (*spec == L'%') - { - *p++ = *spec++; - maxlen--; - continue; - } - spec += WPRINTF_ParseFormatW( - spec, - & format - ); - len = WPRINTF_GetLen( - & format, - args, - number, - (maxlen - 1) - ); - if (!(format.flags & WPRINTF_LEFTALIGN)) - { - for ( i = format.precision; - (i < format.width); - i++, maxlen-- - ) - { - *p++ = L' '; - } - } - switch (format.type) - { - case WPR_WCHAR: - if ((*p = (WCHAR) va_arg( args, int))) - { - p++; - } - else if (format.width > 1) - { - *p++ = L' '; - } - else - { - len = 0; - } - break; - - case WPR_CHAR: - if ((*p = (WCHAR)(CHAR) va_arg( args, int ))) - { - p++; - } - else if (format.width > 1) - { - *p++ = L' '; - } - else - { - len = 0; - } - break; - - case WPR_STRING: - { - LPCSTR ptr = va_arg( args, LPCSTR ); - - for ( i = 0; - (i < len); - i++ - ) - { - *p++ = (WCHAR) *ptr++; - } - } - break; - - case WPR_WSTRING: - if (len) - { - memcpy( - p, - va_arg( args, LPCWSTR ), - (len * sizeof (WCHAR)) - ); - } - p += len; - break; - - case WPR_HEXA: - if ( (format.flags & WPRINTF_PREFIX_HEX) - && (maxlen > 3) - ) - { - *p++ = L'0'; - *p++ = (format.flags & WPRINTF_UPPER_HEX) - ? L'X' - : L'x'; - maxlen -= 2; - len -= 2; - format.precision -= 2; - format.width -= 2; - } - /* fall through */ - - case WPR_SIGNED: - case WPR_UNSIGNED: - for ( i = len; - (i < format.precision); - i++, maxlen-- - ) - { - *p++ = L'0'; - } - for ( i = 0; - (i < len); - i++ - ) - { - *p++ = (WCHAR) number[i]; - } - (void) va_arg( args, INT ); /* Go to the next arg */ - break; - - case WPR_UNKNOWN: - continue; - } /* switch */ - - if (format.flags & WPRINTF_LEFTALIGN) - { - for ( i = format.precision; - (i < format.width); - i++, maxlen-- - ) - { - *p++ = L' '; - } - } - maxlen -= len; - } /* while */ - - *p = L'\0'; - return (maxlen > 1) - ? (INT) (p - buffer) - : -1; -} - - -/*********************************************************************** - * NAME PUBLIC - * wsprintfW (USER32.586) - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * + * wsprintfA (USER32.@) * @implemented */ -INT -CDECL -wsprintfW( - LPWSTR buffer, - LPCWSTR spec, - ... - ) +INT CDECL wsprintfA( LPSTR buffer, LPCSTR spec, ... ) { - va_list valist; - INT res; + va_list valist; + INT res; - va_start( valist, spec ); - res = wvsnprintfW( - buffer, - 0xffffffff, - spec, - valist - ); - va_end( valist ); - return res; + va_start( valist, spec ); + res = wvsnprintfA( buffer, 1024, spec, valist ); + va_end( valist ); + return ( res == -1 ) ? 1024 : res; } - /*********************************************************************** - * NAME PUBLIC - * wvsprintfW (USER32.588) - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - * + * wsprintfW (USER32.@) * @implemented */ -INT -STDCALL -wvsprintfW( - LPWSTR buffer, - LPCWSTR spec, - va_list args - ) +INT CDECL wsprintfW( LPWSTR buffer, LPCWSTR spec, ... ) { - return wvsnprintfW( - buffer, - 0xffffffff, - spec, - args - ); + va_list valist; + INT res; + + va_start( valist, spec ); + res = wvsnprintfW( buffer, 1024, spec, valist ); + va_end( valist ); + return ( res == -1 ) ? 1024 : res; } - -/* EOF */ -