added wxFontMapper::Get/Set
[wxWidgets.git] / src / unix / fontutil.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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$
8 // Copyright: (c) Vadim Zeitlin
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "fontutil.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #endif // PCH
33
34 #ifdef __X__
35 #ifdef __VMS__
36 #pragma message disable nosimpint
37 #endif
38
39 #include <X11/Xlib.h>
40
41 #ifdef __VMS__
42 #pragma message enable nosimpint
43 #endif
44
45 #include "wx/utils.h" // for wxGetDisplay()
46 #elif defined(__WXGTK__)
47 // we have to declare struct tm to avoid problems with first forward
48 // declaring it in C code (glib.h included from gdk.h does it) and then
49 // defining it when time.h is included from the headers below - this is
50 // known not to work at least with Sun CC 6.01
51 #include <time.h>
52
53 #include <gdk/gdk.h>
54 #endif
55
56 #include "wx/fontutil.h"
57 #include "wx/fontmap.h"
58 #include "wx/tokenzr.h"
59 #include "wx/hash.h"
60 #include "wx/module.h"
61
62 // ----------------------------------------------------------------------------
63 // private data
64 // ----------------------------------------------------------------------------
65
66 static wxHashTable *g_fontHash = (wxHashTable*) NULL;
67
68 // ----------------------------------------------------------------------------
69 // private functions
70 // ----------------------------------------------------------------------------
71
72 // define the functions to create and destroy native fonts for this toolkit
73 #ifdef __X__
74 wxNativeFont wxLoadFont(const wxString& fontSpec)
75 {
76 return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
77 }
78
79 inline void wxFreeFont(wxNativeFont font)
80 {
81 XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
82 }
83 #elif defined(__WXGTK__)
84 wxNativeFont wxLoadFont(const wxString& fontSpec)
85 {
86 return gdk_font_load( wxConvertWX2MB(fontSpec) );
87 }
88
89 inline void wxFreeFont(wxNativeFont font)
90 {
91 gdk_font_unref(font);
92 }
93 #else
94 #error "Unknown GUI toolkit"
95 #endif
96
97 static bool wxTestFontSpec(const wxString& fontspec);
98
99 static wxNativeFont wxLoadQueryFont(int pointSize,
100 int family,
101 int style,
102 int weight,
103 bool underlined,
104 const wxString& facename,
105 const wxString& xregistry,
106 const wxString& xencoding,
107 wxString* xFontName);
108
109 // ============================================================================
110 // implementation
111 // ============================================================================
112
113 // ----------------------------------------------------------------------------
114 // wxNativeEncodingInfo
115 // ----------------------------------------------------------------------------
116
117 // convert to/from the string representation: format is
118 // encodingid;registry;encoding[;facename]
119 bool wxNativeEncodingInfo::FromString(const wxString& s)
120 {
121 // use ";", not "-" because it may be part of encoding name
122 wxStringTokenizer tokenizer(s, _T(";"));
123
124 wxString encid = tokenizer.GetNextToken();
125 long enc;
126 if ( !encid.ToLong(&enc) )
127 return FALSE;
128 encoding = (wxFontEncoding)enc;
129
130 xregistry = tokenizer.GetNextToken();
131 if ( !xregistry )
132 return FALSE;
133
134 xencoding = tokenizer.GetNextToken();
135 if ( !xencoding )
136 return FALSE;
137
138 // ok even if empty
139 facename = tokenizer.GetNextToken();
140
141 return TRUE;
142 }
143
144 wxString wxNativeEncodingInfo::ToString() const
145 {
146 wxString s;
147 s << (long)encoding << _T(';') << xregistry << _T(';') << xencoding;
148 if ( !!facename )
149 {
150 s << _T(';') << facename;
151 }
152
153 return s;
154 }
155
156 // ----------------------------------------------------------------------------
157 // wxNativeFontInfo
158 // ----------------------------------------------------------------------------
159
160 void wxNativeFontInfo::Init()
161 {
162 m_isDefault = TRUE;
163 }
164
165 bool wxNativeFontInfo::FromString(const wxString& s)
166 {
167 wxStringTokenizer tokenizer(s, _T(";"));
168
169 // check the version
170 wxString token = tokenizer.GetNextToken();
171 if ( token != _T('0') )
172 return FALSE;
173
174 xFontName = tokenizer.GetNextToken();
175
176 // this should be the end
177 if ( tokenizer.HasMoreTokens() )
178 return FALSE;
179
180 return FromXFontName(xFontName);
181 }
182
183 wxString wxNativeFontInfo::ToString() const
184 {
185 // 0 is the version
186 return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str());
187 }
188
189 bool wxNativeFontInfo::FromUserString(const wxString& s)
190 {
191 return FromXFontName(s);
192 }
193
194 wxString wxNativeFontInfo::ToUserString() const
195 {
196 return GetXFontName();
197 }
198
199 bool wxNativeFontInfo::HasElements() const
200 {
201 // we suppose that the foundry is never empty, so if it is it means that we
202 // had never parsed the XLFD
203 return !fontElements[0].empty();
204 }
205
206 wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
207 {
208 wxCHECK_MSG( field < wxXLFD_MAX, _T(""), _T("invalid XLFD field") );
209
210 if ( !HasElements() )
211 {
212 // const_cast
213 if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
214 return _T("");
215 }
216
217 return fontElements[field];
218 }
219
220 bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
221 {
222 // TODO: we should be able to handle the font aliases here, but how?
223 wxStringTokenizer tokenizer(fontname, _T("-"));
224
225 // skip the leading, usually empty field (font name registry)
226 if ( !tokenizer.HasMoreTokens() )
227 return FALSE;
228
229 (void)tokenizer.GetNextToken();
230
231 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
232 {
233 if ( !tokenizer.HasMoreTokens() )
234 {
235 // not enough elements in the XLFD - or maybe an alias
236 return FALSE;
237 }
238
239 fontElements[n] = tokenizer.GetNextToken();
240 }
241
242 // this should be all
243 return !tokenizer.HasMoreTokens();
244 }
245
246 wxString wxNativeFontInfo::GetXFontName() const
247 {
248 if ( xFontName.empty() )
249 {
250 for ( size_t n = 0; n < WXSIZEOF(fontElements); n++ )
251 {
252 // replace the non specified elements with '*' except for the
253 // additional style which is usually just omitted
254 wxString elt = fontElements[n];
255 if ( elt.empty() && n != wxXLFD_ADDSTYLE )
256 {
257 elt = _T('*');
258 }
259
260 // const_cast
261 ((wxNativeFontInfo *)this)->xFontName << _T('-') << elt;
262 }
263 }
264
265 return xFontName;
266 }
267
268 void
269 wxNativeFontInfo::SetXFontComponent(wxXLFDField field, const wxString& value)
270 {
271 wxCHECK_RET( field < wxXLFD_MAX, _T("invalid XLFD field") );
272
273 // this class should be initialized with a valid font spec first and only
274 // then the fields may be modified!
275 wxASSERT_MSG( !IsDefault(), _T("can't modify an uninitialized XLFD") );
276
277 if ( !HasElements() )
278 {
279 // const_cast
280 if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
281 {
282 wxFAIL_MSG( _T("can't set font element for invalid XLFD") );
283
284 return;
285 }
286 }
287
288 fontElements[field] = value;
289
290 // invalidate the XFLD, it doesn't correspond to the font elements any more
291 xFontName.clear();
292 }
293
294 void wxNativeFontInfo::SetXFontName(const wxString& xFontName_)
295 {
296 // invalidate the font elements, GetXFontComponent() will reparse the XLFD
297 fontElements[0].clear();
298
299 xFontName = xFontName_;
300
301 m_isDefault = FALSE;
302 }
303
304 // ----------------------------------------------------------------------------
305 // common functions
306 // ----------------------------------------------------------------------------
307
308 bool wxGetNativeFontEncoding(wxFontEncoding encoding,
309 wxNativeEncodingInfo *info)
310 {
311 wxCHECK_MSG( info, FALSE, _T("bad pointer in wxGetNativeFontEncoding") );
312
313 if ( encoding == wxFONTENCODING_DEFAULT )
314 {
315 encoding = wxFont::GetDefaultEncoding();
316 }
317
318 switch ( encoding )
319 {
320 case wxFONTENCODING_ISO8859_1:
321 case wxFONTENCODING_ISO8859_2:
322 case wxFONTENCODING_ISO8859_3:
323 case wxFONTENCODING_ISO8859_4:
324 case wxFONTENCODING_ISO8859_5:
325 case wxFONTENCODING_ISO8859_6:
326 case wxFONTENCODING_ISO8859_7:
327 case wxFONTENCODING_ISO8859_8:
328 case wxFONTENCODING_ISO8859_9:
329 case wxFONTENCODING_ISO8859_10:
330 case wxFONTENCODING_ISO8859_11:
331 case wxFONTENCODING_ISO8859_12:
332 case wxFONTENCODING_ISO8859_13:
333 case wxFONTENCODING_ISO8859_14:
334 case wxFONTENCODING_ISO8859_15:
335 {
336 int cp = encoding - wxFONTENCODING_ISO8859_1 + 1;
337 info->xregistry = wxT("iso8859");
338 info->xencoding.Printf(wxT("%d"), cp);
339 }
340 break;
341
342 case wxFONTENCODING_UTF8:
343 info->xregistry = wxT("iso10646");
344 info->xencoding = wxT("*");
345 break;
346
347 case wxFONTENCODING_KOI8:
348 info->xregistry = wxT("koi8");
349
350 // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
351 info->xencoding = wxT("*");
352 break;
353
354 case wxFONTENCODING_CP1250:
355 case wxFONTENCODING_CP1251:
356 case wxFONTENCODING_CP1252:
357 case wxFONTENCODING_CP1253:
358 case wxFONTENCODING_CP1254:
359 case wxFONTENCODING_CP1255:
360 case wxFONTENCODING_CP1256:
361 case wxFONTENCODING_CP1257:
362 {
363 int cp = encoding - wxFONTENCODING_CP1250 + 1250;
364 info->xregistry = wxT("microsoft");
365 info->xencoding.Printf(wxT("cp%d"), cp);
366 }
367 break;
368
369 case wxFONTENCODING_SYSTEM:
370 info->xregistry =
371 info->xencoding = wxT("*");
372 break;
373
374 default:
375 // don't know how to translate this encoding into X fontspec
376 return FALSE;
377 }
378
379 info->encoding = encoding;
380
381 return TRUE;
382 }
383
384 bool wxTestFontEncoding(const wxNativeEncodingInfo& info)
385 {
386 wxString fontspec;
387 fontspec.Printf(_T("-*-%s-*-*-*-*-*-*-*-*-*-*-%s-%s"),
388 !info.facename ? _T("*") : info.facename.c_str(),
389 info.xregistry.c_str(),
390 info.xencoding.c_str());
391
392 return wxTestFontSpec(fontspec);
393 }
394
395 // ----------------------------------------------------------------------------
396 // X-specific functions
397 // ----------------------------------------------------------------------------
398
399 wxNativeFont wxLoadQueryNearestFont(int pointSize,
400 int family,
401 int style,
402 int weight,
403 bool underlined,
404 const wxString &facename,
405 wxFontEncoding encoding,
406 wxString* xFontName)
407 {
408 if ( encoding == wxFONTENCODING_DEFAULT )
409 {
410 encoding = wxFont::GetDefaultEncoding();
411 }
412
413 // first determine the encoding - if the font doesn't exist at all in this
414 // encoding, it's useless to do all other approximations (i.e. size,
415 // family &c don't matter much)
416 wxNativeEncodingInfo info;
417 if ( encoding == wxFONTENCODING_SYSTEM )
418 {
419 // This will always work so we don't test to save time
420 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
421 }
422 else
423 {
424 if ( !wxGetNativeFontEncoding(encoding, &info) ||
425 !wxTestFontEncoding(info) )
426 {
427 #if wxUSE_FONTMAP
428 if ( !wxFontMapper::Get()->GetAltForEncoding(encoding, &info) )
429 #endif // wxUSE_FONTMAP
430 {
431 // unspported encoding - replace it with the default
432 //
433 // NB: we can't just return 0 from here because wxGTK code doesn't
434 // check for it (i.e. it supposes that we'll always succeed),
435 // so it would provoke a crash
436 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
437 }
438 }
439 }
440
441 // OK, we have the correct xregistry/xencoding in info structure
442 wxNativeFont font = 0;
443
444 // if we already have the X font name, try to use it
445 if( xFontName && !xFontName->IsEmpty() )
446 {
447 //
448 // Make sure point size is correct for scale factor.
449 //
450 wxStringTokenizer tokenizer(*xFontName, _T("-"), wxTOKEN_RET_DELIMS);
451 wxString newFontName;
452
453 for(int i = 0; i < 8; i++)
454 newFontName += tokenizer.NextToken();
455
456 (void) tokenizer.NextToken();
457
458 newFontName += wxString::Format("%d-", pointSize);
459
460 while(tokenizer.HasMoreTokens())
461 newFontName += tokenizer.GetNextToken();
462
463 font = wxLoadFont(newFontName);
464
465 if(font)
466 *xFontName = newFontName;
467 }
468
469 // try to load exactly the font requested first
470 if( !font )
471 {
472 font = wxLoadQueryFont( pointSize, family, style, weight,
473 underlined, facename,
474 info.xregistry, info.xencoding,
475 xFontName );
476 }
477
478 if ( !font )
479 {
480 // search up and down by stepsize 10
481 int max_size = pointSize + 20 * (1 + (pointSize/180));
482 int min_size = pointSize - 20 * (1 + (pointSize/180));
483
484 int i;
485
486 // Search for smaller size (approx.)
487 for ( i = pointSize - 10; !font && i >= 10 && i >= min_size; i -= 10 )
488 {
489 font = wxLoadQueryFont(i, family, style, weight, underlined,
490 facename, info.xregistry, info.xencoding,
491 xFontName);
492 }
493
494 // Search for larger size (approx.)
495 for ( i = pointSize + 10; !font && i <= max_size; i += 10 )
496 {
497 font = wxLoadQueryFont(i, family, style, weight, underlined,
498 facename, info.xregistry, info.xencoding,
499 xFontName);
500 }
501
502 // Try default family
503 if ( !font && family != wxDEFAULT )
504 {
505 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
506 underlined, facename,
507 info.xregistry, info.xencoding,
508 xFontName );
509 }
510
511 // ignore size, family, style and weight but try to find font with the
512 // given facename and encoding
513 if ( !font )
514 {
515 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
516 underlined, facename,
517 info.xregistry, info.xencoding,
518 xFontName);
519
520 // ignore family as well
521 if ( !font )
522 {
523 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
524 underlined, wxEmptyString,
525 info.xregistry, info.xencoding,
526 xFontName);
527
528 // if it still failed, try to get the font of any size but
529 // with the requested encoding: this can happen if the
530 // encoding is only available in one size which happens to be
531 // different from 120
532 if ( !font )
533 {
534 font = wxLoadQueryFont(-1, wxDEFAULT, wxNORMAL, wxNORMAL,
535 FALSE, wxEmptyString,
536 info.xregistry, info.xencoding,
537 xFontName);
538
539 // this should never happen as we had tested for it in the
540 // very beginning, but if it does, do return something non
541 // NULL or we'd crash in wxFont code
542 if ( !font )
543 {
544 wxFAIL_MSG( _T("this encoding should be available!") );
545
546 font = wxLoadQueryFont(-1,
547 wxDEFAULT, wxNORMAL, wxNORMAL,
548 FALSE, wxEmptyString,
549 _T("*"), _T("*"),
550 xFontName);
551 }
552 }
553 }
554 }
555 }
556
557 return font;
558 }
559
560 // ----------------------------------------------------------------------------
561 // private functions
562 // ----------------------------------------------------------------------------
563
564 // returns TRUE if there are any fonts matching this font spec
565 static bool wxTestFontSpec(const wxString& fontspec)
566 {
567 // some X servers will fail to load this font because there are too many
568 // matches so we must test explicitly for this
569 if ( fontspec == _T("-*-*-*-*-*-*-*-*-*-*-*-*-*-*") )
570 {
571 return TRUE;
572 }
573
574 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
575 if (test)
576 {
577 return TRUE;
578 }
579
580 test = wxLoadFont(fontspec);
581 g_fontHash->Put( fontspec, (wxObject*) test );
582
583 if ( test )
584 {
585 wxFreeFont(test);
586
587 return TRUE;
588 }
589 else
590 {
591 return FALSE;
592 }
593 }
594
595 static wxNativeFont wxLoadQueryFont(int pointSize,
596 int family,
597 int style,
598 int weight,
599 bool WXUNUSED(underlined),
600 const wxString& facename,
601 const wxString& xregistry,
602 const wxString& xencoding,
603 wxString* xFontName)
604 {
605 wxString xfamily;
606 switch (family)
607 {
608 case wxDECORATIVE: xfamily = wxT("lucida"); break;
609 case wxROMAN: xfamily = wxT("times"); break;
610 case wxMODERN: xfamily = wxT("courier"); break;
611 case wxSWISS: xfamily = wxT("helvetica"); break;
612 case wxTELETYPE: xfamily = wxT("lucidatypewriter"); break;
613 case wxSCRIPT: xfamily = wxT("utopia"); break;
614 default: xfamily = wxT("*");
615 }
616 #if wxUSE_NANOX
617 int xweight;
618 switch (weight)
619 {
620 case wxBOLD:
621 {
622 xweight = MWLF_WEIGHT_BOLD;
623 break;
624 }
625 case wxLIGHT:
626 {
627 xweight = MWLF_WEIGHT_LIGHT;
628 break;
629 }
630 case wxNORMAL:
631 {
632 xweight = MWLF_WEIGHT_NORMAL;
633 break;
634 }
635
636 default:
637 {
638 xweight = MWLF_WEIGHT_DEFAULT;
639 break;
640 }
641 }
642 GR_SCREEN_INFO screenInfo;
643 GrGetScreenInfo(& screenInfo);
644
645 int yPixelsPerCM = screenInfo.ydpcm;
646
647 // A point is 1/72 of an inch.
648 // An inch is 2.541 cm.
649 // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
650 // In fact pointSize is 10 * the normal point size so
651 // divide by 10.
652
653 int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM) ;
654
655 // An alternative: assume that the screen is 72 dpi.
656 //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
657 //int pixelHeight = (int) ((float)pointSize / 10.0) ;
658
659 GR_LOGFONT logFont;
660 logFont.lfHeight = pixelHeight;
661 logFont.lfWidth = 0;
662 logFont.lfEscapement = 0;
663 logFont.lfOrientation = 0;
664 logFont.lfWeight = xweight;
665 logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
666 logFont.lfUnderline = 0;
667 logFont.lfStrikeOut = 0;
668 logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
669 logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
670 logFont.lfClipPrecision = 0; // Not used
671 logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
672 logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
673 logFont.lfSansSerif = !logFont.lfSerif ;
674 logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
675 logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
676 logFont.lfOblique = 0;
677 logFont.lfSmallCaps = 0;
678 logFont.lfPitch = 0; // 0 = default
679 strcpy(logFont.lfFaceName, facename.c_str());
680
681 XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
682 fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
683 GrGetFontInfo(fontInfo->fid, & fontInfo->info);
684 return (wxNativeFont) fontInfo;
685
686 #else
687 wxString fontSpec;
688 if (!facename.IsEmpty())
689 {
690 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
691 facename.c_str());
692
693 if ( wxTestFontSpec(fontSpec) )
694 {
695 xfamily = facename;
696 }
697 //else: no such family, use default one instead
698 }
699
700 wxString xstyle;
701 switch (style)
702 {
703 case wxSLANT:
704 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
705 xfamily.c_str());
706 if ( wxTestFontSpec(fontSpec) )
707 {
708 xstyle = wxT("o");
709 break;
710 }
711 // fall through - try wxITALIC now
712
713 case wxITALIC:
714 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
715 xfamily.c_str());
716 if ( wxTestFontSpec(fontSpec) )
717 {
718 xstyle = wxT("i");
719 }
720 else if ( style == wxITALIC ) // and not wxSLANT
721 {
722 // try wxSLANT
723 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
724 xfamily.c_str());
725 if ( wxTestFontSpec(fontSpec) )
726 {
727 xstyle = wxT("o");
728 }
729 else
730 {
731 // no italic, no slant - leave default
732 xstyle = wxT("*");
733 }
734 }
735 break;
736
737 default:
738 wxFAIL_MSG(_T("unknown font style"));
739 // fall back to normal
740
741 case wxNORMAL:
742 xstyle = wxT("r");
743 break;
744 }
745
746 wxString xweight;
747 switch (weight)
748 {
749 case wxBOLD:
750 {
751 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
752 xfamily.c_str());
753 if ( wxTestFontSpec(fontSpec) )
754 {
755 xweight = wxT("bold");
756 break;
757 }
758 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
759 xfamily.c_str());
760 if ( wxTestFontSpec(fontSpec) )
761 {
762 xweight = wxT("heavy");
763 break;
764 }
765 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
766 xfamily.c_str());
767 if ( wxTestFontSpec(fontSpec) )
768 {
769 xweight = wxT("extrabold");
770 break;
771 }
772 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
773 xfamily.c_str());
774 if ( wxTestFontSpec(fontSpec) )
775 {
776 xweight = wxT("demibold");
777 break;
778 }
779 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
780 xfamily.c_str());
781 if ( wxTestFontSpec(fontSpec) )
782 {
783 xweight = wxT("black");
784 break;
785 }
786 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
787 xfamily.c_str());
788 if ( wxTestFontSpec(fontSpec) )
789 {
790 xweight = wxT("ultrablack");
791 break;
792 }
793 }
794 break;
795 case wxLIGHT:
796 {
797 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
798 xfamily.c_str());
799 if ( wxTestFontSpec(fontSpec) )
800 {
801 xweight = wxT("light");
802 break;
803 }
804 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
805 xfamily.c_str());
806 if ( wxTestFontSpec(fontSpec) )
807 {
808 xweight = wxT("thin");
809 break;
810 }
811 }
812 break;
813 case wxNORMAL:
814 {
815 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
816 xfamily.c_str());
817 if ( wxTestFontSpec(fontSpec) )
818 {
819 xweight = wxT("medium");
820 break;
821 }
822 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
823 xfamily.c_str());
824 if ( wxTestFontSpec(fontSpec) )
825 {
826 xweight = wxT("normal");
827 break;
828 }
829 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
830 xfamily.c_str());
831 if ( wxTestFontSpec(fontSpec) )
832 {
833 xweight = wxT("regular");
834 break;
835 }
836 xweight = wxT("*");
837 }
838 break;
839 default: xweight = wxT("*"); break;
840 }
841
842 // if pointSize is -1, don't specify any
843 wxString sizeSpec;
844 if ( pointSize == -1 )
845 {
846 sizeSpec = _T('*');
847 }
848 else
849 {
850 sizeSpec.Printf(_T("%d"), pointSize);
851 }
852
853 // construct the X font spec from our data
854 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
855 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
856 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
857
858 if( xFontName )
859 *xFontName = fontSpec;
860
861 return wxLoadFont(fontSpec);
862 #endif
863 // wxUSE_NANOX
864 }
865
866 // ----------------------------------------------------------------------------
867 // wxFontModule
868 // ----------------------------------------------------------------------------
869
870 class wxFontModule : public wxModule
871 {
872 public:
873 bool OnInit();
874 void OnExit();
875
876 private:
877 DECLARE_DYNAMIC_CLASS(wxFontModule)
878 };
879
880 IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
881
882 bool wxFontModule::OnInit()
883 {
884 g_fontHash = new wxHashTable( wxKEY_STRING );
885
886 return TRUE;
887 }
888
889 void wxFontModule::OnExit()
890 {
891 delete g_fontHash;
892
893 g_fontHash = (wxHashTable *)NULL;
894 }