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