]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/font.cpp
wxGTK now chooses better font when no matching
[wxWidgets.git] / src / gtk1 / font.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: font.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Id: $Id$
6 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9
10 #ifdef __GNUG__
11 #pragma implementation "font.h"
12 #endif
13
14 #include "wx/font.h"
15 #include "wx/utils.h"
16 #include "wx/log.h"
17 #include <strings.h>
18
19 #include "gdk/gdk.h"
20
21 //-----------------------------------------------------------------------------
22 // local data
23 //-----------------------------------------------------------------------------
24
25 extern wxFontNameDirectory *wxTheFontNameDirectory;
26
27 //-----------------------------------------------------------------------------
28 // wxFont
29 //-----------------------------------------------------------------------------
30
31 class wxFontRefData: public wxObjectRefData
32 {
33 public:
34
35 wxFontRefData();
36 wxFontRefData( const wxFontRefData& data );
37 ~wxFontRefData();
38
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;
45
46 bool m_byXFontName;
47 GdkFont *m_font;
48
49 friend wxFont;
50 };
51
52 wxFontRefData::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;
61 m_font = (GdkFont *) NULL;
62 }
63
64 wxFontRefData::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
78 wxFontRefData::~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 }
88 if (m_font) gdk_font_unref( m_font );
89 }
90
91 //-----------------------------------------------------------------------------
92
93 #define M_FONTDATA ((wxFontRefData *)m_refData)
94
95 IMPLEMENT_DYNAMIC_CLASS(wxFont, wxGDIObject)
96
97 wxFont::wxFont()
98 {
99 if (wxTheFontList) wxTheFontList->Append( this );
100 }
101
102 wxFont::wxFont( char *xFontName )
103 {
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 );
110 }
111
112 wxFont::wxFont( int pointSize, int family, int style, int weight, bool underlined = FALSE,
113 const wxString& face = wxEmptyString )
114 {
115 m_refData = new wxFontRefData();
116
117 if (family == wxDEFAULT) family = wxSWISS;
118 M_FONTDATA->m_family = family;
119
120 if (!face.IsEmpty())
121 {
122 M_FONTDATA->m_faceName = face;
123 M_FONTDATA->m_fontId = wxTheFontNameDirectory->FindOrCreateFontId( face, family );
124 M_FONTDATA->m_family = wxTheFontNameDirectory->GetFamily( family );
125 }
126 else
127 {
128 M_FONTDATA->m_fontId = family;
129 M_FONTDATA->m_family = wxTheFontNameDirectory->GetFamily( family );
130 }
131
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;
139
140 if (wxTheFontList) wxTheFontList->Append( this );
141
142 }
143
144 wxFont::wxFont( const wxFont& font )
145 {
146 Ref( font );
147
148 if (wxTheFontList) wxTheFontList->Append( this );
149 }
150
151 wxFont::~wxFont()
152 {
153 if (wxTheFontList) wxTheFontList->DeleteObject( this );
154 }
155
156 wxFont& wxFont::operator = ( const wxFont& font )
157 {
158 if (*this == font) return (*this);
159 Ref( font );
160 return *this;
161 }
162
163 bool wxFont::operator == ( const wxFont& font )
164 {
165 return m_refData == font.m_refData;
166 }
167
168 bool wxFont::operator != ( const wxFont& font )
169 {
170 return m_refData != font.m_refData;
171 }
172
173 bool wxFont::Ok() const
174 {
175 return (m_refData != NULL);
176 }
177
178 int wxFont::GetPointSize() const
179 {
180 wxCHECK_MSG( Ok(), 0, "invalid font" );
181
182 return M_FONTDATA->m_pointSize;
183 }
184
185 wxString wxFont::GetFaceName() const
186 {
187 wxCHECK_MSG( Ok(), "", "invalid font" );
188
189 wxString s = wxTheFontNameDirectory->GetFontName( M_FONTDATA->m_fontId );
190 return s;
191 }
192
193 int wxFont::GetFamily() const
194 {
195 wxCHECK_MSG( Ok(), 0, "invalid font" );
196
197 return M_FONTDATA->m_family;
198 }
199
200 wxString wxFont::GetFamilyString() const
201 {
202 wxCHECK_MSG( Ok(), "wxDEFAULT", "invalid font" );
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
215 return "wxDEFAULT";
216 }
217
218 int wxFont::GetFontId() const
219 {
220 wxCHECK_MSG( Ok(), 0, "invalid font" );
221
222 return M_FONTDATA->m_fontId; // stub
223 }
224
225 int wxFont::GetStyle() const
226 {
227 wxCHECK_MSG( Ok(), 0, "invalid font" );
228
229 return M_FONTDATA->m_style;
230 }
231
232 wxString wxFont::GetStyleString() const
233 {
234 wxCHECK_MSG( Ok(), "wxDEFAULT", "invalid font" );
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 }
243
244 return wxString("wxDEFAULT");
245 }
246
247 int wxFont::GetWeight() const
248 {
249 wxCHECK_MSG( Ok(), 0, "invalid font" );
250
251 return M_FONTDATA->m_weight;
252 }
253
254 wxString wxFont::GetWeightString() const
255 {
256 wxCHECK_MSG( Ok(), "wxDEFAULT", "invalid font" );
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
269 bool wxFont::GetUnderlined() const
270 {
271 wxCHECK_MSG( Ok(), FALSE, "invalid font" );
272
273 return M_FONTDATA->m_underlined;
274 }
275
276 void 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
290 void wxFont::SetPointSize(int pointSize)
291 {
292 Unshare();
293
294 M_FONTDATA->m_pointSize = pointSize;
295 }
296
297 void wxFont::SetFamily(int family)
298 {
299 Unshare();
300
301 M_FONTDATA->m_family = family;
302 }
303
304 void wxFont::SetStyle(int style)
305 {
306 Unshare();
307
308 M_FONTDATA->m_style = style;
309 }
310
311 void wxFont::SetWeight(int weight)
312 {
313 Unshare();
314
315 M_FONTDATA->m_weight = weight;
316 }
317
318 void wxFont::SetFaceName(const wxString& faceName)
319 {
320 Unshare();
321
322 M_FONTDATA->m_faceName = faceName;
323 }
324
325 void wxFont::SetUnderlined(bool underlined)
326 {
327 Unshare();
328
329 M_FONTDATA->m_underlined = underlined;
330 }
331
332 //-----------------------------------------------------------------------------
333 // get internal representation of font
334 //-----------------------------------------------------------------------------
335
336 // local help function
337 static GdkFont *wxLoadQueryNearestFont(int point_size, int fontid,
338 int style, int weight,
339 bool underlined);
340
341 GdkFont *wxFont::GetInternalFont(float scale) const
342 {
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 {
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)
379 wxLogError("could not load any font");
380
381 return font;
382 }
383
384 //-----------------------------------------------------------------------------
385 // local utilities to find a X font
386 //-----------------------------------------------------------------------------
387
388 static GdkFont *wxLoadQueryFont(int point_size, int fontid, int style,
389 int weight, bool WXUNUSED(underlined))
390 {
391 char buffer[512];
392 char *name = wxTheFontNameDirectory->GetScreenName( fontid, weight, style );
393
394 if (!name)
395 name = "-*-*-*-*-*-*-*-%d-*-*-*-*-*-*";
396 sprintf(buffer, name, point_size);
397
398 return gdk_font_load( buffer );
399 }
400
401 static GdkFont *wxLoadQueryNearestFont(int point_size, int fontid,
402 int style, int weight,
403 bool underlined)
404 {
405 GdkFont *font;
406
407 font = wxLoadQueryFont( point_size, fontid, style, weight, underlined );
408
409 if (!font) {
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);
429 }
430 return font;
431 }
432
433 //-----------------------------------------------------------------------------
434 // face names and index functions
435 //-----------------------------------------------------------------------------
436
437 static 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",
456
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",
479
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 /*
514 "ScreenDefaultBase", "misc-fixed",
515 */
516 "ScreenDefaultBase", "*-times",
517
518 "ScreenRomanBase", "*-times",
519 "ScreenDecorativeBase", "*-helvetica",
520 "ScreenModernBase", "*-courier",
521 "ScreenTeletypeBase", "*-lucidatypewriter",
522 "ScreenSwissBase", "*-lucida",
523 "ScreenScriptBase", "*-zapfchancery",
524
525 "ScreenStdSuffix", "-${Screen$[weight]}-${Screen$[style]}"
526 "-normal-*-*-%d-*-*-*-*-*-*",
527
528 "Screen___",
529 "-${ScreenDefaultBase}${ScreenStdSuffix}",
530 "ScreenRoman__",
531 "-${ScreenRomanBase}${ScreenStdSuffix}",
532 "ScreenDecorative__",
533 "-${ScreenDecorativeBase}${ScreenStdSuffix}",
534 "ScreenModern__",
535 "-${ScreenModernBase}${ScreenStdSuffix}",
536 "ScreenTeletype__",
537 "-${ScreenTeletypeBase}${ScreenStdSuffix}",
538 "ScreenSwiss__",
539 "-${ScreenSwissBase}${ScreenStdSuffix}",
540 "ScreenScript__",
541 "-${ScreenScriptBase}${ScreenStdSuffix}",
542 (char *) NULL
543 };
544
545 enum {wxWEIGHT_NORMAL, wxWEIGHT_BOLD, wxWEIGHT_LIGHT, wxNUM_WEIGHTS};
546 enum {wxSTYLE_NORMAL, wxSTYLE_ITALIC, wxSTYLE_SLANT, wxNUM_STYLES};
547
548 static int WCoordinate(int w)
549 {
550 switch (w)
551 {
552 case wxBOLD: return wxWEIGHT_BOLD;
553 case wxLIGHT: return wxWEIGHT_LIGHT;
554 case wxNORMAL:
555 default: return wxWEIGHT_NORMAL;
556 }
557 };
558
559 static int SCoordinate(int s)
560 {
561 switch (s)
562 {
563 case wxITALIC: return wxSTYLE_ITALIC;
564 case wxSLANT: return wxSTYLE_SLANT;
565 case wxNORMAL:
566 default: return wxSTYLE_NORMAL;
567 }
568 };
569
570 //-----------------------------------------------------------------------------
571 // wxSuffixMap
572 //-----------------------------------------------------------------------------
573
574 class wxSuffixMap
575 {
576 public:
577 ~wxSuffixMap();
578
579 inline char *GetName(int weight, int style)
580 {
581 return ( map [WCoordinate(weight)] [SCoordinate(style)] );
582 }
583
584 char *map[wxNUM_WEIGHTS][wxNUM_STYLES];
585 void Initialize(const char *, const char *);
586 };
587
588 static void SearchResource(const char *prefix, const char **names, int count, char **v)
589 {
590 int k, i, j;
591 char resource[1024], **defaults, *internal;
592
593 k = 1 << count;
594
595 *v = (char *) NULL;
596 internal = (char *) NULL;
597
598 for (i = 0; i < k; i++)
599 {
600 strcpy(resource, prefix);
601 for (j = 0; j < count; j++)
602 {
603 /* upon failure to find a matching fontname
604 in the default fonts above, we substitute more
605 and more values by _ so that at last ScreenMyFontBoldNormal
606 would turn into Screen___ and this will then get
607 converted to -${ScreenDefaultBase}${ScreenStdSuffix}
608 */
609
610 if (!(i & (1 << j)))
611 strcat(resource, names[j]);
612 else
613 strcat(resource, "_");
614 }
615
616 /* we previously search the Xt-resources here */
617
618 if (!internal)
619 {
620 defaults = font_defaults;
621 while (*defaults)
622 {
623 if (!strcmp(*defaults, resource))
624 {
625 internal = defaults[1];
626 break;
627 }
628 defaults += 2;
629 }
630 }
631 }
632
633 if (internal)
634 {
635 if ((strcmp(internal,"-${ScreenDefaultBase}${ScreenStdSuffix}") == 0) &&
636 (strcmp(names[0], "Default") != 0))
637 {
638 /* we did not find any font name in the standard list.
639 this can (hopefully does) mean that someone supplied
640 the facename in the wxFont constructor so we insert
641 it here */
642
643 strcpy( resource,"-*-" ); /* any producer */
644 strcat( resource, names[0] ); /* facename */
645 strcat( resource, "${ScreenStdSuffix}" ); /* add size params later on */
646 *v = copystring(resource);
647 }
648 else
649 {
650 *v = copystring(internal);
651 }
652 }
653 }
654
655 wxSuffixMap::~wxSuffixMap()
656 {
657 int k, j;
658
659 for (k = 0; k < wxNUM_WEIGHTS; ++k)
660 for (j = 0; j < wxNUM_STYLES; ++j)
661 if (map[k][j])
662 {
663 delete[] map[k][j];
664 map[k][j] = (char *) NULL;
665 }
666 }
667
668 void wxSuffixMap::Initialize(const char *resname, const char *devresname)
669 {
670 const char *weight, *style;
671 char *v;
672 int i, j, k;
673 const char *names[3];
674
675 for (k = 0; k < wxNUM_WEIGHTS; k++)
676 {
677 switch (k)
678 {
679 case wxWEIGHT_NORMAL: weight = "Medium"; break;
680 case wxWEIGHT_LIGHT: weight = "Light"; break;
681 case wxWEIGHT_BOLD:
682 default: weight = "Bold";
683 }
684 for (j = 0; j < wxNUM_STYLES; j++)
685 {
686 switch (j)
687 {
688 case wxSTYLE_NORMAL: style = "Straight"; break;
689 case wxSTYLE_ITALIC: style = "Italic"; break;
690 case wxSTYLE_SLANT:
691 default: style = "Slant";
692 }
693 names[0] = resname;
694 names[1] = weight;
695 names[2] = style;
696
697 SearchResource(devresname, names, 3, &v);
698
699 /* Expand macros in the found string: */
700 found:
701 int len, closer = 0, startpos = 0;
702
703 len = (v ? strlen(v) : 0);
704 for (i = 0; i < len; i++)
705 {
706 if (v[i] == '$' && ((v[i+1] == '[') || (v[i+1] == '{')))
707 {
708 startpos = i;
709 closer = (v[i+1] == '[') ? ']' : '}';
710 ++i;
711 }
712 else if (v[i] == closer)
713 {
714 int newstrlen;
715 const char *r = (char *) NULL; bool delete_r = FALSE;
716 char *name;
717
718 name = v + startpos + 2;
719 v[i] = 0;
720
721 if (closer == '}')
722 {
723 int i, count, len;
724 char **names;
725
726 for (i = 0, count = 1; name[i]; i++)
727 if (name[i] == ',')
728 count++;
729
730 len = i;
731
732 names = new char*[count];
733 names[0] = name;
734 for (i = 0, count = 1; i < len; i++)
735 if (name[i] == ',')
736 {
737 names[count++] = name + i + 1;
738 name[i] = 0;
739 }
740
741 SearchResource("", (const char **)names, count, (char **)&r);
742 delete_r = (r != 0);
743 delete[] names;
744
745 if (!r)
746 {
747 for (i = 0; i < len; i++)
748 if (!name[i])
749 name[i] = ',';
750 r = "";
751 wxLogError( "Bad resource name in font lookup." );
752 }
753 } else if (!strcmp(name, "weight")) {
754 r = weight;
755 } else if (!strcmp(name, "style")) {
756 r = style;
757 } else if (!strcmp(name, "family")) {
758 r = resname;
759 } else {
760 r = "";
761 wxLogError( "Bad font macro name." );
762 }
763
764 // add r to v
765 newstrlen = strlen(r);
766 char *naya = new char[startpos + newstrlen + len - i];
767 memcpy(naya, v, startpos);
768 memcpy(naya + startpos, r, newstrlen);
769 memcpy(naya + startpos + newstrlen, v + i + 1, len - i);
770 if (delete_r)
771 delete[] (char*)r;
772 delete[] v;
773 v = naya;
774
775 goto found;
776 }
777 }
778 /* We have a final value: */
779 map[k][j] = v;
780 }
781 }
782 }
783
784 //-----------------------------------------------------------------------------
785 // wxFontNameItem
786 //-----------------------------------------------------------------------------
787
788 class wxFontNameItem : public wxObject
789 {
790 DECLARE_DYNAMIC_CLASS(wxFontNameItem)
791 public:
792 wxFontNameItem(const char *name, int id, int family);
793 ~wxFontNameItem();
794
795 inline char* GetScreenName(int w, int s) {return screen.GetName(w, s);}
796 inline char* GetPostScriptName(int w, int s) {return printing.GetName(w, s);}
797 inline char* GetAFMName(int w, int s) {return afm.GetName(w, s);}
798 inline char* GetName() {return name;}
799 inline int GetFamily() {return family;}
800 inline int GetId() {return id;}
801 inline bool IsRoman() {return isroman;}
802 #if defined(__WXDEBUG__)
803 void Dump(ostream& str);
804 #endif
805
806 int id;
807 int family;
808 char *name;
809 wxSuffixMap screen, printing, afm;
810 bool isroman;
811 };
812
813 IMPLEMENT_ABSTRACT_CLASS(wxFontNameItem, wxObject)
814
815 wxFontNameItem::wxFontNameItem(const char *Name, int Id, int Family)
816 {
817 name = copystring(Name);
818 id = Id;
819 family = Family;
820
821 screen. Initialize(name, "Screen");
822 printing.Initialize(name, "PostScript");
823 afm. Initialize(name, "Afm");
824 }
825
826 wxFontNameItem::~wxFontNameItem()
827 {
828 if (name)
829 delete[] name;
830 name = (char *) NULL;
831 }
832
833 #if defined(__WXDEBUG__)
834 void wxFontNameItem::Dump(ostream& str)
835 {
836 str << "wxFontNameItem(" << name << ")";
837 }
838 #endif
839
840 //-----------------------------------------------------------------------------
841 // wxFontDirectory
842 //-----------------------------------------------------------------------------
843
844 IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory, wxObject)
845
846 wxFontNameDirectory::wxFontNameDirectory()
847 {
848 table = new wxHashTable(wxKEY_INTEGER, 20);
849 nextFontId = -1;
850 }
851
852 wxFontNameDirectory::~wxFontNameDirectory()
853 {
854 // Cleanup wxFontNameItems allocated
855 table->BeginFind();
856 wxNode *node = table->Next();
857 while (node)
858 {
859 wxFontNameItem *item = (wxFontNameItem*)node->Data();
860 delete item;
861 node = table->Next();
862 }
863 delete table;
864 }
865
866 int wxFontNameDirectory::GetNewFontId()
867 {
868 return (nextFontId--);
869 }
870
871 void wxFontNameDirectory::Initialize()
872 {
873 Initialize(wxDEFAULT, wxDEFAULT, "Default");
874 Initialize(wxDECORATIVE, wxDECORATIVE, "Decorative");
875 Initialize(wxROMAN, wxROMAN, "Roman");
876 Initialize(wxMODERN, wxMODERN, "Modern");
877 Initialize(wxTELETYPE, wxTELETYPE, "Teletype");
878 Initialize(wxSWISS, wxSWISS, "Swiss");
879 Initialize(wxSCRIPT, wxSCRIPT, "Script");
880 }
881
882 void wxFontNameDirectory::Initialize(int fontid, int family, const char *resname)
883 {
884 char *fam, resource[256];
885
886 sprintf(resource, "Family%s", resname);
887 SearchResource((const char *)resource, (const char **) NULL, 0, (char **)&fam);
888
889 if (fam)
890 {
891 if (!strcmp(fam, "Default")) family = wxDEFAULT;
892 else if (!strcmp(fam, "Roman")) family = wxROMAN;
893 else if (!strcmp(fam, "Decorative")) family = wxDECORATIVE;
894 else if (!strcmp(fam, "Modern")) family = wxMODERN;
895 else if (!strcmp(fam, "Teletype")) family = wxTELETYPE;
896 else if (!strcmp(fam, "Swiss")) family = wxSWISS;
897 else if (!strcmp(fam, "Script")) family = wxSCRIPT;
898 delete[] fam; // free resource
899 }
900 table->Put(fontid, new wxFontNameItem(resname, fontid, family));
901 }
902
903 int wxFontNameDirectory::FindOrCreateFontId(const char *name, int family)
904 {
905 int id;
906
907 // font exists -> return id
908 if ( (id = GetFontId(name)) ) return id;
909
910 // create new font
911 Initialize(id=GetNewFontId(), family, name);
912 return id;
913 }
914
915 char *wxFontNameDirectory::GetScreenName(int fontid, int weight, int style)
916 {
917 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
918 if (item)
919 return item->GetScreenName(weight, style);
920
921 // font does not exist
922 return (char *) NULL;
923 }
924
925 char *wxFontNameDirectory::GetPostScriptName(int fontid, int weight, int style)
926 {
927 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
928 if (item)
929 return item->GetPostScriptName(weight, style);
930
931 // font does not exist
932 return (char *) NULL;
933 }
934
935 char *wxFontNameDirectory::GetAFMName(int fontid, int weight, int style)
936 {
937 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
938 if (item)
939 return item->GetAFMName(weight, style);
940 // font does not exist
941 return (char *) NULL;
942 }
943
944 char *wxFontNameDirectory::GetFontName(int fontid)
945 {
946 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
947 if (item)
948 return item->GetName();
949
950 // font does not exist
951 return (char *) NULL;
952 }
953
954 int wxFontNameDirectory::GetFontId(const char *name)
955 {
956 wxNode *node;
957
958 table->BeginFind();
959
960 while ( (node = table->Next()) )
961 {
962 wxFontNameItem *item = (wxFontNameItem*)node->Data();
963 if (!strcmp(name, item->name))
964 return item->id;
965 }
966
967 // font does not exist
968 return 0;
969 }
970
971 int wxFontNameDirectory::GetFamily(int fontid)
972 {
973 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid);
974
975 if (item)
976 return item->family;
977
978 // font does not exist
979 return wxDEFAULT;
980 }