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