]> git.saurik.com Git - wxWidgets.git/blame - src/unix/fontenum.cpp
fix for potention crash when conversion fails
[wxWidgets.git] / src / unix / fontenum.cpp
CommitLineData
d111a89a
VZ
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
65571936 9// Licence: wxWindows licence
d111a89a
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
14f355c2
VS
20// for compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
df91131c
WS
23#include "wx/fontenum.h"
24
ad9835c9
WS
25#ifndef WX_PRECOMP
26 #include "wx/dynarray.h"
df91131c 27 #include "wx/string.h"
670f9935 28 #include "wx/app.h"
de6185e2 29 #include "wx/utils.h"
ad9835c9
WS
30#endif
31
6fea4a7a 32#include "wx/regex.h"
79e4b627 33#include "wx/fontmap.h"
7beba2fc 34#include "wx/fontutil.h"
e4ffab29 35#include "wx/encinfo.h"
d111a89a 36
db16cab4 37// ----------------------------------------------------------------------------
2b5f62a0 38// Pango
db16cab4
RR
39// ----------------------------------------------------------------------------
40
2b5f62a0 41#if wxUSE_PANGO
db16cab4 42
2b5f62a0 43#include "pango/pango.h"
db16cab4 44
2b5f62a0
VZ
45#ifdef __WXGTK20__
46#include "gtk/gtk.h"
db16cab4 47extern GtkWidget *wxGetRootWindow();
55034339 48#endif // __WXGTK20__
db16cab4 49
17a1ebd1
VZ
50extern "C" int wxCMPFUNC_CONV
51wxCompareFamilies (const void *a, const void *b)
db16cab4
RR
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);
b578601e 55
db16cab4
RR
56 return g_utf8_collate (a_name, b_name);
57}
58
59// I admit I don't yet understand encodings with Pango
60bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
61 bool fixedWidthOnly)
62{
2696b11c
MR
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{
d0a6ad19 70 OnFacename( wxT("monospace") );
db16cab4
RR
71 }
72 else
55034339 73#endif // __WXGTK20__ || !HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
db16cab4
RR
74 {
75 PangoFontFamily **families = NULL;
76 gint n_families = 0;
55034339 77 pango_context_list_families (
2b5f62a0 78#ifdef __WXGTK20__
db16cab4 79 gtk_widget_get_pango_context( wxGetRootWindow() ),
2b5f62a0
VZ
80#else
81 wxTheApp->GetPangoContext(),
82#endif
db16cab4 83 &families, &n_families );
17a1ebd1 84 qsort (families, n_families, sizeof (PangoFontFamily *), wxCompareFamilies);
db16cab4
RR
85
86 for (int i=0; i<n_families; i++)
87 {
2696b11c
MR
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 ) )
304205f1
VS
95#endif
96 {
97 const gchar *name = pango_font_family_get_name(families[i]);
98 OnFacename(wxString(name, wxConvUTF8));
99 }
db16cab4 100 }
b578601e 101 g_free(families);
db16cab4 102 }
2696b11c 103
55034339 104 return true;
db16cab4
RR
105}
106
107bool wxFontEnumerator::EnumerateEncodings(const wxString& family)
108{
55034339 109 return false;
db16cab4
RR
110}
111
112
113#else
2b5f62a0 114 // Pango
db16cab4 115
3fa056ab
JJ
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
d111a89a 120#include <X11/Xlib.h>
3fa056ab
JJ
121#ifdef __VMS__
122#pragma message enable nosimpint
123#endif
d111a89a
VZ
124
125// ----------------------------------------------------------------------------
126// private functions
127// ----------------------------------------------------------------------------
128
36f210c8
VZ
129// create the list of all fonts with the given spacing and encoding
130static char **CreateFontList(wxChar spacing, wxFontEncoding encoding,
131 int *nFonts);
d111a89a
VZ
132
133// extract all font families from the given font list and call our
3c1866e8 134// OnFacename() for each of them
d111a89a
VZ
135static 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
461e93f9 152#if !wxUSE_NANOX
36f210c8
VZ
153static char **CreateFontList(wxChar spacing,
154 wxFontEncoding encoding,
155 int *nFonts)
d111a89a 156{
7beba2fc
VZ
157 wxNativeEncodingInfo info;
158 wxGetNativeFontEncoding(encoding, &info);
36f210c8 159
1e6feb95 160#if wxUSE_FONTMAP
79e4b627
VZ
161 if ( !wxTestFontEncoding(info) )
162 {
163 // ask font mapper for a replacement
142b3bc2 164 (void)wxFontMapper::Get()->GetAltForEncoding(encoding, &info);
79e4b627 165 }
1e6feb95 166#endif // wxUSE_FONTMAP
79e4b627 167
d111a89a 168 wxString pattern;
36f210c8 169 pattern.Printf(wxT("-*-*-*-*-*-*-*-*-*-*-%c-*-%s-%s"),
7beba2fc
VZ
170 spacing,
171 info.xregistry.c_str(),
172 info.xencoding.c_str());
d111a89a
VZ
173
174 // get the list of all fonts
7dd62924 175 return XListFonts((Display *)wxGetDisplay(), pattern.mb_str(), 32767, nFonts);
d111a89a
VZ
176}
177
178static bool ProcessFamiliesFromFontList(wxFontEnumerator *This,
179 char **fonts,
180 int nFonts)
181{
f1d7cbac
VZ
182#if wxUSE_REGEX
183 wxRegEx re(wxT("^(-[^-]*){14}$"), wxRE_NOSUB);
184#endif // wxUSE_REGEX
185
d111a89a
VZ
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];
f1d7cbac 191#if wxUSE_REGEX
32a2fbc8 192 if ( !re.Matches(font) )
f1d7cbac 193#else // !wxUSE_REGEX
7dd62924 194 if ( !wxString(font).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) )
f1d7cbac 195#endif // wxUSE_REGEX/!wxUSE_REGEX
d111a89a
VZ
196 {
197 // it's not a full font name (probably an alias)
198 continue;
199 }
3c1866e8 200
40a0dc1b 201 // coverity[returned_null]
d111a89a
VZ
202 char *dash = strchr(font + 1, '-');
203 char *family = dash + 1;
204 dash = strchr(family, '-');
205 *dash = '\0'; // !NULL because Matches() above succeeded
7dd62924 206 wxString fam(family);
d111a89a 207
7dd62924 208 if ( families.Index(fam) == wxNOT_FOUND )
d111a89a 209 {
3c1866e8 210 if ( !This->OnFacename(fam) )
d111a89a
VZ
211 {
212 // stop enumerating
55034339 213 return false;
d111a89a
VZ
214 }
215
7dd62924 216 families.Add(fam);
d111a89a
VZ
217 }
218 //else: already seen
219 }
220
55034339 221 return true;
d111a89a 222}
461e93f9
JS
223#endif
224 // wxUSE_NANOX
d111a89a
VZ
225
226// ----------------------------------------------------------------------------
227// wxFontEnumerator
228// ----------------------------------------------------------------------------
229
3c1866e8
VZ
230bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
231 bool fixedWidthOnly)
d111a89a 232{
461e93f9 233#if wxUSE_NANOX
55034339 234 return false;
461e93f9 235#else
d111a89a
VZ
236 int nFonts;
237 char **fonts;
238
239 if ( fixedWidthOnly )
240 {
55034339 241 bool cont = true;
36f210c8 242 fonts = CreateFontList(wxT('m'), encoding, &nFonts);
d111a89a
VZ
243 if ( fonts )
244 {
245 cont = ProcessFamiliesFromFontList(this, fonts, nFonts);
246
247 XFreeFontNames(fonts);
248 }
249
250 if ( !cont )
251 {
55034339 252 return true;
d111a89a
VZ
253 }
254
36f210c8 255 fonts = CreateFontList(wxT('c'), encoding, &nFonts);
d111a89a
VZ
256 if ( !fonts )
257 {
55034339 258 return true;
d111a89a
VZ
259 }
260 }
261 else
262 {
36f210c8 263 fonts = CreateFontList(wxT('*'), encoding, &nFonts);
d111a89a
VZ
264
265 if ( !fonts )
266 {
36f210c8
VZ
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?"));
d111a89a 271
55034339 272 return false;
d111a89a
VZ
273 }
274 }
275
276 (void)ProcessFamiliesFromFontList(this, fonts, nFonts);
277
278 XFreeFontNames(fonts);
55034339 279 return true;
461e93f9
JS
280#endif
281 // wxUSE_NANOX
d111a89a
VZ
282}
283
284bool wxFontEnumerator::EnumerateEncodings(const wxString& family)
285{
461e93f9 286#if wxUSE_NANOX
55034339 287 return false;
461e93f9 288#else
d111a89a
VZ
289 wxString pattern;
290 pattern.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-*-*"),
55034339 291 family.empty() ? wxT("*") : family.c_str());
d111a89a
VZ
292
293 // get the list of all fonts
294 int nFonts;
7dd62924 295 char **fonts = XListFonts((Display *)wxGetDisplay(), pattern.mb_str(),
d111a89a
VZ
296 32767, &nFonts);
297
298 if ( !fonts )
299 {
300 // unknown family?
55034339 301 return false;
d111a89a
VZ
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];
7dd62924 309 if ( !wxString(font).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) )
d111a89a
VZ
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
55034339 321 if ( !family.empty() && (family != familyFont) )
d111a89a
VZ
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
55034339 352 return true;
461e93f9
JS
353#endif
354 // wxUSE_NANOX
d111a89a 355}
db16cab4 356
55034339 357#endif // !wxUSE_PANGO