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