Module: wine Branch: refs/heads/master Commit: bc83ae9fda6bf4a381e881523c3be3dfb3a688b2 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=bc83ae9fda6bf4a381e88152...
Author: Peter Beutner p.beutner@gmx.net Date: Tue May 16 18:18:51 2006 +0200
msvcrt: Fix handling of 'h' prefix in swprintf.
- '%hs' in widechar string functions is wrongly recognized as a widechar string. Fix this by always checking the prefix first. - add testcase - remove code duplication in %c/%s handling by moving code into a function.
---
dlls/msvcrt/tests/printf.c | 7 ++++ dlls/msvcrt/wcs.c | 69 ++++++++++++++++++-------------------------- 2 files changed, 34 insertions(+), 42 deletions(-)
diff --git a/dlls/msvcrt/tests/printf.c b/dlls/msvcrt/tests/printf.c index 64b5d5a..ff0058d 100644 --- a/dlls/msvcrt/tests/printf.c +++ b/dlls/msvcrt/tests/printf.c @@ -469,8 +469,11 @@ static void test_swprintf( void ) double pnumber=789456123; const wchar_t TwentyThreePoint15e[]= {'%','+','#','2','3','.','1','5','e',0}; const wchar_t e008[] = {'e','+','0','0','8',0}; - const char string[]={'s','t','r','i','n','g',0}; + const wchar_t string_w[] = {'s','t','r','i','n','g',0}; + const char string[] = "string"; const wchar_t S[]={'%','S',0}; + const wchar_t hs[] = {'%', 'h', 's', 0}; + swprintf(buffer,TwentyThreePoint15e,pnumber); todo_wine { @@ -480,6 +483,8 @@ static void test_swprintf( void ) ok(wcslen(buffer) == 11,"Problem with long long\n"); swprintf(buffer,S,string); ok(wcslen(buffer) == 6,"Problem with "%%S" interpretation\n"); + swprintf(buffer, hs, string); + ok( wcscmp(string_w,buffer) == 0, "swprintf failed with %%hs\n"); }
static void test_fwprintf( void ) diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c index 9c35c46..095bef7 100644 --- a/dlls/msvcrt/wcs.c +++ b/dlls/msvcrt/wcs.c @@ -357,6 +357,26 @@ static inline int pf_output_format_A( pf return r; }
+static int pf_handle_string_format( pf_output *out, const void* str, int len, + pf_flags *flags, BOOL capital_letter) +{ + if(str == NULL) /* catch NULL pointer */ + return pf_output_format_A( out, "(null)", -1, flags); + + /* prefixes take priority over %c,%s vs. %C,%S, so we handle them first */ + if(flags->WideString || flags->IntegerLength == 'l') + return pf_output_format_W( out, str, len, flags); + if(flags->IntegerLength == 'h') + return pf_output_format_A( out, str, len, flags); + + /* %s,%c -> chars in ansi functions & wchars in unicode + * %S,%C -> wchars in ansi functions & chars in unicode */ + if( capital_letter == out->unicode) /* either both TRUE or both FALSE */ + return pf_output_format_A( out, str, len, flags); + else + return pf_output_format_W( out, str, len, flags); +} + static inline BOOL pf_is_integer_format( char fmt ) { static const char float_fmts[] = "diouxX"; @@ -602,50 +622,17 @@ static int pf_vsnprintf( pf_output *out, flags.Format = *p; r = 0;
- /* output a unicode string */ - if( ( flags.Format == 's' && (flags.WideString || flags.IntegerLength == 'l' )) || - ( !out->unicode && flags.Format == 'S' ) || - ( out->unicode && flags.Format == 's' ) ) - { - LPCWSTR str = va_arg( valist, const WCHAR * ); - - if( str ) - r = pf_output_format_W( out, str, -1, &flags ); - else - r = pf_output_format_A( out, "(null)", -1, &flags ); - } - - /* output a ASCII string */ - else if( ( flags.Format == 's' && flags.IntegerLength == 'h' ) || - ( out->unicode && flags.Format == 'S' ) || - ( !out->unicode && flags.Format == 's' ) ) - { - LPCSTR str = va_arg( valist, const CHAR * ); - - if( str ) - r = pf_output_format_A( out, str, -1, &flags ); - else - r = pf_output_format_A( out, "(null)", -1, &flags ); - } - - /* output a single wide character */ - else if( ( flags.Format == 'c' && flags.IntegerLength == 'w' ) || - ( out->unicode && flags.Format == 'c' ) || - ( !out->unicode && flags.Format == 'C' ) ) - { - WCHAR ch = va_arg( valist, int ); - - r = pf_output_format_W( out, &ch, 1, &flags ); - } + /* output a string */ + if( flags.Format == 's' || flags.Format == 'S' ) + r = pf_handle_string_format( out, va_arg(valist, const void*), -1, + &flags, (flags.Format == 'S') );
- /* output a single ascii character */ - else if( ( flags.Format == 'c' && flags.IntegerLength == 'h' ) || - ( out->unicode && flags.Format == 'C' ) || - ( !out->unicode && flags.Format == 'c' ) ) + /* output a single character */ + else if( flags.Format == 'c' || flags.Format == 'C' ) { - CHAR ch = va_arg( valist, int ); + INT ch = va_arg( valist, int );
- r = pf_output_format_A( out, &ch, 1, &flags ); + r = pf_handle_string_format( out, &ch, 1, &flags, (flags.Format == 'C') ); }
/* output a pointer */