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