]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/fontmap.cpp
Copyright cleanup
[wxWidgets.git] / src / common / fontmap.cpp
index 6b2e3b81deceef99658494b0a3f22f1a54047915..e81d145d65cccd4a29e215361ef4e3a8f6a4eefd 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     04.11.99
 // RCS-ID:      $Id$
 // Copyright:   (c) Vadim Zeitlin
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
@@ -36,6 +36,7 @@
     #include "wx/intl.h"
 #endif // PCH
 
+#include "wx/module.h"
 #include "wx/fontmap.h"
 
 #if wxUSE_CONFIG
@@ -88,6 +89,10 @@ static wxFontEncoding gs_encodings[] =
     wxFONTENCODING_ISO8859_14,
     wxFONTENCODING_ISO8859_15,
     wxFONTENCODING_KOI8,
+    wxFONTENCODING_CP932,
+    wxFONTENCODING_CP936,
+    wxFONTENCODING_CP949,
+    wxFONTENCODING_CP950,
     wxFONTENCODING_CP1250,
     wxFONTENCODING_CP1251,
     wxFONTENCODING_CP1252,
@@ -99,6 +104,7 @@ static wxFontEncoding gs_encodings[] =
     wxFONTENCODING_CP437,
     wxFONTENCODING_UTF7,
     wxFONTENCODING_UTF8,
+    wxFONTENCODING_EUC_JP,
 };
 
 // the descriptions for them
@@ -120,6 +126,10 @@ static const wxChar* gs_encodingDescs[] =
     wxTRANSLATE( "Celtic (ISO-8859-14)" ),
     wxTRANSLATE( "Western European with Euro (ISO-8859-15)" ),
     wxTRANSLATE( "KOI8-R" ),
+    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 Western European (CP 1252)" ),
@@ -131,9 +141,10 @@ static const wxChar* gs_encodingDescs[] =
     wxTRANSLATE( "Windows/DOS OEM (CP 437)" ),
     wxTRANSLATE( "Unicode 7 bit (UTF-7)" ),
     wxTRANSLATE( "Unicode 8 bit (UTF-8)" ),
+    wxTRANSLATE( "Extended Unix Codepage for Japanese (EUC-JP)" ),
 };
 
-// and the internal names
+// and the internal names (these are not translated on purpose!)
 static const wxChar* gs_encodingNames[] =
 {
     wxT( "iso-8859-1" ),
@@ -152,6 +163,10 @@ static const wxChar* gs_encodingNames[] =
     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" ),
@@ -161,19 +176,14 @@ static const wxChar* gs_encodingNames[] =
     wxT( "windows-1256" ),
     wxT( "windows-1257" ),
     wxT( "windows-437" ),
-    wxT( "utf7" ),
-    wxT( "utf8" ),
+    wxT( "utf-7" ),
+    wxT( "utf-8" ),
+    wxT( "euc-jp" ),
 };
 
-// ----------------------------------------------------------------------------
-// global data
-// ----------------------------------------------------------------------------
-
-// private object
-static wxFontMapper gs_fontMapper;
-
-// and public pointer
-wxFontMapper * wxTheFontMapper = &gs_fontMapper;
+wxCOMPILE_TIME_ASSERT( WXSIZEOF(gs_encodingDescs) == WXSIZEOF(gs_encodings) &&
+                       WXSIZEOF(gs_encodingNames) == WXSIZEOF(gs_encodings),
+                       EncodingsArraysNotInSync );
 
 // ----------------------------------------------------------------------------
 // private classes
@@ -201,6 +211,8 @@ private:
     wxFontMapper *m_fontMapper;
     bool          m_ok;
     wxString      m_pathOld;
+
+    DECLARE_NO_COPY_CLASS(wxFontMapperPathChanger)
 };
 
 // ============================================================================
@@ -215,6 +227,7 @@ wxFontMapper::wxFontMapper()
 {
 #if wxUSE_CONFIG
     m_config = NULL;
+    m_configIsDummy = FALSE;
 #endif // wxUSE_CONFIG
 
 #if wxUSE_GUI
@@ -224,8 +237,40 @@ wxFontMapper::wxFontMapper()
 
 wxFontMapper::~wxFontMapper()
 {
+#if wxUSE_CONFIG
+    if ( m_configIsDummy )
+        delete m_config;
+#endif // wxUSE_CONFIG
+}
+
+wxFontMapper *wxFontMapper::sm_instance = NULL;
+
+/*static*/ wxFontMapper *wxFontMapper::Get()
+{
+    if ( !sm_instance )
+        sm_instance = new wxFontMapper;
+    return sm_instance;
+}
+
+/*static*/ wxFontMapper *wxFontMapper::Set(wxFontMapper *mapper)
+{
+    wxFontMapper *old = sm_instance;
+    sm_instance = mapper;
+    return old;
 }
 
+class wxFontMapperModule: public wxModule
+{
+public:
+    wxFontMapperModule() : wxModule() {}
+    virtual bool OnInit() { return TRUE; }
+    virtual void OnExit() { delete wxFontMapper::Set(NULL); }
+
+    DECLARE_DYNAMIC_CLASS(wxFontMapperModule)
+};
+
+IMPLEMENT_DYNAMIC_CLASS(wxFontMapperModule, wxModule)
+
 // ----------------------------------------------------------------------------
 // customisation
 // ----------------------------------------------------------------------------
@@ -264,10 +309,28 @@ wxConfigBase *wxFontMapper::GetConfig()
             // but will allow us to remember the results of the questions at
             // least during this run
             m_config = new wxMemoryConfig;
-            wxConfig::Set(m_config);
+            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;
 }
 
@@ -331,10 +394,7 @@ wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding)
         return _("Default encoding");
     }
 
-    size_t count = WXSIZEOF(gs_encodingDescs);
-
-    wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
-                  wxT("inconsitency detected - forgot to update one of the arrays?") );
+    const size_t count = WXSIZEOF(gs_encodingDescs);
 
     for ( size_t i = 0; i < count; i++ )
     {
@@ -358,16 +418,13 @@ wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
         return _("default");
     }
 
-    size_t count = WXSIZEOF(gs_encodingNames);
-
-    wxASSERT_MSG( count == WXSIZEOF(gs_encodings),
-                  wxT("inconsistency detected - forgot to update one of the arrays?") );
+    const size_t count = WXSIZEOF(gs_encodingNames);
 
     for ( size_t i = 0; i < count; i++ )
     {
         if ( gs_encodings[i] == encoding )
         {
-            return wxGetTranslation(gs_encodingNames[i]);
+            return gs_encodingNames[i];
         }
     }
 
@@ -380,6 +437,12 @@ wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding)
 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
@@ -396,6 +459,12 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
         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;
@@ -422,7 +491,7 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
 
         RestorePath(pathOld);
     }
-#endif
+#endif // wxUSE_CONFIG
 
     // if didn't find it there, try to recognize it ourselves
     if ( encoding == wxFONTENCODING_SYSTEM )
@@ -432,7 +501,7 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
         cs.Trim(FALSE);
 
         // discard the optional quotes
-        if ( !!cs )
+        if ( !cs.empty() )
         {
             if ( cs[0u] == _T('"') && cs.Last() == _T('"') )
             {
@@ -442,7 +511,7 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
 
         cs.MakeUpper();
 
-        if ( !cs || cs == wxT("US-ASCII") )
+        if ( cs.empty() || cs == _T("US-ASCII") )
         {
             encoding = wxFONTENCODING_DEFAULT;
         }
@@ -454,6 +523,25 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
         {
             encoding = wxFONTENCODING_UTF8;
         }
+        else if ( cs == wxT("GB2312") )
+        {
+            encoding = wxFONTENCODING_GB2312;
+        }
+        else if ( cs == wxT("BIG5") )
+        {
+            encoding = wxFONTENCODING_BIG5;
+        }
+        else if ( cs == wxT("SJIS") ||
+                  cs == wxT("SHIFT_JIS") ||
+                  cs == wxT("SHIFT-JIS") )
+        {
+            encoding = wxFONTENCODING_SHIFT_JIS;
+        }
+        else if ( cs == wxT("EUC-JP") ||
+                  cs == wxT("EUC_JP") )
+        {
+            encoding = wxFONTENCODING_EUC_JP;
+        }
         else if ( cs == wxT("KOI8-R") ||
                   cs == wxT("KOI8-U") ||
                   cs == wxT("KOI8-RU") )
@@ -470,10 +558,35 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
             const wxChar *p = cs.c_str() + 3;
             if ( *p == wxT('-') )
                 p++;
+                
+            // printf( "iso %s\n", (const char*) cs.ToAscii() );
 
             unsigned int value;
             if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
             {
+                // printf( "value %d\n", (int)value );
+   
+                // 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
+                    value += wxFONTENCODING_ISO8859_1;
+                    encoding = (wxFontEncoding)value;
+                }
+            }
+        }
+        else if ( cs.Left(4) == wxT("8859") )
+        {
+            const wxChar *p = cs.c_str();
+            
+            unsigned int value;
+            if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 )
+            {
+                // printf( "value %d\n", (int)value );
+   
                 // make it 0 based and check that it is strictly positive in
                 // the process (no such thing as iso8859-0 encoding)
                 if ( (value-- > 0) &&
@@ -522,6 +635,25 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
                             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;
+                    }
                 }
             }
         }
@@ -544,10 +676,7 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
         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),
-                      wxT("inconsitency detected - forgot to update one of the arrays?") );
+        const size_t count = WXSIZEOF(gs_encodingDescs);
 
         wxString *encodingNamesTranslated = new wxString[count];
 
@@ -572,24 +701,25 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset,
         if ( n != -1 )
         {
             encoding = gs_encodings[n];
+        }
 
 #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
-                if ( !config->Write(charset, (long)encoding) )
-                {
-                    wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset.c_str());
-                }
+        if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) )
+        {
+            wxConfigBase *config = GetConfig();
 
-                RestorePath(pathOld);
+            // 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());
             }
-#endif // wxUSE_CONFIG
+
+            RestorePath(pathOld);
         }
-        //else: cancelled
+#endif // wxUSE_CONFIG
     }
 #endif // wxUSE_GUI
 
@@ -676,12 +806,13 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
     // message
     if ( encoding == wxFONTENCODING_SYSTEM )
     {
-        wxFatalError(_("can't load any font, aborting"));
+        wxLogFatalError(_("can't load any font, aborting"));
 
-        // wxFatalError doesn't return
+        // wxLogFatalError doesn't return
     }
 
-    wxString configEntry, encName = GetEncodingName(encoding);
+    wxString configEntry,
+             encName = GetEncodingName(encoding);
     if ( !!facename )
     {
         configEntry = facename + _T("_");
@@ -737,36 +868,71 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding 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) )
+            {
+                equivEncoding = equiv[i];
+
+                foundEquivEncoding = TRUE;
+            }
+        }
+    }
+
     // ask the user
+#if wxUSE_FONTDLG
     if ( interactive )
     {
         wxString title(m_titleDialog);
         if ( !title )
             title << wxTheApp->GetAppName() << _(": unknown encoding");
 
-        // the message
-        wxString msg;
-        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)?"),
-                     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,
-                          wxICON_QUESTION | wxYES_NO, parent) == wxYES )
+                          wxICON_QUESTION | wxYES_NO,
+                          m_windowParent) == answer )
         {
             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();
-                info -> encoding = retData.GetEncoding();
+                info->encoding = retData.GetEncoding();
 
 #if wxUSE_CONFIG
                 // remember this in the config
@@ -784,12 +950,19 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
         }
         else
         {
-            // the user doesn't want to select a font for this encoding,
+            // 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, FONTMAPPER_FONT_DONT_ASK);
+                GetConfig()->Write
+                             (
+                                configEntry,
+                                foundEquivEncoding ? info->ToString().c_str()
+                                                   : FONTMAPPER_FONT_DONT_ASK
+                             );
 
                 RestorePath(pathOld);
             }
@@ -797,20 +970,9 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,
         }
     }
     //else: we're in non-interactive mode
+#endif // wxUSE_FONTDLG
 
-    // now try the default mappings:
-    wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding);
-    size_t count = equiv.GetCount();
-    if ( count )
-    {
-        for ( size_t i = (equiv[0] == encoding) ? 1 : 0; i < count; i++ )
-        {
-            if ( TestAltEncoding(configEntry, equiv[i], info) )
-                return TRUE;
-        }
-    }
-
-    return FALSE;
+    return foundEquivEncoding;
 }
 
 bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding,