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