+#endif // wxUSE_FONTMAP
+
+// ============================================================================
+// wxCSConv implementation
+// ============================================================================
+
+void wxCSConv::Init()
+{
+ m_name = NULL;
+ m_convReal = NULL;
+ m_deferred = true;
+}
+
+wxCSConv::wxCSConv(const wxChar *charset)
+{
+ Init();
+
+ if ( charset )
+ {
+ SetName(charset);
+ }
+
+ m_encoding = wxFONTENCODING_SYSTEM;
+}
+
+wxCSConv::wxCSConv(wxFontEncoding encoding)
+{
+ if ( encoding == wxFONTENCODING_MAX || encoding == wxFONTENCODING_DEFAULT )
+ {
+ wxFAIL_MSG( _T("invalid encoding value in wxCSConv ctor") );
+
+ encoding = wxFONTENCODING_SYSTEM;
+ }
+
+ Init();
+
+ m_encoding = encoding;
+}
+
+wxCSConv::~wxCSConv()
+{
+ Clear();
+}
+
+wxCSConv::wxCSConv(const wxCSConv& conv)
+ : wxMBConv()
+{
+ Init();
+
+ SetName(conv.m_name);
+ m_encoding = conv.m_encoding;
+}
+
+wxCSConv& wxCSConv::operator=(const wxCSConv& conv)
+{
+ Clear();
+
+ SetName(conv.m_name);
+ m_encoding = conv.m_encoding;
+
+ return *this;
+}
+
+void wxCSConv::Clear()
+{
+ free(m_name);
+ delete m_convReal;
+
+ m_name = NULL;
+ m_convReal = NULL;
+}
+
+void wxCSConv::SetName(const wxChar *charset)
+{
+ if (charset)
+ {
+ m_name = wxStrdup(charset);
+ m_deferred = true;
+ }
+}
+
+wxMBConv *wxCSConv::DoCreate() const
+{
+ // check for the special case of ASCII or ISO8859-1 charset: as we have
+ // special knowledge of it anyhow, we don't need to create a special
+ // conversion object
+ if ( m_encoding == wxFONTENCODING_ISO8859_1 )
+ {
+ // don't convert at all
+ return NULL;
+ }
+
+ // we trust OS to do conversion better than we can so try external
+ // conversion methods first
+ //
+ // the full order is:
+ // 1. OS conversion (iconv() under Unix or Win32 API)
+ // 2. hard coded conversions for UTF
+ // 3. wxEncodingConverter as fall back
+
+ // step (1)
+#ifdef HAVE_ICONV
+#if !wxUSE_FONTMAP
+ if ( m_name )
+#endif // !wxUSE_FONTMAP
+ {
+ wxString name(m_name);
+
+#if wxUSE_FONTMAP
+ if ( name.empty() )
+ name = wxFontMapper::Get()->GetEncodingName(m_encoding);
+#endif // wxUSE_FONTMAP
+
+ wxMBConv_iconv *conv = new wxMBConv_iconv(name);
+ if ( conv->IsOk() )
+ return conv;
+
+ delete conv;
+ }
+#endif // HAVE_ICONV
+
+#ifdef wxHAVE_WIN32_MB2WC
+ {
+ wxMBConv_win32 *conv = m_name ? new wxMBConv_win32(m_name)
+ : new wxMBConv_win32(m_encoding);
+ if ( conv->IsOk() )
+ return conv;
+
+ delete conv;
+ }
+#endif // wxHAVE_WIN32_MB2WC
+#if defined(__WXMAC__)
+ {
+ if ( m_name || ( m_encoding < wxFONTENCODING_UTF16BE ) )
+ {
+
+ wxMBConv_mac *conv = m_name ? new wxMBConv_mac(m_name)
+ : new wxMBConv_mac(m_encoding);
+ if ( conv->IsOk() )
+ return conv;
+
+ delete conv;
+ }
+ }
+#endif
+ // step (2)
+ wxFontEncoding enc = m_encoding;
+#if wxUSE_FONTMAP
+ if ( enc == wxFONTENCODING_SYSTEM && m_name )
+ {
+ // use "false" to suppress interactive dialogs -- we can be called from
+ // anywhere and popping up a dialog from here is the last thing we want to
+ // do
+ enc = wxFontMapper::Get()->CharsetToEncoding(m_name, false);
+ }
+#endif // wxUSE_FONTMAP
+
+ switch ( enc )
+ {
+ case wxFONTENCODING_UTF7:
+ return new wxMBConvUTF7;
+
+ case wxFONTENCODING_UTF8:
+ return new wxMBConvUTF8;
+
+ case wxFONTENCODING_UTF16BE:
+ return new wxMBConvUTF16BE;
+
+ case wxFONTENCODING_UTF16LE:
+ return new wxMBConvUTF16LE;
+
+ case wxFONTENCODING_UTF32BE:
+ return new wxMBConvUTF32BE;
+
+ case wxFONTENCODING_UTF32LE:
+ return new wxMBConvUTF32LE;
+
+ default:
+ // nothing to do but put here to suppress gcc warnings
+ ;
+ }
+
+ // step (3)
+#if wxUSE_FONTMAP
+ {
+ wxMBConv_wxwin *conv = m_name ? new wxMBConv_wxwin(m_name)
+ : new wxMBConv_wxwin(m_encoding);
+ if ( conv->IsOk() )
+ return conv;
+
+ delete conv;
+ }
+#endif // wxUSE_FONTMAP
+
+ // NB: This is a hack to prevent deadlock. What could otherwise happen
+ // in Unicode build: wxConvLocal creation ends up being here
+ // because of some failure and logs the error. But wxLog will try to
+ // attach timestamp, for which it will need wxConvLocal (to convert
+ // time to char* and then wchar_t*), but that fails, tries to log
+ // error, but wxLog has a (already locked) critical section that
+ // guards static buffer.
+ static bool alreadyLoggingError = false;
+ if (!alreadyLoggingError)
+ {
+ alreadyLoggingError = true;
+ wxLogError(_("Cannot convert from the charset '%s'!"),
+ m_name ? m_name
+ :
+#if wxUSE_FONTMAP
+ wxFontMapper::GetEncodingDescription(m_encoding).c_str()
+#else // !wxUSE_FONTMAP
+ wxString::Format(_("encoding %s"), m_encoding).c_str()
+#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
+ );
+ alreadyLoggingError = false;
+ }
+
+ return NULL;
+}
+
+void wxCSConv::CreateConvIfNeeded() const
+{
+ if ( m_deferred )
+ {
+ wxCSConv *self = (wxCSConv *)this; // const_cast
+
+#if wxUSE_INTL
+ // if we don't have neither the name nor the encoding, use the default
+ // encoding for this system
+ if ( !m_name && m_encoding == wxFONTENCODING_SYSTEM )
+ {
+ self->m_name = wxStrdup(wxLocale::GetSystemEncodingName());
+ }
+#endif // wxUSE_INTL
+
+ self->m_convReal = DoCreate();
+ self->m_deferred = false;
+ }
+}
+
+size_t wxCSConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
+{
+ CreateConvIfNeeded();
+
+ if (m_convReal)
+ return m_convReal->MB2WC(buf, psz, n);
+
+ // latin-1 (direct)
+ size_t len = strlen(psz);
+
+ if (buf)
+ {
+ for (size_t c = 0; c <= len; c++)
+ buf[c] = (unsigned char)(psz[c]);
+ }
+
+ return len;
+}
+
+size_t wxCSConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
+{
+ CreateConvIfNeeded();
+
+ if (m_convReal)
+ return m_convReal->WC2MB(buf, psz, n);
+
+ // latin-1 (direct)
+ const size_t len = wxWcslen(psz);
+ if (buf)
+ {
+ for (size_t c = 0; c <= len; c++)
+ {
+ if (psz[c] > 0xFF)
+ return (size_t)-1;
+ buf[c] = psz[c];
+ }
+ }
+ else
+ {
+ for (size_t c = 0; c <= len; c++)
+ {
+ if (psz[c] > 0xFF)
+ return (size_t)-1;
+ }
+ }
+
+ return len;
+}