-public:
- wxFormatConverter(const wxChar *format);
-
- // notice that we only translated the string if m_fmtOrig == NULL (as set
- // by CopyAllBefore()), otherwise we should simply use the original format
- operator const wxChar *() const
- { return m_fmtOrig ? m_fmtOrig : m_fmt.c_str(); }
-
-private:
- // copy another character to the translated format: this function does the
- // copy if we are translating but doesn't do anything at all if we don't,
- // so we don't create the translated format string at all unless we really
- // need to (i.e. InsertFmtChar() is called)
- wxChar CopyFmtChar(wxChar ch)
- {
- if ( !m_fmtOrig )
- {
- // we're translating, do copy
- m_fmt += ch;
- }
- else
- {
- // simply increase the count which should be copied by
- // CopyAllBefore() later if needed
- m_nCopied++;
- }
-
- return ch;
- }
-
- // insert an extra character
- void InsertFmtChar(wxChar ch)
- {
- if ( m_fmtOrig )
- {
- // so far we haven't translated anything yet
- CopyAllBefore();
- }
-
- m_fmt += ch;
- }
-
- void CopyAllBefore()
- {
- wxASSERT_MSG( m_fmtOrig && m_fmt.empty(), _T("logic error") );
-
- m_fmt = wxString(m_fmtOrig, m_nCopied);
-
- // we won't need it any longer
- m_fmtOrig = NULL;
- }
-
- static bool IsFlagChar(wxChar ch)
- {
- return ch == _T('-') || ch == _T('+') ||
- ch == _T('0') || ch == _T(' ') || ch == _T('#');
- }
-
- void SkipDigits(const wxChar **ptpc)
- {
- while ( **ptpc >= _T('0') && **ptpc <= _T('9') )
- CopyFmtChar(*(*ptpc)++);
- }
-
- // the translated format
- wxString m_fmt;
-
- // the original format
- const wxChar *m_fmtOrig;
-
- // the number of characters already copied
- size_t m_nCopied;
-};
-
-wxFormatConverter::wxFormatConverter(const wxChar *format)
-{
- m_fmtOrig = format;
- m_nCopied = 0;
-
- while ( *format )
- {
- if ( CopyFmtChar(*format++) == _T('%') )
- {
- // skip any flags
- while ( IsFlagChar(*format) )
- CopyFmtChar(*format++);
-
- // and possible width
- if ( *format == _T('*') )
- CopyFmtChar(*format++);
- else
- SkipDigits(&format);
-
- // precision?
- if ( *format == _T('.') )
- {
- CopyFmtChar(*format++);
- if ( *format == _T('*') )
- CopyFmtChar(*format++);
- else
- SkipDigits(&format);
- }
-
- // next we can have a size modifier
- enum
- {
- Default,
- Short,
- Long
- } size;
-
- switch ( *format )
- {
- case _T('h'):
- size = Short;
- format++;
- break;
-
- case _T('l'):
- // "ll" has a different meaning!
- if ( format[1] != _T('l') )
- {
- size = Long;
- format++;
- break;
- }
- //else: fall through
-
- default:
- size = Default;
- }
-
- // and finally we should have the type
- switch ( *format )
- {
- case _T('C'):
- case _T('S'):
- // %C and %hC -> %c and %lC -> %lc
- if ( size == Long )
- CopyFmtChar(_T('l'));
-
- InsertFmtChar(*format++ == _T('C') ? _T('c') : _T('s'));
- break;
-
- case _T('c'):
- case _T('s'):
- // %c -> %lc but %hc stays %hc and %lc is still %lc
- if ( size == Default)
- InsertFmtChar(_T('l'));
- // fall through
-
- default:
- // nothing special to do
- if ( size != Default )
- CopyFmtChar(*(format - 1));
- CopyFmtChar(*format++);
- }
- }
- }
-}