]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/font.cpp
Restored the ability to scroll.
[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 "wx/gdicmn.h"
18 #include <strings.h>
19
20 #include "gdk/gdk.h"
21
22 //-----------------------------------------------------------------------------
23 // local data
24 //-----------------------------------------------------------------------------
25
26 /*
27 extern wxFontNameDirectory *wxTheFontNameDirectory;
28 */
29
30 //-----------------------------------------------------------------------------
31 // wxFont
32 //-----------------------------------------------------------------------------
33
34 class wxFontRefData: public wxObjectRefData
35 {
36 public:
37
38 wxFontRefData();
39 wxFontRefData( const wxFontRefData& data );
40 ~wxFontRefData();
41
42 wxList m_scaled_xfonts;
43 int m_pointSize;
44 int m_family, m_style, m_weight;
45 bool m_underlined;
46 wxString m_faceName;
47
48 bool m_byXFontName;
49 GdkFont *m_font;
50
51 friend wxFont;
52 };
53
54 wxFontRefData::wxFontRefData() : m_scaled_xfonts(wxKEY_INTEGER)
55 {
56 m_byXFontName = FALSE;
57 m_pointSize = 12;
58 m_family = wxSWISS;
59 m_style = wxNORMAL;
60 m_weight = wxNORMAL;
61 m_underlined = FALSE;
62 m_font = (GdkFont *) NULL;
63 }
64
65 wxFontRefData::wxFontRefData( const wxFontRefData& data ) : m_scaled_xfonts(wxKEY_INTEGER)
66 {
67 m_byXFontName = FALSE;
68 m_pointSize = data.m_pointSize;
69 m_family = data.m_family;
70 m_style = data.m_style;
71 m_weight = data.m_weight;
72 m_underlined = data.m_underlined;
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, const wxString& face )
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 ) const
164 {
165 return m_refData == font.m_refData;
166 }
167
168 bool wxFont::operator != ( const wxFont& font ) const
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, _T("invalid font") );
181
182 return M_FONTDATA->m_pointSize;
183 }
184
185 wxString wxFont::GetFaceName() const
186 {
187 wxCHECK_MSG( Ok(), _T(""), _T("invalid font") );
188
189 return M_FONTDATA->m_faceName;
190 }
191
192 int wxFont::GetFamily() const
193 {
194 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
195
196 return M_FONTDATA->m_family;
197 }
198
199 wxString wxFont::GetFamilyString() const
200 {
201 wxCHECK_MSG( Ok(), _T("wxDEFAULT"), _T("invalid font") );
202
203 switch (M_FONTDATA->m_family)
204 {
205 case wxDECORATIVE: return wxString(_T("wxDECORATIVE"));
206 case wxROMAN: return wxString(_T("wxROMAN"));
207 case wxSCRIPT: return wxString(_T("wxSCRIPT"));
208 case wxSWISS: return wxString(_T("wxSWISS"));
209 case wxMODERN: return wxString(_T("wxMODERN"));
210 case wxTELETYPE: return wxString(_T("wxTELETYPE"));
211 default: return _T("wxDEFAULT");
212 }
213
214 return "wxDEFAULT";
215 }
216
217 int wxFont::GetStyle() const
218 {
219 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
220
221 return M_FONTDATA->m_style;
222 }
223
224 wxString wxFont::GetStyleString() const
225 {
226 wxCHECK_MSG( Ok(), _T("wxDEFAULT"), _T("invalid font") );
227
228 switch (M_FONTDATA->m_style)
229 {
230 case wxNORMAL: return wxString(_T("wxNORMAL"));
231 case wxSLANT: return wxString(_T("wxSLANT"));
232 case wxITALIC: return wxString(_T("wxITALIC"));
233 default: return wxString(_T("wxDEFAULT"));
234 }
235
236 return wxString(_T("wxDEFAULT"));
237 }
238
239 int wxFont::GetWeight() const
240 {
241 wxCHECK_MSG( Ok(), 0, _T("invalid font") );
242
243 return M_FONTDATA->m_weight;
244 }
245
246 wxString wxFont::GetWeightString() const
247 {
248 wxCHECK_MSG( Ok(), _T("wxDEFAULT"), _T("invalid font") );
249
250 switch (M_FONTDATA->m_weight)
251 {
252 case wxNORMAL: return wxString(_T("wxNORMAL"));
253 case wxBOLD: return wxString(_T("wxBOLD"));
254 case wxLIGHT: return wxString(_T("wxLIGHT"));
255 default: return wxString(_T("wxDEFAULT"));
256 }
257
258 return wxString(_T("wxDEFAULT"));
259 }
260
261 bool wxFont::GetUnderlined() const
262 {
263 wxCHECK_MSG( Ok(), FALSE, _T("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( _T("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(_T("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 wxChar *xfamily = (wxChar*) NULL;
388 wxChar *xstyle = (wxChar*) NULL;
389 wxChar *xweight = (wxChar*) NULL;
390
391 switch (family)
392 {
393 case wxDECORATIVE: xfamily = _T("lucida"); break;
394 case wxROMAN: xfamily = _T("times"); break;
395 case wxMODERN: xfamily = _T("courier"); break;
396 case wxSWISS: xfamily = _T("helvetica"); break;
397 case wxTELETYPE: xfamily = _T("lucidatypewriter"); break;
398 case wxSCRIPT: xfamily = _T("utopia"); break;
399 default: xfamily = _T("*");
400 }
401
402 if (!facename.IsEmpty())
403 {
404 wxSprintf( wxBuffer, _T("-*-%s-*-*-normal-*-*-*-*-*-*-*-*-*"), facename.c_str() );
405 GdkFont *test = gdk_font_load( wxConvCurrent->cWX2MB(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 = _T("i"); break;
416 case wxSLANT: xstyle = _T("o"); break;
417 case wxNORMAL: xstyle = _T("r"); break;
418 default: xstyle = _T("*"); break;
419 }
420 switch (weight)
421 {
422 case wxBOLD: xweight = _T("bold"); break;
423 case wxLIGHT:
424 case wxNORMAL: xweight = _T("medium"); break;
425 default: xweight = _T("*"); break;
426 }
427
428 wxSprintf( wxBuffer, _T("-*-%s-%s-%s-normal-*-*-%d-*-*-*-*-*-*"),
429 xfamily, xweight, xstyle, pointSize);
430
431 return gdk_font_load( wxConvCurrent->cWX2MB(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 int i;
446
447 /* Search for smaller size (approx.) */
448 for (i=point_size-10; !font && i >= 10 && i >= min_size; i -= 10)
449 font = wxLoadQueryFont(i, family, style, weight, underlined, facename );
450
451 /* Search for larger size (approx.) */
452 for (i=point_size+10; !font && i <= max_size; i += 10)
453 font = wxLoadQueryFont( i, family, style, weight, underlined, facename );
454
455 /* Try default family */
456 if (!font && family != wxDEFAULT)
457 font = wxLoadQueryFont( point_size, wxDEFAULT, style, weight, underlined, facename );
458
459 /* Bogus font */
460 if (!font)
461 font = wxLoadQueryFont(120, wxDEFAULT, wxNORMAL, wxNORMAL, underlined, facename );
462 }
463
464 return font;
465 }
466
467 /*
468
469 //-----------------------------------------------------------------------------
470 // face names and index functions
471 //-----------------------------------------------------------------------------
472
473 static char *font_defaults[] = {
474 "FamilyDefault", "Default",
475 "FamilyRoman", "Roman",
476 "FamilyDecorative", "Decorative",
477 "FamilyModern", "Modern",
478 "FamilyTeletype", "Teletype",
479 "FamilySwiss", "Swiss",
480 "FamilyScript", "Script",
481
482 "AfmMedium", "",
483 "AfmBold", "Bo",
484 "AfmLight", "",
485 "AfmStraight", "",
486 "AfmItalic", "${AfmSlant}",
487 "AfmSlant", "O",
488 "AfmRoman", "Ro",
489 "AfmTimes", "Times",
490 "AfmHelvetica", "Helv",
491 "AfmCourier", "Cour",
492
493 "Afm___", "${AfmTimes,$[weight],$[style]}",
494
495 "AfmTimes__", "${AfmTimes}${Afm$[weight]}${Afm$[style]}",
496 "AfmTimesMediumStraight", "${AfmTimes}${AfmRoman}",
497 "AfmTimesLightStraight", "${AfmTimes}${AfmRoman}",
498 "AfmTimes_Italic", "${AfmTimes}$[weight]${AfmItalic}",
499 "AfmTimes_Slant", "${AfmTimes}$[weight]${AfmItalic}",
500
501 "AfmSwiss__", "${AfmHelvetica}${Afm$[weight]}${Afm$[style]}",
502 "AfmModern__", "${AfmCourier}${Afm$[weight]}${Afm$[style]}",
503
504 "AfmTeletype__", "${AfmModern,$[weight],$[style]}",
505
506 "PostScriptMediumStraight", "",
507 "PostScriptMediumItalic", "-Oblique",
508 "PostScriptMediumSlant", "-Oblique",
509 "PostScriptLightStraight", "",
510 "PostScriptLightItalic", "-Oblique",
511 "PostScriptLightSlant", "-Oblique",
512 "PostScriptBoldStraight", "-Bold",
513 "PostScriptBoldItalic", "-BoldOblique",
514 "PostScriptBoldSlant", "-BoldOblique",
515
516 #if WX_NORMALIZED_PS_FONTS
517 "PostScript___", "${PostScriptTimes,$[weight],$[style]}",
518 #else
519 "PostScriptRoman__", "${PostScriptTimes,$[weight],$[style]}",
520 "PostScript___", "LucidaSans${PostScript$[weight]$[style]}",
521 #endif
522
523 "PostScriptTimesMedium", "",
524 "PostScriptTimesLight", "",
525 "PostScriptTimesBold", "Bold",
526
527 "PostScriptTimes__", "Times${PostScript$[weight]$[style]}",
528 "PostScriptTimesMediumStraight", "Times-Roman",
529 "PostScriptTimesLightStraight", "Times-Roman",
530 "PostScriptTimes_Slant", "Times-${PostScriptTimes$[weight]}Italic",
531 "PostScriptTimes_Italic", "Times-${PostScriptTimes$[weight]}Italic",
532
533 "PostScriptSwiss__", "Helvetica${PostScript$[weight]$[style]}",
534 "PostScriptModern__", "Courier${PostScript$[weight]$[style]}",
535
536 "PostScriptTeletype__", "${PostScriptModern,$[weight],$[style]}",
537
538 #if !WX_NORMALIZED_PS_FONTS
539 "PostScriptScript__", "Zapf-Chancery-MediumItalic",
540 #endif
541
542 "ScreenMedium", "medium",
543 "ScreenBold", "bold",
544 "ScreenLight", "light",
545 "ScreenStraight", "r",
546 "ScreenItalic", "i",
547 "ScreenSlant", "o",
548
549 "ScreenDefaultBase", "*-times",
550
551 "ScreenRomanBase", "*-times",
552 "ScreenDecorativeBase", "*-helvetica",
553 "ScreenModernBase", "*-courier",
554 "ScreenTeletypeBase", "*-lucidatypewriter",
555 "ScreenSwissBase", "*-lucida",
556 "ScreenScriptBase", "*-zapfchancery",
557
558 "ScreenStdSuffix", "-${Screen$[weight]}-${Screen$[style]}"
559 "-normal-*-*-%d-*-*-*-*-*-*",
560
561 "Screen___",
562 "-${ScreenDefaultBase}${ScreenStdSuffix}",
563 "ScreenRoman__",
564 "-${ScreenRomanBase}${ScreenStdSuffix}",
565 "ScreenDecorative__",
566 "-${ScreenDecorativeBase}${ScreenStdSuffix}",
567 "ScreenModern__",
568 "-${ScreenModernBase}${ScreenStdSuffix}",
569 "ScreenTeletype__",
570 "-${ScreenTeletypeBase}${ScreenStdSuffix}",
571 "ScreenSwiss__",
572 "-${ScreenSwissBase}${ScreenStdSuffix}",
573 "ScreenScript__",
574 "-${ScreenScriptBase}${ScreenStdSuffix}",
575 (char *) NULL
576 };
577
578 enum {wxWEIGHT_NORMAL, wxWEIGHT_BOLD, wxWEIGHT_LIGHT, wxNUM_WEIGHTS};
579 enum {wxSTYLE_NORMAL, wxSTYLE_ITALIC, wxSTYLE_SLANT, wxNUM_STYLES};
580
581 static int WCoordinate(int w)
582 {
583 switch (w)
584 {
585 case wxBOLD: return wxWEIGHT_BOLD;
586 case wxLIGHT: return wxWEIGHT_LIGHT;
587 case wxNORMAL:
588 default: return wxWEIGHT_NORMAL;
589 }
590 };
591
592 static int SCoordinate(int s)
593 {
594 switch (s)
595 {
596 case wxITALIC: return wxSTYLE_ITALIC;
597 case wxSLANT: return wxSTYLE_SLANT;
598 case wxNORMAL:
599 default: return wxSTYLE_NORMAL;
600 }
601 };
602
603 //-----------------------------------------------------------------------------
604 // wxSuffixMap
605 //-----------------------------------------------------------------------------
606
607 class wxSuffixMap
608 {
609 public:
610 ~wxSuffixMap();
611
612 inline char *GetName(int weight, int style)
613 {
614 return ( map [WCoordinate(weight)] [SCoordinate(style)] );
615 }
616
617 char *map[wxNUM_WEIGHTS][wxNUM_STYLES];
618 void Initialize(const char *, const char *);
619 };
620
621 static void SearchResource(const char *prefix, const char **names, int count, char **v)
622 {
623 int k, i, j;
624 char resource[1024], **defaults, *internal;
625
626 k = 1 << count;
627
628 *v = (char *) NULL;
629 internal = (char *) NULL;
630
631 for (i = 0; i < k; i++)
632 {
633 strcpy(resource, prefix);
634 for (j = 0; j < count; j++)
635 {
636 // upon failure to find a matching fontname
637 // in the default fonts above, we substitute more
638 // and more values by _ so that at last ScreenMyFontBoldNormal
639 // would turn into Screen___ and this will then get
640 // converted to -${ScreenDefaultBase}${ScreenStdSuffix}
641
642 if (!(i & (1 << j)))
643 strcat(resource, names[j]);
644 else
645 strcat(resource, "_");
646 }
647
648 // we previously search the Xt-resources here
649
650 if (!internal)
651 {
652 defaults = font_defaults;
653 while (*defaults)
654 {
655 if (!strcmp(*defaults, resource))
656 {
657 internal = defaults[1];
658 break;
659 }
660 defaults += 2;
661 }
662 }
663 }
664
665 if (internal)
666 {
667 if ((strcmp(internal,"-${ScreenDefaultBase}${ScreenStdSuffix}") == 0) &&
668 (strcmp(names[0], "Default") != 0))
669 {
670 // we did not find any font name in the standard list.
671 // this can (hopefully does) mean that someone supplied
672 // the facename in the wxFont constructor so we insert
673 // it here
674
675 strcpy( resource,"-*-" ); // any producer
676 strcat( resource, names[0] ); // facename
677 strcat( resource, "${ScreenStdSuffix}" ); // add size params later on
678 *v = copystring(resource);
679 }
680 else
681 {
682 *v = copystring(internal);
683 }
684 }
685 }
686
687 wxSuffixMap::~wxSuffixMap()
688 {
689 int k, j;
690
691 for (k = 0; k < wxNUM_WEIGHTS; ++k)
692 for (j = 0; j < wxNUM_STYLES; ++j)
693 if (map[k][j])
694 {
695 delete[] map[k][j];
696 map[k][j] = (char *) NULL;
697 }
698 }
699
700 void wxSuffixMap::Initialize(const char *resname, const char *devresname)
701 {
702 const char *weight, *style;
703 char *v;
704 int i, j, k;
705 const char *names[3];
706
707 for (k = 0; k < wxNUM_WEIGHTS; k++)
708 {
709 switch (k)
710 {
711 case wxWEIGHT_NORMAL: weight = "Medium"; break;
712 case wxWEIGHT_LIGHT: weight = "Light"; break;
713 case wxWEIGHT_BOLD:
714 default: weight = "Bold";
715 }
716 for (j = 0; j < wxNUM_STYLES; j++)
717 {
718 switch (j)
719 {
720 case wxSTYLE_NORMAL: style = "Straight"; break;
721 case wxSTYLE_ITALIC: style = "Italic"; break;
722 case wxSTYLE_SLANT:
723 default: style = "Slant";
724 }
725 names[0] = resname;
726 names[1] = weight;
727 names[2] = style;
728
729 SearchResource(devresname, names, 3, &v);
730
731 // Expand macros in the found string:
732 found:
733 int len, closer = 0, startpos = 0;
734
735 len = (v ? strlen(v) : 0);
736 for (i = 0; i < len; i++)
737 {
738 if (v[i] == '$' && ((v[i+1] == '[') || (v[i+1] == '{')))
739 {
740 startpos = i;
741 closer = (v[i+1] == '[') ? ']' : '}';
742 ++i;
743 }
744 else if (v[i] == closer)
745 {
746 int newstrlen;
747 const char *r = (char *) NULL; bool delete_r = FALSE;
748 char *name;
749
750 name = v + startpos + 2;
751 v[i] = 0;
752
753 if (closer == '}')
754 {
755 int i, count, len;
756 char **names;
757
758 for (i = 0, count = 1; name[i]; i++)
759 if (name[i] == ',')
760 count++;
761
762 len = i;
763
764 names = new char*[count];
765 names[0] = name;
766 for (i = 0, count = 1; i < len; i++)
767 if (name[i] == ',')
768 {
769 names[count++] = name + i + 1;
770 name[i] = 0;
771 }
772
773 SearchResource("", (const char **)names, count, (char **)&r);
774 delete_r = (r != 0);
775 delete[] names;
776
777 if (!r)
778 {
779 for (i = 0; i < len; i++)
780 if (!name[i])
781 name[i] = ',';
782 r = "";
783 wxLogError( "Bad resource name in font lookup." );
784 }
785 } else if (!strcmp(name, "weight")) {
786 r = weight;
787 } else if (!strcmp(name, "style")) {
788 r = style;
789 } else if (!strcmp(name, "family")) {
790 r = resname;
791 } else {
792 r = "";
793 wxLogError( "Bad font macro name." );
794 }
795
796 // add r to v
797 newstrlen = strlen(r);
798 char *naya = new char[startpos + newstrlen + len - i];
799 memcpy(naya, v, startpos);
800 memcpy(naya + startpos, r, newstrlen);
801 memcpy(naya + startpos + newstrlen, v + i + 1, len - i);
802 if (delete_r)
803 delete[] (char*)r;
804 delete[] v;
805 v = naya;
806
807 goto found;
808 }
809 }
810 // We have a final value:
811 map[k][j] = v;
812 }
813 }
814 }
815
816 //-----------------------------------------------------------------------------
817 // wxFontNameItem
818 //-----------------------------------------------------------------------------
819
820 class wxFontNameItem : public wxObject
821 {
822 DECLARE_DYNAMIC_CLASS(wxFontNameItem)
823 public:
824 wxFontNameItem(const char *name, int id, int family);
825 ~wxFontNameItem();
826
827 inline char* GetScreenName(int w, int s) {return screen.GetName(w, s);}
828 inline char* GetPostScriptName(int w, int s) {return printing.GetName(w, s);}
829 inline char* GetAFMName(int w, int s) {return afm.GetName(w, s);}
830 inline char* GetName() {return name;}
831 inline int GetFamily() {return family;}
832 inline int GetId() {return id;}
833 inline bool IsRoman() {return isroman;}
834 #if defined(__WXDEBUG__)
835 void Dump(ostream& str);
836 #endif
837
838 int id;
839 int family;
840 char *name;
841 wxSuffixMap screen, printing, afm;
842 bool isroman;
843 };
844
845 IMPLEMENT_ABSTRACT_CLASS(wxFontNameItem, wxObject)
846
847 wxFontNameItem::wxFontNameItem(const char *Name, int Id, int Family)
848 {
849 name = copystring(Name);
850 id = Id;
851 family = Family;
852
853 screen. Initialize(name, "Screen");
854 printing.Initialize(name, "PostScript");
855 afm. Initialize(name, "Afm");
856 }
857
858 wxFontNameItem::~wxFontNameItem()
859 {
860 if (name)
861 delete[] name;
862 name = (char *) NULL;
863 }
864
865 #if defined(__WXDEBUG__)
866 void wxFontNameItem::Dump(ostream& str)
867 {
868 str << "wxFontNameItem(" << name << ")";
869 }
870 #endif
871
872 //-----------------------------------------------------------------------------
873 // wxFontDirectory
874 //-----------------------------------------------------------------------------
875
876 IMPLEMENT_DYNAMIC_CLASS(wxFontNameDirectory, wxObject)
877
878 wxFontNameDirectory::wxFontNameDirectory()
879 {
880 table = new wxHashTable(wxKEY_INTEGER, 20);
881 nextFontId = -1;
882 }
883
884 wxFontNameDirectory::~wxFontNameDirectory()
885 {
886 // Cleanup wxFontNameItems allocated
887 table->BeginFind();
888 wxNode *node = table->Next();
889 while (node)
890 {
891 wxFontNameItem *item = (wxFontNameItem*)node->Data();
892 delete item;
893 node = table->Next();
894 }
895 delete table;
896 }
897
898 int wxFontNameDirectory::GetNewFontId()
899 {
900 return (nextFontId--);
901 }
902
903 void wxFontNameDirectory::Initialize()
904 {
905 Initialize(wxDEFAULT, wxDEFAULT, "Default");
906 Initialize(wxDECORATIVE, wxDECORATIVE, "Decorative");
907 Initialize(wxROMAN, wxROMAN, "Roman");
908 Initialize(wxMODERN, wxMODERN, "Modern");
909 Initialize(wxTELETYPE, wxTELETYPE, "Teletype");
910 Initialize(wxSWISS, wxSWISS, "Swiss");
911 Initialize(wxSCRIPT, wxSCRIPT, "Script");
912 }
913
914 void wxFontNameDirectory::Initialize(int fontid, int family, const char *resname)
915 {
916 char *fam, resource[256];
917
918 sprintf(resource, "Family%s", resname);
919 SearchResource((const char *)resource, (const char **) NULL, 0, (char **)&fam);
920
921 if (fam)
922 {
923 if (!strcmp(fam, "Default")) family = wxDEFAULT;
924 else if (!strcmp(fam, "Roman")) family = wxROMAN;
925 else if (!strcmp(fam, "Decorative")) family = wxDECORATIVE;
926 else if (!strcmp(fam, "Modern")) family = wxMODERN;
927 else if (!strcmp(fam, "Teletype")) family = wxTELETYPE;
928 else if (!strcmp(fam, "Swiss")) family = wxSWISS;
929 else if (!strcmp(fam, "Script")) family = wxSCRIPT;
930 delete[] fam; // free resource
931 }
932 table->Put(fontid, new wxFontNameItem(resname, fontid, family));
933 }
934
935 int wxFontNameDirectory::FindOrCreateFontId(const char *name, int family)
936 {
937 int id;
938
939 // font exists -> return id
940 if ( (id = GetFontId(name)) ) return id;
941
942 // create new font
943 Initialize(id=GetNewFontId(), family, name);
944 return id;
945 }
946
947 char *wxFontNameDirectory::GetScreenName(int fontid, int weight, int style)
948 {
949 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
950 if (item)
951 return item->GetScreenName(weight, style);
952
953 // font does not exist
954 return (char *) NULL;
955 }
956
957 char *wxFontNameDirectory::GetPostScriptName(int fontid, int weight, int style)
958 {
959 wxFontNameItem *item = (wxFontNameItem*)table->Get(fontid); // find font
960 if (item)
961 return item->GetPostScriptName(weight, style);
962
963 // font does not exist
964 return (char *) NULL;
965 }
966
967 char *wxFontNameDirectory::GetAFMName(int fontid, int weight, int style)
968 {
969 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
970 if (item)
971 return item->GetAFMName(weight, style);
972 // font does not exist
973 return (char *) NULL;
974 }
975
976 char *wxFontNameDirectory::GetFontName(int fontid)
977 {
978 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid); // find font
979 if (item)
980 return item->GetName();
981
982 // font does not exist
983 return (char *) NULL;
984 }
985
986 int wxFontNameDirectory::GetFontId(const char *name)
987 {
988 wxNode *node;
989
990 table->BeginFind();
991
992 while ( (node = table->Next()) )
993 {
994 wxFontNameItem *item = (wxFontNameItem*)node->Data();
995 if (!strcmp(name, item->name))
996 return item->id;
997 }
998
999 // font does not exist
1000 return 0;
1001 }
1002
1003 int wxFontNameDirectory::GetFamily(int fontid)
1004 {
1005 wxFontNameItem *item = (wxFontNameItem *)table->Get(fontid);
1006
1007 if (item)
1008 return item->family;
1009
1010 // font does not exist
1011 return wxDEFAULT;
1012 }
1013
1014 */