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