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