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