1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/unix/fontenum.cpp 
   3 // Purpose:     wxFontEnumerator class for X11/GDK 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) Vadim Zeitlin 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "fontenum.h" 
  24 // for compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  27 #include "wx/dynarray.h" 
  28 #include "wx/string.h" 
  32 #include "wx/fontmap.h" 
  33 #include "wx/fontenum.h" 
  34 #include "wx/fontutil.h" 
  35 #include "wx/encinfo.h" 
  37 // ---------------------------------------------------------------------------- 
  39 // ---------------------------------------------------------------------------- 
  43 #include "pango/pango.h" 
  47 extern GtkWidget 
*wxGetRootWindow(); 
  51 cmp_families (const void *a
, const void *b
) 
  53   const char *a_name 
= pango_font_family_get_name (*(PangoFontFamily 
**)a
); 
  54   const char *b_name 
= pango_font_family_get_name (*(PangoFontFamily 
**)b
); 
  56   return g_utf8_collate (a_name
, b_name
); 
  59 // I admit I don't yet understand encodings with Pango 
  60 bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding
, 
  63 #ifndef HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE 
  66         OnFacename( wxT("monospace") ); 
  71         PangoFontFamily 
**families 
= NULL
; 
  73         pango_context_list_families (  
  75             gtk_widget_get_pango_context( wxGetRootWindow() ), 
  77             wxTheApp
->GetPangoContext(), 
  79             &families
, &n_families 
); 
  80         qsort (families
, n_families
, sizeof (PangoFontFamily 
*), cmp_families
); 
  82         for (int i
=0; i
<n_families
; i
++) 
  84 #ifdef HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE 
  85             if (!fixedWidthOnly 
|| 
  86                 pango_font_family_is_monospace(families
[i
])) 
  89                 const gchar 
*name 
= pango_font_family_get_name(families
[i
]); 
  90                 OnFacename(wxString(name
, wxConvUTF8
)); 
  99 bool wxFontEnumerator::EnumerateEncodings(const wxString
& family
) 
 108 #ifdef __VMS__ // Xlib.h for VMS is not (yet) compatible with C++ 
 109                // The resulting warnings are switched off here 
 110 #pragma message disable nosimpint 
 112 #include <X11/Xlib.h> 
 114 #pragma message enable nosimpint 
 117 // ---------------------------------------------------------------------------- 
 119 // ---------------------------------------------------------------------------- 
 121 // create the list of all fonts with the given spacing and encoding 
 122 static char **CreateFontList(wxChar spacing
, wxFontEncoding encoding
, 
 125 // extract all font families from the given font list and call our 
 126 // OnFacename() for each of them 
 127 static bool ProcessFamiliesFromFontList(wxFontEnumerator 
*This
, 
 132 // ---------------------------------------------------------------------------- 
 134 // ---------------------------------------------------------------------------- 
 136 // ============================================================================ 
 138 // ============================================================================ 
 140 // ---------------------------------------------------------------------------- 
 142 // ---------------------------------------------------------------------------- 
 145 static char **CreateFontList(wxChar spacing
, 
 146                              wxFontEncoding encoding
, 
 149     wxNativeEncodingInfo info
; 
 150     wxGetNativeFontEncoding(encoding
, &info
); 
 153     if ( !wxTestFontEncoding(info
) ) 
 155         // ask font mapper for a replacement 
 156         (void)wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
); 
 158 #endif // wxUSE_FONTMAP 
 161     pattern
.Printf(wxT("-*-*-*-*-*-*-*-*-*-*-%c-*-%s-%s"), 
 163                    info
.xregistry
.c_str(), 
 164                    info
.xencoding
.c_str()); 
 166     // get the list of all fonts 
 167     return XListFonts((Display 
*)wxGetDisplay(), pattern
.mb_str(), 32767, nFonts
); 
 170 static bool ProcessFamiliesFromFontList(wxFontEnumerator 
*This
, 
 175     wxRegEx 
re(wxT("^(-[^-]*){14}$"), wxRE_NOSUB
); 
 176 #endif // wxUSE_REGEX 
 178     // extract the list of (unique) font families 
 179     wxSortedArrayString families
; 
 180     for ( int n 
= 0; n 
< nFonts
; n
++ ) 
 182         char *font 
= fonts
[n
]; 
 184         if ( !re
.Matches(font
) ) 
 185 #else // !wxUSE_REGEX 
 186         if ( !wxString(font
).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) ) 
 187 #endif // wxUSE_REGEX/!wxUSE_REGEX 
 189             // it's not a full font name (probably an alias) 
 193         char *dash 
= strchr(font 
+ 1, '-'); 
 194         char *family 
= dash 
+ 1; 
 195         dash 
= strchr(family
, '-'); 
 196         *dash 
= '\0'; // !NULL because Matches() above succeeded 
 197         wxString 
fam(family
); 
 199         if ( families
.Index(fam
) == wxNOT_FOUND 
) 
 201             if ( !This
->OnFacename(fam
) ) 
 217 // ---------------------------------------------------------------------------- 
 219 // ---------------------------------------------------------------------------- 
 221 bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding
, 
 230     if ( fixedWidthOnly 
) 
 233         fonts 
= CreateFontList(wxT('m'), encoding
, &nFonts
); 
 236             cont 
= ProcessFamiliesFromFontList(this, fonts
, nFonts
); 
 238             XFreeFontNames(fonts
); 
 246         fonts 
= CreateFontList(wxT('c'), encoding
, &nFonts
); 
 254         fonts 
= CreateFontList(wxT('*'), encoding
, &nFonts
); 
 258             // it's ok if there are no fonts in given encoding - but it's not 
 259             // ok if there are no fonts at all 
 260             wxASSERT_MSG(encoding 
!= wxFONTENCODING_SYSTEM
, 
 261                          wxT("No fonts at all on this system?")); 
 267     (void)ProcessFamiliesFromFontList(this, fonts
, nFonts
); 
 269     XFreeFontNames(fonts
); 
 275 bool wxFontEnumerator::EnumerateEncodings(const wxString
& family
) 
 281     pattern
.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-*-*"), 
 282                    family
.IsEmpty() ? wxT("*") : family
.c_str()); 
 284     // get the list of all fonts 
 286     char **fonts 
= XListFonts((Display 
*)wxGetDisplay(), pattern
.mb_str(), 
 295     // extract the list of (unique) encodings 
 296     wxSortedArrayString encodings
; 
 297     for ( int n 
= 0; n 
< nFonts
; n
++ ) 
 299         char *font 
= fonts
[n
]; 
 300         if ( !wxString(font
).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) ) 
 302             // it's not a full font name (probably an alias) 
 306         // extract the family 
 307         char *dash 
= strchr(font 
+ 1, '-'); 
 308         char *familyFont 
= dash 
+ 1; 
 309         dash 
= strchr(familyFont
, '-'); 
 310         *dash 
= '\0'; // !NULL because Matches() above succeeded 
 312         if ( !family
.IsEmpty() && (family 
!= familyFont
) ) 
 314             // family doesn't match 
 318         // now extract the registry/encoding 
 319         char *p 
= dash 
+ 1; // just after the dash after family 
 320         dash 
= strrchr(p
, '-'); 
 322         wxString 
registry(dash 
+ 1); 
 325         dash 
= strrchr(p
, '-'); 
 326         wxString 
encoding(dash 
+ 1); 
 328         encoding 
<< wxT('-') << registry
; 
 329         if ( encodings
.Index(encoding
) == wxNOT_FOUND 
) 
 331             if ( !OnFontEncoding(familyFont
, encoding
) ) 
 336             encodings
.Add(encoding
); 
 338         //else: already had this one 
 341     XFreeFontNames(fonts
);