X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/50e27899137071a7379e0bcca3ced4097d982e5b..bc1e0d4dab7a3d028bbb9cd68aa2db9e561b3817:/src/common/strvararg.cpp diff --git a/src/common/strvararg.cpp b/src/common/strvararg.cpp index 34cac3ca1d..e71c060b10 100644 --- a/src/common/strvararg.cpp +++ b/src/common/strvararg.cpp @@ -25,6 +25,8 @@ #include "wx/strvararg.h" #include "wx/string.h" +#include "wx/crt.h" +#include "wx/private/wxprintf.h" // ============================================================================ // implementation @@ -45,13 +47,17 @@ const wxStringCharType *wxArgNormalizerNative::get() const } #if wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY -wxArgNormalizerWchar::wxArgNormalizerWchar(const wxString& s) - : wxArgNormalizerWithBuffer(s.wc_str()) +wxArgNormalizerWchar::wxArgNormalizerWchar( + const wxString& s, + const wxFormatString *fmt, unsigned index) + : wxArgNormalizerWithBuffer(s.wc_str(), fmt, index) { } -wxArgNormalizerWchar::wxArgNormalizerWchar(const wxCStrData& s) - : wxArgNormalizerWithBuffer(s.AsWCharBuf()) +wxArgNormalizerWchar::wxArgNormalizerWchar( + const wxCStrData& s, + const wxFormatString *fmt, unsigned index) + : wxArgNormalizerWithBuffer(s.AsWCharBuf(), fmt, index) { } #endif // wxUSE_UNICODE_UTF8 && !wxUSE_UTF8_LOCALE_ONLY @@ -66,14 +72,14 @@ wxString wxArgNormalizedString::GetString() const return wxEmptyString; #if wxUSE_UTF8_LOCALE_ONLY - return wxString(wx_reinterpret_cast(const char*, m_ptr)); + return wxString(reinterpret_cast(m_ptr)); #else #if wxUSE_UNICODE_UTF8 if ( wxLocaleIsUtf8 ) - return wxString(wx_reinterpret_cast(const char*, m_ptr)); + return wxString(reinterpret_cast(m_ptr)); else #endif - return wxString(wx_reinterpret_cast(const wxChar*, m_ptr)); + return wxString(reinterpret_cast(m_ptr)); #endif // !wxUSE_UTF8_LOCALE_ONLY } @@ -127,10 +133,6 @@ wxArgNormalizedString::operator wxString() const And, of course, the same should be done for %c as well. - 4) Finally, in UTF-8 build when calling ANSI printf() function, we need to - translate %c to %s, because not every Unicode character can be - represented by a char. - wxScanf() family of functions is simpler, because we don't normalize their variadic arguments and we only have to handle 2) above and only for widechar @@ -150,7 +152,7 @@ public: m_nCopied = 0; } - wxCharTypeBuffer Convert(const CharType *format) + wxScopedCharTypeBuffer Convert(const CharType *format) { // this is reset to NULL if we modify the format string m_fmtOrig = format; @@ -261,12 +263,14 @@ public: // format if ( m_fmtOrig ) { - return wxCharTypeBuffer::CreateNonOwned(m_fmtOrig); + return wxScopedCharTypeBuffer::CreateNonOwned(m_fmtOrig); } else { - // NULL-terminate converted format string: - *m_fmtLast = 0; + // shrink converted format string to actual size (instead of + // over-sized allocation from CopyAllBefore()) and NUL-terminate + // it: + m_fmt.shrink(m_fmtLast - m_fmt.data()); return m_fmt; } } @@ -371,9 +375,7 @@ private: size_t m_nCopied; }; - - -#ifdef __WINDOWS +#ifdef __WINDOWS__ // on Windows, we should use %s and %c regardless of the build: class wxPrintfFormatConverterWchar : public wxFormatConverterBase @@ -435,9 +437,10 @@ class wxPrintfFormatConverterUtf8 : public wxFormatConverterBase SizeModifier WXUNUSED(size), CharType& outConv, SizeModifier& outSize) { - // added complication: %c should be translated to %s in UTF-8 build - outConv = 's'; - outSize = Size_Default; + // chars are represented using wchar_t in both builds, so this is + // the same as above + outConv = 'c'; + outSize = Size_Long; } }; #endif // wxUSE_UNICODE_UTF8 @@ -517,7 +520,7 @@ class wxScanfFormatConverterWchar : public wxFormatConverterBase } }; -const wxWCharBuffer wxScanfConvertFormatW(const wchar_t *format) +const wxScopedWCharBuffer wxScanfConvertFormatW(const wchar_t *format) { return wxScanfFormatConverterWchar().Convert(format); } @@ -607,3 +610,65 @@ const wchar_t* wxFormatString::AsWChar() return m_convertedWChar.data(); } #endif // wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY + +wxString wxFormatString::InputAsString() const +{ + if ( m_str ) + return *m_str; + if ( m_cstr ) + return m_cstr->AsString(); + if ( m_wchar ) + return wxString(m_wchar); + if ( m_char ) + return wxString(m_char); + + wxFAIL_MSG( "invalid wxFormatString - not initialized?" ); + return wxString(); +} + +// ---------------------------------------------------------------------------- +// wxFormatString::GetArgumentType() +// ---------------------------------------------------------------------------- + +namespace +{ + +template +wxFormatString::ArgumentType DoGetArgumentType(const CharType *format, + unsigned n) +{ + wxCHECK_MSG( format, wxFormatString::Arg_Other, + "empty format string not allowed here" ); + + wxPrintfConvSpecParser parser(format); + + wxCHECK_MSG( parser.pspec[n-1] != NULL, wxFormatString::Arg_Other, + "requested argument not found - invalid format string?" ); + + switch ( parser.pspec[n-1]->m_type ) + { + case wxPAT_CHAR: + case wxPAT_WCHAR: + return wxFormatString::Arg_Char; + + default: + return wxFormatString::Arg_Other; + } +} + +} // anonymous namespace + +wxFormatString::ArgumentType wxFormatString::GetArgumentType(unsigned n) const +{ + if ( m_char ) + return DoGetArgumentType(m_char.data(), n); + else if ( m_wchar ) + return DoGetArgumentType(m_wchar.data(), n); + else if ( m_str ) + return DoGetArgumentType(m_str->wx_str(), n); + else if ( m_cstr ) + return DoGetArgumentType(m_cstr->AsInternal(), n); + + wxFAIL_MSG( "unreachable code" ); + return Arg_Other; +}