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