]> git.saurik.com Git - wxWidgets.git/blame - src/unix/fontutil.cpp
Various changes to make pop up menus work
[wxWidgets.git] / src / unix / fontutil.cpp
CommitLineData
7beba2fc
VZ
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
79e4b627 34#ifdef __X__
4ea45e6b
VZ
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
79e4b627
VZ
44
45 #include "wx/utils.h" // for wxGetDisplay()
46#elif defined(__WXGTK__)
4ea45e6b
VZ
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>
79e4b627
VZ
54#endif
55
7beba2fc
VZ
56#include "wx/fontutil.h"
57#include "wx/fontmap.h"
58#include "wx/tokenzr.h"
2e0e025e
RR
59#include "wx/hash.h"
60#include "wx/module.h"
61
62// ----------------------------------------------------------------------------
63// private data
64// ----------------------------------------------------------------------------
65
66static wxHashTable *g_fontHash = (wxHashTable*) NULL;
7beba2fc
VZ
67
68// ----------------------------------------------------------------------------
69// private functions
70// ----------------------------------------------------------------------------
71
72// define the functions to create and destroy native fonts for this toolkit
73#ifdef __X__
3fe34ed0 74 wxNativeFont wxLoadFont(const wxString& fontSpec)
7beba2fc
VZ
75 {
76 return XLoadQueryFont((Display *)wxGetDisplay(), fontSpec);
77 }
78
409d5a58 79 inline void wxFreeFont(wxNativeFont font)
7beba2fc 80 {
a5fc62a1 81 XFreeFont((Display *)wxGetDisplay(), (XFontStruct *)font);
7beba2fc
VZ
82 }
83#elif defined(__WXGTK__)
3fe34ed0 84 wxNativeFont wxLoadFont(const wxString& fontSpec)
7beba2fc 85 {
97d3f0ee 86 return gdk_font_load( wxConvertWX2MB(fontSpec) );
7beba2fc
VZ
87 }
88
409d5a58 89 inline void wxFreeFont(wxNativeFont font)
7beba2fc
VZ
90 {
91 gdk_font_unref(font);
92 }
93#else
94 #error "Unknown GUI toolkit"
95#endif
96
97static bool wxTestFontSpec(const wxString& fontspec);
98
99static wxNativeFont wxLoadQueryFont(int pointSize,
100 int family,
101 int style,
102 int weight,
103 bool underlined,
104 const wxString& facename,
105 const wxString& xregistry,
30764ab5
VZ
106 const wxString& xencoding,
107 wxString* xFontName);
7beba2fc
VZ
108
109// ============================================================================
110// implementation
111// ============================================================================
112
113// ----------------------------------------------------------------------------
114// wxNativeEncodingInfo
115// ----------------------------------------------------------------------------
116
117// convert to/from the string representation: format is
1e1d0be1 118// encodingid;registry;encoding[;facename]
7beba2fc
VZ
119bool wxNativeEncodingInfo::FromString(const wxString& s)
120{
6c49baf2 121 // use ";", not "-" because it may be part of encoding name
1e1d0be1 122 wxStringTokenizer tokenizer(s, _T(";"));
1e1d0be1
VS
123
124 wxString encid = tokenizer.GetNextToken();
125 long enc;
126 if ( !encid.ToLong(&enc) )
127 return FALSE;
128 encoding = (wxFontEncoding)enc;
7beba2fc
VZ
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
144wxString wxNativeEncodingInfo::ToString() const
145{
146 wxString s;
1e1d0be1 147 s << (long)encoding << _T(';') << xregistry << _T(';') << xencoding;
7beba2fc
VZ
148 if ( !!facename )
149 {
1e1d0be1 150 s << _T(';') << facename;
7beba2fc
VZ
151 }
152
153 return s;
154}
155
ab5fe833
VZ
156// ----------------------------------------------------------------------------
157// wxNativeFontInfo
158// ----------------------------------------------------------------------------
159
160void wxNativeFontInfo::Init()
161{
409d5a58 162 m_isDefault = TRUE;
ab5fe833
VZ
163}
164
165bool 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
183wxString wxNativeFontInfo::ToString() const
184{
185 // 0 is the version
186 return wxString::Format(_T("%d;%s"), 0, GetXFontName().c_str());
187}
188
189bool wxNativeFontInfo::FromUserString(const wxString& s)
190{
191 return FromXFontName(s);
192}
193
194wxString wxNativeFontInfo::ToUserString() const
195{
196 return GetXFontName();
197}
198
409d5a58
VZ
199bool 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
53f6aab7
VZ
206wxString wxNativeFontInfo::GetXFontComponent(wxXLFDField field) const
207{
208 wxCHECK_MSG( field < wxXLFD_MAX, _T(""), _T("invalid XLFD field") );
209
409d5a58 210 if ( !HasElements() )
53f6aab7
VZ
211 {
212 // const_cast
213 if ( !((wxNativeFontInfo *)this)->FromXFontName(xFontName) )
214 return _T("");
215 }
216
217 return fontElements[field];
218}
219
295272bd 220bool wxNativeFontInfo::FromXFontName(const wxString& fontname)
ab5fe833
VZ
221{
222 // TODO: we should be able to handle the font aliases here, but how?
409d5a58
VZ
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();
ab5fe833
VZ
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
246wxString 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];
409d5a58 255 if ( elt.empty() && n != wxXLFD_ADDSTYLE )
ab5fe833
VZ
256 {
257 elt = _T('*');
258 }
259
260 // const_cast
261 ((wxNativeFontInfo *)this)->xFontName << _T('-') << elt;
262 }
263 }
264
265 return xFontName;
266}
267
409d5a58
VZ
268void
269wxNativeFontInfo::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
294void 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
7beba2fc
VZ
304// ----------------------------------------------------------------------------
305// common functions
306// ----------------------------------------------------------------------------
307
308bool 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:
80a24267 331 case wxFONTENCODING_ISO8859_12:
7beba2fc
VZ
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
bb84929e 342 case wxFONTENCODING_UTF8:
5707316c 343 info->xregistry = wxT("iso10646");
bb84929e
VZ
344 info->xencoding = wxT("*");
345 break;
346
7beba2fc
VZ
347 case wxFONTENCODING_KOI8:
348 info->xregistry = wxT("koi8");
349
5707316c 350 // we don't make distinction between koi8-r, koi8-u and koi8-ru (so far)
7beba2fc
VZ
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 =
81c67e27 371 info->xencoding = wxT("*");
7beba2fc
VZ
372 break;
373
374 default:
375 // don't know how to translate this encoding into X fontspec
376 return FALSE;
377 }
378
ab5fe833 379 info->encoding = encoding;
6b0eebc5 380
7beba2fc
VZ
381 return TRUE;
382}
383
384bool 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
399wxNativeFont wxLoadQueryNearestFont(int pointSize,
400 int family,
401 int style,
402 int weight,
403 bool underlined,
404 const wxString &facename,
30764ab5
VZ
405 wxFontEncoding encoding,
406 wxString* xFontName)
7beba2fc 407{
97d3f0ee
VZ
408 if ( encoding == wxFONTENCODING_DEFAULT )
409 {
410 encoding = wxFont::GetDefaultEncoding();
411 }
412
7beba2fc
VZ
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;
97d3f0ee 417 if ( encoding == wxFONTENCODING_SYSTEM )
81c67e27
RR
418 {
419 // This will always work so we don't test to save time
420 wxGetNativeFontEncoding(wxFONTENCODING_SYSTEM, &info);
421 }
422 else
7beba2fc 423 {
81c67e27
RR
424 if ( !wxGetNativeFontEncoding(encoding, &info) ||
425 !wxTestFontEncoding(info) )
7beba2fc 426 {
1e6feb95 427#if wxUSE_FONTMAP
81c67e27 428 if ( !wxTheFontMapper->GetAltForEncoding(encoding, &info) )
1e6feb95 429#endif // wxUSE_FONTMAP
81c67e27
RR
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 }
97d3f0ee 438 }
7beba2fc 439 }
6c49baf2 440
81c67e27 441 // OK, we have the correct xregistry/xencoding in info structure
30764ab5
VZ
442 wxNativeFont font = 0;
443
444 // if we already have the X font name, try to use it
445 if( xFontName && !xFontName->IsEmpty() )
6c49baf2
VZ
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 }
30764ab5 468
f139dfe8 469 // try to load exactly the font requested first
30764ab5 470 if( !font )
f139dfe8 471 {
30764ab5 472 font = wxLoadQueryFont( pointSize, family, style, weight,
f139dfe8 473 underlined, facename,
30764ab5
VZ
474 info.xregistry, info.xencoding,
475 xFontName );
f139dfe8 476 }
7beba2fc
VZ
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,
30764ab5
VZ
490 facename, info.xregistry, info.xencoding,
491 xFontName);
7beba2fc
VZ
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,
30764ab5
VZ
498 facename, info.xregistry, info.xencoding,
499 xFontName);
7beba2fc
VZ
500 }
501
502 // Try default family
503 if ( !font && family != wxDEFAULT )
504 {
505 font = wxLoadQueryFont(pointSize, wxDEFAULT, style, weight,
506 underlined, facename,
30764ab5
VZ
507 info.xregistry, info.xencoding,
508 xFontName );
7beba2fc
VZ
509 }
510
f139dfe8
VZ
511 // ignore size, family, style and weight but try to find font with the
512 // given facename and encoding
7beba2fc
VZ
513 if ( !font )
514 {
515 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL,
516 underlined, facename,
30764ab5
VZ
517 info.xregistry, info.xencoding,
518 xFontName);
7beba2fc 519
f139dfe8
VZ
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 }
7beba2fc
VZ
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
565static bool wxTestFontSpec(const wxString& fontspec)
566{
97d3f0ee
VZ
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
2e0e025e
RR
574 wxNativeFont test = (wxNativeFont) g_fontHash->Get( fontspec );
575 if (test)
576 {
2e0e025e
RR
577 return TRUE;
578 }
579
580 test = wxLoadFont(fontspec);
581 g_fontHash->Put( fontspec, (wxObject*) test );
6c49baf2 582
7beba2fc
VZ
583 if ( test )
584 {
585 wxFreeFont(test);
586
587 return TRUE;
588 }
589 else
590 {
591 return FALSE;
592 }
593}
594
595static 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,
30764ab5
VZ
602 const wxString& xencoding,
603 wxString* xFontName)
7beba2fc
VZ
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 }
16d865f7 616#if wxUSE_NANOX
c2ff68d3
JS
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 }
16d865f7
JS
642 GR_SCREEN_INFO screenInfo;
643 GrGetScreenInfo(& screenInfo);
644
645 int yPixelsPerCM = screenInfo.ydpcm;
646
0a68bc69 647 // A point is 1/72 of an inch.
16d865f7 648 // An inch is 2.541 cm.
0a68bc69 649 // So pixelHeight = (pointSize / 72) (inches) * 2.541 (for cm) * yPixelsPerCM (for pixels)
c2ff68d3
JS
650 // In fact pointSize is 10 * the normal point size so
651 // divide by 10.
652
0a68bc69 653 int pixelHeight = (int) ( (((float)pointSize) / 720.0) * 2.541 * (float) yPixelsPerCM * fudgeFactor) ;
c2ff68d3
JS
654
655 // An alternative: assume that the screen is 72 dpi.
0a68bc69
JS
656 //int pixelHeight = (int) (((float)pointSize / 720.0) * 72.0) ;
657 //int pixelHeight = (int) ((float)pointSize / 10.0) ;
16d865f7
JS
658
659 GR_LOGFONT logFont;
660 logFont.lfHeight = pixelHeight;
661 logFont.lfWidth = 0;
662 logFont.lfEscapement = 0;
663 logFont.lfOrientation = 0;
c2ff68d3 664 logFont.lfWeight = xweight;
16d865f7
JS
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
7beba2fc
VZ
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 {
f9dbf34f
VZ
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;
7beba2fc
VZ
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
f139dfe8
VZ
842 // if pointSize is -1, don't specify any
843 wxString sizeSpec;
844 if ( fontSpec == -1 )
845 {
846 sizeSpec = _T('*');
847 }
848 else
849 {
850 sizeSpec.Printf(_T("%d"), pointSize);
851 }
852
7beba2fc 853 // construct the X font spec from our data
f139dfe8 854 fontSpec.Printf(wxT("-*-%s-%s-%s-normal-*-*-%s-*-*-*-*-%s-%s"),
7beba2fc 855 xfamily.c_str(), xweight.c_str(), xstyle.c_str(),
f139dfe8 856 sizeSpec.c_str(), xregistry.c_str(), xencoding.c_str());
7beba2fc 857
30764ab5
VZ
858 if( xFontName )
859 *xFontName = fontSpec;
860
7beba2fc 861 return wxLoadFont(fontSpec);
16d865f7
JS
862#endif
863 // wxUSE_NANOX
7beba2fc
VZ
864}
865
2e0e025e
RR
866// ----------------------------------------------------------------------------
867// wxFontModule
868// ----------------------------------------------------------------------------
869
870class wxFontModule : public wxModule
871{
872public:
873 bool OnInit();
874 void OnExit();
875
876private:
877 DECLARE_DYNAMIC_CLASS(wxFontModule)
878};
879
880IMPLEMENT_DYNAMIC_CLASS(wxFontModule, wxModule)
881
882bool wxFontModule::OnInit()
883{
884 g_fontHash = new wxHashTable( wxKEY_STRING );
885
886 return TRUE;
887}
888
889void wxFontModule::OnExit()
890{
891 delete g_fontHash;
892
893 g_fontHash = (wxHashTable *)NULL;
894}