]> git.saurik.com Git - wxWidgets.git/blame - src/unix/fontenum.cpp
Return optimal label width from DrawHeaderButton
[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
db16cab4
RR
59bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
60 bool fixedWidthOnly)
61{
1acca470
VZ
62 if ( encoding != wxFONTENCODING_SYSTEM && encoding != wxFONTENCODING_UTF8 )
63 {
64 // Pango supports only UTF-8 encoding (and system means any, so we
65 // accept it too)
66 return false;
67 }
68
2696b11c
MR
69#if defined(__WXGTK20__) || !defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
70 if ( fixedWidthOnly
71#if defined(__WXGTK24__)
72 && (gtk_check_version(2,4,0) != NULL)
73#endif
74 )
1acca470 75 {
d0a6ad19 76 OnFacename( wxT("monospace") );
db16cab4 77 }
1acca470 78 else // !fixedWidthOnly
55034339 79#endif // __WXGTK20__ || !HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
db16cab4
RR
80 {
81 PangoFontFamily **families = NULL;
82 gint n_families = 0;
55034339 83 pango_context_list_families (
2b5f62a0 84#ifdef __WXGTK20__
db16cab4 85 gtk_widget_get_pango_context( wxGetRootWindow() ),
2b5f62a0
VZ
86#else
87 wxTheApp->GetPangoContext(),
88#endif
db16cab4 89 &families, &n_families );
17a1ebd1 90 qsort (families, n_families, sizeof (PangoFontFamily *), wxCompareFamilies);
db16cab4
RR
91
92 for (int i=0; i<n_families; i++)
93 {
2696b11c
MR
94#if defined(__WXGTK24__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
95 if (!fixedWidthOnly || (
96#ifdef __WXGTK24__
97 !gtk_check_version(2,4,0) &&
98#endif
99 pango_font_family_is_monospace(families[i])
100 ) )
304205f1
VS
101#endif
102 {
103 const gchar *name = pango_font_family_get_name(families[i]);
104 OnFacename(wxString(name, wxConvUTF8));
105 }
db16cab4 106 }
b578601e 107 g_free(families);
db16cab4 108 }
2696b11c 109
55034339 110 return true;
db16cab4
RR
111}
112
1acca470 113bool wxFontEnumerator::EnumerateEncodings(const wxString& facename)
db16cab4 114{
1acca470
VZ
115 // name of UTF-8 encoding: no need to use wxFontMapper for it as it's
116 // unlikely to change
117 const wxString utf8(_T("UTF-8"));
118
119
120 // all fonts are in UTF-8 only when using Pango
121 if ( !facename.empty() )
122 {
123 OnFontEncoding(facename, utf8);
124 return true;
125 }
126
127 // so enumerating all facenames supporting this encoding is the same as
128 // enumerating all facenames
129 const wxArrayString facenames(GetFacenames(wxFONTENCODING_UTF8));
130 const size_t count = facenames.size();
131 if ( !count )
132 return false;
133
134 for ( size_t n = 0; n < count; n++ )
135 {
136 OnFontEncoding(facenames[n], utf8);
137 }
138
139 return true;
db16cab4
RR
140}
141
142
1acca470 143#else // !wxUSE_PANGO
db16cab4 144
3fa056ab
JJ
145#ifdef __VMS__ // Xlib.h for VMS is not (yet) compatible with C++
146 // The resulting warnings are switched off here
147#pragma message disable nosimpint
148#endif
d111a89a 149#include <X11/Xlib.h>
3fa056ab
JJ
150#ifdef __VMS__
151#pragma message enable nosimpint
152#endif
d111a89a
VZ
153
154// ----------------------------------------------------------------------------
155// private functions
156// ----------------------------------------------------------------------------
157
36f210c8
VZ
158// create the list of all fonts with the given spacing and encoding
159static char **CreateFontList(wxChar spacing, wxFontEncoding encoding,
160 int *nFonts);
d111a89a
VZ
161
162// extract all font families from the given font list and call our
3c1866e8 163// OnFacename() for each of them
d111a89a
VZ
164static bool ProcessFamiliesFromFontList(wxFontEnumerator *This,
165 char **fonts,
166 int nFonts);
167
168
169// ----------------------------------------------------------------------------
170// private types
171// ----------------------------------------------------------------------------
172
173// ============================================================================
174// implementation
175// ============================================================================
176
177// ----------------------------------------------------------------------------
178// helpers
179// ----------------------------------------------------------------------------
180
461e93f9 181#if !wxUSE_NANOX
36f210c8
VZ
182static char **CreateFontList(wxChar spacing,
183 wxFontEncoding encoding,
184 int *nFonts)
d111a89a 185{
7beba2fc
VZ
186 wxNativeEncodingInfo info;
187 wxGetNativeFontEncoding(encoding, &info);
36f210c8 188
1e6feb95 189#if wxUSE_FONTMAP
79e4b627
VZ
190 if ( !wxTestFontEncoding(info) )
191 {
192 // ask font mapper for a replacement
142b3bc2 193 (void)wxFontMapper::Get()->GetAltForEncoding(encoding, &info);
79e4b627 194 }
1e6feb95 195#endif // wxUSE_FONTMAP
79e4b627 196
d111a89a 197 wxString pattern;
36f210c8 198 pattern.Printf(wxT("-*-*-*-*-*-*-*-*-*-*-%c-*-%s-%s"),
7beba2fc
VZ
199 spacing,
200 info.xregistry.c_str(),
201 info.xencoding.c_str());
d111a89a
VZ
202
203 // get the list of all fonts
7dd62924 204 return XListFonts((Display *)wxGetDisplay(), pattern.mb_str(), 32767, nFonts);
d111a89a
VZ
205}
206
207static bool ProcessFamiliesFromFontList(wxFontEnumerator *This,
208 char **fonts,
209 int nFonts)
210{
f1d7cbac
VZ
211#if wxUSE_REGEX
212 wxRegEx re(wxT("^(-[^-]*){14}$"), wxRE_NOSUB);
213#endif // wxUSE_REGEX
214
d111a89a
VZ
215 // extract the list of (unique) font families
216 wxSortedArrayString families;
217 for ( int n = 0; n < nFonts; n++ )
218 {
219 char *font = fonts[n];
f1d7cbac 220#if wxUSE_REGEX
32a2fbc8 221 if ( !re.Matches(font) )
f1d7cbac 222#else // !wxUSE_REGEX
7dd62924 223 if ( !wxString(font).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) )
f1d7cbac 224#endif // wxUSE_REGEX/!wxUSE_REGEX
d111a89a
VZ
225 {
226 // it's not a full font name (probably an alias)
227 continue;
228 }
3c1866e8 229
40a0dc1b 230 // coverity[returned_null]
d111a89a
VZ
231 char *dash = strchr(font + 1, '-');
232 char *family = dash + 1;
233 dash = strchr(family, '-');
234 *dash = '\0'; // !NULL because Matches() above succeeded
7dd62924 235 wxString fam(family);
d111a89a 236
7dd62924 237 if ( families.Index(fam) == wxNOT_FOUND )
d111a89a 238 {
3c1866e8 239 if ( !This->OnFacename(fam) )
d111a89a
VZ
240 {
241 // stop enumerating
55034339 242 return false;
d111a89a
VZ
243 }
244
7dd62924 245 families.Add(fam);
d111a89a
VZ
246 }
247 //else: already seen
248 }
249
55034339 250 return true;
d111a89a 251}
461e93f9
JS
252#endif
253 // wxUSE_NANOX
d111a89a
VZ
254
255// ----------------------------------------------------------------------------
256// wxFontEnumerator
257// ----------------------------------------------------------------------------
258
3c1866e8
VZ
259bool wxFontEnumerator::EnumerateFacenames(wxFontEncoding encoding,
260 bool fixedWidthOnly)
d111a89a 261{
461e93f9 262#if wxUSE_NANOX
55034339 263 return false;
461e93f9 264#else
d111a89a
VZ
265 int nFonts;
266 char **fonts;
267
268 if ( fixedWidthOnly )
269 {
55034339 270 bool cont = true;
36f210c8 271 fonts = CreateFontList(wxT('m'), encoding, &nFonts);
d111a89a
VZ
272 if ( fonts )
273 {
274 cont = ProcessFamiliesFromFontList(this, fonts, nFonts);
275
276 XFreeFontNames(fonts);
277 }
278
279 if ( !cont )
280 {
55034339 281 return true;
d111a89a
VZ
282 }
283
36f210c8 284 fonts = CreateFontList(wxT('c'), encoding, &nFonts);
d111a89a
VZ
285 if ( !fonts )
286 {
55034339 287 return true;
d111a89a
VZ
288 }
289 }
290 else
291 {
36f210c8 292 fonts = CreateFontList(wxT('*'), encoding, &nFonts);
d111a89a
VZ
293
294 if ( !fonts )
295 {
36f210c8
VZ
296 // it's ok if there are no fonts in given encoding - but it's not
297 // ok if there are no fonts at all
298 wxASSERT_MSG(encoding != wxFONTENCODING_SYSTEM,
299 wxT("No fonts at all on this system?"));
d111a89a 300
55034339 301 return false;
d111a89a
VZ
302 }
303 }
304
305 (void)ProcessFamiliesFromFontList(this, fonts, nFonts);
306
307 XFreeFontNames(fonts);
55034339 308 return true;
461e93f9
JS
309#endif
310 // wxUSE_NANOX
d111a89a
VZ
311}
312
313bool wxFontEnumerator::EnumerateEncodings(const wxString& family)
314{
461e93f9 315#if wxUSE_NANOX
55034339 316 return false;
461e93f9 317#else
d111a89a
VZ
318 wxString pattern;
319 pattern.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-*-*"),
55034339 320 family.empty() ? wxT("*") : family.c_str());
d111a89a
VZ
321
322 // get the list of all fonts
323 int nFonts;
7dd62924 324 char **fonts = XListFonts((Display *)wxGetDisplay(), pattern.mb_str(),
d111a89a
VZ
325 32767, &nFonts);
326
327 if ( !fonts )
328 {
329 // unknown family?
55034339 330 return false;
d111a89a
VZ
331 }
332
333 // extract the list of (unique) encodings
334 wxSortedArrayString encodings;
335 for ( int n = 0; n < nFonts; n++ )
336 {
337 char *font = fonts[n];
7dd62924 338 if ( !wxString(font).Matches(wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*")) )
d111a89a
VZ
339 {
340 // it's not a full font name (probably an alias)
341 continue;
342 }
343
344 // extract the family
345 char *dash = strchr(font + 1, '-');
346 char *familyFont = dash + 1;
347 dash = strchr(familyFont, '-');
348 *dash = '\0'; // !NULL because Matches() above succeeded
349
55034339 350 if ( !family.empty() && (family != familyFont) )
d111a89a
VZ
351 {
352 // family doesn't match
353 continue;
354 }
355
356 // now extract the registry/encoding
357 char *p = dash + 1; // just after the dash after family
358 dash = strrchr(p, '-');
359
360 wxString registry(dash + 1);
361 *dash = '\0';
362
363 dash = strrchr(p, '-');
364 wxString encoding(dash + 1);
365
366 encoding << wxT('-') << registry;
367 if ( encodings.Index(encoding) == wxNOT_FOUND )
368 {
369 if ( !OnFontEncoding(familyFont, encoding) )
370 {
371 break;
372 }
373
374 encodings.Add(encoding);
375 }
376 //else: already had this one
377 }
378
379 XFreeFontNames(fonts);
380
55034339 381 return true;
461e93f9
JS
382#endif
383 // wxUSE_NANOX
d111a89a 384}
db16cab4 385
55034339 386#endif // !wxUSE_PANGO