]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/fontmap.cpp
PyCrust updates
[wxWidgets.git] / src / common / fontmap.cpp
index b0a2aa7a242104ea92cf2febd82f2eb9f77b8a29..f40ea75e954a4d131fd43f072e43d0e8f2072304 100644 (file)
@@ -28,6 +28,8 @@
     #pragma hdrstop
 #endif
 
     #pragma hdrstop
 #endif
 
+#if wxUSE_FONTMAP
+
 #ifndef WX_PRECOMP
     #include "wx/app.h"
     #include "wx/log.h"
 #ifndef WX_PRECOMP
     #include "wx/app.h"
     #include "wx/log.h"
 #endif // PCH
 
 #include "wx/fontmap.h"
 #endif // PCH
 
 #include "wx/fontmap.h"
-#include "wx/config.h"
 
 
-#include "wx/msgdlg.h"
-#include "wx/fontdlg.h"
-#include "wx/choicdlg.h"
+#if wxUSE_CONFIG
+    #include "wx/config.h"
+    #include "wx/memconf.h"
+#endif
+
+#if wxUSE_GUI
+    #include "wx/fontutil.h"
+    #include "wx/msgdlg.h"
+    #include "wx/fontdlg.h"
+    #include "wx/choicdlg.h"
+#endif // wxUSE_GUI
+
+#include "wx/encconv.h"
 
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
 
 // the config paths we use
 
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
 
 // the config paths we use
-static const char* FONTMAPPER_ROOT_PATH = _T("FontMapper");
-static const char* FONTMAPPER_CHARSET_PATH = _T("Charsets");
-static const char* FONTMAPPER_CHARSET_ALIAS_PATH = _T("Aliases");
-static const char* FONTMAPPER_FONT_FROM_ENCODING_PATH = _T("Encodings");
+#if wxUSE_CONFIG
+static const wxChar* FONTMAPPER_ROOT_PATH = wxT("/wxWindows/FontMapper");
+static const wxChar* FONTMAPPER_CHARSET_PATH = wxT("Charsets");
+static const wxChar* FONTMAPPER_CHARSET_ALIAS_PATH = wxT("Aliases");
+
+// we only ask questions in GUI mode
+#if wxUSE_GUI
+    static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings");
+    static const wxChar* FONTMAPPER_FONT_DONT_ASK = wxT("none");
+#endif // wxUSE_GUI
+#endif // wxUSE_CONFIG
 
 // encodings supported by GetEncodingDescription
 static wxFontEncoding gs_encodings[] =
 
 // encodings supported by GetEncodingDescription
 static wxFontEncoding gs_encodings[] =
@@ -70,6 +88,10 @@ static wxFontEncoding gs_encodings[] =
     wxFONTENCODING_ISO8859_14,
     wxFONTENCODING_ISO8859_15,
     wxFONTENCODING_KOI8,
     wxFONTENCODING_ISO8859_14,
     wxFONTENCODING_ISO8859_15,
     wxFONTENCODING_KOI8,
+    wxFONTENCODING_CP932,
+    wxFONTENCODING_CP936,
+    wxFONTENCODING_CP949,
+    wxFONTENCODING_CP950,
     wxFONTENCODING_CP1250,
     wxFONTENCODING_CP1251,
     wxFONTENCODING_CP1252,
     wxFONTENCODING_CP1250,
     wxFONTENCODING_CP1251,
     wxFONTENCODING_CP1252,
@@ -78,64 +100,81 @@ static wxFontEncoding gs_encodings[] =
     wxFONTENCODING_CP1255,
     wxFONTENCODING_CP1256,
     wxFONTENCODING_CP1257,
     wxFONTENCODING_CP1255,
     wxFONTENCODING_CP1256,
     wxFONTENCODING_CP1257,
+    wxFONTENCODING_CP437,
+    wxFONTENCODING_UTF7,
+    wxFONTENCODING_UTF8,
 };
 
 // the descriptions for them
 static const wxChar* gs_encodingDescs[] =
 {
 };
 
 // the descriptions for them
 static const wxChar* gs_encodingDescs[] =
 {
-    wxTRANSLATE( "West European (ISO-8859-1/Latin 1)" ),
-    wxTRANSLATE( "Central European (ISO-8859-2/Latin 2)" ),
+    wxTRANSLATE( "Western European (ISO-8859-1)" ),
+    wxTRANSLATE( "Central European (ISO-8859-2)" ),
     wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
     wxTRANSLATE( "Esperanto (ISO-8859-3)" ),
-    wxTRANSLATE( "Baltic (ISO-8859-4)" ),
-    wxTRANSLATE( "Cyrillic (Latin 5)" ),
+    wxTRANSLATE( "Baltic (old) (ISO-8859-4)" ),
+    wxTRANSLATE( "Cyrillic (ISO-8859-5)" ),
     wxTRANSLATE( "Arabic (ISO-8859-6)" ),
     wxTRANSLATE( "Greek (ISO-8859-7)" ),
     wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
     wxTRANSLATE( "Turkish (ISO-8859-9)" ),
     wxTRANSLATE( "Arabic (ISO-8859-6)" ),
     wxTRANSLATE( "Greek (ISO-8859-7)" ),
     wxTRANSLATE( "Hebrew (ISO-8859-8)" ),
     wxTRANSLATE( "Turkish (ISO-8859-9)" ),
-    wxTRANSLATE( "Baltic II (ISO-8859-10)" ),
+    wxTRANSLATE( "Nordic (ISO-8859-10)" ),
     wxTRANSLATE( "Thai (ISO-8859-11)" ),
     wxTRANSLATE( "Thai (ISO-8859-11)" ),
-    wxTRANSLATE( "ISO-8859-12" ),
-    wxTRANSLATE( "ISO-8859-13" ),
-    wxTRANSLATE( "ISO-8859-14" ),
-    wxTRANSLATE( "West European new (ISO-8859-15/Latin 0)" ),
+    wxTRANSLATE( "Indian (ISO-8859-12)" ),
+    wxTRANSLATE( "Baltic (ISO-8859-13)" ),
+    wxTRANSLATE( "Celtic (ISO-8859-14)" ),
+    wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
     wxTRANSLATE( "KOI8-R" ),
     wxTRANSLATE( "KOI8-R" ),
-    wxTRANSLATE( "Windows Latin 2 (CP 1250)" ),
+    wxTRANSLATE( "Windows Japanese (CP 932)" ),
+    wxTRANSLATE( "Windows Chinese Simplified (CP 936)" ),
+    wxTRANSLATE( "Windows Korean (CP 949)" ),
+    wxTRANSLATE( "Windows Chinese Traditional (CP 950)" ),
+    wxTRANSLATE( "Windows Central European (CP 1250)" ),
     wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
     wxTRANSLATE( "Windows Cyrillic (CP 1251)" ),
-    wxTRANSLATE( "Windows Latin 1 (CP 1252)" ),
+    wxTRANSLATE( "Windows Western European (CP 1252)" ),
     wxTRANSLATE( "Windows Greek (CP 1253)" ),
     wxTRANSLATE( "Windows Turkish (CP 1254)" ),
     wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
     wxTRANSLATE( "Windows Arabic (CP 1256)" ),
     wxTRANSLATE( "Windows Baltic (CP 1257)" ),
     wxTRANSLATE( "Windows Greek (CP 1253)" ),
     wxTRANSLATE( "Windows Turkish (CP 1254)" ),
     wxTRANSLATE( "Windows Hebrew (CP 1255)" ),
     wxTRANSLATE( "Windows Arabic (CP 1256)" ),
     wxTRANSLATE( "Windows Baltic (CP 1257)" ),
+    wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
+    wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
+    wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
 };
 
 };
 
-// and the internal names
+// and the internal names (these are not translated on purpose!)
 static const wxChar* gs_encodingNames[] =
 {
 static const wxChar* gs_encodingNames[] =
 {
-    "iso8859-1",
-    "iso8859-2",
-    "iso8859-3",
-    "iso8859-4",
-    "iso8859-5",
-    "iso8859-6",
-    "iso8859-7",
-    "iso8859-8",
-    "iso8859-9",
-    "iso8859-10",
-    "iso8859-11",
-    "iso8859-12",
-    "iso8859-13",
-    "iso8859-14",
-    "iso8859-15",
-    "koi8-r",
-    "windows1250",
-    "windows1251",
-    "windows1252",
-    "windows1253",
-    "windows1254",
-    "windows1255",
-    "windows1256",
-    "windows1257",
+    wxT( "iso-8859-1" ),
+    wxT( "iso-8859-2" ),
+    wxT( "iso-8859-3" ),
+    wxT( "iso-8859-4" ),
+    wxT( "iso-8859-5" ),
+    wxT( "iso-8859-6" ),
+    wxT( "iso-8859-7" ),
+    wxT( "iso-8859-8" ),
+    wxT( "iso-8859-9" ),
+    wxT( "iso-8859-10" ),
+    wxT( "iso-8859-11" ),
+    wxT( "iso-8859-12" ),
+    wxT( "iso-8859-13" ),
+    wxT( "iso-8859-14" ),
+    wxT( "iso-8859-15" ),
+    wxT( "koi8-r" ),
+    wxT( "windows-932" ),
+    wxT( "windows-936" ),
+    wxT( "windows-949" ),
+    wxT( "windows-950" ),
+    wxT( "windows-1250" ),
+    wxT( "windows-1251" ),
+    wxT( "windows-1252" ),
+    wxT( "windows-1253" ),
+    wxT( "windows-1254" ),
+    wxT( "windows-1255" ),
+    wxT( "windows-1256" ),
+    wxT( "windows-1257" ),
+    wxT( "windows-437" ),
+    wxT( "utf-7" ),
+    wxT( "utf-8" ),
 };
 
 // ----------------------------------------------------------------------------
 };
 
 // ----------------------------------------------------------------------------
@@ -146,7 +185,7 @@ static const wxChar* gs_encodingNames[] =
 static wxFontMapper gs_fontMapper;
 
 // and public pointer
 static wxFontMapper gs_fontMapper;
 
 // and public pointer
-wxFontMapper * WXDLLEXPORT wxTheFontMapper = &gs_fontMapper;
+wxFontMapper * wxTheFontMapper = &gs_fontMapper;
 
 // ----------------------------------------------------------------------------
 // private classes
 
 // ----------------------------------------------------------------------------
 // private classes
@@ -186,18 +225,30 @@ private:
 
 wxFontMapper::wxFontMapper()
 {
 
 wxFontMapper::wxFontMapper()
 {
+#if wxUSE_CONFIG
     m_config = NULL;
     m_config = NULL;
+    m_configIsDummy = FALSE;
+#endif // wxUSE_CONFIG
+
+#if wxUSE_GUI
     m_windowParent = NULL;
     m_windowParent = NULL;
+#endif // wxUSE_GUI
 }
 
 wxFontMapper::~wxFontMapper()
 {
 }
 
 wxFontMapper::~wxFontMapper()
 {
+#if wxUSE_CONFIG
+    if ( m_configIsDummy )
+        delete m_config;
+#endif // wxUSE_CONFIG
 }
 
 // ----------------------------------------------------------------------------
 // customisation
 // ----------------------------------------------------------------------------
 
 }
 
 // ----------------------------------------------------------------------------
 // customisation
 // ----------------------------------------------------------------------------
 
+#if wxUSE_CONFIG
+
 /* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
 {
     return FONTMAPPER_ROOT_PATH;
 /* static */ const wxChar *wxFontMapper::GetDefaultConfigPath()
 {
     return FONTMAPPER_ROOT_PATH;
@@ -206,13 +257,11 @@ wxFontMapper::~wxFontMapper()
 void wxFontMapper::SetConfigPath(const wxString& prefix)
 {
     wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
 void wxFontMapper::SetConfigPath(const wxString& prefix)
 {
     wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR,
-                 _T("an absolute path should be given to "
-                     "wxFontMapper::SetConfigPath()") );
+                 wxT("an absolute path should be given to wxFontMapper::SetConfigPath()") );
 
     m_configRootPath = prefix;
 }
 
 
     m_configRootPath = prefix;
 }
 
-
 // ----------------------------------------------------------------------------
 // get config object and path for it
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // get config object and path for it
 // ----------------------------------------------------------------------------
@@ -222,7 +271,36 @@ wxConfigBase *wxFontMapper::GetConfig()
     if ( !m_config )
     {
         // try the default
     if ( !m_config )
     {
         // try the default
-        m_config = wxConfig::Get();
+        m_config = wxConfig::Get(FALSE /*don't create on demand*/ );
+
+        if ( !m_config )
+        {
+            // we still want to have a config object because otherwise we would
+            // keep asking the user the same questions in the interactive mode,
+            // so create a dummy config which won't write to any files/registry
+            // but will allow us to remember the results of the questions at
+            // least during this run
+            m_config = new wxMemoryConfig;
+            m_configIsDummy = TRUE;
+            // VS: we can't call wxConfig::Set(m_config) here because that would
+            //     disable automatic wxConfig instance creation if this code was
+            //     called before wxApp::OnInit (this happens in wxGTK -- it sets
+            //     default wxFont encoding in wxApp::Initialize())
+        }
+    }
+
+    if ( m_configIsDummy && wxConfig::Get(FALSE) != NULL )
+    {
+        // VS: in case we created dummy m_config (see above), we want to switch back
+        //     to the real one as soon as one becomes available.
+        delete m_config;
+        m_config = wxConfig::Get(FALSE);
+        m_configIsDummy = FALSE;
+        // FIXME: ideally, we should add keys from dummy config to the real one now,
+        //        but it is a low-priority task because typical wxWin application
+        //        either doesn't use wxConfig at all or creates wxConfig object in
+        //        wxApp::OnInit(), before any real interaction with the user takes
+        //        place...
     }
 
     return m_config;
     }
 
     return m_config;
@@ -238,9 +316,11 @@ const wxString& wxFontMapper::GetConfigPath()
 
     return m_configRootPath;
 }
 
     return m_configRootPath;
 }
+#endif
 
 bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
 {
 
 bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
 {
+#if wxUSE_CONFIG
     wxConfigBase *config = GetConfig();
     if ( !config )
         return FALSE;
     wxConfigBase *config = GetConfig();
     if ( !config )
         return FALSE;
@@ -254,18 +334,24 @@ bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld)
     }
 
     wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
     }
 
     wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR),
-                  _T("should be a relative path") );
+                  wxT("should be a relative path") );
 
     path += pathNew;
 
     config->SetPath(path);
 
     return TRUE;
 
     path += pathNew;
 
     config->SetPath(path);
 
     return TRUE;
+#else
+    return FALSE;
+#endif
 }
 
 void wxFontMapper::RestorePath(const wxString& pathOld)
 {
 }
 
 void wxFontMapper::RestorePath(const wxString& pathOld)
 {
+#if wxUSE_CONFIG
     GetConfig()->SetPath(pathOld);
     GetConfig()->SetPath(pathOld);
+#else
+#endif
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
@@ -275,11 +361,15 @@ void wxFontMapper::RestorePath(const wxString& pathOld)
 /* static */
 wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
 {
 /* static */
 wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
 {
+    if ( encoding == wxFONTENCODING_DEFAULT )
+    {
+        return _("Default encoding");
+    }
+
     size_t count = WXSIZEOF(gs_encodingDescs);
 
     wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
     size_t count = WXSIZEOF(gs_encodingDescs);
 
     wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
-                  _T("inconsitency detected - forgot to update one of "
-                     "the arrays?") );
+                  wxT("inconsitency detected - forgot to update one of the arrays?") );
 
     for ( size_t i = 0; i < count; i++ )
     {
 
     for ( size_t i = 0; i < count; i++ )
     {
@@ -298,17 +388,21 @@ wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
 /* static */
 wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
 {
 /* static */
 wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
 {
+    if ( encoding == wxFONTENCODING_DEFAULT )
+    {
+        return _("default");
+    }
+
     size_t count = WXSIZEOF(gs_encodingNames);
 
     wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
     size_t count = WXSIZEOF(gs_encodingNames);
 
     wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
-                  _T("inconsitency detected - forgot to update one of "
-                     "the arrays?") );
+                  wxT("inconsistency detected - forgot to update one of the arrays?") );
 
     for ( size_t i = 0; i < count; i++ )
     {
         if ( gs_encodings[i] == encoding )
         {
 
     for ( size_t i = 0; i < count; i++ )
     {
         if ( gs_encodings[i] == encoding )
         {
-            return wxGetTranslation(gs_encodingNames[i]);
+            return gs_encodingNames[i];
         }
     }
 
         }
     }
 
@@ -321,11 +415,18 @@ wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
 wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
                                                bool interactive)
 {
 wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
                                                bool interactive)
 {
+    // a special pseudo encoding which means "don't ask me about this charset
+    // any more" - we need it to avoid driving the user crazy with asking him
+    // time after time about the same charset which he [presumably] doesn't
+    // have the fonts fot
+    static const int wxFONTENCODING_UNKNOWN = -2;
+
     wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
 
     // we're going to modify it, make a copy
     wxString cs = charset;
 
     wxFontEncoding encoding = wxFONTENCODING_SYSTEM;
 
     // we're going to modify it, make a copy
     wxString cs = charset;
 
+#if wxUSE_CONFIG
     // first try the user-defined settings
     wxString pathOld;
     if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
     // first try the user-defined settings
     wxString pathOld;
     if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
@@ -336,14 +437,20 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
         long value = config->Read(charset, -1l);
         if ( value != -1 )
         {
         long value = config->Read(charset, -1l);
         if ( value != -1 )
         {
+            if ( value == wxFONTENCODING_UNKNOWN )
+            {
+                // don't try to find it, in particular don't ask the user
+                return wxFONTENCODING_SYSTEM;
+            }
+
             if ( value >= 0 && value <= wxFONTENCODING_MAX )
             {
                 encoding = (wxFontEncoding)value;
             }
             else
             {
             if ( value >= 0 && value <= wxFONTENCODING_MAX )
             {
                 encoding = (wxFontEncoding)value;
             }
             else
             {
-                wxLogDebug(_T("corrupted config data - invalid encoding %ld "
-                              "for charset '%s'"), value, charset.c_str());
+                wxLogDebug(wxT("corrupted config data: invalid encoding %ld for charset '%s' ignored"),
+                           value, charset.c_str());
             }
         }
 
             }
         }
 
@@ -362,50 +469,124 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
 
         RestorePath(pathOld);
     }
 
         RestorePath(pathOld);
     }
+#endif // wxUSE_CONFIG
 
 
-    // if didn't find it there, try to reckognise it ourselves
+    // if didn't find it there, try to recognize it ourselves
     if ( encoding == wxFONTENCODING_SYSTEM )
     {
     if ( encoding == wxFONTENCODING_SYSTEM )
     {
+        // trim any spaces
+        cs.Trim(TRUE);
+        cs.Trim(FALSE);
+
+        // discard the optional quotes
+        if ( !!cs )
+        {
+            if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
+            {
+                cs = wxString(cs.c_str(), cs.length() - 1);
+            }
+        }
+
         cs.MakeUpper();
 
         cs.MakeUpper();
 
-        if ( !cs || cs == _T("US-ASCII") )
+        if ( !cs || cs == wxT("US-ASCII") )
+        {
             encoding = wxFONTENCODING_DEFAULT;
             encoding = wxFONTENCODING_DEFAULT;
-        else if ( cs == _T("KOI8-R") || cs == _T("KOI8-U") )
+        }
+        else if ( cs == wxT("UTF-7") )
+        {
+            encoding = wxFONTENCODING_UTF7;
+        }
+        else if ( cs == wxT("UTF-8") )
+        {
+            encoding = wxFONTENCODING_UTF8;
+        }
+        else if ( cs == wxT("KOI8-R") ||
+                  cs == wxT("KOI8-U") ||
+                  cs == wxT("KOI8-RU") )
+        {
+            // although koi8-ru is not strictly speaking the same as koi8-r,
+            // they are similar enough to make mapping it to koi8 better than
+            // not reckognizing it at all
             encoding = wxFONTENCODING_KOI8;
             encoding = wxFONTENCODING_KOI8;
-        else if ( cs.Left(3) == _T("ISO") )
+        }
+        else if ( cs.Left(3) == wxT("ISO") )
         {
             // the dash is optional (or, to be exact, it is not, but
             // several brokenmails "forget" it)
             const wxChar *p = cs.c_str() + 3;
         {
             // the dash is optional (or, to be exact, it is not, but
             // several brokenmails "forget" it)
             const wxChar *p = cs.c_str() + 3;
-            if ( *p == _T('-') )
+            if ( *p == wxT('-') )
                 p++;
 
             unsigned int value;
                 p++;
 
             unsigned int value;
-            if ( wxSscanf(p, _T("8859-%u"), &value) == 1 )
+            if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
             {
             {
-                if ( value < wxFONTENCODING_ISO8859_MAX -
-                             wxFONTENCODING_ISO8859_1 )
+                // make it 0 based and check that it is strictly positive in
+                // the process (no such thing as iso8859-0 encoding)
+                if ( (value-- > 0) &&
+                     (value < wxFONTENCODING_ISO8859_MAX -
+                              wxFONTENCODING_ISO8859_1) )
                 {
                     // it's a valid ISO8859 encoding
                 {
                     // it's a valid ISO8859 encoding
-                    value += wxFONTENCODING_ISO8859_1 - 1;
+                    value += wxFONTENCODING_ISO8859_1;
                     encoding = (wxFontEncoding)value;
                 }
             }
         }
                     encoding = (wxFontEncoding)value;
                 }
             }
         }
-        else if ( cs.Left(8) == _T("WINDOWS-") )
+        else // check for Windows charsets
         {
         {
-            int value;
-            if ( wxSscanf(cs.c_str() + 8, "%u", &value) == 1 )
+            size_t len;
+            if ( cs.Left(7) == wxT("WINDOWS") )
+            {
+                len = 7;
+            }
+            else if ( cs.Left(2) == wxT("CP") )
+            {
+                len = 2;
+            }
+            else // not a Windows encoding
             {
             {
-                if ( value >= 1250 )
+                len = 0;
+            }
+
+            if ( len )
+            {
+                const wxChar *p = cs.c_str() + len;
+                if ( *p == wxT('-') )
+                    p++;
+
+                int value;
+                if ( wxSscanf(p, wxT("%u"), &value) == 1 )
                 {
                 {
-                    value -= 1250;
-                    if ( value < wxFONTENCODING_CP12_MAX -
-                                 wxFONTENCODING_CP1250 - 1 )
+                    if ( value >= 1250 )
                     {
                     {
-                        // a valid Windows code page
-                        value += wxFONTENCODING_CP1250;
-                        encoding = (wxFontEncoding)value;
+                        value -= 1250;
+                        if ( value < wxFONTENCODING_CP12_MAX -
+                                     wxFONTENCODING_CP1250 )
+                        {
+                            // a valid Windows code page
+                            value += wxFONTENCODING_CP1250;
+                            encoding = (wxFontEncoding)value;
+                        }
+                    }
+
+                    switch ( value )
+                    {
+                        case 932:
+                            encoding = wxFONTENCODING_CP932;
+                            break;
+
+                        case 936:
+                            encoding = wxFONTENCODING_CP936;
+                            break;
+
+                        case 949:
+                            encoding = wxFONTENCODING_CP949;
+                            break;
+
+                        case 950:
+                            encoding = wxFONTENCODING_CP950;
+                            break;
                     }
                 }
             }
                     }
                 }
             }
@@ -413,6 +594,7 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
         //else: unknown
     }
 
         //else: unknown
     }
 
+#if wxUSE_GUI
     // if still no luck, ask the user - unless disabled
     if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
     {
     // if still no luck, ask the user - unless disabled
     if ( (encoding == wxFONTENCODING_SYSTEM) && interactive )
     {
@@ -425,16 +607,13 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
 
         // the message
         wxString msg;
 
         // the message
         wxString msg;
-        msg.Printf(_("The charset '%s' is unknown. You may select another "
-                     "charset to replace it with or choose [Cancel] if it "
-                     "cannot be replaced"), charset.c_str());
+        msg.Printf(_("The charset '%s' is unknown. You may select\nanother charset to replace it with or choose\n[Cancel] if it cannot be replaced"), charset.c_str());
 
         // the list of choices
         size_t count = WXSIZEOF(gs_encodingDescs);
 
         wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
 
         // the list of choices
         size_t count = WXSIZEOF(gs_encodingDescs);
 
         wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
-                      _T("inconsitency detected - forgot to update one of "
-                         "the arrays?") );
+                      wxT("inconsitency detected - forgot to update one of the arrays?") );
 
         wxString *encodingNamesTranslated = new wxString[count];
 
 
         wxString *encodingNamesTranslated = new wxString[count];
 
@@ -458,12 +637,28 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
 
         if ( n != -1 )
         {
 
         if ( n != -1 )
         {
-            // TODO save the result in the config!
-
             encoding = gs_encodings[n];
         }
             encoding = gs_encodings[n];
         }
-        //else: cancelled
+
+#if wxUSE_CONFIG
+        // save the result in the config now
+        if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
+        {
+            wxConfigBase *config = GetConfig();
+
+            // remember the alt encoding for this charset - or remember that
+            // we don't know it
+            long value = n == -1 ? wxFONTENCODING_UNKNOWN : (long)encoding;
+            if ( !config->Write(charset, value) )
+            {
+                wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
+            }
+
+            RestorePath(pathOld);
+        }
+#endif // wxUSE_CONFIG
     }
     }
+#endif // wxUSE_GUI
 
     return encoding;
 }
 
     return encoding;
 }
@@ -474,6 +669,8 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
 // correspond to which is used by GetFontForEncoding() function
 // ----------------------------------------------------------------------------
 
 // correspond to which is used by GetFontForEncoding() function
 // ----------------------------------------------------------------------------
 
+#if wxUSE_GUI
+
 bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
                                    wxFontEncoding encReplacement,
                                    wxNativeEncodingInfo *info)
 bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
                                    wxFontEncoding encReplacement,
                                    wxNativeEncodingInfo *info)
@@ -481,6 +678,7 @@ bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
     if ( wxGetNativeFontEncoding(encReplacement, info) &&
          wxTestFontEncoding(*info) )
     {
     if ( wxGetNativeFontEncoding(encReplacement, info) &&
          wxTestFontEncoding(*info) )
     {
+#if wxUSE_CONFIG
         // remember the mapping in the config
         wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
 
         // remember the mapping in the config
         wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH);
 
@@ -488,21 +686,77 @@ bool wxFontMapper::TestAltEncoding(const wxString& configEntry,
         {
             GetConfig()->Write(configEntry, info->ToString());
         }
         {
             GetConfig()->Write(configEntry, info->ToString());
         }
-
+#endif // wxUSE_CONFIG
         return TRUE;
     }
 
     return FALSE;
 }
 
         return TRUE;
     }
 
     return FALSE;
 }
 
+#if wxUSE_GUI
+class ReentrancyBlocker
+{
+public:
+    ReentrancyBlocker(bool& b) : m_b(b) { m_b = TRUE; }
+    ~ReentrancyBlocker() { m_b = FALSE; }
+
+private:
+    bool& m_b;
+};
+#endif
+
 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
                                      wxNativeEncodingInfo *info,
 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
                                      wxNativeEncodingInfo *info,
+                                     const wxString& facename,
                                      bool interactive)
 {
                                      bool interactive)
 {
-    wxCHECK_MSG( info, FALSE, _T("bad pointer in GetAltForEncoding") );
+#if wxUSE_GUI
+    // we need a flag to prevent infinite recursion which happens, for
+    // example, when GetAltForEncoding() is called from an OnPaint() handler:
+    // in this case, wxYield() which is called from wxMessageBox() we use here
+    // will lead to another call of OnPaint() and hence to another call of
+    // GetAltForEncoding() - and it is impossible to catch this from the user
+    // code because we are called from wxFont ctor implicitly.
+
+    // assume we're always called from the main thread, so that it is safe to
+    // use a static var
+    static bool s_inGetAltForEncoding = FALSE;
+
+    if ( interactive && s_inGetAltForEncoding )
+        return FALSE;
+
+    ReentrancyBlocker blocker(s_inGetAltForEncoding);
+#endif // wxUSE_GUI
 
 
-    wxString configEntry = GetEncodingName(encoding);
+    wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") );
 
 
+    info->facename = facename;
+
+    if ( encoding == wxFONTENCODING_DEFAULT )
+    {
+        encoding = wxFont::GetDefaultEncoding();
+    }
+
+    // if we failed to load the system default encoding, something is really
+    // wrong and we'd better stop now - otherwise we will go into endless
+    // recursion trying to create the font in the msg box with the error
+    // message
+    if ( encoding == wxFONTENCODING_SYSTEM )
+    {
+        wxFatalError(_("can't load any font, aborting"));
+
+        // wxFatalError doesn't return
+    }
+
+    wxString configEntry,
+             encName = GetEncodingName(encoding);
+    if ( !!facename )
+    {
+        configEntry = facename + _T("_");
+    }
+    configEntry += encName;
+
+#if wxUSE_CONFIG
     // do we have a font spec for this encoding?
     wxString pathOld;
     if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
     // do we have a font spec for this encoding?
     wxString pathOld;
     if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
@@ -513,59 +767,111 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
 
         RestorePath(pathOld);
 
 
         RestorePath(pathOld);
 
-        if ( !!fontinfo )
+        // this special value means that we don't know of fonts for this
+        // encoding but, moreover, have already asked the user as well and he
+        // didn't specify any font neither
+        if ( fontinfo == FONTMAPPER_FONT_DONT_ASK )
         {
         {
-            if ( info->FromString(fontinfo) )
+            interactive = FALSE;
+        }
+        else // use the info entered the last time
+        {
+            if ( !!fontinfo && !!facename )
             {
             {
-                if ( wxTestFontEncoding(*info) )
+                // we tried to find a match with facename - now try without it
+                fontinfo = config->Read(encName);
+            }
+
+            if ( !!fontinfo )
+            {
+                if ( info->FromString(fontinfo) )
                 {
                 {
-                    // ok, got something
-                    return TRUE;
+                    if ( wxTestFontEncoding(*info) )
+                    {
+                        // ok, got something
+                        return TRUE;
+                    }
+                    //else: no such fonts, look for something else
+                    //      (should we erase the outdated value?)
+                }
+                else
+                {
+                    wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"),
+                               fontinfo.c_str());
                 }
                 }
-                //else: no such fonts, look for something else
             }
             }
-            else
+            //else: there is no information in config about this encoding
+        }
+    }
+#endif // wxUSE_CONFIG
+
+    // now try to map this encoding to a compatible one which we have on this
+    // system
+    wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
+    size_t count = equiv.GetCount();
+    bool foundEquivEncoding = FALSE;
+    wxFontEncoding equivEncoding = wxFONTENCODING_SYSTEM;
+    if ( count )
+    {
+        for ( size_t i = 0; i < count && !foundEquivEncoding; i++ )
+        {
+            // don't test for encoding itself, we already know we don't have it
+            if ( equiv[i] == encoding )
+                continue;
+
+            if ( TestAltEncoding(configEntry, equiv[i], info) )
             {
             {
-                wxLogDebug(_T("corrupted config data: string '%s' is not "
-                              "a valid font encoding info"), fontinfo.c_str());
+                equivEncoding = equiv[i];
+
+                foundEquivEncoding = TRUE;
             }
         }
     }
 
     // ask the user
             }
         }
     }
 
     // ask the user
+#if wxUSE_FONTDLG
     if ( interactive )
     {
         wxString title(m_titleDialog);
         if ( !title )
             title << wxTheApp->GetAppName() << _(": unknown encoding");
 
     if ( interactive )
     {
         wxString title(m_titleDialog);
         if ( !title )
             title << wxTheApp->GetAppName() << _(": unknown encoding");
 
-        // the message
-        wxString msg;
-        msg.Printf(_("The encoding '%s' is unknown.\n"
-                     "Would you like to select a font to be used for this "
-                     "encoding\n"
-                     "(otherwise the text in this encoding will not be "
-                     "shown correctly)?"),
-                     GetEncodingDescription(encoding).c_str());
+        // built the message
+        wxString encDesc = GetEncodingDescription(encoding),
+                 msg;
+        if ( foundEquivEncoding )
+        {
+            // ask the user if he wants to override found alternative encoding
+            msg.Printf(_("No font for displaying text in encoding '%s' found,\nbut an alternative encoding '%s' is available.\nDo you want to use this encoding (otherwise you will have to choose another one)?"),
+                       encDesc.c_str(), GetEncodingDescription(equivEncoding).c_str());
+        }
+        else
+        {
+            msg.Printf(_("No font for displaying text in encoding '%s' found.\nWould you like to select a font to be used for this encoding\n(otherwise the text in this encoding will not be shown correctly)?"),
+                       encDesc.c_str());
+        }
 
 
-        wxWindow *parent = m_windowParent;
-        if ( !parent )
-            parent = wxTheApp->GetTopWindow();
+        // the question is different in 2 cases so the answer has to be
+        // interpreted differently as well
+        int answer = foundEquivEncoding ? wxNO : wxYES;
 
         if ( wxMessageBox(msg, title,
 
         if ( wxMessageBox(msg, title,
-                          wxICON_QUESTION | wxYES_NO, parent) == wxYES )
+                          wxICON_QUESTION | wxYES_NO,
+                          m_windowParent) == answer )
         {
             wxFontData data;
             data.SetEncoding(encoding);
             data.EncodingInfo() = *info;
         {
             wxFontData data;
             data.SetEncoding(encoding);
             data.EncodingInfo() = *info;
-            wxFontDialog dialog(parent, &data);
+            wxFontDialog dialog(m_windowParent, &data);
             if ( dialog.ShowModal() == wxID_OK )
             {
                 wxFontData retData = dialog.GetFontData();
                 wxFont font = retData.GetChosenFont();
 
                 *info = retData.EncodingInfo();
             if ( dialog.ShowModal() == wxID_OK )
             {
                 wxFontData retData = dialog.GetFontData();
                 wxFont font = retData.GetChosenFont();
 
                 *info = retData.EncodingInfo();
+                info->encoding = retData.GetEncoding();
 
 
+#if wxUSE_CONFIG
                 // remember this in the config
                 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
                 {
                 // remember this in the config
                 if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
                 {
@@ -573,80 +879,64 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
 
                     RestorePath(pathOld);
                 }
 
                     RestorePath(pathOld);
                 }
+#endif // wxUSE_CONFIG
 
                 return TRUE;
             }
             //else: the user canceled the font selection dialog
         }
 
                 return TRUE;
             }
             //else: the user canceled the font selection dialog
         }
-        //else: the user doesn't want to select a font
+        else
+        {
+            // the user doesn't want to select a font for this encoding
+            // or selected to use equivalent encoding
+            //
+            // remember it to avoid asking the same question again later
+#if wxUSE_CONFIG
+            if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) )
+            {
+                GetConfig()->Write
+                             (
+                                configEntry,
+                                foundEquivEncoding ? info->ToString().c_str()
+                                                   : FONTMAPPER_FONT_DONT_ASK
+                             );
+
+                RestorePath(pathOld);
+            }
+#endif // wxUSE_CONFIG
+        }
     }
     //else: we're in non-interactive mode
     }
     //else: we're in non-interactive mode
+#endif // wxUSE_FONTDLG
 
 
-    // now try the default mappings
-    switch ( encoding )
-    {
-        case wxFONTENCODING_ISO8859_15:
-            // iso8859-15 is slightly modified iso8859-1
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_1, info) )
-                return TRUE;
-            // fall through
-
-        case wxFONTENCODING_ISO8859_1:
-            // iso8859-1 is identical to CP1252
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_CP1252, info) )
-                return TRUE;
-
-            break;
-
-        case wxFONTENCODING_CP1252:
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_1, info) )
-                return TRUE;
-
-            break;
-
-        // iso8859-13 is quite similar to WinBaltic
-        case wxFONTENCODING_ISO8859_13:
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_CP1257, info) )
-                return TRUE;
-
-            break;
-
-        case wxFONTENCODING_CP1257:
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_13, info) )
-                return TRUE;
-
-            break;
-
-        // iso8859-8 is almost identical to WinHebrew
-        case wxFONTENCODING_ISO8859_8:
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_CP1255, info) )
-                return TRUE;
-
-            break;
-
-        case wxFONTENCODING_CP1255:
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_8, info) )
-                return TRUE;
-
-            break;
-
-        // and iso8859-7 is not too different from WinGreek
-        case wxFONTENCODING_ISO8859_7:
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_CP1253, info) )
-                return TRUE;
-
-            break;
+    return foundEquivEncoding;
+}
 
 
-        case wxFONTENCODING_CP1253:
-            if ( TestAltEncoding(configEntry, wxFONTENCODING_ISO8859_7, info) )
-                return TRUE;
+bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
+                                     wxFontEncoding *alt_encoding,
+                                     const wxString& facename,
+                                     bool interactive)
+{
+    wxNativeEncodingInfo info;
+    bool r = GetAltForEncoding(encoding, &info, facename, interactive);
+    *alt_encoding = info.encoding;
+    return r;
+}
 
 
-            break;
+bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding,
+                                       const wxString& facename)
+{
+    wxNativeEncodingInfo info;
 
 
-        default:
-           // TODO add other mappings...
-           ;
+    if (wxGetNativeFontEncoding(encoding, &info))
+    {
+        info.facename = facename;
+        return wxTestFontEncoding(info);
     }
 
     return FALSE;
 }
     }
 
     return FALSE;
 }
+
+#endif // wxUSE_GUI
+
+#endif // wxUSE_FONTMAP