X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/065eb1427abb5313be08d091dc81800effe19adb..850df2d78866c3edcf848103b5dbc7e7fa1ee5fa:/src/common/fontmap.cpp diff --git a/src/common/fontmap.cpp b/src/common/fontmap.cpp index 4bf7daa110..88f9add423 100644 --- a/src/common/fontmap.cpp +++ b/src/common/fontmap.cpp @@ -1,12 +1,12 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: common/fontmap.cpp +// Name: src/common/fontmap.cpp // Purpose: wxFontMapper class // Author: Vadim Zeitlin // Modified by: // Created: 04.11.99 // RCS-ID: $Id$ -// Copyright: (c) Vadim Zeitlin -// Licence: wxWindows license +// Copyright: (c) 1999-2003 Vadim Zeitlin +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "fontmap.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -28,153 +24,123 @@ #pragma hdrstop #endif +#if wxUSE_FONTMAP + +#include "wx/fontmap.h" + #ifndef WX_PRECOMP #include "wx/app.h" #include "wx/log.h" #include "wx/intl.h" + #include "wx/msgdlg.h" + #include "wx/choicdlg.h" #endif // PCH -#include "wx/fontmap.h" -#include "wx/config.h" +#if wxUSE_CONFIG + #include "wx/config.h" +#endif // wxUSE_CONFIG -#include "wx/msgdlg.h" +#if defined(__WXMSW__) + #include "wx/msw/private.h" // includes windows.h for LOGFONT + #include "wx/msw/winundef.h" +#endif + +#include "wx/fmappriv.h" +#include "wx/fontutil.h" #include "wx/fontdlg.h" -#include "wx/choicdlg.h" +#include "wx/encinfo.h" + #include "wx/encconv.h" +#if wxUSE_EXTENDED_RTTI + +wxBEGIN_ENUM( wxFontEncoding ) + wxENUM_MEMBER( wxFONTENCODING_SYSTEM ) + wxENUM_MEMBER( wxFONTENCODING_DEFAULT ) + + wxENUM_MEMBER( wxFONTENCODING_ISO8859_1 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_2 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_3 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_4 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_5 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_6 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_7 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_8 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_9 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_10 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_11 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_12 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_13 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_14 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_15 ) + wxENUM_MEMBER( wxFONTENCODING_ISO8859_MAX ) + wxENUM_MEMBER( wxFONTENCODING_KOI8 ) + wxENUM_MEMBER( wxFONTENCODING_KOI8_U ) + wxENUM_MEMBER( wxFONTENCODING_ALTERNATIVE ) + wxENUM_MEMBER( wxFONTENCODING_BULGARIAN ) + wxENUM_MEMBER( wxFONTENCODING_CP437 ) + wxENUM_MEMBER( wxFONTENCODING_CP850 ) + wxENUM_MEMBER( wxFONTENCODING_CP852 ) + wxENUM_MEMBER( wxFONTENCODING_CP855 ) + wxENUM_MEMBER( wxFONTENCODING_CP866 ) + + wxENUM_MEMBER( wxFONTENCODING_CP874 ) + wxENUM_MEMBER( wxFONTENCODING_CP932 ) + wxENUM_MEMBER( wxFONTENCODING_CP936 ) + wxENUM_MEMBER( wxFONTENCODING_CP949 ) + wxENUM_MEMBER( wxFONTENCODING_CP950 ) + wxENUM_MEMBER( wxFONTENCODING_CP1250 ) + wxENUM_MEMBER( wxFONTENCODING_CP1251 ) + wxENUM_MEMBER( wxFONTENCODING_CP1252 ) + wxENUM_MEMBER( wxFONTENCODING_CP1253 ) + wxENUM_MEMBER( wxFONTENCODING_CP1254 ) + wxENUM_MEMBER( wxFONTENCODING_CP1255 ) + wxENUM_MEMBER( wxFONTENCODING_CP1256 ) + wxENUM_MEMBER( wxFONTENCODING_CP1257 ) + wxENUM_MEMBER( wxFONTENCODING_CP12_MAX ) + wxENUM_MEMBER( wxFONTENCODING_UTF7 ) + wxENUM_MEMBER( wxFONTENCODING_UTF8 ) + wxENUM_MEMBER( wxFONTENCODING_GB2312 ) + wxENUM_MEMBER( wxFONTENCODING_BIG5 ) + wxENUM_MEMBER( wxFONTENCODING_SHIFT_JIS ) + wxENUM_MEMBER( wxFONTENCODING_EUC_JP ) + wxENUM_MEMBER( wxFONTENCODING_UNICODE ) +wxEND_ENUM( wxFontEncoding ) +#endif + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- // the config paths we use -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"); -static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings"); - -// encodings supported by GetEncodingDescription -static wxFontEncoding gs_encodings[] = -{ - wxFONTENCODING_ISO8859_1, - wxFONTENCODING_ISO8859_2, - wxFONTENCODING_ISO8859_3, - wxFONTENCODING_ISO8859_4, - wxFONTENCODING_ISO8859_5, - wxFONTENCODING_ISO8859_6, - wxFONTENCODING_ISO8859_7, - wxFONTENCODING_ISO8859_8, - wxFONTENCODING_ISO8859_9, - wxFONTENCODING_ISO8859_10, - wxFONTENCODING_ISO8859_11, - wxFONTENCODING_ISO8859_12, - wxFONTENCODING_ISO8859_13, - wxFONTENCODING_ISO8859_14, - wxFONTENCODING_ISO8859_15, - wxFONTENCODING_KOI8, - wxFONTENCODING_CP1250, - wxFONTENCODING_CP1251, - wxFONTENCODING_CP1252, - wxFONTENCODING_CP1253, - wxFONTENCODING_CP1254, - wxFONTENCODING_CP1255, - wxFONTENCODING_CP1256, - wxFONTENCODING_CP1257, -}; - -// 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( "Esperanto (ISO-8859-3)" ), - wxTRANSLATE( "Baltic (ISO-8859-4)" ), - wxTRANSLATE( "Cyrillic (Latin 5)" ), - 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( "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( "KOI8-R" ), - wxTRANSLATE( "Windows Latin 2 (CP 1250)" ), - wxTRANSLATE( "Windows Cyrillic (CP 1251)" ), - wxTRANSLATE( "Windows Latin 1 (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)" ), -}; - -// and the internal names -static const wxChar* gs_encodingNames[] = -{ - wxT( "iso8859-1" ), - wxT( "iso8859-2" ), - wxT( "iso8859-3" ), - wxT( "iso8859-4" ), - wxT( "iso8859-5" ), - wxT( "iso8859-6" ), - wxT( "iso8859-7" ), - wxT( "iso8859-8" ), - wxT( "iso8859-9" ), - wxT( "iso8859-10" ), - wxT( "iso8859-11" ), - wxT( "iso8859-12" ), - wxT( "iso8859-13" ), - wxT( "iso8859-14" ), - wxT( "iso8859-15" ), - wxT( "koi8-r" ), - wxT( "windows1250" ), - wxT( "windows1251" ), - wxT( "windows1252" ), - wxT( "windows1253" ), - wxT( "windows1254" ), - wxT( "windows1255" ), - wxT( "windows1256" ), - wxT( "windows1257" ), -}; - -// ---------------------------------------------------------------------------- -// global data -// ---------------------------------------------------------------------------- +#if wxUSE_CONFIG -// private object -static wxFontMapper gs_fontMapper; +static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings"); +static const wxChar* FONTMAPPER_FONT_DONT_ASK = wxT("none"); -// and public pointer -wxFontMapper * wxTheFontMapper = &gs_fontMapper; +#endif // wxUSE_CONFIG // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- -// change the config path during the lifetime of this object -class wxFontMapperPathChanger +// it may happen that while we're showing a dialog asking the user about +// something, another request for an encoding mapping arrives: in this case it +// is best to not do anything because otherwise we risk to enter an infinite +// loop so we create an object of this class on stack to test for this in all +// interactive functions +class ReentrancyBlocker { public: - wxFontMapperPathChanger(wxFontMapper *fontMapper, const wxString& path) - { - m_fontMapper = fontMapper; - m_ok = m_fontMapper->ChangePath(path, &m_pathOld); - } - - bool IsOk() const { return m_ok; } - - ~wxFontMapperPathChanger() - { - if ( IsOk() ) - m_fontMapper->RestorePath(m_pathOld); - } + ReentrancyBlocker(bool& flag) : m_flagOld(flag), m_flag(flag) + { m_flag = true; } + ~ReentrancyBlocker() { m_flag = m_flagOld; } private: - wxFontMapper *m_fontMapper; - bool m_ok; - wxString m_pathOld; + bool m_flagOld; + bool& m_flag; + + DECLARE_NO_COPY_CLASS(ReentrancyBlocker) }; // ============================================================================ @@ -187,7 +153,6 @@ private: wxFontMapper::wxFontMapper() { - m_config = NULL; m_windowParent = NULL; } @@ -195,253 +160,54 @@ wxFontMapper::~wxFontMapper() { } -// ---------------------------------------------------------------------------- -// customisation -// ---------------------------------------------------------------------------- - -/* static */ const wxChar *wxFontMapper::GetDefaultConfigPath() -{ - return FONTMAPPER_ROOT_PATH; -} - -void wxFontMapper::SetConfigPath(const wxString& prefix) -{ - wxCHECK_RET( !prefix.IsEmpty() && prefix[0] == wxCONFIG_PATH_SEPARATOR, - wxT("an absolute path should be given to " - "wxFontMapper::SetConfigPath()") ); - - m_configRootPath = prefix; -} - - -// ---------------------------------------------------------------------------- -// get config object and path for it -// ---------------------------------------------------------------------------- - -wxConfigBase *wxFontMapper::GetConfig() -{ - if ( !m_config ) - { - // try the default - m_config = wxConfig::Get(FALSE/*don't create on demand*/); - } - - return m_config; -} - -const wxString& wxFontMapper::GetConfigPath() -{ - if ( !m_configRootPath ) - { - // use the default - m_configRootPath = GetDefaultConfigPath(); - } - - return m_configRootPath; -} - -bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld) -{ - wxConfigBase *config = GetConfig(); - if ( !config ) - return FALSE; - - *pathOld = config->GetPath(); - - wxString path = GetConfigPath(); - if ( path.IsEmpty() || path.Last() != wxCONFIG_PATH_SEPARATOR ) - { - path += wxCONFIG_PATH_SEPARATOR; - } - - wxASSERT_MSG( !pathNew || (pathNew[0] != wxCONFIG_PATH_SEPARATOR), - wxT("should be a relative path") ); - - path += pathNew; - - config->SetPath(path); - - return TRUE; -} - -void wxFontMapper::RestorePath(const wxString& pathOld) -{ - GetConfig()->SetPath(pathOld); -} - -// ---------------------------------------------------------------------------- -// charset/encoding correspondence -// ---------------------------------------------------------------------------- - /* static */ -wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding) +wxFontMapper *wxFontMapper::Get() { - size_t count = WXSIZEOF(gs_encodingDescs); - - wxASSERT_MSG( count == WXSIZEOF(gs_encodings), - wxT("inconsitency detected - forgot to update one of " - "the arrays?") ); - - for ( size_t i = 0; i < count; i++ ) - { - if ( gs_encodings[i] == encoding ) - { - return wxGetTranslation(gs_encodingDescs[i]); - } - } - - wxString str; - str.Printf(_("Unknown encoding (%d)"), encoding); - - return str; -} - -/* static */ -wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding) -{ - size_t count = WXSIZEOF(gs_encodingNames); - - wxASSERT_MSG( count == WXSIZEOF(gs_encodings), - wxT("inconsitency detected - forgot to update one of " - "the arrays?") ); - - for ( size_t i = 0; i < count; i++ ) - { - if ( gs_encodings[i] == encoding ) - { - return wxGetTranslation(gs_encodingNames[i]); - } - } - - wxString str; - str.Printf(_("unknown-%d"), encoding); - - return str; + wxFontMapperBase *fontmapper = wxFontMapperBase::Get(); + wxASSERT_MSG( !fontmapper->IsDummy(), + wxT("GUI code requested a wxFontMapper but we only have a wxFontMapperBase.") ); + + // Now return it anyway because there's a chance the GUI code might just + // only want to call wxFontMapperBase functions and it's better than + // crashing by returning NULL + return (wxFontMapper *)fontmapper; } -wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset, - bool interactive) +wxFontEncoding +wxFontMapper::CharsetToEncoding(const wxString& charset, bool interactive) { - wxFontEncoding encoding = wxFONTENCODING_SYSTEM; - - // we're going to modify it, make a copy - wxString cs = charset; + // try the ways not needing the users intervention first + int encoding = wxFontMapperBase::NonInteractiveCharsetToEncoding(charset); - // first try the user-defined settings - wxString pathOld; - if ( ChangePath(FONTMAPPER_CHARSET_PATH, &pathOld) ) + // if we failed to find the encoding, ask the user -- unless disabled + if ( encoding == wxFONTENCODING_UNKNOWN ) { - wxConfigBase *config = GetConfig(); - - // do we have an encoding for this charset? - long value = config->Read(charset, -1l); - if ( value != -1 ) - { - if ( value >= 0 && value <= wxFONTENCODING_MAX ) - { - encoding = (wxFontEncoding)value; - } - else - { - wxLogDebug(wxT("corrupted config data - invalid encoding %ld " - "for charset '%s'"), value, charset.c_str()); - } - } - - if ( encoding == wxFONTENCODING_SYSTEM ) - { - // may be we have an alias? - config->SetPath(FONTMAPPER_CHARSET_ALIAS_PATH); - - wxString alias = config->Read(charset); - if ( !!alias ) - { - // yes, we do - use it instead - cs = alias; - } - } - - RestorePath(pathOld); + // this is the special value which disables asking the user (he had + // chosen to suppress this the last time) + encoding = wxFONTENCODING_SYSTEM; } - - // if didn't find it there, try to reckognise it ourselves - if ( encoding == wxFONTENCODING_SYSTEM ) - { - cs.MakeUpper(); - - if ( !cs || cs == wxT("US-ASCII") ) - encoding = wxFONTENCODING_DEFAULT; - else if ( cs == wxT("KOI8-R") || cs == wxT("KOI8-U") ) - encoding = wxFONTENCODING_KOI8; - 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; - if ( *p == wxT('-') ) - p++; - - unsigned int value; - if ( wxSscanf(p, wxT("8859-%u"), &value) == 1 ) - { - if ( value < wxFONTENCODING_ISO8859_MAX - - wxFONTENCODING_ISO8859_1 ) - { - // it's a valid ISO8859 encoding - value += wxFONTENCODING_ISO8859_1 - 1; - encoding = (wxFontEncoding)value; - } - } - } - else if ( cs.Left(8) == wxT("WINDOWS-") ) - { - int value; - if ( wxSscanf(cs.c_str() + 8, wxT("%u"), &value) == 1 ) - { - if ( value >= 1250 ) - { - value -= 1250; - if ( value < wxFONTENCODING_CP12_MAX - - wxFONTENCODING_CP1250 - 1 ) - { - // a valid Windows code page - value += wxFONTENCODING_CP1250; - encoding = (wxFontEncoding)value; - } - } - } - } - //else: unknown - } - - // if still no luck, ask the user - unless disabled - if ( (encoding == wxFONTENCODING_SYSTEM) && interactive ) +#if wxUSE_CHOICEDLG + else if ( (encoding == wxFONTENCODING_SYSTEM) && interactive ) { // prepare the dialog data // the dialog title wxString title(m_titleDialog); if ( !title ) - title << wxTheApp->GetAppName() << _(": unknown charset"); + title << wxTheApp->GetAppDisplayName() << _(": unknown charset"); // the message wxString msg; - msg.Printf(_("The charset '%s' is unknown. You may select\n" - "another charset to replace it with or choose\n" - "[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); // 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 = GetSupportedEncodingsCount(); wxString *encodingNamesTranslated = new wxString[count]; for ( size_t i = 0; i < count; i++ ) { - encodingNamesTranslated[i] = wxGetTranslation(gs_encodingDescs[i]); + encodingNamesTranslated[i] = GetEncodingDescription(GetEncoding(i)); } // the parent window @@ -459,14 +225,31 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset, if ( n != -1 ) { - // TODO save the result in the config! + encoding = GetEncoding(n); + } + +#if wxUSE_CONFIG && wxUSE_FILECONFIG + // save the result in the config now + wxFontMapperPathChanger path(this, FONTMAPPER_CHARSET_PATH); + if ( path.IsOk() ) + { + wxConfigBase *config = GetConfig(); - encoding = gs_encodings[n]; + // remember the alt encoding for this charset -- or remember that + // we don't know it + long value = n == -1 ? (long)wxFONTENCODING_UNKNOWN : (long)encoding; + if ( !config->Write(charset, value) ) + { + wxLogError(_("Failed to remember the encoding for the charset '%s'."), charset); + } } - //else: cancelled +#endif // wxUSE_CONFIG } +#else + wxUnusedVar(interactive); +#endif // wxUSE_CHOICEDLG - return encoding; + return (wxFontEncoding)encoding; } // ---------------------------------------------------------------------------- @@ -482,6 +265,7 @@ bool wxFontMapper::TestAltEncoding(const wxString& configEntry, if ( wxGetNativeFontEncoding(encReplacement, info) && wxTestFontEncoding(*info) ) { +#if wxUSE_CONFIG && wxUSE_FILECONFIG // remember the mapping in the config wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH); @@ -489,11 +273,13 @@ bool wxFontMapper::TestAltEncoding(const wxString& configEntry, { GetConfig()->Write(configEntry, info->ToString()); } - - return TRUE; +#else + wxUnusedVar(configEntry); +#endif // wxUSE_CONFIG + return true; } - return FALSE; + return false; } bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding, @@ -501,7 +287,25 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding, const wxString& facename, bool interactive) { - wxCHECK_MSG( info, FALSE, wxT("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 + + wxCHECK_MSG( info, false, wxT("bad pointer in GetAltForEncoding") ); info->facename = facename; @@ -511,133 +315,206 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding, } // 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 + // 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")); + wxLogFatalError(_("can't load any font, aborting")); - // wxFatalError doesn't return + // wxLogFatalError doesn't return } - wxString configEntry = facename + _T("_") + GetEncodingName(encoding); + wxString configEntry, + encName = GetEncodingName(encoding); + if ( !facename.empty() ) + { + configEntry = facename + _T("_"); + } + configEntry += encName; +#if wxUSE_CONFIG && wxUSE_FILECONFIG // do we have a font spec for this encoding? - wxString pathOld; - if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) ) + wxString fontinfo; + wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH); + if ( path.IsOk() ) { - wxConfigBase *config = GetConfig(); - - wxString fontinfo = config->Read(configEntry); + fontinfo = GetConfig()->Read(configEntry); + } - RestorePath(pathOld); + // 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 ) + { + interactive = false; + } + else // use the info entered the last time + { + if ( !fontinfo.empty() && !facename.empty() ) + { + // we tried to find a match with facename -- now try without it + fontinfo = GetConfig()->Read(encName); + } - if ( !!fontinfo ) + if ( !fontinfo.empty() ) { if ( info->FromString(fontinfo) ) { if ( wxTestFontEncoding(*info) ) { // ok, got something - return TRUE; + 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()); + wxLogDebug(wxT("corrupted config data: string '%s' is not a valid font encoding info"), + fontinfo); + } + } + //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) ) + { + equivEncoding = equiv[i]; + + foundEquivEncoding = true; } } } // ask the user +#if wxUSE_FONTDLG if ( interactive ) { wxString title(m_titleDialog); if ( !title ) - title << wxTheApp->GetAppName() << _(": unknown encoding"); + title << wxTheApp->GetAppDisplayName() << _(": 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, GetEncodingDescription(equivEncoding)); + } + 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); + } - 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 && wxUSE_FILECONFIG // remember this in the config - if ( ChangePath(FONTMAPPER_FONT_FROM_ENCODING_PATH, &pathOld) ) + wxFontMapperPathChanger path2(this, + FONTMAPPER_FONT_FROM_ENCODING_PATH); + if ( path2.IsOk() ) { GetConfig()->Write(configEntry, info->ToString()); - - RestorePath(pathOld); } +#endif // wxUSE_CONFIG - return TRUE; + 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 && wxUSE_FILECONFIG + wxFontMapperPathChanger path2(this, + FONTMAPPER_FONT_FROM_ENCODING_PATH); + if ( path2.IsOk() ) + { + GetConfig()->Write + ( + configEntry, + foundEquivEncoding + ? (const wxChar*)info->ToString().c_str() + : FONTMAPPER_FONT_DONT_ASK + ); + } +#endif // wxUSE_CONFIG + } } //else: we're in non-interactive mode +#else + wxUnusedVar(equivEncoding); +#endif // wxUSE_FONTDLG - - // now try the default mappings: - wxFontEncodingArray equiv = wxEncodingConverter::GetAllEquivalents(encoding); - for ( unsigned i = (equiv[0] == encoding) ? 1 : 0; i < equiv.GetCount(); i++ ) - if ( TestAltEncoding(configEntry, equiv[i], info) ) - return TRUE; - - return FALSE; + return foundEquivEncoding; } - - bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding, - wxFontEncoding *alt_encoding, + wxFontEncoding *encodingAlt, const wxString& facename, bool interactive) { + wxCHECK_MSG( encodingAlt, false, + _T("wxFontEncoding::GetAltForEncoding(): NULL pointer") ); + wxNativeEncodingInfo info; - bool r = GetAltForEncoding(encoding, &info, facename, interactive); - *alt_encoding = info.encoding; - return r; -} + if ( !GetAltForEncoding(encoding, &info, facename, interactive) ) + return false; + *encodingAlt = info.encoding; + return true; +} bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding, const wxString& facename) { wxNativeEncodingInfo info; - if (wxGetNativeFontEncoding(encoding, &info)) - { - info.facename = facename; - return wxTestFontEncoding(info); - } - else - return FALSE; + if ( !wxGetNativeFontEncoding(encoding, &info) ) + return false; + + info.facename = facename; + return wxTestFontEncoding(info); } + +#endif // wxUSE_FONTMAP