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