X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5fe8354960174a56ee21c456ac3ba521a7b9bae5..3871d4ca7599c1156e4cca908ebdeb1474608650:/src/common/fontmap.cpp diff --git a/src/common/fontmap.cpp b/src/common/fontmap.cpp index 8b159319d4..dca0806910 100644 --- a/src/common/fontmap.cpp +++ b/src/common/fontmap.cpp @@ -5,8 +5,8 @@ // 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" @@ -36,171 +32,114 @@ #include "wx/intl.h" #endif // PCH -#include "wx/fontmap.h" - #if wxUSE_CONFIG #include "wx/config.h" - #include "wx/memconf.h" +#endif // wxUSE_CONFIG + +#if defined(__WXMSW__) + #include "wx/msw/private.h" // includes windows.h for LOGFONT + #include "wx/msw/winundef.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/fontmap.h" +#include "wx/fmappriv.h" +#include "wx/fontutil.h" +#include "wx/msgdlg.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 #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[] = -{ - 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, - wxFONTENCODING_CP437, - wxFONTENCODING_UTF7, - wxFONTENCODING_UTF8, -}; -// the descriptions for them -static const wxChar* gs_encodingDescs[] = -{ - wxTRANSLATE( "Western European (ISO-8859-1)" ), - wxTRANSLATE( "Central European (ISO-8859-2)" ), - wxTRANSLATE( "Esperanto (ISO-8859-3)" ), - 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( "Nordic (ISO-8859-10)" ), - wxTRANSLATE( "Thai (ISO-8859-11)" ), - 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( "Windows Central European (CP 1250)" ), - wxTRANSLATE( "Windows Cyrillic (CP 1251)" ), - 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/DOS OEM (CP 437)" ), - wxTRANSLATE( "Unicode 7 bit (UTF-7)" ), - wxTRANSLATE( "Unicode 8 bit (UTF-8)" ), -}; - -// and the internal names -static const wxChar* gs_encodingNames[] = -{ - 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-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( "utf7" ), - wxT( "utf8" ), -}; - -// ---------------------------------------------------------------------------- -// global data -// ---------------------------------------------------------------------------- +static const wxChar* FONTMAPPER_FONT_FROM_ENCODING_PATH = wxT("Encodings"); +static const wxChar* FONTMAPPER_FONT_DONT_ASK = wxT("none"); -// private object -static wxFontMapper gs_fontMapper; - -// 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) }; // ============================================================================ @@ -213,342 +152,41 @@ private: wxFontMapper::wxFontMapper() { -#if wxUSE_CONFIG - m_config = NULL; - m_configIsDummy = FALSE; -#endif // wxUSE_CONFIG - -#if wxUSE_GUI m_windowParent = NULL; -#endif // wxUSE_GUI } wxFontMapper::~wxFontMapper() { } -// ---------------------------------------------------------------------------- -// customisation -// ---------------------------------------------------------------------------- - -#if wxUSE_CONFIG - -/* 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*/ ); - - 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. - 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; -} - -const wxString& wxFontMapper::GetConfigPath() -{ - if ( !m_configRootPath ) - { - // use the default - m_configRootPath = GetDefaultConfigPath(); - } - - return m_configRootPath; -} -#endif - -bool wxFontMapper::ChangePath(const wxString& pathNew, wxString *pathOld) -{ -#if wxUSE_CONFIG - 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; -#else - return FALSE; -#endif -} - -void wxFontMapper::RestorePath(const wxString& pathOld) -{ -#if wxUSE_CONFIG - GetConfig()->SetPath(pathOld); -#else -#endif -} - -// ---------------------------------------------------------------------------- -// charset/encoding correspondence -// ---------------------------------------------------------------------------- +bool wxFontMapper::IsWxFontMapper() +{ return true; } /* static */ -wxString wxFontMapper::GetEncodingDescription(wxFontEncoding encoding) +wxFontMapper *wxFontMapper::Get() { - if ( encoding == wxFONTENCODING_DEFAULT ) - { - 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?") ); - - 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; + wxFontMapperBase *fontmapper = wxFontMapperBase::Get(); + wxASSERT_MSG(fontmapper->IsWxFontMapper(), 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. + return (wxFontMapper*)fontmapper; } -/* static */ -wxString wxFontMapper::GetEncodingName(wxFontEncoding encoding) +wxFontEncoding +wxFontMapper::CharsetToEncoding(const wxString& charset, bool interactive) { - if ( encoding == wxFONTENCODING_DEFAULT ) - { - return _("default"); - } - - size_t count = WXSIZEOF(gs_encodingNames); - - wxASSERT_MSG( count == WXSIZEOF(gs_encodings), - wxT("inconsistency 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; -} - -wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset, - bool interactive) -{ - 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) ) - { - 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' ignored"), - value, charset.c_str()); - } - } + // try the ways not needing the users intervention first + int encoding = wxFontMapperBase::NonInteractiveCharsetToEncoding(charset); - 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); - } -#endif - - // if didn't find it there, try to recognize it ourselves - if ( encoding == wxFONTENCODING_SYSTEM ) + // if we failed to find the encoding, ask the user -- unless disabled + if ( encoding == wxFONTENCODING_UNKNOWN ) { - // 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(); - - if ( !cs || cs == wxT("US-ASCII") ) - { - encoding = wxFONTENCODING_DEFAULT; - } - 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; - } - 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 ) - { - // 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 // check for Windows charsets - { - 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 - { - len = 0; - } - - if ( len ) - { - const wxChar *p = cs.c_str() + len; - if ( *p == wxT('-') ) - p++; - - int value; - if ( wxSscanf(p, wxT("%u"), &value) == 1 ) - { - if ( value >= 1250 ) - { - value -= 1250; - if ( value < wxFONTENCODING_CP12_MAX - - wxFONTENCODING_CP1250 ) - { - // a valid Windows code page - value += wxFONTENCODING_CP1250; - encoding = (wxFontEncoding)value; - } - } - } - } - } - //else: unknown + // this is the special value which disables asking the user (he had + // chosen to suppress this the last time) + encoding = wxFONTENCODING_SYSTEM; } - -#if wxUSE_GUI - // 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 @@ -562,16 +200,13 @@ 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 = 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 @@ -589,29 +224,31 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset, if ( n != -1 ) { - encoding = gs_encodings[n]; + encoding = GetEncoding(n); + } -#if wxUSE_CONFIG +#if wxUSE_CONFIG && wxUSE_FILECONFIG // 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()); - } + wxFontMapperPathChanger path(this, FONTMAPPER_CHARSET_PATH); + if ( path.IsOk() ) + { + wxConfigBase *config = GetConfig(); - RestorePath(pathOld); + // 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.c_str()); } -#endif // wxUSE_CONFIG } - //else: cancelled +#endif // wxUSE_CONFIG } -#endif // wxUSE_GUI +#else + wxUnusedVar(interactive); +#endif // wxUSE_CHOICEDLG - return encoding; + return (wxFontEncoding)encoding; } // ---------------------------------------------------------------------------- @@ -620,8 +257,6 @@ wxFontEncoding wxFontMapper::CharsetToEncoding(const wxString& charset, // correspond to which is used by GetFontForEncoding() function // ---------------------------------------------------------------------------- -#if wxUSE_GUI - bool wxFontMapper::TestAltEncoding(const wxString& configEntry, wxFontEncoding encReplacement, wxNativeEncodingInfo *info) @@ -629,7 +264,7 @@ bool wxFontMapper::TestAltEncoding(const wxString& configEntry, if ( wxGetNativeFontEncoding(encReplacement, info) && wxTestFontEncoding(*info) ) { -#if wxUSE_CONFIG +#if wxUSE_CONFIG && wxUSE_FILECONFIG // remember the mapping in the config wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH); @@ -637,25 +272,15 @@ bool wxFontMapper::TestAltEncoding(const wxString& configEntry, { GetConfig()->Write(configEntry, info->ToString()); } +#else + wxUnusedVar(configEntry); #endif // wxUSE_CONFIG - return TRUE; + return true; } - return FALSE; + 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, const wxString& facename, @@ -666,20 +291,20 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding, // 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 + // 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; + static bool s_inGetAltForEncoding = false; if ( interactive && s_inGetAltForEncoding ) - return FALSE; + return false; ReentrancyBlocker blocker(s_inGetAltForEncoding); #endif // wxUSE_GUI - wxCHECK_MSG( info, FALSE, wxT("bad pointer in GetAltForEncoding") ); + wxCHECK_MSG( info, false, wxT("bad pointer in GetAltForEncoding") ); info->facename = facename; @@ -689,72 +314,93 @@ 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, encName = GetEncodingName(encoding); - if ( !!facename ) + wxString configEntry, + encName = GetEncodingName(encoding); + if ( !facename.empty() ) { configEntry = facename + _T("_"); } configEntry += encName; -#if wxUSE_CONFIG +#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); - - RestorePath(pathOld); + fontinfo = GetConfig()->Read(configEntry); + } - // 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 ) + // 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() ) { - interactive = FALSE; + // we tried to find a match with facename -- now try without it + fontinfo = GetConfig()->Read(encName); } - else // use the info entered the last time - { - if ( !!fontinfo && !!facename ) - { - // we tried to find a match with facename - now try without it - fontinfo = config->Read(encName); - } - if ( !!fontinfo ) + if ( !fontinfo.empty() ) + { + if ( info->FromString(fontinfo) ) { - if ( info->FromString(fontinfo) ) + if ( wxTestFontEncoding(*info) ) { - 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()); + // 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: there is no information in config about this encoding } + //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 ) @@ -763,85 +409,105 @@ bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding, 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 +#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 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) ) +#if wxUSE_CONFIG && wxUSE_FILECONFIG + wxFontMapperPathChanger path2(this, + FONTMAPPER_FONT_FROM_ENCODING_PATH); + if ( path2.IsOk() ) { - GetConfig()->Write(configEntry, FONTMAPPER_FONT_DONT_ASK); - - RestorePath(pathOld); + GetConfig()->Write + ( + configEntry, + foundEquivEncoding ? 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); - 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, - wxFontEncoding *alt_encoding, + wxFontEncoding *encodingAlt, const wxString& facename, bool interactive) { + wxCHECK_MSG( encodingAlt, false, + _T("wxFontEncoding::GetAltForEncoding(): NULL pointer") ); + +#ifdef __WXGTK20__ + // in GTK+ 2 we can always use UTF-8 for everything so just do it, + // especially as no other font encodings are currently supported + *encodingAlt = wxFONTENCODING_UTF8; + return true; +#else // !wxGTK2 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; +#endif // wxGTK2/!wxGTK2 } bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding, @@ -849,15 +515,11 @@ bool wxFontMapper::IsEncodingAvailable(wxFontEncoding encoding, { wxNativeEncodingInfo info; - if (wxGetNativeFontEncoding(encoding, &info)) - { - info.facename = facename; - return wxTestFontEncoding(info); - } + if ( !wxGetNativeFontEncoding(encoding, &info) ) + return false; - return FALSE; + info.facename = facename; + return wxTestFontEncoding(info); } -#endif // wxUSE_GUI - #endif // wxUSE_FONTMAP