bool wxFontMapper::GetAltForEncoding(wxFontEncoding encoding, wxNativeEncodingInfo *info, const wxString& facename, bool interactive) { #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; 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 ) { wxLogFatalError(_("can't load any font, aborting")); // wxLogFatalError doesn't return } wxString configEntry, encName = GetEncodingName(encoding); if ( !facename.empty() ) { configEntry = facename + wxT("_"); } configEntry += encName; #if wxUSE_CONFIG && wxUSE_FILECONFIG // do we have a font spec for this encoding? wxString fontinfo; wxFontMapperPathChanger path(this, FONTMAPPER_FONT_FROM_ENCODING_PATH); if ( path.IsOk() ) { 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 ) { 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.empty() ) { if ( info->FromString(fontinfo) ) { 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); } } //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->GetAppDisplayName() << _(": unknown encoding"); // 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); } // 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, m_windowParent) == answer ) { wxFontData data; data.SetEncoding(encoding); data.EncodingInfo() = *info; wxFontDialog dialog(m_windowParent, data); if ( dialog.ShowModal() == wxID_OK ) { wxFontData retData = dialog.GetFontData(); *info = retData.EncodingInfo(); info->encoding = retData.GetEncoding(); #if wxUSE_CONFIG && wxUSE_FILECONFIG // remember this in the config wxFontMapperPathChanger path2(this, FONTMAPPER_FONT_FROM_ENCODING_PATH); if ( path2.IsOk() ) { GetConfig()->Write(configEntry, info->ToString()); } #endif // wxUSE_CONFIG return true; } //else: the user canceled the font selection dialog } 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 return foundEquivEncoding; }
bool wxFontEnumerator::EnumerateEncodings(const wxString& family) { static wxFontEncoding 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_CP1250, wxFONTENCODING_CP1251, wxFONTENCODING_CP1252, wxFONTENCODING_CP1253, wxFONTENCODING_CP1254, wxFONTENCODING_CP1255, wxFONTENCODING_CP1256, wxFONTENCODING_CP1257, wxFONTENCODING_KOI8, wxFONTENCODING_SYSTEM }; static const char *encodingNames[] = { "iso88590-1", "iso88590-2", "iso88590-3", "iso88590-4", "iso88590-5", "iso88590-6", "iso88590-7", "iso88590-8", "iso88590-9", "iso88590-10", "iso88590-13", "iso88590-14", "iso88590-15", "windows-1250", "windows-1251", "windows-1252", "windows-1253", "windows-1254", "windows-1255", "windows-1256", "windows-1257", "koi-8", NULL }; wxNativeEncodingInfo info; info.facename = family; for (size_t i = 0; encodings[i] != wxFONTENCODING_SYSTEM; i++) { if ( !wxGetNativeFontEncoding(encodings[i], &info) || !wxTestFontEncoding(info) ) continue; if ( !OnFontEncoding(family, encodingNames[i]) ) break; } return true; }
wxNativeFont wxLoadQueryNearestFont(int pointSize, int family, int style, int weight, bool underlined, const wxString &facename, wxFontEncoding encoding, wxString* xFontName) { if ( encoding == wxFONTENCODING_DEFAULT ) { encoding = wxFont::GetDefaultEncoding(); } // first determine the encoding - if the font doesn't exist at all in this // encoding, it's useless to do all other approximations (i.e. size, // family &c don't matter much) wxNativeEncodingInfo info; if ( encoding == wxFONTENCODING_SYSTEM ) { // This will always work so we don't test to save time wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info); } else { if ( !wxGetNativeFontEncoding(encoding, &info) || !wxTestFontEncoding(info) ) { #if wxUSE_FONTMAP if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) ) #endif // wxUSE_FONTMAP { // unspported encoding - replace it with the default // // NB: we can't just return 0 from here because wxGTK code doesn't // check for it (i.e. it supposes that we'll always succeed), // so it would provoke a crash wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info); } } } // OK, we have the correct xregistry/xencoding in info structure wxNativeFont font = 0; // if we already have the X font name, try to use it if( xFontName && !xFontName->empty() ) { // // Make sure point size is correct for scale factor. // wxStringTokenizer tokenizer(*xFontName, wxT("-"), wxTOKEN_RET_DELIMS); wxString newFontName; for(int i = 0; i < 8; i++) newFontName += tokenizer.NextToken(); (void) tokenizer.NextToken(); newFontName += wxString::Format(wxT("%d-"), pointSize); while(tokenizer.HasMoreTokens()) newFontName += tokenizer.GetNextToken(); font = wxLoadFont(newFontName); if(font) *xFontName = newFontName; } if ( !font ) { // search up and down by stepsize 10 int max_size = pointSize + 20 * (1 + (pointSize/180)); int min_size = pointSize - 20 * (1 + (pointSize/180)); int i, round; // counters // first round: search for equal, then for smaller and for larger size // with the given weight and style int testweight = weight; int teststyle = style; for ( round = 0; round < 3; round++ ) { // second round: use normal weight if ( round == 1 ) { if ( testweight != wxNORMAL ) { testweight = wxNORMAL; } else { ++round; // fall through to third round } } // third round: ... and use normal style if ( round == 2 ) { if ( teststyle != wxNORMAL ) { teststyle = wxNORMAL; } else { break; } } // Search for equal or smaller size (approx.) for ( i = pointSize; !font && i >= 10 && i >= min_size; i -= 10 ) { font = wxLoadQueryFont(i, family, teststyle, testweight, underlined, facename, info.xregistry, info.xencoding, xFontName); } // Search for larger size (approx.) for ( i = pointSize + 10; !font && i <= max_size; i += 10 ) { font = wxLoadQueryFont(i, family, teststyle, testweight, underlined, facename, info.xregistry, info.xencoding, xFontName); } } // Try default family if ( !font && family != wxDEFAULT ) { font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight, underlined, facename, info.xregistry, info.xencoding, xFontName ); } // ignore size, family, style and weight but try to find font with the // given facename and encoding if ( !font ) { font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL, underlined, facename, info.xregistry, info.xencoding, xFontName); // ignore family as well if ( !font ) { font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL, underlined, wxEmptyString, info.xregistry, info.xencoding, xFontName); // if it still failed, try to get the font of any size but // with the requested encoding: this can happen if the // encoding is only available in one size which happens to be // different from 120 if ( !font ) { font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL, false, wxEmptyString, info.xregistry, info.xencoding, xFontName); // this should never happen as we had tested for it in the // very beginning, but if it does, do return something non // NULL or we'd crash in wxFont code if ( !font ) { wxFAIL_MSG( wxT("this encoding should be available!") ); font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL, false, wxEmptyString, wxT("*"), wxT("*"), xFontName); } } } } } return font; }