Attempt at creating appropriate fonts in Nano-X
[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 GR_SCREEN_INFO screenInfo;
618 GrGetScreenInfo(& screenInfo);
619
620 int yPixelsPerCM = screenInfo.ydpcm;
621
622 // A point is 1/20 of an inch.
623 // An inch is 2.541 cm.
624 // So pixelHeight = (pointSize / 20) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
625
626 int pixelHeight = (int) ( (((float)pointSize) / 20.0) * 2.541 * (float) yPixelsPerCM) ;
627
628 GR_LOGFONT logFont;
629 logFont.lfHeight = pixelHeight;
630 logFont.lfWidth = 0;
631 logFont.lfEscapement = 0;
632 logFont.lfOrientation = 0;
633 logFont.lfWeight = weight; // TODO: check of conversion req'd
634 logFont.lfItalic = (style == wxNORMAL ? 0 : 1) ;
635 logFont.lfUnderline = 0;
636 logFont.lfStrikeOut = 0;
637 logFont.lfCharSet = MWLF_CHARSET_DEFAULT; // TODO: select appropriate one
638 logFont.lfOutPrecision = MWLF_TYPE_DEFAULT;
639 logFont.lfClipPrecision = 0; // Not used
640 logFont.lfRoman = (family == wxROMAN ? 1 : 0) ;
641 logFont.lfSerif = (family == wxSWISS ? 0 : 1) ;
642 logFont.lfSansSerif = !logFont.lfSerif ;
643 logFont.lfModern = (family == wxMODERN ? 1 : 0) ;
644 logFont.lfProportional = (family == wxTELETYPE ? 0 : 1) ;
645 logFont.lfOblique = 0;
646 logFont.lfSmallCaps = 0;
647 logFont.lfPitch = 0; // 0 = default
648 strcpy(logFont.lfFaceName, facename.c_str());
649
650 XFontStruct* fontInfo = (XFontStruct*) malloc(sizeof(XFontStruct));
651 fontInfo->fid = GrCreateFont((GR_CHAR*) facename.c_str(), pixelHeight, & logFont);
652 GrGetFontInfo(fontInfo->fid, & fontInfo->info);
653 return (wxNativeFont) fontInfo;
654
655 #else
656 wxString fontSpec;
657 if (!facename.IsEmpty())
658 {
659 fontSpec.Printf(wxT("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"),
660 facename.c_str());
661
662 if ( wxTestFontSpec(fontSpec) )
663 {
664 xfamily = facename;
665 }
666 //else: no such family, use default one instead
667 }
668
669 wxString xstyle;
670 switch (style)
671 {
672 case wxSLANT:
673 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
674 xfamily.c_str());
675 if ( wxTestFontSpec(fontSpec) )
676 {
677 xstyle = wxT("o");
678 break;
679 }
680 // fall through - try wxITALIC now
681
682 case wxITALIC:
683 fontSpec.Printf(wxT("-*-%s-*-i-*-*-*-*-*-*-*-*-*-*"),
684 xfamily.c_str());
685 if ( wxTestFontSpec(fontSpec) )
686 {
687 xstyle = wxT("i");
688 }
689 else if ( style == wxITALIC ) // and not wxSLANT
690 {
691 // try wxSLANT
692 fontSpec.Printf(wxT("-*-%s-*-o-*-*-*-*-*-*-*-*-*-*"),
693 xfamily.c_str());
694 if ( wxTestFontSpec(fontSpec) )
695 {
696 xstyle = wxT("o");
697 }
698 else
699 {
700 // no italic, no slant - leave default
701 xstyle = wxT("*");
702 }
703 }
704 break;
705
706 default:
707 wxFAIL_MSG(_T("unknown font style"));
708 // fall back to normal
709
710 case wxNORMAL:
711 xstyle = wxT("r");
712 break;
713 }
714
715 wxString xweight;
716 switch (weight)
717 {
718 case wxBOLD:
719 {
720 fontSpec.Printf(wxT("-*-%s-bold-*-*-*-*-*-*-*-*-*-*-*"),
721 xfamily.c_str());
722 if ( wxTestFontSpec(fontSpec) )
723 {
724 xweight = wxT("bold");
725 break;
726 }
727 fontSpec.Printf(wxT("-*-%s-heavy-*-*-*-*-*-*-*-*-*-*-*"),
728 xfamily.c_str());
729 if ( wxTestFontSpec(fontSpec) )
730 {
731 xweight = wxT("heavy");
732 break;
733 }
734 fontSpec.Printf(wxT("-*-%s-extrabold-*-*-*-*-*-*-*-*-*-*-*"),
735 xfamily.c_str());
736 if ( wxTestFontSpec(fontSpec) )
737 {
738 xweight = wxT("extrabold");
739 break;
740 }
741 fontSpec.Printf(wxT("-*-%s-demibold-*-*-*-*-*-*-*-*-*-*-*"),
742 xfamily.c_str());
743 if ( wxTestFontSpec(fontSpec) )
744 {
745 xweight = wxT("demibold");
746 break;
747 }
748 fontSpec.Printf(wxT("-*-%s-black-*-*-*-*-*-*-*-*-*-*-*"),
749 xfamily.c_str());
750 if ( wxTestFontSpec(fontSpec) )
751 {
752 xweight = wxT("black");
753 break;
754 }
755 fontSpec.Printf(wxT("-*-%s-ultrablack-*-*-*-*-*-*-*-*-*-*-*"),
756 xfamily.c_str());
757 if ( wxTestFontSpec(fontSpec) )
758 {
759 xweight = wxT("ultrablack");
760 break;
761 }
762 }
763 break;
764 case wxLIGHT:
765 {
766 fontSpec.Printf(wxT("-*-%s-light-*-*-*-*-*-*-*-*-*-*-*"),
767 xfamily.c_str());
768 if ( wxTestFontSpec(fontSpec) )
769 {
770 xweight = wxT("light");
771 break;
772 }
773 fontSpec.Printf(wxT("-*-%s-thin-*-*-*-*-*-*-*-*-*-*-*"),
774 xfamily.c_str());
775 if ( wxTestFontSpec(fontSpec) )
776 {
777 xweight = wxT("thin");
778 break;
779 }
780 }
781 break;
782 case wxNORMAL:
783 {
784 fontSpec.Printf(wxT("-*-%s-medium-*-*-*-*-*-*-*-*-*-*-*"),
785 xfamily.c_str());
786 if ( wxTestFontSpec(fontSpec) )
787 {
788 xweight = wxT("medium");
789 break;
790 }
791 fontSpec.Printf(wxT("-*-%s-normal-*-*-*-*-*-*-*-*-*-*-*"),
792 xfamily.c_str());
793 if ( wxTestFontSpec(fontSpec) )
794 {
795 xweight = wxT("normal");
796 break;
797 }
798 fontSpec.Printf(wxT("-*-%s-regular-*-*-*-*-*-*-*-*-*-*-*"),
799 xfamily.c_str());
800 if ( wxTestFontSpec(fontSpec) )
801 {
802 xweight = wxT("regular");
803 break;
804 }
805 xweight = wxT("*");
806 }
807 break;
808 default: xweight = wxT("*"); break;
809 }
810
811 // if pointSize is -1, don't specify any
812 wxString sizeSpec;
813 if ( fontSpec == -1 )
814 {
815 sizeSpec = _T('*');
816 }
817 else
818 {
819 sizeSpec.Printf(_T("%d"), pointSize);
820 }
821
822 // construct the X font spec from our data
823 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
824 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
825 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
826
827 if( xFontName )
828 *xFontName = fontSpec;
829
830 return wxLoadFont(fontSpec);
831 #endif
832 // wxUSE_NANOX
833 }
834
835 // ----------------------------------------------------------------------------
836 // wxFontModule
837 // ----------------------------------------------------------------------------
838
839 class wxFontModule : public wxModule
840 {
841 public:
842 bool OnInit();
843 void OnExit();
844
845 private:
846 DECLARE_DYNAMIC_CLASS(wxFontModule)
847 };
848
849 IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
850
851 bool wxFontModule::OnInit()
852 {
853 g_fontHash = new wxHashTable( wxKEY_STRING );
854
855 return TRUE;
856 }
857
858 void wxFontModule::OnExit()
859 {
860 delete g_fontHash;
861
862 g_fontHash = (wxHashTable *)NULL;
863 }