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 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
23 #include "wx/fontenum.h"
26 #include "wx/dynarray.h"
27 #include "wx/string.h"
33 #include "wx/fontmap.h"
34 #include "wx/fontutil.h"
35 #include "wx/encinfo.h"
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
43 #include "pango/pango.h"
47 extern GtkWidget
*wxGetRootWindow();
50 extern "C" int wxCMPFUNC_CONV
51 wxCompareFamilies (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 bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding
,
62 if ( encoding
!= wxFONTENCODING_SYSTEM
&& encoding
!= wxFONTENCODING_UTF8
)
64 // Pango supports only UTF-8 encoding (and system means any, so we
69 #if defined(__WXGTK20__) || !defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
71 #if defined(__WXGTK24__)
72 && (gtk_check_version(2,4,0) != NULL
)
76 OnFacename( wxT("monospace") );
78 else // !fixedWidthOnly
79 #endif // __WXGTK20__ || !HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
81 PangoFontFamily
**families
= NULL
;
83 pango_context_list_families (
85 gtk_widget_get_pango_context( wxGetRootWindow() ),
87 wxTheApp
->GetPangoContext(),
89 &families
, &n_families
);
90 qsort (families
, n_families
, sizeof (PangoFontFamily
*), wxCompareFamilies
);
92 for (int i
=0; i
<n_families
; i
++)
94 #if defined(__WXGTK24__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
95 if (!fixedWidthOnly
|| (
97 !gtk_check_version(2,4,0) &&
99 pango_font_family_is_monospace(families
[i
])
103 const gchar
*name
= pango_font_family_get_name(families
[i
]);
104 OnFacename(wxString(name
, wxConvUTF8
));
113 bool wxFontEnumerator::EnumerateEncodings(const wxString
& facename
)
115 // name of UTF-8 encoding: no need to use wxFontMapper for it as it's
116 // unlikely to change
117 const wxString
utf8(_T("UTF-8"));
120 // all fonts are in UTF-8 only when using Pango
121 if ( !facename
.empty() )
123 OnFontEncoding(facename
, utf8
);
127 // so enumerating all facenames supporting this encoding is the same as
128 // enumerating all facenames
129 const wxArrayString
facenames(GetFacenames(wxFONTENCODING_UTF8
));
130 const size_t count
= facenames
.size();
134 for ( size_t n
= 0; n
< count
; n
++ )
136 OnFontEncoding(facenames
[n
], utf8
);
143 #else // !wxUSE_PANGO
145 #ifdef __VMS__ // Xlib.h for VMS is not (yet) compatible with C++
146 // The resulting warnings are switched off here
147 #pragma message disable nosimpint
149 #include <X11/Xlib.h>
151 #pragma message enable nosimpint
154 // ----------------------------------------------------------------------------
156 // ----------------------------------------------------------------------------
158 // create the list of all fonts with the given spacing and encoding
159 static char **CreateFontList(wxChar spacing
, wxFontEncoding encoding
,
162 // extract all font families from the given font list and call our
163 // OnFacename() for each of them
164 static bool ProcessFamiliesFromFontList(wxFontEnumerator
*This
,
169 // ----------------------------------------------------------------------------
171 // ----------------------------------------------------------------------------
173 // ============================================================================
175 // ============================================================================
177 // ----------------------------------------------------------------------------
179 // ----------------------------------------------------------------------------
182 static char **CreateFontList(wxChar spacing
,
183 wxFontEncoding encoding
,
186 wxNativeEncodingInfo info
;
187 wxGetNativeFontEncoding(encoding
, &info
);
190 if ( !wxTestFontEncoding(info
) )
192 // ask font mapper for a replacement
193 (void)wxFontMapper::Get()->GetAltForEncoding(encoding
, &info
);
195 #endif // wxUSE_FONTMAP
198 pattern
.Printf(wxT("-*-*-*-*-*-*-*-*-*-*-%c-*-%s-%s"),
200 info
.xregistry
.c_str(),
201 info
.xencoding
.c_str());
203 // get the list of all fonts
204 return XListFonts((Display
*)wxGetDisplay(), pattern
.mb_str(), 32767, nFonts
);
207 static bool ProcessFamiliesFromFontList(wxFontEnumerator
*This
,
212 wxRegEx
re(wxT("^(-[^-]*){14}$"), wxRE_NOSUB
);
213 #endif // wxUSE_REGEX
215 // extract the list of (unique) font families
216 wxSortedArrayString families
;
217 for ( int n
= 0; n
< nFonts
; n
++ )
219 char *font
= fonts
[n
];
221 if ( !re
.Matches(font
) )
222 #else // !wxUSE_REGEX
223 if ( !wxString(font
).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) )
224 #endif // wxUSE_REGEX/!wxUSE_REGEX
226 // it's not a full font name (probably an alias)
230 // coverity[returned_null]
231 char *dash
= strchr(font
+ 1, '-');
232 char *family
= dash
+ 1;
233 dash
= strchr(family
, '-');
234 *dash
= '\0'; // !NULL because Matches() above succeeded
235 wxString
fam(family
);
237 if ( families
.Index(fam
) == wxNOT_FOUND
)
239 if ( !This
->OnFacename(fam
) )
255 // ----------------------------------------------------------------------------
257 // ----------------------------------------------------------------------------
259 bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding
,
268 if ( fixedWidthOnly
)
271 fonts
= CreateFontList(wxT('m'), encoding
, &nFonts
);
274 cont
= ProcessFamiliesFromFontList(this, fonts
, nFonts
);
276 XFreeFontNames(fonts
);
284 fonts
= CreateFontList(wxT('c'), encoding
, &nFonts
);
292 fonts
= CreateFontList(wxT('*'), encoding
, &nFonts
);
296 // it's ok if there are no fonts in given encoding - but it's not
297 // ok if there are no fonts at all
298 wxASSERT_MSG(encoding
!= wxFONTENCODING_SYSTEM
,
299 wxT("No fonts at all on this system?"));
305 (void)ProcessFamiliesFromFontList(this, fonts
, nFonts
);
307 XFreeFontNames(fonts
);
313 bool wxFontEnumerator::EnumerateEncodings(const wxString
& family
)
319 pattern
.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-*-*"),
320 family
.empty() ? wxT("*") : family
.c_str());
322 // get the list of all fonts
324 char **fonts
= XListFonts((Display
*)wxGetDisplay(), pattern
.mb_str(),
333 // extract the list of (unique) encodings
334 wxSortedArrayString encodings
;
335 for ( int n
= 0; n
< nFonts
; n
++ )
337 char *font
= fonts
[n
];
338 if ( !wxString(font
).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) )
340 // it's not a full font name (probably an alias)
344 // extract the family
345 char *dash
= strchr(font
+ 1, '-');
346 char *familyFont
= dash
+ 1;
347 dash
= strchr(familyFont
, '-');
348 *dash
= '\0'; // !NULL because Matches() above succeeded
350 if ( !family
.empty() && (family
!= familyFont
) )
352 // family doesn't match
356 // now extract the registry/encoding
357 char *p
= dash
+ 1; // just after the dash after family
358 dash
= strrchr(p
, '-');
360 wxString
registry(dash
+ 1);
363 dash
= strrchr(p
, '-');
364 wxString
encoding(dash
+ 1);
366 encoding
<< wxT('-') << registry
;
367 if ( encodings
.Index(encoding
) == wxNOT_FOUND
)
369 if ( !OnFontEncoding(familyFont
, encoding
) )
374 encodings
.Add(encoding
);
376 //else: already had this one
379 XFreeFontNames(fonts
);
386 #endif // !wxUSE_PANGO