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