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