Got dialog sizing to work, downsized fonts a bit (though it always returns
[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 ( !wxTheFontMapper->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/20 of an inch.
648 // An inch is 2.541 cm.
649 // So pixelHeight = (pointSize / 20) (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 // I don't know why this is necessary, but otherwise fonts
654 // are just too big.
655 float fudgeFactor = 0.6 ;
656 int pixelHeight = (int) ( (((float)pointSize) / 200.0) * 2.541 * (float) yPixelsPerCM * fudgeFactor) ;
657
658 // An alternative: assume that the screen is 72 dpi.
659 // This gets a similar result to above (pre-fudge factor)
660 //int pixelHeight = (int) (((float)pointSize / 200.0) * 72.0) ;
661
662 GR_LOGFONT logFont;
663 logFont.lfHeight = pixelHeight;
664 logFont.lfWidth = 0;
665 logFont.lfEscapement = 0;
666 logFont.lfOrientation = 0;
667 logFont.lfWeight = xweight;
668 logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
669 logFont.lfUnderline = 0;
670 logFont.lfStrikeOut = 0;
671 logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
672 logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
673 logFont.lfClipPrecision = 0; // Not used
674 logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
675 logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
676 logFont.lfSansSerif = !logFont.lfSerif ;
677 logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
678 logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
679 logFont.lfOblique = 0;
680 logFont.lfSmallCaps = 0;
681 logFont.lfPitch = 0; // 0 = default
682 strcpy(logFont.lfFaceName, facename.c_str());
683
684 XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
685 fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
686 GrGetFontInfo(fontInfo->fid, & fontInfo->info);
687 return (wxNativeFont) fontInfo;
688
689 #else
690 wxString fontSpec;
691 if (!facename.IsEmpty())
692 {
693 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
694 facename.c_str());
695
696 if ( wxTestFontSpec(fontSpec) )
697 {
698 xfamily = facename;
699 }
700 //else: no such family, use default one instead
701 }
702
703 wxString xstyle;
704 switch (style)
705 {
706 case wxSLANT:
707 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
708 xfamily.c_str());
709 if ( wxTestFontSpec(fontSpec) )
710 {
711 xstyle = wxT("o");
712 break;
713 }
714 // fall through - try wxITALIC now
715
716 case wxITALIC:
717 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
718 xfamily.c_str());
719 if ( wxTestFontSpec(fontSpec) )
720 {
721 xstyle = wxT("i");
722 }
723 else if ( style == wxITALIC ) // and not wxSLANT
724 {
725 // try wxSLANT
726 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
727 xfamily.c_str());
728 if ( wxTestFontSpec(fontSpec) )
729 {
730 xstyle = wxT("o");
731 }
732 else
733 {
734 // no italic, no slant - leave default
735 xstyle = wxT("*");
736 }
737 }
738 break;
739
740 default:
741 wxFAIL_MSG(_T("unknown font style"));
742 // fall back to normal
743
744 case wxNORMAL:
745 xstyle = wxT("r");
746 break;
747 }
748
749 wxString xweight;
750 switch (weight)
751 {
752 case wxBOLD:
753 {
754 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
755 xfamily.c_str());
756 if ( wxTestFontSpec(fontSpec) )
757 {
758 xweight = wxT("bold");
759 break;
760 }
761 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
762 xfamily.c_str());
763 if ( wxTestFontSpec(fontSpec) )
764 {
765 xweight = wxT("heavy");
766 break;
767 }
768 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
769 xfamily.c_str());
770 if ( wxTestFontSpec(fontSpec) )
771 {
772 xweight = wxT("extrabold");
773 break;
774 }
775 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
776 xfamily.c_str());
777 if ( wxTestFontSpec(fontSpec) )
778 {
779 xweight = wxT("demibold");
780 break;
781 }
782 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
783 xfamily.c_str());
784 if ( wxTestFontSpec(fontSpec) )
785 {
786 xweight = wxT("black");
787 break;
788 }
789 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
790 xfamily.c_str());
791 if ( wxTestFontSpec(fontSpec) )
792 {
793 xweight = wxT("ultrablack");
794 break;
795 }
796 }
797 break;
798 case wxLIGHT:
799 {
800 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
801 xfamily.c_str());
802 if ( wxTestFontSpec(fontSpec) )
803 {
804 xweight = wxT("light");
805 break;
806 }
807 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
808 xfamily.c_str());
809 if ( wxTestFontSpec(fontSpec) )
810 {
811 xweight = wxT("thin");
812 break;
813 }
814 }
815 break;
816 case wxNORMAL:
817 {
818 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
819 xfamily.c_str());
820 if ( wxTestFontSpec(fontSpec) )
821 {
822 xweight = wxT("medium");
823 break;
824 }
825 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
826 xfamily.c_str());
827 if ( wxTestFontSpec(fontSpec) )
828 {
829 xweight = wxT("normal");
830 break;
831 }
832 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
833 xfamily.c_str());
834 if ( wxTestFontSpec(fontSpec) )
835 {
836 xweight = wxT("regular");
837 break;
838 }
839 xweight = wxT("*");
840 }
841 break;
842 default: xweight = wxT("*"); break;
843 }
844
845 // if pointSize is -1, don't specify any
846 wxString sizeSpec;
847 if ( fontSpec == -1 )
848 {
849 sizeSpec = _T('*');
850 }
851 else
852 {
853 sizeSpec.Printf(_T("%d"), pointSize);
854 }
855
856 // construct the X font spec from our data
857 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
858 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
859 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
860
861 if( xFontName )
862 *xFontName = fontSpec;
863
864 return wxLoadFont(fontSpec);
865 #endif
866 // wxUSE_NANOX
867 }
868
869 // ----------------------------------------------------------------------------
870 // wxFontModule
871 // ----------------------------------------------------------------------------
872
873 class wxFontModule : public wxModule
874 {
875 public:
876 bool OnInit();
877 void OnExit();
878
879 private:
880 DECLARE_DYNAMIC_CLASS(wxFontModule)
881 };
882
883 IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
884
885 bool wxFontModule::OnInit()
886 {
887 g_fontHash = new wxHashTable( wxKEY_STRING );
888
889 return TRUE;
890 }
891
892 void wxFontModule::OnExit()
893 {
894 delete g_fontHash;
895
896 g_fontHash = (wxHashTable *)NULL;
897 }