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