1///////////////////////////////////////////////////////////////////////////// 2// Name: src/unix/fontenum.cpp 3// Purpose: wxFontEnumerator class for X11/GDK 4// Author: Vadim Zeitlin 5// Modified by: 6// Created: 01.10.99 7// RCS-ID: $Id: fontenum.cpp 43727 2006-12-01 10:14:28Z VS $ 8// Copyright: (c) Vadim Zeitlin 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// ============================================================================ 13// declarations 14// ============================================================================ 15 16// ---------------------------------------------------------------------------- 17// headers 18// ---------------------------------------------------------------------------- 19 20// for compilers that support precompilation, includes "wx.h". 21#include "wx/wxprec.h" 22 23#include "wx/fontenum.h" 24 25#ifndef WX_PRECOMP 26 #include "wx/dynarray.h" 27 #include "wx/string.h" 28 #include "wx/app.h" 29 #include "wx/utils.h" 30#endif 31 32#include "wx/regex.h" 33#include "wx/fontmap.h" 34#include "wx/fontutil.h" 35#include "wx/encinfo.h" 36 37// ---------------------------------------------------------------------------- 38// Pango 39// ---------------------------------------------------------------------------- 40 41#if wxUSE_PANGO 42 43#include "pango/pango.h" 44 45#ifdef __WXGTK20__ 46#include "gtk/gtk.h" 47extern GtkWidget *wxGetRootWindow(); 48#endif // __WXGTK20__ 49 50extern "C" int wxCMPFUNC_CONV 51wxCompareFamilies (const void *a, const void *b) 52{ 53 const char *a_name = pango_font_family_get_name (*(PangoFontFamily **)a); 54 const char *b_name = pango_font_family_get_name (*(PangoFontFamily **)b); 55 56 return g_utf8_collate (a_name, b_name); 57} 58 59bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding, 60 bool fixedWidthOnly) 61{ 62 if ( encoding != wxFONTENCODING_SYSTEM && encoding != wxFONTENCODING_UTF8 ) 63 { 64 // Pango supports only UTF-8 encoding (and system means any, so we 65 // accept it too) 66 return false; 67 } 68 69#if defined(__WXGTK20__) || !defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE) 70 if ( fixedWidthOnly 71#if defined(__WXGTK24__) 72 && (gtk_check_version(2,4,0) != NULL) 73#endif 74 ) 75 { 76 OnFacename( wxT("monospace") ); 77 } 78 else // !fixedWidthOnly 79#endif // __WXGTK20__ || !HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE 80 { 81 PangoFontFamily **families = NULL; 82 gint n_families = 0; 83 pango_context_list_families ( 84#ifdef __WXGTK20__ 85 gtk_widget_get_pango_context( wxGetRootWindow() ), 86#else 87 wxTheApp->GetPangoContext(), 88#endif 89 &families, &n_families ); 90 qsort (families, n_families, sizeof (PangoFontFamily *), wxCompareFamilies); 91 92 for (int i=0; i<n_families; i++) 93 { 94#if defined(__WXGTK24__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE) 95 if (!fixedWidthOnly || ( 96#ifdef __WXGTK24__ 97 !gtk_check_version(2,4,0) && 98#endif 99 pango_font_family_is_monospace(families[i]) 100 ) ) 101#endif 102 { 103 const gchar *name = pango_font_family_get_name(families[i]); 104 OnFacename(wxString(name, wxConvUTF8)); 105 } 106 } 107 g_free(families); 108 } 109 110 return true; 111} 112 113bool wxFontEnumerator::EnumerateEncodings(const wxString& facename) 114{ 115 return EnumerateEncodingsUTF8(facename); 116} 117 118 119#else // !wxUSE_PANGO 120 121#ifdef __VMS__ // Xlib.h for VMS is not (yet) compatible with C++ 122 // The resulting warnings are switched off here 123#pragma message disable nosimpint 124#endif 125#include <X11/Xlib.h> 126#ifdef __VMS__ 127#pragma message enable nosimpint 128#endif 129 130// ---------------------------------------------------------------------------- 131// private functions 132// ---------------------------------------------------------------------------- 133 134// create the list of all fonts with the given spacing and encoding 135static char **CreateFontList(wxChar spacing, wxFontEncoding encoding, 136 int *nFonts); 137 138// extract all font families from the given font list and call our 139// OnFacename() for each of them 140static bool ProcessFamiliesFromFontList(wxFontEnumerator *This, 141 char **fonts, 142 int nFonts); 143 144 145// ---------------------------------------------------------------------------- 146// private types 147// ---------------------------------------------------------------------------- 148 149// ============================================================================ 150// implementation 151// ============================================================================ 152 153// ---------------------------------------------------------------------------- 154// helpers 155// ---------------------------------------------------------------------------- 156 157#if !wxUSE_NANOX 158static char **CreateFontList(wxChar spacing, 159 wxFontEncoding encoding, 160 int *nFonts) 161{ 162 wxNativeEncodingInfo info; 163 wxGetNativeFontEncoding(encoding, &info); 164 165#if wxUSE_FONTMAP 166 if ( !wxTestFontEncoding(info) ) 167 { 168 // ask font mapper for a replacement 169 (void)wxFontMapper::Get()->GetAltForEncoding(encoding, &info); 170 } 171#endif // wxUSE_FONTMAP 172 173 wxString pattern; 174 pattern.Printf(wxT("-*-*-*-*-*-*-*-*-*-*-%c-*-%s-%s"), 175 spacing, 176 info.xregistry.c_str(), 177 info.xencoding.c_str()); 178 179 // get the list of all fonts 180 return XListFonts((Display *)wxGetDisplay(), pattern.mb_str(), 32767, nFonts); 181} 182 183static bool ProcessFamiliesFromFontList(wxFontEnumerator *This, 184 char **fonts, 185 int nFonts) 186{ 187#if wxUSE_REGEX 188 wxRegEx re(wxT("^(-[^-]*){14}$"), wxRE_NOSUB); 189#endif // wxUSE_REGEX 190 191 // extract the list of (unique) font families 192 wxSortedArrayString families; 193 for ( int n = 0; n < nFonts; n++ ) 194 { 195 char *font = fonts[n]; 196#if wxUSE_REGEX 197 if ( !re.Matches(font) ) 198#else // !wxUSE_REGEX 199 if ( !wxString(font).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) ) 200#endif // wxUSE_REGEX/!wxUSE_REGEX 201 { 202 // it's not a full font name (probably an alias) 203 continue; 204 } 205 206 // coverity[returned_null] 207 char *dash = strchr(font + 1, '-'); 208 char *family = dash + 1; 209 dash = strchr(family, '-'); 210 *dash = '\0'; // !NULL because Matches() above succeeded 211 wxString fam(family); 212 213 if ( families.Index(fam) == wxNOT_FOUND ) 214 { 215 if ( !This->OnFacename(fam) ) 216 { 217 // stop enumerating 218 return false; 219 } 220 221 families.Add(fam); 222 } 223 //else: already seen 224 } 225 226 return true; 227} 228#endif 229 // wxUSE_NANOX 230 231// ---------------------------------------------------------------------------- 232// wxFontEnumerator 233// ---------------------------------------------------------------------------- 234 235bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding, 236 bool fixedWidthOnly) 237{ 238#if wxUSE_NANOX 239 return false; 240#else 241 int nFonts; 242 char **fonts; 243 244 if ( fixedWidthOnly ) 245 { 246 bool cont = true; 247 fonts = CreateFontList(wxT('m'), encoding, &nFonts); 248 if ( fonts ) 249 { 250 cont = ProcessFamiliesFromFontList(this, fonts, nFonts); 251 252 XFreeFontNames(fonts); 253 } 254 255 if ( !cont ) 256 { 257 return true; 258 } 259 260 fonts = CreateFontList(wxT('c'), encoding, &nFonts); 261 if ( !fonts ) 262 { 263 return true; 264 } 265 } 266 else 267 { 268 fonts = CreateFontList(wxT('*'), encoding, &nFonts); 269 270 if ( !fonts ) 271 { 272 // it's ok if there are no fonts in given encoding - but it's not 273 // ok if there are no fonts at all 274 wxASSERT_MSG(encoding != wxFONTENCODING_SYSTEM, 275 wxT("No fonts at all on this system?")); 276 277 return false; 278 } 279 } 280 281 (void)ProcessFamiliesFromFontList(this, fonts, nFonts); 282 283 XFreeFontNames(fonts); 284 return true; 285#endif 286 // wxUSE_NANOX 287} 288 289bool wxFontEnumerator::EnumerateEncodings(const wxString& family) 290{ 291#if wxUSE_NANOX 292 return false; 293#else 294 wxString pattern; 295 pattern.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-*-*"), 296 family.empty() ? wxT("*") : family.c_str()); 297 298 // get the list of all fonts 299 int nFonts; 300 char **fonts = XListFonts((Display *)wxGetDisplay(), pattern.mb_str(), 301 32767, &nFonts); 302 303 if ( !fonts ) 304 { 305 // unknown family? 306 return false; 307 } 308 309 // extract the list of (unique) encodings 310 wxSortedArrayString encodings; 311 for ( int n = 0; n < nFonts; n++ ) 312 { 313 char *font = fonts[n]; 314 if ( !wxString(font).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) ) 315 { 316 // it's not a full font name (probably an alias) 317 continue; 318 } 319 320 // extract the family 321 char *dash = strchr(font + 1, '-'); 322 char *familyFont = dash + 1; 323 dash = strchr(familyFont, '-'); 324 *dash = '\0'; // !NULL because Matches() above succeeded 325 326 if ( !family.empty() && (family != familyFont) ) 327 { 328 // family doesn't match 329 continue; 330 } 331 332 // now extract the registry/encoding 333 char *p = dash + 1; // just after the dash after family 334 dash = strrchr(p, '-'); 335 336 wxString registry(dash + 1); 337 *dash = '\0'; 338 339 dash = strrchr(p, '-'); 340 wxString encoding(dash + 1); 341 342 encoding << wxT('-') << registry; 343 if ( encodings.Index(encoding) == wxNOT_FOUND ) 344 { 345 if ( !OnFontEncoding(familyFont, encoding) ) 346 { 347 break; 348 } 349 350 encodings.Add(encoding); 351 } 352 //else: already had this one 353 } 354 355 XFreeFontNames(fonts); 356 357 return true; 358#endif 359 // wxUSE_NANOX 360} 361 362#endif // !wxUSE_PANGO 363