+ void CopyAllBefore()
+ {
+ wxASSERT_MSG( m_fmtOrig && m_fmt.data() == NULL, "logic error" );
+
+ // the modified format string is guaranteed to be no longer than
+ // 3/2 of the original (worst case: the entire format string consists
+ // of "%s" repeated and is expanded to "%ls" on Unix), so we can
+ // allocate the buffer now and not worry about running out of space if
+ // we over-allocate a bit:
+ size_t fmtLen = wxStrlen(m_fmtOrig);
+ // worst case is of even length, so there's no rounding error in *3/2:
+ m_fmt.extend(fmtLen * 3 / 2);
+
+ if ( m_nCopied > 0 )
+ wxStrncpy(m_fmt.data(), m_fmtOrig, m_nCopied);
+ m_fmtLast = m_fmt.data() + m_nCopied;
+
+ // we won't need it any longer and resetting it also indicates that we
+ // modified the format
+ m_fmtOrig = NULL;
+ }
+
+ static bool IsFlagChar(CharType ch)
+ {
+ return ch == _T('-') || ch == _T('+') ||
+ ch == _T('0') || ch == _T(' ') || ch == _T('#');
+ }
+
+ void SkipDigits(const CharType **ptpc)
+ {
+ while ( **ptpc >= _T('0') && **ptpc <= _T('9') )
+ CopyFmtChar(*(*ptpc)++);
+ }
+
+ // the translated format
+ wxCharTypeBuffer<CharType> m_fmt;
+ CharType *m_fmtLast;
+
+ // the original format
+ const CharType *m_fmtOrig;
+
+ // the number of characters already copied (i.e. already parsed, but left
+ // unmodified)
+ size_t m_nCopied;
+};
+
+
+
+#ifdef __WINDOWS
+
+// on Windows, we should use %s and %c regardless of the build:
+class wxPrintfFormatConverterWchar : public wxFormatConverterBase<wchar_t>
+{
+ virtual void HandleString(CharType WXUNUSED(conv),
+ SizeModifier WXUNUSED(size),
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 's';
+ outSize = Size_Default;
+ }
+
+ virtual void HandleChar(CharType WXUNUSED(conv),
+ SizeModifier WXUNUSED(size),
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 'c';
+ outSize = Size_Default;
+ }
+};
+
+#else // !__WINDOWS__
+
+// on Unix, it's %s for ANSI functions and %ls for widechar:
+
+#if !wxUSE_UTF8_LOCALE_ONLY
+class wxPrintfFormatConverterWchar : public wxFormatConverterBase<wchar_t>
+{
+ virtual void HandleString(CharType WXUNUSED(conv),
+ SizeModifier WXUNUSED(size),
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 's';
+ outSize = Size_Long;
+ }
+
+ virtual void HandleChar(CharType WXUNUSED(conv),
+ SizeModifier WXUNUSED(size),
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 'c';
+ outSize = Size_Long;
+ }
+};
+#endif // !wxUSE_UTF8_LOCALE_ONLY
+
+#if wxUSE_UNICODE_UTF8
+class wxPrintfFormatConverterUtf8 : public wxFormatConverterBase<char>
+{
+ virtual void HandleString(CharType WXUNUSED(conv),
+ SizeModifier WXUNUSED(size),
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 's';
+ outSize = Size_Default;
+ }
+
+ virtual void HandleChar(CharType WXUNUSED(conv),
+ SizeModifier WXUNUSED(size),
+ CharType& outConv, SizeModifier& outSize)
+ {
+ // added complication: %c should be translated to %s in UTF-8 build
+ outConv = 's';
+ outSize = Size_Default;
+ }
+};
+#endif // wxUSE_UNICODE_UTF8
+
+#endif // __WINDOWS__/!__WINDOWS__
+
+#if !wxUSE_UNICODE // FIXME-UTF8: remove
+class wxPrintfFormatConverterANSI : public wxFormatConverterBase<char>
+{
+ virtual void HandleString(CharType WXUNUSED(conv),
+ SizeModifier WXUNUSED(size),
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 's';
+ outSize = Size_Default;
+ }
+
+ virtual void HandleChar(CharType WXUNUSED(conv),
+ SizeModifier WXUNUSED(size),
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 'c';
+ outSize = Size_Default;
+ }
+};
+#endif // ANSI
+
+#ifndef __WINDOWS__
+/*
+
+ wxScanf() format translation is different, we need to translate %s to %ls
+ and %c to %lc on Unix (but not Windows and for widechar functions only!).
+
+ So to use native functions in order to get our semantics we must do the
+ following translations in Unicode mode:
+
+ wxWidgets specifier POSIX specifier
+ ----------------------------------------
+
+ %hc, %C, %hC %c
+ %c %lc
+
+ */
+class wxScanfFormatConverterWchar : public wxFormatConverterBase<wchar_t>
+{
+ virtual void HandleString(CharType conv, SizeModifier size,
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 's';
+ outSize = GetOutSize(conv == 'S', size);
+ }
+
+ virtual void HandleChar(CharType conv, SizeModifier size,
+ CharType& outConv, SizeModifier& outSize)
+ {
+ outConv = 'c';
+ outSize = GetOutSize(conv == 'C', size);
+ }
+
+ SizeModifier GetOutSize(bool convIsUpper, SizeModifier size)
+ {
+ // %S and %hS -> %s and %lS -> %ls
+ if ( convIsUpper )
+ {
+ if ( size == Size_Long )
+ return Size_Long;
+ else
+ return Size_Default;
+ }
+ else // %s or %c
+ {
+ if ( size == Size_Default )
+ return Size_Long;
+ else
+ return size;
+ }
+ }
+};
+
+const wxWCharBuffer wxScanfConvertFormatW(const wchar_t *format)