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