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