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