]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/font.cpp
Added distribution script
[wxWidgets.git] / src / gtk1 / font.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: font.cpp
3// Purpose:
4// Author: Robert Roebling
a81258be 5// Id: $Id$
c801d85f 6// Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8bbe427f 7// Licence: wxWindows licence
c801d85f
KB
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "font.h"
12#endif
13
14#include "wx/font.h"
15#include "wx/utils.h"
5705323e 16#include "wx/log.h"
c801d85f
KB
17#include <strings.h>
18
83624f79
RR
19#include "gdk/gdk.h"
20
c801d85f
KB
21//-----------------------------------------------------------------------------
22// local data
23//-----------------------------------------------------------------------------
24
36b3b54a 25/*
a3622daa 26extern wxFontNameDirectory *wxTheFontNameDirectory;
36b3b54a 27*/
c801d85f
KB
28
29//-----------------------------------------------------------------------------
30// wxFont
31//-----------------------------------------------------------------------------
32
33class wxFontRefData: public wxObjectRefData
34{
8bbe427f
VZ
35public:
36
37 wxFontRefData();
358fc25c 38 wxFontRefData( const wxFontRefData& data );
8bbe427f
VZ
39 ~wxFontRefData();
40
358fc25c
RR
41 wxList m_scaled_xfonts;
42 int m_pointSize;
43 int m_family, m_style, m_weight;
44 bool m_underlined;
358fc25c 45 wxString m_faceName;
8bbe427f 46
358fc25c
RR
47 bool m_byXFontName;
48 GdkFont *m_font;
8bbe427f 49
c801d85f
KB
50 friend wxFont;
51};
52
8bbe427f
VZ
53wxFontRefData::wxFontRefData() : m_scaled_xfonts(wxKEY_INTEGER)
54{
55 m_byXFontName = FALSE;
56 m_pointSize = 12;
57 m_family = wxSWISS;
58 m_style = wxNORMAL;
59 m_weight = wxNORMAL;
60 m_underlined = FALSE;
8bbe427f
VZ
61 m_font = (GdkFont *) NULL;
62}
63
358fc25c
RR
64wxFontRefData::wxFontRefData( const wxFontRefData& data ) : m_scaled_xfonts(wxKEY_INTEGER)
65{
66 m_byXFontName = FALSE;
67 m_pointSize = data.m_pointSize;
68 m_family = data.m_family;
69 m_style = data.m_style;
70 m_weight = data.m_weight;
71 m_underlined = data.m_underlined;
358fc25c
RR
72 m_faceName = data.m_faceName;
73 m_font = (GdkFont *) NULL;
74 if (data.m_font) m_font = gdk_font_ref( data.m_font );
75}
76
8bbe427f
VZ
77wxFontRefData::~wxFontRefData()
78{
79 wxNode *node = m_scaled_xfonts.First();
80 while (node)
81 {
82 GdkFont *font = (GdkFont*)node->Data();
83 wxNode *next = node->Next();
84 gdk_font_unref( font );
85 node = next;
86 }
8bbe427f 87 if (m_font) gdk_font_unref( m_font );
ff7b1510 88}
c801d85f
KB
89
90//-----------------------------------------------------------------------------
91
92#define M_FONTDATA ((wxFontRefData *)m_refData)
93
94IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
95
8bbe427f 96wxFont::wxFont()
c801d85f 97{
8bbe427f 98 if (wxTheFontList) wxTheFontList->Append( this );
ff7b1510 99}
c801d85f
KB
100
101wxFont::wxFont( char *xFontName )
102{
8bbe427f
VZ
103 if (!xFontName) return;
104
105 m_refData = new wxFontRefData();
106
107 M_FONTDATA->m_byXFontName = TRUE;
108 M_FONTDATA->m_font = gdk_font_load( xFontName );
ff7b1510 109}
c801d85f 110
358fc25c
RR
111wxFont::wxFont( int pointSize, int family, int style, int weight, bool underlined = FALSE,
112 const wxString& face = wxEmptyString )
8bbe427f
VZ
113{
114 m_refData = new wxFontRefData();
115
36b3b54a
RR
116 if (family == wxDEFAULT)
117 M_FONTDATA->m_family = wxSWISS;
8bbe427f 118 else
36b3b54a
RR
119 M_FONTDATA->m_family = family;
120
121 if (!face.IsEmpty()) M_FONTDATA->m_faceName = face;
8bbe427f 122
36b3b54a
RR
123 if (style == wxDEFAULT)
124 M_FONTDATA->m_style = wxNORMAL;
125 else
126 M_FONTDATA->m_style = style;
127
128 if (weight == wxDEFAULT)
129 M_FONTDATA->m_weight = wxNORMAL;
130 else
131 M_FONTDATA->m_weight = weight;
132
133 if (pointSize == wxDEFAULT)
134 M_FONTDATA->m_pointSize = 12;
135 else
136 M_FONTDATA->m_pointSize = pointSize;
137
358fc25c 138 M_FONTDATA->m_underlined = underlined;
8bbe427f
VZ
139
140 if (wxTheFontList) wxTheFontList->Append( this );
358fc25c 141
ff7b1510 142}
c801d85f 143
8bbe427f
VZ
144wxFont::wxFont( const wxFont& font )
145{
146 Ref( font );
147
148 if (wxTheFontList) wxTheFontList->Append( this );
ff7b1510 149}
c801d85f 150
8bbe427f 151wxFont::~wxFont()
c801d85f 152{
8bbe427f 153 if (wxTheFontList) wxTheFontList->DeleteObject( this );
ff7b1510 154}
c801d85f 155
8bbe427f
VZ
156wxFont& wxFont::operator = ( const wxFont& font )
157{
158 if (*this == font) return (*this);
159 Ref( font );
160 return *this;
ff7b1510 161}
c801d85f 162
8bbe427f
VZ
163bool wxFont::operator == ( const wxFont& font )
164{
165 return m_refData == font.m_refData;
ff7b1510 166}
c801d85f 167
8bbe427f
VZ
168bool wxFont::operator != ( const wxFont& font )
169{
170 return m_refData != font.m_refData;
ff7b1510 171}
c801d85f 172
d84eb083 173bool wxFont::Ok() const
c801d85f 174{
8bbe427f 175 return (m_refData != NULL);
ff7b1510 176}
c801d85f 177
8bbe427f 178int wxFont::GetPointSize() const
c801d85f 179{
1ecc4d80 180 wxCHECK_MSG( Ok(), 0, "invalid font" );
8bbe427f
VZ
181
182 return M_FONTDATA->m_pointSize;
ff7b1510 183}
c801d85f 184
8bbe427f 185wxString wxFont::GetFaceName() const
c801d85f 186{
1ecc4d80 187 wxCHECK_MSG( Ok(), "", "invalid font" );
8bbe427f 188
36b3b54a 189 return M_FONTDATA->m_faceName;
ff7b1510 190}
c801d85f 191
8bbe427f 192int wxFont::GetFamily() const
c801d85f 193{
1ecc4d80 194 wxCHECK_MSG( Ok(), 0, "invalid font" );
8bbe427f
VZ
195
196 return M_FONTDATA->m_family;
ff7b1510 197}
c801d85f 198
8bbe427f 199wxString wxFont::GetFamilyString() const
c801d85f 200{
1ecc4d80 201 wxCHECK_MSG( Ok(), "wxDEFAULT", "invalid font" );
8bbe427f
VZ
202
203 switch (M_FONTDATA->m_family)
204 {
205 case wxDECORATIVE: return wxString("wxDECORATIVE");
206 case wxROMAN: return wxString("wxROMAN");
207 case wxSCRIPT: return wxString("wxSCRIPT");
208 case wxSWISS: return wxString("wxSWISS");
209 case wxMODERN: return wxString("wxMODERN");
210 case wxTELETYPE: return wxString("wxTELETYPE");
211 default: return "wxDEFAULT";
212 }
213
e55ad60e 214 return "wxDEFAULT";
ff7b1510 215}
c801d85f 216
8bbe427f 217int wxFont::GetStyle() const
c801d85f 218{
1ecc4d80 219 wxCHECK_MSG( Ok(), 0, "invalid font" );
d84eb083 220
8bbe427f 221 return M_FONTDATA->m_style;
ff7b1510 222}
c801d85f 223
8bbe427f 224wxString wxFont::GetStyleString() const
c801d85f 225{
1ecc4d80 226 wxCHECK_MSG( Ok(), "wxDEFAULT", "invalid font" );
8bbe427f
VZ
227
228 switch (M_FONTDATA->m_style)
229 {
230 case wxNORMAL: return wxString("wxNORMAL");
231 case wxSLANT: return wxString("wxSLANT");
232 case wxITALIC: return wxString("wxITALIC");
233 default: return wxString("wxDEFAULT");
234 }
d84eb083 235
8bbe427f 236 return wxString("wxDEFAULT");
ff7b1510 237}
c801d85f 238
8bbe427f 239int wxFont::GetWeight() const
c801d85f 240{
1ecc4d80 241 wxCHECK_MSG( Ok(), 0, "invalid font" );
8bbe427f
VZ
242
243 return M_FONTDATA->m_weight;
244}
245
246wxString wxFont::GetWeightString() const
247{
1ecc4d80 248 wxCHECK_MSG( Ok(), "wxDEFAULT", "invalid font" );
8bbe427f
VZ
249
250 switch (M_FONTDATA->m_weight)
251 {
252 case wxNORMAL: return wxString("wxNORMAL");
253 case wxBOLD: return wxString("wxBOLD");
254 case wxLIGHT: return wxString("wxLIGHT");
255 default: return wxString("wxDEFAULT");
256 }
257
258 return wxString("wxDEFAULT");
259}
260
261bool wxFont::GetUnderlined() const
262{
1ecc4d80 263 wxCHECK_MSG( Ok(), FALSE, "invalid font" );
8bbe427f
VZ
264
265 return M_FONTDATA->m_underlined;
ff7b1510 266}
c801d85f 267
358fc25c
RR
268void wxFont::Unshare()
269{
270 if (!m_refData)
271 {
272 m_refData = new wxFontRefData();
273 }
274 else
275 {
276 wxFontRefData* ref = new wxFontRefData(*(wxFontRefData*)m_refData);
277 UnRef();
278 m_refData = ref;
279 }
280}
281
282void wxFont::SetPointSize(int pointSize)
283{
284 Unshare();
285
286 M_FONTDATA->m_pointSize = pointSize;
287}
288
289void wxFont::SetFamily(int family)
290{
291 Unshare();
292
293 M_FONTDATA->m_family = family;
294}
295
296void wxFont::SetStyle(int style)
297{
298 Unshare();
299
300 M_FONTDATA->m_style = style;
301}
302
303void wxFont::SetWeight(int weight)
304{
305 Unshare();
306
307 M_FONTDATA->m_weight = weight;
308}
309
310void wxFont::SetFaceName(const wxString& faceName)
311{
312 Unshare();
313
314 M_FONTDATA->m_faceName = faceName;
315}
316
317void wxFont::SetUnderlined(bool underlined)
318{
319 Unshare();
320
321 M_FONTDATA->m_underlined = underlined;
322}
323
c801d85f
KB
324//-----------------------------------------------------------------------------
325// get internal representation of font
326//-----------------------------------------------------------------------------
327
36b3b54a
RR
328static GdkFont *wxLoadQueryNearestFont( int point_size, int family, int style, int weight,
329 bool underlined, const wxString &facename );
c801d85f 330
36b3b54a 331GdkFont *wxFont::GetInternalFont( float scale ) const
c801d85f 332{
8bbe427f
VZ
333 if (!Ok())
334 {
335 wxFAIL_MSG( "invalid font" );
336 return (GdkFont*) NULL;
337 }
338
36b3b54a 339 /* short cut if the special X font constructor has been used */
8bbe427f
VZ
340 if (M_FONTDATA->m_byXFontName) return M_FONTDATA->m_font;
341
36b3b54a 342 long int_scale = long(scale * 100.0 + 0.5); /* key for fontlist */
8bbe427f
VZ
343 int point_scale = (M_FONTDATA->m_pointSize * 10 * int_scale) / 100;
344 GdkFont *font = (GdkFont *) NULL;
345
346 wxNode *node = M_FONTDATA->m_scaled_xfonts.Find(int_scale);
347 if (node)
348 {
349 font = (GdkFont*)node->Data();
350 }
351 else
352 {
36b3b54a 353/*
8bbe427f
VZ
354 if ((int_scale == 100) &&
355 (M_FONTDATA->m_family == wxSWISS) &&
356 (M_FONTDATA->m_style == wxNORMAL) &&
357 (M_FONTDATA->m_pointSize == 12) &&
358 (M_FONTDATA->m_weight == wxNORMAL) &&
359 (M_FONTDATA->m_underlined == FALSE))
360 {
361 font = gdk_font_load( "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*" );
362 }
363 else
36b3b54a 364*/
8bbe427f 365 {
36b3b54a
RR
366 font = wxLoadQueryNearestFont( point_scale, M_FONTDATA->m_family, M_FONTDATA->m_style,
367 M_FONTDATA->m_weight, M_FONTDATA->m_underlined, M_FONTDATA->m_faceName );
8bbe427f
VZ
368 }
369 M_FONTDATA->m_scaled_xfonts.Append( int_scale, (wxObject*)font );
370 }
36b3b54a 371
8bbe427f 372 if (!font)
36b3b54a 373 {
5705323e 374 wxLogError("could not load any font");
36b3b54a 375 }
5705323e 376
8bbe427f 377 return font;
ff7b1510 378}
c801d85f
KB
379
380//-----------------------------------------------------------------------------
381// local utilities to find a X font
382//-----------------------------------------------------------------------------
383
36b3b54a
RR
384static GdkFont*wxLoadQueryFont( int pointSize, int family, int style, int weight,
385 bool underlined, const wxString &facename )
c801d85f 386{
36b3b54a
RR
387 char *xfamily = (char*) NULL;
388 char *xstyle = (char*) NULL;
389 char *xweight = (char*) NULL;
390
391 switch (family)
392 {
393 case wxDECORATIVE: xfamily = "lucida"; break;
394 case wxROMAN: xfamily = "times"; break;
395 case wxMODERN: xfamily = "courier"; break;
396 case wxSWISS: xfamily = "helvetica"; break;
397 case wxTELETYPE: xfamily = "lucidatypewriter"; break;
398 case wxSCRIPT: xfamily = "utopia"; break;
399 default: xfamily = "*";
400 }
401
402 if (!facename.IsEmpty())
403 {
404 sprintf( wxBuffer, "-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*", facename.c_str() );
405 GdkFont *test = gdk_font_load( wxBuffer );
406 if (test)
407 {
408 gdk_font_unref( test );
409 xfamily = WXSTRINGCAST facename;
410 }
411 }
412
413 switch (style)
414 {
415 case wxITALIC: xstyle = "i"; break;
416 case wxSLANT: xstyle = "o"; break;
417 case wxNORMAL: xstyle = "r"; break;
418 default: xstyle = "*"; break;
419 }
420 switch (weight)
421 {
422 case wxBOLD: xweight = "bold"; break;
423 case wxLIGHT:
424 case wxNORMAL: xweight = "medium"; break;
425 default: xweight = "*"; break;
426 }
427
428 sprintf( wxBuffer, "-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*",
429 xfamily, xweight, xstyle, pointSize);
430
431 return gdk_font_load( wxBuffer );
c801d85f
KB
432}
433
36b3b54a
RR
434static GdkFont *wxLoadQueryNearestFont( int point_size, int family, int style, int weight,
435 bool underlined, const wxString &facename )
c801d85f 436{
36b3b54a 437 GdkFont *font = wxLoadQueryFont( point_size, family, style, weight, underlined, facename );
c801d85f 438
36b3b54a
RR
439 if (!font)
440 {
441 /* search up and down by stepsize 10 */
8bbe427f
VZ
442 int max_size = point_size + 20 * (1 + (point_size/180));
443 int min_size = point_size - 20 * (1 + (point_size/180));
36b3b54a
RR
444
445 /* Search for smaller size (approx.) */
446 for (int i=point_size-10; !font && i >= 10 && i >= min_size; i -= 10)
447 font = wxLoadQueryFont(i, family, style, weight, underlined, facename );
448
449 /* Search for larger size (approx.) */
450 for (int i=point_size+10; !font && i <= max_size; i += 10)
451 font = wxLoadQueryFont( i, family, style, weight, underlined, facename );
452
453 /* Try default family */
454 if (!font && family != wxDEFAULT)
455 font = wxLoadQueryFont( point_size, wxDEFAULT, style, weight, underlined, facename );
456
457 /* Bogus font */
8bbe427f 458 if (!font)
36b3b54a 459 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL, underlined, facename );
c801d85f 460 }
36b3b54a 461
c801d85f
KB
462 return font;
463}
464
36b3b54a
RR
465/*
466
c801d85f
KB
467//-----------------------------------------------------------------------------
468// face names and index functions
469//-----------------------------------------------------------------------------
470
471static char *font_defaults[] = {
472 "FamilyDefault", "Default",
473 "FamilyRoman", "Roman",
474 "FamilyDecorative", "Decorative",
475 "FamilyModern", "Modern",
476 "FamilyTeletype", "Teletype",
477 "FamilySwiss", "Swiss",
478 "FamilyScript", "Script",
479
480 "AfmMedium", "",
481 "AfmBold", "Bo",
482 "AfmLight", "",
483 "AfmStraight", "",
484 "AfmItalic", "${AfmSlant}",
485 "AfmSlant", "O",
486 "AfmRoman", "Ro",
487 "AfmTimes", "Times",
488 "AfmHelvetica", "Helv",
489 "AfmCourier", "Cour",
8bbe427f 490
c801d85f
KB
491 "Afm___", "${AfmTimes,$[weight],$[style]}",
492
493 "AfmTimes__", "${AfmTimes}${Afm$[weight]}${Afm$[style]}",
494 "AfmTimesMediumStraight", "${AfmTimes}${AfmRoman}",
495 "AfmTimesLightStraight", "${AfmTimes}${AfmRoman}",
496 "AfmTimes_Italic", "${AfmTimes}$[weight]${AfmItalic}",
497 "AfmTimes_Slant", "${AfmTimes}$[weight]${AfmItalic}",
498
499 "AfmSwiss__", "${AfmHelvetica}${Afm$[weight]}${Afm$[style]}",
500 "AfmModern__", "${AfmCourier}${Afm$[weight]}${Afm$[style]}",
501
502 "AfmTeletype__", "${AfmModern,$[weight],$[style]}",
503
504 "PostScriptMediumStraight", "",
505 "PostScriptMediumItalic", "-Oblique",
506 "PostScriptMediumSlant", "-Oblique",
507 "PostScriptLightStraight", "",
508 "PostScriptLightItalic", "-Oblique",
509 "PostScriptLightSlant", "-Oblique",
510 "PostScriptBoldStraight", "-Bold",
511 "PostScriptBoldItalic", "-BoldOblique",
512 "PostScriptBoldSlant", "-BoldOblique",
8bbe427f 513
c801d85f
KB
514#if WX_NORMALIZED_PS_FONTS
515 "PostScript___", "${PostScriptTimes,$[weight],$[style]}",
516#else
517 "PostScriptRoman__", "${PostScriptTimes,$[weight],$[style]}",
518 "PostScript___", "LucidaSans${PostScript$[weight]$[style]}",
519#endif
520
521 "PostScriptTimesMedium", "",
522 "PostScriptTimesLight", "",
523 "PostScriptTimesBold", "Bold",
524
525 "PostScriptTimes__", "Times${PostScript$[weight]$[style]}",
526 "PostScriptTimesMediumStraight", "Times-Roman",
527 "PostScriptTimesLightStraight", "Times-Roman",
528 "PostScriptTimes_Slant", "Times-${PostScriptTimes$[weight]}Italic",
529 "PostScriptTimes_Italic", "Times-${PostScriptTimes$[weight]}Italic",
530
531 "PostScriptSwiss__", "Helvetica${PostScript$[weight]$[style]}",
532 "PostScriptModern__", "Courier${PostScript$[weight]$[style]}",
533
534 "PostScriptTeletype__", "${PostScriptModern,$[weight],$[style]}",
535
536#if !WX_NORMALIZED_PS_FONTS
537 "PostScriptScript__", "Zapf-Chancery-MediumItalic",
538#endif
539
540 "ScreenMedium", "medium",
541 "ScreenBold", "bold",
542 "ScreenLight", "light",
543 "ScreenStraight", "r",
544 "ScreenItalic", "i",
545 "ScreenSlant", "o",
546
b1c71cd0
RR
547 "ScreenDefaultBase", "*-times",
548
c801d85f
KB
549 "ScreenRomanBase", "*-times",
550 "ScreenDecorativeBase", "*-helvetica",
551 "ScreenModernBase", "*-courier",
552 "ScreenTeletypeBase", "*-lucidatypewriter",
553 "ScreenSwissBase", "*-lucida",
554 "ScreenScriptBase", "*-zapfchancery",
555
556 "ScreenStdSuffix", "-${Screen$[weight]}-${Screen$[style]}"
8bbe427f 557 "-normal-*-*-%d-*-*-*-*-*-*",
c801d85f
KB
558
559 "Screen___",
560 "-${ScreenDefaultBase}${ScreenStdSuffix}",
561 "ScreenRoman__",
562 "-${ScreenRomanBase}${ScreenStdSuffix}",
563 "ScreenDecorative__",
564 "-${ScreenDecorativeBase}${ScreenStdSuffix}",
565 "ScreenModern__",
566 "-${ScreenModernBase}${ScreenStdSuffix}",
567 "ScreenTeletype__",
568 "-${ScreenTeletypeBase}${ScreenStdSuffix}",
569 "ScreenSwiss__",
570 "-${ScreenSwissBase}${ScreenStdSuffix}",
571 "ScreenScript__",
572 "-${ScreenScriptBase}${ScreenStdSuffix}",
c67daf87 573 (char *) NULL
c801d85f
KB
574};
575
576enum {wxWEIGHT_NORMAL, wxWEIGHT_BOLD, wxWEIGHT_LIGHT, wxNUM_WEIGHTS};
577enum {wxSTYLE_NORMAL, wxSTYLE_ITALIC, wxSTYLE_SLANT, wxNUM_STYLES};
578
579static int WCoordinate(int w)
580{
5705323e
RR
581 switch (w)
582 {
8bbe427f
VZ
583 case wxBOLD: return wxWEIGHT_BOLD;
584 case wxLIGHT: return wxWEIGHT_LIGHT;
585 case wxNORMAL:
586 default: return wxWEIGHT_NORMAL;
c801d85f 587 }
ff7b1510 588};
c801d85f
KB
589
590static int SCoordinate(int s)
591{
5705323e
RR
592 switch (s)
593 {
8bbe427f
VZ
594 case wxITALIC: return wxSTYLE_ITALIC;
595 case wxSLANT: return wxSTYLE_SLANT;
596 case wxNORMAL:
597 default: return wxSTYLE_NORMAL;
c801d85f 598 }
ff7b1510 599};
c801d85f
KB
600
601//-----------------------------------------------------------------------------
602// wxSuffixMap
603//-----------------------------------------------------------------------------
604
5705323e
RR
605class wxSuffixMap
606{
c801d85f 607public:
8bbe427f 608 ~wxSuffixMap();
c801d85f
KB
609
610 inline char *GetName(int weight, int style)
611 {
8bbe427f 612 return ( map [WCoordinate(weight)] [SCoordinate(style)] );
c801d85f
KB
613 }
614
615 char *map[wxNUM_WEIGHTS][wxNUM_STYLES];
616 void Initialize(const char *, const char *);
617};
618
c801d85f
KB
619static void SearchResource(const char *prefix, const char **names, int count, char **v)
620{
621 int k, i, j;
622 char resource[1024], **defaults, *internal;
623
624 k = 1 << count;
8bbe427f 625
c67daf87
UR
626 *v = (char *) NULL;
627 internal = (char *) NULL;
c801d85f 628
5705323e
RR
629 for (i = 0; i < k; i++)
630 {
8bbe427f 631 strcpy(resource, prefix);
5705323e
RR
632 for (j = 0; j < count; j++)
633 {
36b3b54a
RR
634 // upon failure to find a matching fontname
635 // in the default fonts above, we substitute more
636 // and more values by _ so that at last ScreenMyFontBoldNormal
637 // would turn into Screen___ and this will then get
638 // converted to -${ScreenDefaultBase}${ScreenStdSuffix}
5705323e 639
8bbe427f
VZ
640 if (!(i & (1 << j)))
641 strcat(resource, names[j]);
642 else
643 strcat(resource, "_");
644 }
5705323e 645
36b3b54a 646 // we previously search the Xt-resources here
5705323e
RR
647
648 if (!internal)
649 {
8bbe427f 650 defaults = font_defaults;
5705323e
RR
651 while (*defaults)
652 {
653 if (!strcmp(*defaults, resource))
654 {
8bbe427f
VZ
655 internal = defaults[1];
656 break;
657 }
658 defaults += 2;
659 }
660 }
c801d85f 661 }
5705323e 662
c801d85f 663 if (internal)
5705323e 664 {
b1c71cd0
RR
665 if ((strcmp(internal,"-${ScreenDefaultBase}${ScreenStdSuffix}") == 0) &&
666 (strcmp(names[0], "Default") != 0))
5705323e 667 {
36b3b54a
RR
668 // we did not find any font name in the standard list.
669 // this can (hopefully does) mean that someone supplied
670 // the facename in the wxFont constructor so we insert
671 // it here
5705323e 672
36b3b54a
RR
673 strcpy( resource,"-*-" ); // any producer
674 strcat( resource, names[0] ); // facename
675 strcat( resource, "${ScreenStdSuffix}" ); // add size params later on
5705323e
RR
676 *v = copystring(resource);
677 }
678 else
679 {
680 *v = copystring(internal);
681 }
682 }
c801d85f
KB
683}
684
8bbe427f 685wxSuffixMap::~wxSuffixMap()
c801d85f
KB
686{
687 int k, j;
688
689 for (k = 0; k < wxNUM_WEIGHTS; ++k)
8bbe427f 690 for (j = 0; j < wxNUM_STYLES; ++j)
5705323e
RR
691 if (map[k][j])
692 {
8bbe427f
VZ
693 delete[] map[k][j];
694 map[k][j] = (char *) NULL;
695 }
c801d85f
KB
696}
697
698void wxSuffixMap::Initialize(const char *resname, const char *devresname)
699{
700 const char *weight, *style;
701 char *v;
702 int i, j, k;
703 const char *names[3];
704
5705323e
RR
705 for (k = 0; k < wxNUM_WEIGHTS; k++)
706 {
707 switch (k)
708 {
8bbe427f
VZ
709 case wxWEIGHT_NORMAL: weight = "Medium"; break;
710 case wxWEIGHT_LIGHT: weight = "Light"; break;
711 case wxWEIGHT_BOLD:
5705323e 712 default: weight = "Bold";
8bbe427f 713 }
5705323e
RR
714 for (j = 0; j < wxNUM_STYLES; j++)
715 {
716 switch (j)
717 {
8bbe427f
VZ
718 case wxSTYLE_NORMAL: style = "Straight"; break;
719 case wxSTYLE_ITALIC: style = "Italic"; break;
720 case wxSTYLE_SLANT:
721 default: style = "Slant";
722 }
723 names[0] = resname;
724 names[1] = weight;
725 names[2] = style;
726
727 SearchResource(devresname, names, 3, &v);
5705323e 728
36b3b54a 729 // Expand macros in the found string:
8bbe427f
VZ
730found:
731 int len, closer = 0, startpos = 0;
732
733 len = (v ? strlen(v) : 0);
5705323e
RR
734 for (i = 0; i < len; i++)
735 {
736 if (v[i] == '$' && ((v[i+1] == '[') || (v[i+1] == '{')))
737 {
8bbe427f
VZ
738 startpos = i;
739 closer = (v[i+1] == '[') ? ']' : '}';
740 ++i;
5705323e
RR
741 }
742 else if (v[i] == closer)
743 {
8bbe427f
VZ
744 int newstrlen;
745 const char *r = (char *) NULL; bool delete_r = FALSE;
746 char *name;
747
748 name = v + startpos + 2;
749 v[i] = 0;
750
5705323e
RR
751 if (closer == '}')
752 {
8bbe427f
VZ
753 int i, count, len;
754 char **names;
755
756 for (i = 0, count = 1; name[i]; i++)
757 if (name[i] == ',')
758 count++;
759
760 len = i;
761
762 names = new char*[count];
763 names[0] = name;
764 for (i = 0, count = 1; i < len; i++)
5705323e
RR
765 if (name[i] == ',')
766 {
8bbe427f
VZ
767 names[count++] = name + i + 1;
768 name[i] = 0;
769 }
770
771 SearchResource("", (const char **)names, count, (char **)&r);
772 delete_r = (r != 0);
773 delete[] names;
774
5705323e
RR
775 if (!r)
776 {
8bbe427f
VZ
777 for (i = 0; i < len; i++)
778 if (!name[i])
779 name[i] = ',';
780 r = "";
5705323e 781 wxLogError( "Bad resource name in font lookup." );
8bbe427f
VZ
782 }
783 } else if (!strcmp(name, "weight")) {
784 r = weight;
785 } else if (!strcmp(name, "style")) {
786 r = style;
787 } else if (!strcmp(name, "family")) {
788 r = resname;
789 } else {
790 r = "";
5705323e 791 wxLogError( "Bad font macro name." );
8bbe427f
VZ
792 }
793
794 // add r to v
795 newstrlen = strlen(r);
796 char *naya = new char[startpos + newstrlen + len - i];
797 memcpy(naya, v, startpos);
798 memcpy(naya + startpos, r, newstrlen);
799 memcpy(naya + startpos + newstrlen, v + i + 1, len - i);
800 if (delete_r)
801 delete[] (char*)r;
802 delete[] v;
803 v = naya;
804
805 goto found;
806 }
807 }
36b3b54a 808 // We have a final value:
8bbe427f
VZ
809 map[k][j] = v;
810 }
c801d85f
KB
811 }
812}
813
814//-----------------------------------------------------------------------------
815// wxFontNameItem
816//-----------------------------------------------------------------------------
817
358fc25c
RR
818class wxFontNameItem : public wxObject
819{
8bbe427f 820 DECLARE_DYNAMIC_CLASS(wxFontNameItem)
c801d85f 821public:
8bbe427f
VZ
822 wxFontNameItem(const char *name, int id, int family);
823 ~wxFontNameItem();
824
825 inline char* GetScreenName(int w, int s) {return screen.GetName(w, s);}
826 inline char* GetPostScriptName(int w, int s) {return printing.GetName(w, s);}
827 inline char* GetAFMName(int w, int s) {return afm.GetName(w, s);}
828 inline char* GetName() {return name;}
829 inline int GetFamily() {return family;}
830 inline int GetId() {return id;}
831 inline bool IsRoman() {return isroman;}
ea57084d 832#if defined(__WXDEBUG__)
8bbe427f 833 void Dump(ostream& str);
c801d85f
KB
834#endif
835
8bbe427f
VZ
836 int id;
837 int family;
838 char *name;
839 wxSuffixMap screen, printing, afm;
840 bool isroman;
c801d85f
KB
841};
842
843IMPLEMENT_ABSTRACT_CLASS(wxFontNameItem, wxObject)
844
845wxFontNameItem::wxFontNameItem(const char *Name, int Id, int Family)
846{
847 name = copystring(Name);
848 id = Id;
849 family = Family;
850
851 screen. Initialize(name, "Screen");
852 printing.Initialize(name, "PostScript");
853 afm. Initialize(name, "Afm");
854}
855
8bbe427f 856wxFontNameItem::~wxFontNameItem()
c801d85f
KB
857{
858 if (name)
8bbe427f 859 delete[] name;
c67daf87 860 name = (char *) NULL;
c801d85f
KB
861}
862
ea57084d 863#if defined(__WXDEBUG__)
c801d85f
KB
864void wxFontNameItem::Dump(ostream& str)
865{
866 str << "wxFontNameItem(" << name << ")";
867}
868#endif
869
870//-----------------------------------------------------------------------------
871// wxFontDirectory
872//-----------------------------------------------------------------------------
873
874IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory, wxObject)
875
8bbe427f 876wxFontNameDirectory::wxFontNameDirectory()
c801d85f
KB
877{
878 table = new wxHashTable(wxKEY_INTEGER, 20);
879 nextFontId = -1;
c801d85f
KB
880}
881
882wxFontNameDirectory::~wxFontNameDirectory()
883{
884 // Cleanup wxFontNameItems allocated
885 table->BeginFind();
886 wxNode *node = table->Next();
358fc25c
RR
887 while (node)
888 {
8bbe427f
VZ
889 wxFontNameItem *item = (wxFontNameItem*)node->Data();
890 delete item;
891 node = table->Next();
c801d85f
KB
892 }
893 delete table;
894}
895
8bbe427f 896int wxFontNameDirectory::GetNewFontId()
c801d85f
KB
897{
898 return (nextFontId--);
899}
900
901void wxFontNameDirectory::Initialize()
902{
903 Initialize(wxDEFAULT, wxDEFAULT, "Default");
904 Initialize(wxDECORATIVE, wxDECORATIVE, "Decorative");
905 Initialize(wxROMAN, wxROMAN, "Roman");
906 Initialize(wxMODERN, wxMODERN, "Modern");
907 Initialize(wxTELETYPE, wxTELETYPE, "Teletype");
908 Initialize(wxSWISS, wxSWISS, "Swiss");
909 Initialize(wxSCRIPT, wxSCRIPT, "Script");
910}
911
912void wxFontNameDirectory::Initialize(int fontid, int family, const char *resname)
913{
914 char *fam, resource[256];
8bbe427f 915
c801d85f 916 sprintf(resource, "Family%s", resname);
c67daf87 917 SearchResource((const char *)resource, (const char **) NULL, 0, (char **)&fam);
5705323e 918
358fc25c
RR
919 if (fam)
920 {
8bbe427f
VZ
921 if (!strcmp(fam, "Default")) family = wxDEFAULT;
922 else if (!strcmp(fam, "Roman")) family = wxROMAN;
923 else if (!strcmp(fam, "Decorative")) family = wxDECORATIVE;
924 else if (!strcmp(fam, "Modern")) family = wxMODERN;
925 else if (!strcmp(fam, "Teletype")) family = wxTELETYPE;
926 else if (!strcmp(fam, "Swiss")) family = wxSWISS;
927 else if (!strcmp(fam, "Script")) family = wxSCRIPT;
928 delete[] fam; // free resource
c801d85f
KB
929 }
930 table->Put(fontid, new wxFontNameItem(resname, fontid, family));
931}
932
933int wxFontNameDirectory::FindOrCreateFontId(const char *name, int family)
934{
935 int id;
5705323e 936
c801d85f
KB
937 // font exists -> return id
938 if ( (id = GetFontId(name)) ) return id;
358fc25c 939
c801d85f
KB
940 // create new font
941 Initialize(id=GetNewFontId(), family, name);
942 return id;
943}
944
945char *wxFontNameDirectory::GetScreenName(int fontid, int weight, int style)
946{
947 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
948 if (item)
8bbe427f 949 return item->GetScreenName(weight, style);
358fc25c 950
c801d85f 951 // font does not exist
c67daf87 952 return (char *) NULL;
c801d85f
KB
953}
954
955char *wxFontNameDirectory::GetPostScriptName(int fontid, int weight, int style)
956{
957 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
958 if (item)
8bbe427f 959 return item->GetPostScriptName(weight, style);
358fc25c 960
c801d85f 961 // font does not exist
c67daf87 962 return (char *) NULL;
c801d85f
KB
963}
964
965char *wxFontNameDirectory::GetAFMName(int fontid, int weight, int style)
966{
967 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
968 if (item)
8bbe427f 969 return item->GetAFMName(weight, style);
c801d85f 970 // font does not exist
c67daf87 971 return (char *) NULL;
c801d85f
KB
972}
973
974char *wxFontNameDirectory::GetFontName(int fontid)
975{
976 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
977 if (item)
8bbe427f 978 return item->GetName();
358fc25c 979
c801d85f 980 // font does not exist
c67daf87 981 return (char *) NULL;
c801d85f
KB
982}
983
984int wxFontNameDirectory::GetFontId(const char *name)
985{
986 wxNode *node;
987
988 table->BeginFind();
989
358fc25c
RR
990 while ( (node = table->Next()) )
991 {
8bbe427f
VZ
992 wxFontNameItem *item = (wxFontNameItem*)node->Data();
993 if (!strcmp(name, item->name))
994 return item->id;
c801d85f 995 }
358fc25c 996
c801d85f
KB
997 // font does not exist
998 return 0;
999}
1000
1001int wxFontNameDirectory::GetFamily(int fontid)
1002{
1003 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid);
8bbe427f 1004
c801d85f 1005 if (item)
8bbe427f 1006 return item->family;
358fc25c 1007
c801d85f
KB
1008 // font does not exist
1009 return wxDEFAULT;
1010}
36b3b54a
RR
1011
1012*/