sAlways iInclude wx/encinfo.h from src/unix/fontutil.cpp.
[wxWidgets.git] / src / unix / fontutil.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/unix/fontutil.cpp
3 // Purpose: Font helper functions for wxX11, wxGTK, wxMotif
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 05.11.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 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24 #pragma hdrstop
25 #endif
26
27 #include "wx/fontutil.h"
28
29 #ifndef WX_PRECOMP
30 #include "wx/app.h"
31 #include "wx/font.h" // wxFont enums
32 #include "wx/hash.h"
33 #include "wx/utils.h" // for wxGetDisplay()
34 #include "wx/module.h"
35 #endif // PCH
36
37 #include "wx/encinfo.h"
38 #include "wx/fontmap.h"
39 #include "wx/tokenzr.h"
40 #include "wx/fontenum.h"
41
42 #if wxUSE_PANGO
43
44 #include "pango/pango.h"
45
46 #ifdef __WXGTK20__
47 #include "wx/gtk/private.h"
48 extern GtkWidget *wxGetRootWindow();
49
50 #define wxPANGO_CONV wxGTK_CONV_SYS
51 #define wxPANGO_CONV_BACK wxGTK_CONV_BACK_SYS
52 #else
53 #include "wx/x11/private.h"
54 #include "wx/gtk/private/string.h"
55
56 #define wxPANGO_CONV(s) s.utf8_str()
57 #define wxPANGO_CONV_BACK(s) wxString::FromUTF8Unchecked(s)
58 #endif
59
60 // ----------------------------------------------------------------------------
61 // wxNativeFontInfo
62 // ----------------------------------------------------------------------------
63
64 void wxNativeFontInfo::Init()
65 {
66 description = NULL;
67 m_underlined = false;
68 m_strikethrough = false;
69 }
70
71 void wxNativeFontInfo::Init(const wxNativeFontInfo& info)
72 {
73 if (info.description)
74 {
75 description = pango_font_description_copy(info.description);
76 m_underlined = info.GetUnderlined();
77 m_strikethrough = info.GetStrikethrough();
78 }
79 else
80 {
81 description = NULL;
82 m_underlined = false;
83 m_strikethrough = false;
84 }
85 }
86
87 void wxNativeFontInfo::Free()
88 {
89 if (description)
90 pango_font_description_free(description);
91 }
92
93 int wxNativeFontInfo::GetPointSize() const
94 {
95 return pango_font_description_get_size( description ) / PANGO_SCALE;
96 }
97
98 wxFontStyle wxNativeFontInfo::GetStyle() const
99 {
100 wxFontStyle m_style = wxFONTSTYLE_NORMAL;
101
102 switch (pango_font_description_get_style( description ))
103 {
104 case PANGO_STYLE_NORMAL:
105 m_style = wxFONTSTYLE_NORMAL;
106 break;
107 case PANGO_STYLE_ITALIC:
108 m_style = wxFONTSTYLE_ITALIC;
109 break;
110 case PANGO_STYLE_OBLIQUE:
111 m_style = wxFONTSTYLE_SLANT;
112 break;
113 }
114
115 return m_style;
116 }
117
118 wxFontWeight wxNativeFontInfo::GetWeight() const
119 {
120 // We seem to currently initialize only by string.
121 // In that case PANGO_FONT_MASK_WEIGHT is always set.
122 // if (!(pango_font_description_get_set_fields(description) & PANGO_FONT_MASK_WEIGHT))
123 // return wxFONTWEIGHT_NORMAL;
124
125 PangoWeight pango_weight = pango_font_description_get_weight( description );
126
127 // Until the API can be changed the following ranges of weight values are used:
128 // wxFONTWEIGHT_LIGHT: 100 .. 349 - range of 250
129 // wxFONTWEIGHT_NORMAL: 350 .. 599 - range of 250
130 // wxFONTWEIGHT_BOLD: 600 .. 900 - range of 301 (600 is "semibold" already)
131
132 if (pango_weight >= 600)
133 return wxFONTWEIGHT_BOLD;
134
135 if (pango_weight < 350)
136 return wxFONTWEIGHT_LIGHT;
137
138 return wxFONTWEIGHT_NORMAL;
139 }
140
141 bool wxNativeFontInfo::GetUnderlined() const
142 {
143 return m_underlined;
144 }
145
146 bool wxNativeFontInfo::GetStrikethrough() const
147 {
148 return m_strikethrough;
149 }
150
151 wxString wxNativeFontInfo::GetFaceName() const
152 {
153 // the Pango "family" is the wx "face name"
154 return wxPANGO_CONV_BACK(pango_font_description_get_family(description));
155 }
156
157 wxFontFamily wxNativeFontInfo::GetFamily() const
158 {
159 wxFontFamily ret = wxFONTFAMILY_UNKNOWN;
160
161 const char *family_name = pango_font_description_get_family( description );
162
163 // note: not passing -1 as the 2nd parameter to g_ascii_strdown to work
164 // around a bug in the 64-bit glib shipped with solaris 10, -1 causes it
165 // to try to allocate 2^32 bytes.
166 if ( !family_name )
167 return ret;
168 wxGtkString family_text(g_ascii_strdown(family_name, strlen(family_name)));
169
170 // Check for some common fonts, to salvage what we can from the current
171 // win32 centric wxFont API:
172 if (wxStrnicmp( family_text, "monospace", 9 ) == 0)
173 ret = wxFONTFAMILY_TELETYPE; // begins with "Monospace"
174 else if (wxStrnicmp( family_text, "courier", 7 ) == 0)
175 ret = wxFONTFAMILY_TELETYPE; // begins with "Courier"
176 #if defined(__WXGTK20__) || defined(HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE)
177 else
178 {
179 PangoFontFamily **families;
180 PangoFontFamily *family = NULL;
181 int n_families;
182 pango_context_list_families(
183 #ifdef __WXGTK20__
184 gtk_widget_get_pango_context( wxGetRootWindow() ),
185 #else
186 wxTheApp->GetPangoContext(),
187 #endif
188 &families, &n_families);
189
190 for (int i = 0; i < n_families; ++i)
191 {
192 if (g_ascii_strcasecmp(pango_font_family_get_name( families[i] ),
193 pango_font_description_get_family( description )) == 0 )
194 {
195 family = families[i];
196 break;
197 }
198 }
199
200 g_free(families);
201
202 // Some gtk+ systems might query for a non-existing font from
203 // wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT) on initialization,
204 // don't assert until wxSystemSettings::GetFont is checked for this - MR
205 // wxASSERT_MSG( family, "No appropriate PangoFontFamily found for ::description" );
206
207 if (family != NULL && pango_font_family_is_monospace( family ))
208 ret = wxFONTFAMILY_TELETYPE; // is deemed a monospace font by pango
209 }
210 #endif // GTK+ 2 || HAVE_PANGO_FONT_FAMILY_IS_MONOSPACE
211
212 if (ret == wxFONTFAMILY_UNKNOWN)
213 {
214 if (strstr( family_text, "sans" ) != NULL || strstr( family_text, "Sans" ) != NULL)
215 // checked before serif, so that "* Sans Serif" fonts are detected correctly
216 ret = wxFONTFAMILY_SWISS; // contains "Sans"
217 else if (strstr( family_text, "serif" ) != NULL || strstr( family_text, "Serif" ) != NULL)
218 ret = wxFONTFAMILY_ROMAN; // contains "Serif"
219 else if (wxStrnicmp( family_text, "times", 5 ) == 0)
220 ret = wxFONTFAMILY_ROMAN; // begins with "Times"
221 else if (wxStrnicmp( family_text, "old", 3 ) == 0)
222 ret = wxFONTFAMILY_DECORATIVE; // begins with "Old" - "Old English", "Old Town"
223 }
224
225 return ret;
226 }
227
228 wxFontEncoding wxNativeFontInfo::GetEncoding() const
229 {
230 return wxFONTENCODING_SYSTEM;
231 }
232
233 void wxNativeFontInfo::SetPointSize(int pointsize)
234 {
235 pango_font_description_set_size( description, pointsize * PANGO_SCALE );
236 }
237
238 void wxNativeFontInfo::SetStyle(wxFontStyle style)
239 {
240 switch (style)
241 {
242 case wxFONTSTYLE_ITALIC:
243 pango_font_description_set_style( description, PANGO_STYLE_ITALIC );
244 break;
245 case wxFONTSTYLE_SLANT:
246 pango_font_description_set_style( description, PANGO_STYLE_OBLIQUE );
247 break;
248 default:
249 wxFAIL_MSG( "unknown font style" );
250 // fall through
251 case wxFONTSTYLE_NORMAL:
252 pango_font_description_set_style( description, PANGO_STYLE_NORMAL );
253 break;
254 }
255 }
256
257 void wxNativeFontInfo::SetWeight(wxFontWeight weight)
258 {
259 switch (weight)
260 {
261 case wxFONTWEIGHT_BOLD:
262 pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
263 break;
264 case wxFONTWEIGHT_LIGHT:
265 pango_font_description_set_weight(description, PANGO_WEIGHT_LIGHT);
266 break;
267 default:
268 wxFAIL_MSG( "unknown font weight" );
269 // fall through
270 case wxFONTWEIGHT_NORMAL:
271 pango_font_description_set_weight(description, PANGO_WEIGHT_NORMAL);
272 }
273 }
274
275 void wxNativeFontInfo::SetUnderlined(bool underlined)
276 {
277 // Pango doesn't have the underlined attribute so we store it separately
278 // (and handle it specially in wxWindowDCImpl::DoDrawText()).
279 m_underlined = underlined;
280 }
281
282 void wxNativeFontInfo::SetStrikethrough(bool strikethrough)
283 {
284 // As with the underlined attribute above, we handle this one separately as
285 // Pango doesn't support it as part of the font description.
286 m_strikethrough = strikethrough;
287 }
288
289 bool wxNativeFontInfo::SetFaceName(const wxString& facename)
290 {
291 pango_font_description_set_family(description, wxPANGO_CONV(facename));
292
293 // we return true because Pango doesn't tell us if the call failed or not;
294 // instead on wxGTK wxFont::SetFaceName() will call wxFontBase::SetFaceName()
295 // which does the check
296 return true;
297 }
298
299 void wxNativeFontInfo::SetFamily(wxFontFamily family)
300 {
301 wxArrayString facename;
302
303 // the list of fonts associated with a family was partially
304 // taken from http://www.codestyle.org/css/font-family
305
306 switch ( family )
307 {
308 case wxFONTFAMILY_SCRIPT:
309 // corresponds to the cursive font family in the page linked above
310 facename.Add(wxS("URW Chancery L"));
311 facename.Add(wxS("Comic Sans MS"));
312 break;
313
314 case wxFONTFAMILY_DECORATIVE:
315 // corresponds to the fantasy font family in the page linked above
316 facename.Add(wxS("Impact"));
317 break;
318
319 case wxFONTFAMILY_ROMAN:
320 // corresponds to the serif font family in the page linked above
321 facename.Add(wxS("Serif"));
322 facename.Add(wxS("DejaVu Serif"));
323 facename.Add(wxS("DejaVu LGC Serif"));
324 facename.Add(wxS("Bitstream Vera Serif"));
325 facename.Add(wxS("Liberation Serif"));
326 facename.Add(wxS("FreeSerif"));
327 facename.Add(wxS("Luxi Serif"));
328 facename.Add(wxS("Times New Roman"));
329 facename.Add(wxS("Century Schoolbook L"));
330 facename.Add(wxS("URW Bookman L"));
331 facename.Add(wxS("URW Palladio L"));
332 facename.Add(wxS("Times"));
333 break;
334
335 case wxFONTFAMILY_TELETYPE:
336 case wxFONTFAMILY_MODERN:
337 // corresponds to the monospace font family in the page linked above
338 facename.Add(wxS("Monospace"));
339 facename.Add(wxS("DejaVu Sans Mono"));
340 facename.Add(wxS("DejaVu LGC Sans Mono"));
341 facename.Add(wxS("Bitstream Vera Sans Mono"));
342 facename.Add(wxS("Liberation Mono"));
343 facename.Add(wxS("FreeMono"));
344 facename.Add(wxS("Luxi Mono"));
345 facename.Add(wxS("Courier New"));
346 facename.Add(wxS("Lucida Sans Typewriter"));
347 facename.Add(wxS("Nimbus Mono L"));
348 facename.Add(wxS("Andale Mono"));
349 facename.Add(wxS("Courier"));
350 break;
351
352 case wxFONTFAMILY_SWISS:
353 case wxFONTFAMILY_DEFAULT:
354 default:
355 // corresponds to the sans-serif font family in the page linked above
356 facename.Add(wxS("Sans"));
357 facename.Add(wxS("DejaVu Sans"));
358 facename.Add(wxS("DejaVu LGC Sans"));
359 facename.Add(wxS("Bitstream Vera Sans"));
360 facename.Add(wxS("Liberation Sans"));
361 facename.Add(wxS("FreeSans"));
362 facename.Add(wxS("Luxi Sans"));
363 facename.Add(wxS("Arial"));
364 facename.Add(wxS("Lucida Sans"));
365 facename.Add(wxS("Nimbus Sans L"));
366 facename.Add(wxS("URW Gothic L"));
367 break;
368 }
369
370 SetFaceName(facename);
371 }
372
373 void wxNativeFontInfo::SetEncoding(wxFontEncoding WXUNUSED(encoding))
374 {
375 wxFAIL_MSG( "not implemented: Pango encoding is always UTF8" );
376 }
377
378 bool wxNativeFontInfo::FromString(const wxString& s)
379 {
380 wxString str(s);
381
382 // Pango font description doesn't have 'underlined' or 'strikethrough'
383 // attributes, so we handle them specially by extracting them from the
384 // string before passing it to Pango.
385 m_underlined = str.StartsWith(wxS("underlined "), &str);
386 m_strikethrough = str.StartsWith(wxS("strikethrough "), &str);
387
388 if (description)
389 pango_font_description_free( description );
390
391 // there is a bug in at least pango <= 1.13 which makes it (or its backends)
392 // segfault for very big point sizes and for negative point sizes.
393 // To workaround that bug for pango <= 1.13
394 // (see http://bugzilla.gnome.org/show_bug.cgi?id=340229)
395 // we do the check on the size here using same (arbitrary) limits used by
396 // pango > 1.13. Note that the segfault could happen also for pointsize
397 // smaller than this limit !!
398 const size_t pos = str.find_last_of(wxS(" "));
399 double size;
400 if ( pos != wxString::npos && wxString(str, pos + 1).ToDouble(&size) )
401 {
402 wxString sizeStr;
403 if ( size < 1 )
404 sizeStr = wxS("1");
405 else if ( size >= 1E6 )
406 sizeStr = wxS("1E6");
407
408 if ( !sizeStr.empty() )
409 {
410 // replace the old size with the adjusted one
411 str = wxString(s, 0, pos) + sizeStr;
412 }
413 }
414
415 description = pango_font_description_from_string(wxPANGO_CONV(str));
416
417 #if wxUSE_FONTENUM
418 // ensure a valid facename is selected
419 if (!wxFontEnumerator::IsValidFacename(GetFaceName()))
420 SetFaceName(wxNORMAL_FONT->GetFaceName());
421 #endif // wxUSE_FONTENUM
422
423 return true;
424 }
425
426 wxString wxNativeFontInfo::ToString() const
427 {
428 wxGtkString str(pango_font_description_to_string( description ));
429 wxString desc = wxPANGO_CONV_BACK(str);
430
431 // Augment the string with the attributes not handled by Pango.
432 //
433 // Notice that we must add them in the same order they are extracted in
434 // FromString() above.
435 if (m_strikethrough)
436 desc.insert(0, wxS("strikethrough "));
437 if (m_underlined)
438 desc.insert(0, wxS("underlined "));
439
440 return desc;
441 }
442
443 bool wxNativeFontInfo::FromUserString(const wxString& s)
444 {
445 return FromString( s );
446 }
447
448 wxString wxNativeFontInfo::ToUserString() const
449 {
450 return ToString();
451 }
452
453 #else // GTK+ 1.x
454
455 #ifdef __X__
456 #ifdef __VMS__
457 #pragma message disable nosimpint
458 #endif
459
460 #include <X11/Xlib.h>
461
462 #ifdef __VMS__
463 #pragma message enable nosimpint
464 #endif
465
466 #elif defined(__WXGTK__)
467 // we have to declare struct tm to avoid problems with first forward
468 // declaring it in C code (glib.h included from gdk.h does it) and then
469 // defining it when time.h is included from the headers below - this is
470 // known not to work at least with Sun CC 6.01
471 #include <time.h>
472
473 #include <gdk/gdk.h>
474 #endif
475
476
477 // ----------------------------------------------------------------------------
478 // private data
479 // ----------------------------------------------------------------------------
480
481 static wxHashTable *g_fontHash = NULL;
482
483 // ----------------------------------------------------------------------------
484 // private functions
485 // ----------------------------------------------------------------------------
486
487 // define the functions to create and destroy native fonts for this toolkit
488 #ifdef __X__
489 wxNativeFont wxLoadFont(const wxString& fontSpec)
490 {
491 return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
492 }
493
494 inline void wxFreeFont(wxNativeFont font)
495 {
496 XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
497 }
498 #elif defined(__WXGTK__)
499 wxNativeFont wxLoadFont(const wxString& fontSpec)
500 {
501 // VZ: we should use gdk_fontset_load() instead of gdk_font_load()
502 // here to be able to display Japanese fonts correctly (at least
503 // this is what people report) but unfortunately doing it results
504 // in tons of warnings when using GTK with "normal" European
505 // languages and so we can't always do it and I don't know enough
506 // to determine when should this be done... (FIXME)
507 return gdk_font_load( wxConvertWX2MB(fontSpec) );
508 }
509
510 inline void wxFreeFont(wxNativeFont font)
511 {
512 gdk_font_unref(font);
513 }
514 #else
515 #error "Unknown GUI toolkit"
516 #endif
517
518 static bool wxTestFontSpec(const wxString& fontspec);
519
520 static wxNativeFont wxLoadQueryFont(int pointSize,
521 int family,
522 int style,
523 int weight,
524 bool underlined,
525 const wxString& facename,
526 const wxString& xregistry,
527 const wxString& xencoding,
528 wxString* xFontName);
529
530 // ============================================================================
531 // implementation
532 // ============================================================================
533
534 // ----------------------------------------------------------------------------
535 // wxNativeEncodingInfo
536 // ----------------------------------------------------------------------------
537
538 // convert to/from the string representation: format is
539 // encodingid;registry;encoding[;facename]
540 bool wxNativeEncodingInfo::FromString(const wxString& s)
541 {
542 // use ";", not "-" because it may be part of encoding name
543 wxStringTokenizer tokenizer(s, wxT(";"));
544
545 wxString encid = tokenizer.GetNextToken();
546 long enc;
547 if ( !encid.ToLong(&enc) )
548 return false;
549 encoding = (wxFontEncoding)enc;
550
551 xregistry = tokenizer.GetNextToken();
552 if ( !xregistry )
553 return false;
554
555 xencoding = tokenizer.GetNextToken();
556 if ( !xencoding )
557 return false;
558
559 // ok even if empty
560 facename = tokenizer.GetNextToken();
561
562 return true;
563 }
564
565 wxString wxNativeEncodingInfo::ToString() const
566 {
567 wxString s;
568 s << (long)encoding << wxT(';') << xregistry << wxT(';') << xencoding;
569 if ( !facename.empty() )
570 {
571 s << wxT(';') << facename;
572 }
573
574 return s;
575 }
576
577 // ----------------------------------------------------------------------------
578 // wxNativeFontInfo
579 // ----------------------------------------------------------------------------
580
581 void wxNativeFontInfo::Init()
582 {
583 m_isDefault = true;
584 }
585
586 bool wxNativeFontInfo::FromString(const wxString& s)
587 {
588 wxStringTokenizer tokenizer(s, wxT(";"));
589
590 // check the version
591 wxString token = tokenizer.GetNextToken();
592 if ( token != wxT('0') )
593 return false;
594
595 xFontName = tokenizer.GetNextToken();
596
597 // this should be the end
598 if ( tokenizer.HasMoreTokens() )
599 return false;
600
601 return FromXFontName(xFontName);
602 }
603
604 wxString wxNativeFontInfo::ToString() const
605 {
606 // 0 is the version
607 return wxString::Format(wxT("%d;%s"), 0, GetXFontName().c_str());
608 }
609
610 bool wxNativeFontInfo::FromUserString(const wxString& s)
611 {
612 return FromXFontName(s);
613 }
614
615 wxString wxNativeFontInfo::ToUserString() const
616 {
617 return GetXFontName();
618 }
619
620 bool wxNativeFontInfo::HasElements() const
621 {
622 // we suppose that the foundry is never empty, so if it is it means that we
623 // had never parsed the XLFD
624 return !fontElements[0].empty();
625 }
626
627 wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
628 {
629 wxCHECK_MSG( field < wxXLFD_MAX, wxEmptyString, wxT("invalid XLFD field") );
630
631 if ( !HasElements() )
632 {
633 if ( !const_cast<wxNativeFontInfo *>(this)->FromXFontName(xFontName) )
634 return wxEmptyString;
635 }
636
637 return fontElements[field];
638 }
639
640 bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
641 {
642 // TODO: we should be able to handle the font aliases here, but how?
643 wxStringTokenizer tokenizer(fontname, wxT("-"));
644
645 // skip the leading, usually empty field (font name registry)
646 if ( !tokenizer.HasMoreTokens() )
647 return false;
648
649 (void)tokenizer.GetNextToken();
650
651 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
652 {
653 if ( !tokenizer.HasMoreTokens() )
654 {
655 // not enough elements in the XLFD - or maybe an alias
656 return false;
657 }
658
659 wxString field = tokenizer.GetNextToken();
660 if ( !field.empty() && field != wxT('*') )
661 {
662 // we're really initialized now
663 m_isDefault = false;
664 }
665
666 fontElements[n] = field;
667 }
668
669 // this should be all
670 if ( tokenizer.HasMoreTokens() )
671 return false;
672
673 return true;
674 }
675
676 wxString wxNativeFontInfo::GetXFontName() const
677 {
678 if ( xFontName.empty() )
679 {
680 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
681 {
682 // replace the non specified elements with '*' except for the
683 // additional style which is usually just omitted
684 wxString elt = fontElements[n];
685 if ( elt.empty() && n != wxXLFD_ADDSTYLE )
686 {
687 elt = wxT('*');
688 }
689
690 const_cast<wxNativeFontInfo *>(this)->xFontName << wxT('-') << elt;
691 }
692 }
693
694 return xFontName;
695 }
696
697 void
698 wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
699 {
700 wxCHECK_RET( field < wxXLFD_MAX, wxT("invalid XLFD field") );
701
702 // this class should be initialized with a valid font spec first and only
703 // then the fields may be modified!
704 wxASSERT_MSG( !IsDefault(), wxT("can't modify an uninitialized XLFD") );
705
706 if ( !HasElements() )
707 {
708 if ( !const_cast<wxNativeFontInfo *>(this)->FromXFontName(xFontName) )
709 {
710 wxFAIL_MSG( wxT("can't set font element for invalid XLFD") );
711
712 return;
713 }
714 }
715
716 fontElements[field] = value;
717
718 // invalidate the XFLD, it doesn't correspond to the font elements any more
719 xFontName.clear();
720 }
721
722 void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
723 {
724 // invalidate the font elements, GetXFontComponent() will reparse the XLFD
725 fontElements[0].clear();
726
727 xFontName = xFontName_;
728
729 m_isDefault = false;
730 }
731
732 int wxNativeFontInfo::GetPointSize() const
733 {
734 const wxString s = GetXFontComponent(wxXLFD_POINTSIZE);
735
736 // return -1 to indicate that the size is unknown
737 long l;
738 return s.ToLong(&l) ? l : -1;
739 }
740
741 wxFontStyle wxNativeFontInfo::GetStyle() const
742 {
743 const wxString s = GetXFontComponent(wxXLFD_SLANT);
744
745 if ( s.length() != 1 )
746 {
747 // it is really unknown but we don't have any way to return it from
748 // here
749 return wxFONTSTYLE_NORMAL;
750 }
751
752 switch ( s[0].GetValue() )
753 {
754 default:
755 // again, unknown but consider normal by default
756
757 case wxT('r'):
758 return wxFONTSTYLE_NORMAL;
759
760 case wxT('i'):
761 return wxFONTSTYLE_ITALIC;
762
763 case wxT('o'):
764 return wxFONTSTYLE_SLANT;
765 }
766 }
767
768 wxFontWeight wxNativeFontInfo::GetWeight() const
769 {
770 const wxString s = GetXFontComponent(wxXLFD_WEIGHT).MakeLower();
771 if ( s.find(wxT("bold")) != wxString::npos || s == wxT("black") )
772 return wxFONTWEIGHT_BOLD;
773 else if ( s == wxT("light") )
774 return wxFONTWEIGHT_LIGHT;
775
776 return wxFONTWEIGHT_NORMAL;
777 }
778
779 bool wxNativeFontInfo::GetUnderlined() const
780 {
781 // X fonts are never underlined
782 return false;
783 }
784
785 wxString wxNativeFontInfo::GetFaceName() const
786 {
787 // wxWidgets facename probably more accurately corresponds to X family
788 return GetXFontComponent(wxXLFD_FAMILY);
789 }
790
791 wxFontFamily wxNativeFontInfo::GetFamily() const
792 {
793 // and wxWidgets family -- to X foundry, but we have to translate it to
794 // wxFontFamily somehow...
795 wxFAIL_MSG(wxT("not implemented")); // GetXFontComponent(wxXLFD_FOUNDRY);
796
797 return wxFONTFAMILY_DEFAULT;
798 }
799
800 wxFontEncoding wxNativeFontInfo::GetEncoding() const
801 {
802 // we already have the code for this but need to refactor it first
803 wxFAIL_MSG( wxT("not implemented") );
804
805 return wxFONTENCODING_MAX;
806 }
807
808 void wxNativeFontInfo::SetPointSize(int pointsize)
809 {
810 SetXFontComponent(wxXLFD_POINTSIZE, wxString::Format(wxT("%d"), pointsize));
811 }
812
813 void wxNativeFontInfo::SetStyle(wxFontStyle style)
814 {
815 wxString s;
816 switch ( style )
817 {
818 case wxFONTSTYLE_ITALIC:
819 s = wxT('i');
820 break;
821
822 case wxFONTSTYLE_SLANT:
823 s = wxT('o');
824 break;
825
826 case wxFONTSTYLE_NORMAL:
827 s = wxT('r');
828
829 default:
830 wxFAIL_MSG( wxT("unknown wxFontStyle in wxNativeFontInfo::SetStyle") );
831 return;
832 }
833
834 SetXFontComponent(wxXLFD_SLANT, s);
835 }
836
837 void wxNativeFontInfo::SetWeight(wxFontWeight weight)
838 {
839 wxString s;
840 switch ( weight )
841 {
842 case wxFONTWEIGHT_BOLD:
843 s = wxT("bold");
844 break;
845
846 case wxFONTWEIGHT_LIGHT:
847 s = wxT("light");
848 break;
849
850 case wxFONTWEIGHT_NORMAL:
851 s = wxT("medium");
852 break;
853
854 default:
855 wxFAIL_MSG( wxT("unknown wxFontWeight in wxNativeFontInfo::SetWeight") );
856 return;
857 }
858
859 SetXFontComponent(wxXLFD_WEIGHT, s);
860 }
861
862 void wxNativeFontInfo::SetUnderlined(bool WXUNUSED(underlined))
863 {
864 // can't do this under X
865 }
866
867 void wxNativeFontInfo::SetStrikethrough(bool WXUNUSED(strikethrough))
868 {
869 // this is not supported by Pango fonts neither
870 }
871
872 bool wxNativeFontInfo::SetFaceName(const wxString& facename)
873 {
874 SetXFontComponent(wxXLFD_FAMILY, facename);
875 return true;
876 }
877
878 void wxNativeFontInfo::SetFamily(wxFontFamily WXUNUSED(family))
879 {
880 // wxFontFamily -> X foundry, anyone?
881 wxFAIL_MSG( wxT("not implemented") );
882
883 // SetXFontComponent(wxXLFD_FOUNDRY, ...);
884 }
885
886 void wxNativeFontInfo::SetEncoding(wxFontEncoding encoding)
887 {
888 wxNativeEncodingInfo info;
889 if ( wxGetNativeFontEncoding(encoding, &info) )
890 {
891 SetXFontComponent(wxXLFD_ENCODING, info.xencoding);
892 SetXFontComponent(wxXLFD_REGISTRY, info.xregistry);
893 }
894 }
895
896 // ----------------------------------------------------------------------------
897 // common functions
898 // ----------------------------------------------------------------------------
899
900 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
901 wxNativeEncodingInfo *info)
902 {
903 wxCHECK_MSG( info, false, wxT("bad pointer in wxGetNativeFontEncoding") );
904
905 if ( encoding == wxFONTENCODING_DEFAULT )
906 {
907 encoding = wxFont::GetDefaultEncoding();
908 }
909
910 switch ( encoding )
911 {
912 case wxFONTENCODING_ISO8859_1:
913 case wxFONTENCODING_ISO8859_2:
914 case wxFONTENCODING_ISO8859_3:
915 case wxFONTENCODING_ISO8859_4:
916 case wxFONTENCODING_ISO8859_5:
917 case wxFONTENCODING_ISO8859_6:
918 case wxFONTENCODING_ISO8859_7:
919 case wxFONTENCODING_ISO8859_8:
920 case wxFONTENCODING_ISO8859_9:
921 case wxFONTENCODING_ISO8859_10:
922 case wxFONTENCODING_ISO8859_11:
923 case wxFONTENCODING_ISO8859_12:
924 case wxFONTENCODING_ISO8859_13:
925 case wxFONTENCODING_ISO8859_14:
926 case wxFONTENCODING_ISO8859_15:
927 {
928 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
929 info->xregistry = wxT("iso8859");
930 info->xencoding.Printf(wxT("%d"), cp);
931 }
932 break;
933
934 case wxFONTENCODING_UTF8:
935 info->xregistry = wxT("iso10646");
936 info->xencoding = wxT("*");
937 break;
938
939 case wxFONTENCODING_GB2312:
940 info->xregistry = wxT("GB2312"); // or the otherway round?
941 info->xencoding = wxT("*");
942 break;
943
944 case wxFONTENCODING_KOI8:
945 case wxFONTENCODING_KOI8_U:
946 info->xregistry = wxT("koi8");
947
948 // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
949 info->xencoding = wxT("*");
950 break;
951
952 case wxFONTENCODING_CP1250:
953 case wxFONTENCODING_CP1251:
954 case wxFONTENCODING_CP1252:
955 case wxFONTENCODING_CP1253:
956 case wxFONTENCODING_CP1254:
957 case wxFONTENCODING_CP1255:
958 case wxFONTENCODING_CP1256:
959 case wxFONTENCODING_CP1257:
960 {
961 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
962 info->xregistry = wxT("microsoft");
963 info->xencoding.Printf(wxT("cp%d"), cp);
964 }
965 break;
966
967 case wxFONTENCODING_EUC_JP:
968 case wxFONTENCODING_SHIFT_JIS:
969 info->xregistry = "jis*";
970 info->xencoding = "*";
971 break;
972
973 case wxFONTENCODING_SYSTEM:
974 info->xregistry =
975 info->xencoding = wxT("*");
976 break;
977
978 default:
979 // don't know how to translate this encoding into X fontspec
980 return false;
981 }
982
983 info->encoding = encoding;
984
985 return true;
986 }
987
988 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
989 {
990 wxString fontspec;
991 fontspec.Printf(wxT("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
992 !info.facename ? wxT("*") : info.facename.c_str(),
993 info.xregistry.c_str(),
994 info.xencoding.c_str());
995
996 return wxTestFontSpec(fontspec);
997 }
998
999 // ----------------------------------------------------------------------------
1000 // X-specific functions
1001 // ----------------------------------------------------------------------------
1002
1003 wxNativeFont wxLoadQueryNearestFont(int pointSize,
1004 int family,
1005 int style,
1006 int weight,
1007 bool underlined,
1008 const wxString &facename,
1009 wxFontEncoding encoding,
1010 wxString* xFontName)
1011 {
1012 if ( encoding == wxFONTENCODING_DEFAULT )
1013 {
1014 encoding = wxFont::GetDefaultEncoding();
1015 }
1016
1017 // first determine the encoding - if the font doesn't exist at all in this
1018 // encoding, it's useless to do all other approximations (i.e. size,
1019 // family &c don't matter much)
1020 wxNativeEncodingInfo info;
1021 if ( encoding == wxFONTENCODING_SYSTEM )
1022 {
1023 // This will always work so we don't test to save time
1024 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
1025 }
1026 else
1027 {
1028 if ( !wxGetNativeFontEncoding(encoding, &info) ||
1029 !wxTestFontEncoding(info) )
1030 {
1031 #if wxUSE_FONTMAP
1032 if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
1033 #endif // wxUSE_FONTMAP
1034 {
1035 // unspported encoding - replace it with the default
1036 //
1037 // NB: we can't just return 0 from here because wxGTK code doesn't
1038 // check for it (i.e. it supposes that we'll always succeed),
1039 // so it would provoke a crash
1040 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
1041 }
1042 }
1043 }
1044
1045 // OK, we have the correct xregistry/xencoding in info structure
1046 wxNativeFont font = 0;
1047
1048 // if we already have the X font name, try to use it
1049 if( xFontName && !xFontName->empty() )
1050 {
1051 //
1052 // Make sure point size is correct for scale factor.
1053 //
1054 wxStringTokenizer tokenizer(*xFontName, wxT("-"), wxTOKEN_RET_DELIMS);
1055 wxString newFontName;
1056
1057 for(int i = 0; i < 8; i++)
1058 newFontName += tokenizer.NextToken();
1059
1060 (void) tokenizer.NextToken();
1061
1062 newFontName += wxString::Format(wxT("%d-"), pointSize);
1063
1064 while(tokenizer.HasMoreTokens())
1065 newFontName += tokenizer.GetNextToken();
1066
1067 font = wxLoadFont(newFontName);
1068
1069 if(font)
1070 *xFontName = newFontName;
1071 }
1072
1073 if ( !font )
1074 {
1075 // search up and down by stepsize 10
1076 int max_size = pointSize + 20 * (1 + (pointSize/180));
1077 int min_size = pointSize - 20 * (1 + (pointSize/180));
1078
1079 int i, round; // counters
1080
1081 // first round: search for equal, then for smaller and for larger size
1082 // with the given weight and style
1083 int testweight = weight;
1084 int teststyle = style;
1085
1086 for ( round = 0; round < 3; round++ )
1087 {
1088 // second round: use normal weight
1089 if ( round == 1 )
1090 {
1091 if ( testweight != wxNORMAL )
1092 {
1093 testweight = wxNORMAL;
1094 }
1095 else
1096 {
1097 ++round; // fall through to third round
1098 }
1099 }
1100
1101 // third round: ... and use normal style
1102 if ( round == 2 )
1103 {
1104 if ( teststyle != wxNORMAL )
1105 {
1106 teststyle = wxNORMAL;
1107 }
1108 else
1109 {
1110 break;
1111 }
1112 }
1113 // Search for equal or smaller size (approx.)
1114 for ( i = pointSize; !font && i >= 10 && i >= min_size; i -= 10 )
1115 {
1116 font = wxLoadQueryFont(i, family, teststyle, testweight, underlined,
1117 facename, info.xregistry, info.xencoding,
1118 xFontName);
1119 }
1120
1121 // Search for larger size (approx.)
1122 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
1123 {
1124 font = wxLoadQueryFont(i, family, teststyle, testweight, underlined,
1125 facename, info.xregistry, info.xencoding,
1126 xFontName);
1127 }
1128 }
1129
1130 // Try default family
1131 if ( !font && family != wxDEFAULT )
1132 {
1133 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
1134 underlined, facename,
1135 info.xregistry, info.xencoding,
1136 xFontName );
1137 }
1138
1139 // ignore size, family, style and weight but try to find font with the
1140 // given facename and encoding
1141 if ( !font )
1142 {
1143 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
1144 underlined, facename,
1145 info.xregistry, info.xencoding,
1146 xFontName);
1147
1148 // ignore family as well
1149 if ( !font )
1150 {
1151 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
1152 underlined, wxEmptyString,
1153 info.xregistry, info.xencoding,
1154 xFontName);
1155
1156 // if it still failed, try to get the font of any size but
1157 // with the requested encoding: this can happen if the
1158 // encoding is only available in one size which happens to be
1159 // different from 120
1160 if ( !font )
1161 {
1162 font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
1163 false, wxEmptyString,
1164 info.xregistry, info.xencoding,
1165 xFontName);
1166
1167 // this should never happen as we had tested for it in the
1168 // very beginning, but if it does, do return something non
1169 // NULL or we'd crash in wxFont code
1170 if ( !font )
1171 {
1172 wxFAIL_MSG( wxT("this encoding should be available!") );
1173
1174 font = wxLoadQueryFont(-1,
1175 wxDEFAULT, wxNORMAL, wxNORMAL,
1176 false, wxEmptyString,
1177 wxT("*"), wxT("*"),
1178 xFontName);
1179 }
1180 }
1181 }
1182 }
1183 }
1184
1185 return font;
1186 }
1187
1188 // ----------------------------------------------------------------------------
1189 // private functions
1190 // ----------------------------------------------------------------------------
1191
1192 // returns true if there are any fonts matching this font spec
1193 static bool wxTestFontSpec(const wxString& fontspec)
1194 {
1195 // some X servers will fail to load this font because there are too many
1196 // matches so we must test explicitly for this
1197 if ( fontspec == wxT("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
1198 {
1199 return true;
1200 }
1201
1202 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
1203 if (test)
1204 {
1205 return true;
1206 }
1207
1208 test = wxLoadFont(fontspec);
1209 g_fontHash->Put( fontspec, (wxObject*) test );
1210
1211 if ( test )
1212 {
1213 wxFreeFont(test);
1214
1215 return true;
1216 }
1217 else
1218 {
1219 return false;
1220 }
1221 }
1222
1223 static wxNativeFont wxLoadQueryFont(int pointSize,
1224 int family,
1225 int style,
1226 int weight,
1227 bool WXUNUSED(underlined),
1228 const wxString& facename,
1229 const wxString& xregistry,
1230 const wxString& xencoding,
1231 wxString* xFontName)
1232 {
1233 wxString xfamily;
1234 switch (family)
1235 {
1236 case wxDECORATIVE: xfamily = wxT("lucida"); break;
1237 case wxROMAN: xfamily = wxT("times"); break;
1238 case wxMODERN: xfamily = wxT("courier"); break;
1239 case wxSWISS: xfamily = wxT("helvetica"); break;
1240 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
1241 case wxSCRIPT: xfamily = wxT("utopia"); break;
1242 default: xfamily = wxT("*");
1243 }
1244 #if wxUSE_NANOX
1245 int xweight;
1246 switch (weight)
1247 {
1248 case wxBOLD:
1249 {
1250 xweight = MWLF_WEIGHT_BOLD;
1251 break;
1252 }
1253 case wxLIGHT:
1254 {
1255 xweight = MWLF_WEIGHT_LIGHT;
1256 break;
1257 }
1258 case wxNORMAL:
1259 {
1260 xweight = MWLF_WEIGHT_NORMAL;
1261 break;
1262 }
1263
1264 default:
1265 {
1266 xweight = MWLF_WEIGHT_DEFAULT;
1267 break;
1268 }
1269 }
1270 GR_SCREEN_INFO screenInfo;
1271 GrGetScreenInfo(& screenInfo);
1272
1273 int yPixelsPerCM = screenInfo.ydpcm;
1274
1275 // A point is 1/72 of an inch.
1276 // An inch is 2.541 cm.
1277 // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
1278 // In fact pointSize is 10 * the normal point size so
1279 // divide by 10.
1280
1281 int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
1282
1283 // An alternative: assume that the screen is 72 dpi.
1284 //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
1285 //int pixelHeight = (int) ((float)pointSize / 10.0) ;
1286
1287 GR_LOGFONT logFont;
1288 logFont.lfHeight = pixelHeight;
1289 logFont.lfWidth = 0;
1290 logFont.lfEscapement = 0;
1291 logFont.lfOrientation = 0;
1292 logFont.lfWeight = xweight;
1293 logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
1294 logFont.lfUnderline = 0;
1295 logFont.lfStrikeOut = 0;
1296 logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
1297 logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
1298 logFont.lfClipPrecision = 0; // Not used
1299 logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
1300 logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
1301 logFont.lfSansSerif = !logFont.lfSerif ;
1302 logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
1303 logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
1304 logFont.lfOblique = 0;
1305 logFont.lfSmallCaps = 0;
1306 logFont.lfPitch = 0; // 0 = default
1307 strcpy(logFont.lfFaceName, facename.c_str());
1308
1309 XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
1310 fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
1311 GrGetFontInfo(fontInfo->fid, & fontInfo->info);
1312 return (wxNativeFont) fontInfo;
1313
1314 #else
1315 wxString fontSpec;
1316 if (!facename.empty())
1317 {
1318 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
1319 facename.c_str());
1320
1321 if ( wxTestFontSpec(fontSpec) )
1322 {
1323 xfamily = facename;
1324 }
1325 //else: no such family, use default one instead
1326 }
1327
1328 wxString xstyle;
1329 switch (style)
1330 {
1331 case wxSLANT:
1332 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
1333 xfamily.c_str());
1334 if ( wxTestFontSpec(fontSpec) )
1335 {
1336 xstyle = wxT("o");
1337 break;
1338 }
1339 // fall through - try wxITALIC now
1340
1341 case wxITALIC:
1342 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
1343 xfamily.c_str());
1344 if ( wxTestFontSpec(fontSpec) )
1345 {
1346 xstyle = wxT("i");
1347 }
1348 else if ( style == wxITALIC ) // and not wxSLANT
1349 {
1350 // try wxSLANT
1351 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
1352 xfamily.c_str());
1353 if ( wxTestFontSpec(fontSpec) )
1354 {
1355 xstyle = wxT("o");
1356 }
1357 else
1358 {
1359 // no italic, no slant - leave default
1360 xstyle = wxT("*");
1361 }
1362 }
1363 break;
1364
1365 default:
1366 wxFAIL_MSG(wxT("unknown font style"));
1367 // fall back to normal
1368
1369 case wxNORMAL:
1370 xstyle = wxT("r");
1371 break;
1372 }
1373
1374 wxString xweight;
1375 switch (weight)
1376 {
1377 case wxBOLD:
1378 {
1379 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
1380 xfamily.c_str());
1381 if ( wxTestFontSpec(fontSpec) )
1382 {
1383 xweight = wxT("bold");
1384 break;
1385 }
1386 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
1387 xfamily.c_str());
1388 if ( wxTestFontSpec(fontSpec) )
1389 {
1390 xweight = wxT("heavy");
1391 break;
1392 }
1393 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
1394 xfamily.c_str());
1395 if ( wxTestFontSpec(fontSpec) )
1396 {
1397 xweight = wxT("extrabold");
1398 break;
1399 }
1400 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
1401 xfamily.c_str());
1402 if ( wxTestFontSpec(fontSpec) )
1403 {
1404 xweight = wxT("demibold");
1405 break;
1406 }
1407 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
1408 xfamily.c_str());
1409 if ( wxTestFontSpec(fontSpec) )
1410 {
1411 xweight = wxT("black");
1412 break;
1413 }
1414 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
1415 xfamily.c_str());
1416 if ( wxTestFontSpec(fontSpec) )
1417 {
1418 xweight = wxT("ultrablack");
1419 break;
1420 }
1421 }
1422 break;
1423 case wxLIGHT:
1424 {
1425 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
1426 xfamily.c_str());
1427 if ( wxTestFontSpec(fontSpec) )
1428 {
1429 xweight = wxT("light");
1430 break;
1431 }
1432 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
1433 xfamily.c_str());
1434 if ( wxTestFontSpec(fontSpec) )
1435 {
1436 xweight = wxT("thin");
1437 break;
1438 }
1439 }
1440 break;
1441 case wxNORMAL:
1442 {
1443 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
1444 xfamily.c_str());
1445 if ( wxTestFontSpec(fontSpec) )
1446 {
1447 xweight = wxT("medium");
1448 break;
1449 }
1450 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
1451 xfamily.c_str());
1452 if ( wxTestFontSpec(fontSpec) )
1453 {
1454 xweight = wxT("normal");
1455 break;
1456 }
1457 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
1458 xfamily.c_str());
1459 if ( wxTestFontSpec(fontSpec) )
1460 {
1461 xweight = wxT("regular");
1462 break;
1463 }
1464 xweight = wxT("*");
1465 }
1466 break;
1467 default: xweight = wxT("*"); break;
1468 }
1469
1470 // if pointSize is -1, don't specify any
1471 wxString sizeSpec;
1472 if ( pointSize == -1 )
1473 {
1474 sizeSpec = wxT('*');
1475 }
1476 else
1477 {
1478 sizeSpec.Printf(wxT("%d"), pointSize);
1479 }
1480
1481 // construct the X font spec from our data
1482 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
1483 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
1484 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
1485
1486 if( xFontName )
1487 *xFontName = fontSpec;
1488
1489 return wxLoadFont(fontSpec);
1490 #endif
1491 // wxUSE_NANOX
1492 }
1493
1494 // ----------------------------------------------------------------------------
1495 // wxFontModule
1496 // ----------------------------------------------------------------------------
1497
1498 class wxFontModule : public wxModule
1499 {
1500 public:
1501 bool OnInit();
1502 void OnExit();
1503
1504 private:
1505 DECLARE_DYNAMIC_CLASS(wxFontModule)
1506 };
1507
1508 IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
1509
1510 bool wxFontModule::OnInit()
1511 {
1512 g_fontHash = new wxHashTable( wxKEY_STRING );
1513
1514 return true;
1515 }
1516
1517 void wxFontModule::OnExit()
1518 {
1519 wxDELETE(g_fontHash);
1520 }
1521
1522 #endif // GTK 2.0/1.x